about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--mu.arc19
-rw-r--r--mu.arc.t197
2 files changed, 123 insertions, 93 deletions
diff --git a/mu.arc b/mu.arc
index f540e776..fc6f3747 100644
--- a/mu.arc
+++ b/mu.arc
@@ -292,12 +292,17 @@
                 ; control flow
                 jump
                   (do (= pc.context (+ 1 pc.context (v arg.0)))
-;?                       (prn "jumping to " pc.context)
+;?                       (trace "jump" "jumping to " pc.context)
                       (continue))
                 jump-if
                   (when (is t (m arg.0))
                     (= pc.context (+ 1 pc.context (v arg.1)))
-;?                     (prn "jumping to " pc.context)
+;?                     (trace "jump-if" "jumping to " pc.context)
+                    (continue))
+                jump-unless  ; convenient helper
+                  (unless (is t (m arg.0))
+                    (= pc.context (+ 1 pc.context (v arg.1)))
+;?                     (trace "jump-unless" "jumping to " pc.context)
                     (continue))
 
                 ; data management: scalars, arrays, records
@@ -517,6 +522,11 @@
 ;?                       (prn "break-if: " instr)
                       (assert:is oarg nil)
                       (yield `(jump-if ,arg.0 (,(close-offset pc locs) offset))))
+                  break-unless
+                    (do
+;?                       (prn "break-if: " instr)
+                      (assert:is oarg nil)
+                      (yield `(jump-unless ,arg.0 (,(close-offset pc locs) offset))))
                   continue
                     (do
                       (assert:is oarg nil)
@@ -527,6 +537,11 @@
                       (trace "cvt0" "continue-if: " instr " => " (- stack.0 1))
                       (assert:is oarg nil)
                       (yield `(jump-if ,arg.0 (,(- stack.0 1 pc) offset))))
+                  continue-unless
+                    (do
+                      (trace "cvt0" "continue-if: " instr " => " (- stack.0 1))
+                      (assert:is oarg nil)
+                      (yield `(jump-unless ,arg.0 (,(- stack.0 1 pc) offset))))
                   ;else
                     (yield instr))))
             (++ pc))))))))
diff --git a/mu.arc.t b/mu.arc.t
index 2ade18d9..4be95dcc 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -977,97 +977,6 @@
                          4 1  5 3  6 4))
   (prn "F - 'reply' permits a function to return multiple values at once"))
 
