shithub: orca

Download patch

ref: d207514a1ac74107c65330daf0bfc711f8103cb8
parent: a72945474330a20e3efcb2d0fbc63cc29836b037
author: cancel <cancel@cancel.fm>
date: Tue Nov 27 06:55:47 EST 2018

Add more operator macros

--- a/.clang-format
+++ b/.clang-format
@@ -2,5 +2,5 @@
 PointerAlignment: Left
 ReflowComments: false
 
-MacroBlockBegin: "^OPER_SOLO_PHASE_.|^OPER_DUAL_PHASE_."
+MacroBlockBegin: "^OPER_SOLO_PHASE_.|^OPER_DUAL_PHASE_.|^OPER_DUAL_PORTS|^OPER_HASTE"
 MacroBlockEnd: "^OPER_END"
--- a/sim.c
+++ b/sim.c
@@ -113,13 +113,17 @@
       Glyph const This_oper_char) {                                            \
     OPER_IGNORE_COMMON_ARGS()                                                  \
     (void)cell_flags;                                                          \
-    (void)This_oper_char;
+    bool const Dual_is_uppercase =                                             \
+        Orca_oper_char_##_upper_oper_name == This_oper_char;                   \
+    (void)Dual_is_uppercase;
 #define OPER_DUAL_PHASE_1(_upper_oper_name)                                    \
   static inline void oper_phase1_##_upper_oper_name(                           \
       Gbuffer const gbuffer, Mbuffer const mbuffer, Usz const height,          \
       Usz const width, Usz const y, Usz const x, Glyph const This_oper_char) { \
     OPER_IGNORE_COMMON_ARGS()                                                  \
-    (void)This_oper_char;
+    bool const Dual_is_uppercase =                                             \
+        Orca_oper_char_##_upper_oper_name == This_oper_char;                   \
+    (void)Dual_is_uppercase;
 
 #define OPER_END }
 
@@ -140,14 +144,38 @@
 #define PORT_UNLOCKED Mark_flag_none
 #define PORT_HASTE Mark_flag_haste_input
 
-#define OPER_PORT_INPUT(_delta_y, _delta_x, _flags)                            \
-  mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y,       \
-                                 _delta_x, Mark_flag_input | _flags)
+#define OPER_DUAL_ACTIVATION()                                                 \
+  bool const Dual_is_active =                                                  \
+      Dual_is_uppercase |                                                      \
+      oper_has_neighboring_bang(gbuffer, height, width, y, x);
 
+#define OPER_DUAL_PORTS                                                        \
+  {                                                                            \
+    bool const Oper_ports_enabled = Dual_is_active;
+
+#define OPER_DUAL_REQUIRE_TRIGGER()                                            \
+  if (!Dual_is_active)                                                         \
+  return
+
+#define OPER_PORT_INPUT(_delta_y, _delta_x, _flags)                            \
+  mbuffer_poke_relative_flags_or(                                              \
+      mbuffer, height, width, y, x, _delta_y, _delta_x,                        \
+      Mark_flag_input | ((_flags)&Mark_flag_haste_input) |                     \
+          (Oper_ports_enabled &&                                               \
+                   (cell_flags & (Mark_flag_lock | Mark_flag_sleep))           \
+               ? Mark_flag_none                                                \
+               : (_flags)))
 #define OPER_PORT_OUTPUT(_delta_y, _delta_x, _flags)                           \
-  mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y,       \
-                                 _delta_x, Mark_flag_output | _flags)
+  mbuffer_poke_relative_flags_or(                                              \
+      mbuffer, height, width, y, x, _delta_y, _delta_x,                        \
+      Mark_flag_input | ((_flags)&Mark_flag_haste_input) |                     \
+          (Oper_ports_enabled &&                                               \
+                   (cell_flags & (Mark_flag_lock | Mark_flag_sleep))           \
+               ? Mark_flag_none                                                \
+               : (_flags)))
 