-; 'type' and 'otype' let us create generic functions that run different code
-; based on what args the caller provides, or what oargs the caller expects.
-;
-; These operations are almost certainly bad ideas; they violate our constraint
-; of easily assembling down to native code. We'll eventually switch to dynamic
-; typing with tagged-values.
-
-(reset)
-(new-trace "dispatch-otype")
-(add-fns
-  '((test1
-      ((4 type) <- otype 0)
-      ((5 boolean) <- neq (4 type) (integer literal))
-      (jump-if (5 boolean) (3 offset))
-      ((6 integer) <- arg)
-      ((7 integer) <- arg)
-      ((8 integer) <- add (6 integer) (7 integer))
-      (reply (8 integer)))
-    (main
-      ((1 integer) <- test1 (1 literal) (3 literal)))))
-(run 'main)
-;? (prn memory*)
-(if (~iso memory* (obj 1 4
-                         ; add-fn's temporaries
-                         4 'integer  5 nil  6 1  7 3  8 4))
-  (prn "F - an example function that checks that its oarg is an integer"))
-;? (quit)
-
-; todo - test that reply increments pc for caller frame after popping current frame
-
-(reset)
-(new-trace "dispatch-otype-multiple-clauses")
-(add-fns
-  '((test-fn
-      ((4 type) <- otype 0)
-      ; integer needed? add args
-      ((5 boolean) <- neq (4 type) (integer literal))
-      (jump-if (5 boolean) (4 offset))
-      ((6 integer) <- arg)
-      ((7 integer) <- arg)
-      ((8 integer) <- add (6 integer) (7 integer))
-      (reply (8 integer))
-      ; boolean needed? 'or' args
-      ((5 boolean) <- neq (4 type) (boolean literal))
-      (jump-if (5 boolean) (4 offset))
-      ((6 boolean) <- arg)
-      ((7 boolean) <- arg)
-      ((8 boolean) <- or (6 boolean) (7 boolean))
-      (reply (8 boolean)))
-    (main
-      ((1 boolean) <- test-fn (t literal) (t literal)))))
-(run 'main)
-;? (prn memory*)
-(if (~is memory*.1 t)
-  (prn "F - an example function that can do different things (dispatch) based on the type of its args or oargs"))
-(if (~iso memory* (obj 1 t
-                       ; add-fn's temporaries
-                       4 'boolean  5 nil  6 t  7 t  8 t))
-  (prn "F - an example function that can do different things (dispatch) based on the type of its args or oargs (internals)"))
-;? (quit)
-
-(reset)
-(new-trace "dispatch-otype-multiple-calls")
-(add-fns
-  '((test-fn
-      ((4 type) <- otype 0)
-      ((5 boolean) <- neq (4 type) (integer literal))
-      (jump-if (5 boolean) (4 offset))
-      ((6 integer) <- arg)
-      ((7 integer) <- arg)
-      ((8 integer) <- add (6 integer) (7 integer))
-      (reply (8 integer))
-      ((5 boolean) <- neq (4 type) (boolean literal))
-      (jump-if (5 boolean) (6 offset))
-      ((6 boolean) <- arg)
-      ((7 boolean) <- arg)
-      ((8 boolean) <- or (6 boolean) (7 boolean))
-      (reply (8 boolean)))
-    (main
-      ((1 boolean) <- test-fn (t literal) (t literal))
-      ((2 integer) <- test-fn (3 literal) (4 literal)))))
-(run 'main)
-;? (prn memory*)
-(if (~and (is memory*.1 t) (is memory*.2 7))
-  (prn "F - different calls can exercise different clauses of the same function"))
-(if (~iso memory* (obj ; results of first and second calls to test-fn
-                       1 t  2 7
-                       ; temporaries for most recent call to test-fn
-                       4 'integer  5 nil  6 3  7 4  8 7))
-  (prn "F - different calls can exercise different clauses of the same function (internals)"))
-
 ; Our control operators are quite inconvenient to use, so mu provides a
 ; lightweight tool called 'convert-braces' to work in a slightly more
 ; convenient format with nested braces:
@@ -1228,6 +1137,112 @@
 (if (~iso memory* (obj 1 4  2 4  3 nil  4 34))
   (prn "F - continue might never trigger"))
 
+; 'type' and 'otype' let us create generic functions that run different code
+; based on what args the caller provides, or what oargs the caller expects.
+;
+; These operations are almost certainly bad ideas; they violate our constraint
+; of easily assembling down to native code. We'll eventually switch to dynamic
+; typing with tagged-values.
+
+(reset)
+(new-trace "dispatch-otype")
+(add-fns
+  '((test1
+      ((4 type) <- otype 0)
+      { begin
+        ((5 boolean) <- eq (4 type) (integer literal))
+        (break-unless (5 boolean))
+        ((6 integer) <- arg)
+        ((7 integer) <- arg)
+        ((8 integer) <- add (6 integer) (7 integer))
+      }
+      (reply (8 integer)))
+    (main
+      ((1 integer) <- test1 (1 literal) (3 literal)))))
+(run 'main)
+;? (prn memory*)
+(if (~iso memory* (obj 1 4
+                         ; add-fn's temporaries
+                         4 'integer  5 t  6 1  7 3  8 4))
+  (prn "F - an example function that checks that its oarg is an integer"))
+;? (quit)
+
+; todo - test that reply increments pc for caller frame after popping current frame
+
+(reset)
+(new-trace "dispatch-otype-multiple-clauses")
+;? (set dump-trace*)
+(add-fns
+  '((test-fn
+      ((4 type) <- otype 0)
+      { begin
+        ; integer needed? add args
+        ((5 boolean) <- eq (4 type) (integer literal))
+        (break-unless (5 boolean))
+        ((6 integer) <- arg)
+        ((7 integer) <- arg)
+        ((8 integer) <- add (6 integer) (7 integer))
+        (reply (8 integer))
+      }
+      { begin
+        ; boolean needed? 'or' args
+        ((5 boolean) <- eq (4 type) (boolean literal))
+        (break-unless (5 boolean) (4 offset))
+        ((6 boolean) <- arg)
+        ((7 boolean) <- arg)
+        ((8 boolean) <- or (6 boolean) (7 boolean))
+        (reply (8 boolean))
+      })
+    (main
+      ((1 boolean) <- test-fn (t literal) (t literal)))))
+;? (each stmt function*!test-fn
+;?   (prn "  " stmt))
+(run 'main)
+;? (wipe dump-trace*)
+;? (prn memory*)
+(if (~is memory*.1 t)
+  (prn "F - an example function that can do different things (dispatch) based on the type of its args or oargs"))
+(if (~iso memory* (obj 1 t
+                       ; add-fn's temporaries
+                       4 'boolean  5 t  6 t  7 t  8 t))
+  (prn "F - an example function that can do different things (dispatch) based on the type of its args or oargs (internals)"))
+;? (quit)
+
+(reset)
+(new-trace "dispatch-otype-multiple-calls")
+(add-fns
+  '((test-fn
+      ((4 type) <- otype 0)
+      { begin
+        ((5 boolean) <- eq (4 type) (integer literal))
+        (break-unless (5 boolean))
+        ((6 integer) <- arg)
+        ((7 integer) <- arg)
+        ((8 integer) <- add (6 integer) (7 integer))
+        (reply (8 integer))
+      }
+      { begin
+        ((5 boolean) <- eq (4 type) (boolean literal))
+        (break-unless (5 boolean))
+        ((6 boolean) <- arg)
+        ((7 boolean) <- arg)
+        ((8 boolean) <- or (6 boolean) (7 boolean))
+        (reply (8 boolean))
+      })
+    (main
+      ((1 boolean) <- test-fn (t literal) (t literal))
+      ((2 integer) <- test-fn (3 literal) (4 literal)))))
+(run 'main)
+;? (prn memory*)
+(if (~and (is memory*.1 t) (is memory*.2 7))
+  (prn "F - different calls can exercise different clauses of the same function"))
+(if (~iso memory* (obj ; results of first and second calls to test-fn
+                       1 t  2 7
+                       ; temporaries for most recent call to test-fn
+                       4 'integer  5 t  6 3  7 4  8 7))
+  (prn "F - different calls can exercise different clauses of the same function (internals)"))
+
+
 ; A rudimentary memory allocator. Eventually we want to write this in mu.
 
 (reset)