+#define OPER_HASTE if (!(cell_flags & (Mark_flag_lock | Mark_flag_sleep))) {
+
 #define OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x)                               \
   oper_move_relative_or_explode(gbuffer, mbuffer, height, width,               \
                                 This_oper_char, y, x, _delta_y, _delta_x)
@@ -155,7 +183,11 @@
 #define OPER_DEFINE_DIRECTIONAL(_upper_oper_name, _lower_oper_name, _delta_y,  \
                                 _delta_x)                                      \
   OPER_DUAL_PHASE_0(_upper_oper_name)                                          \
-    OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x);                                  \
+    OPER_HASTE                                                                 \
+      OPER_DUAL_ACTIVATION();                                                  \
+      OPER_DUAL_REQUIRE_TRIGGER();                                             \
+      OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x);                                \
+    OPER_END                                                                   \
   OPER_END                                                                     \
   OPER_DUAL_PHASE_1(_upper_oper_name)                                          \
   OPER_END
@@ -183,11 +215,16 @@
 OPER_DEFINE_DIRECTIONAL(West, west, 0, -1)
 
 OPER_DUAL_PHASE_0(Add)
-  OPER_PORT_INPUT(0, 1, PORT_LOCKED);
-  OPER_PORT_INPUT(0, 2, PORT_LOCKED);
-  OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_DUAL_ACTIVATION();
+  OPER_DUAL_PORTS
+    OPER_PORT_INPUT(0, 1, PORT_LOCKED);
+    OPER_PORT_INPUT(0, 2, PORT_LOCKED);
+    OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_END
 OPER_END
 OPER_DUAL_PHASE_1(Add)
+  OPER_DUAL_ACTIVATION();
+  OPER_DUAL_REQUIRE_TRIGGER();
   Glyph inp0 = OPER_PEEK(0, 1);
   Glyph inp1 = OPER_PEEK(0, 2);
   Glyph g = glyphs_sum(inp0, inp1);
@@ -195,11 +232,16 @@
 OPER_END
 
 OPER_DUAL_PHASE_0(Modulo)
-  OPER_PORT_INPUT(0, 1, PORT_LOCKED);
-  OPER_PORT_INPUT(0, 2, PORT_LOCKED);
-  OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_DUAL_ACTIVATION();
+  OPER_DUAL_PORTS
+    OPER_PORT_INPUT(0, 1, PORT_LOCKED);
+    OPER_PORT_INPUT(0, 2, PORT_LOCKED);
+    OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_END
 OPER_END
 OPER_DUAL_PHASE_1(Modulo)
+  OPER_DUAL_ACTIVATION();
+  OPER_DUAL_REQUIRE_TRIGGER();
   Glyph inp0 = OPER_PEEK(0, 1);
   Glyph inp1 = OPER_PEEK(0, 2);
   Glyph g = glyphs_mod(inp0, inp1);
@@ -207,17 +249,22 @@
 OPER_END
 
 OPER_DUAL_PHASE_0(Increment)
-  OPER_PORT_INPUT(0, 1, PORT_LOCKED);
-  OPER_PORT_INPUT(0, 2, PORT_LOCKED);
-  OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_DUAL_ACTIVATION();
+  OPER_DUAL_PORTS
+    OPER_PORT_INPUT(0, 1, PORT_LOCKED);
+    OPER_PORT_INPUT(0, 2, PORT_LOCKED);
+    OPER_PORT_OUTPUT(1, 0, PORT_LOCKED);
+  OPER_END
 OPER_END
 OPER_DUAL_PHASE_1(Increment)
 OPER_END
 
 OPER_SOLO_PHASE_0(bang)
+  OPER_HASTE
+    OPER_POKE_SELF('.');
+  OPER_END
 OPER_END
 OPER_SOLO_PHASE_1(bang)
-  OPER_POKE_SELF('.');
 OPER_END
 
 //////// Run simulation