diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2014-10-14 18:24:46 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2014-10-14 18:24:46 -0700 |
commit | 554ac51249633f529860ffd902af6969ef73b209 (patch) | |
tree | 05c043126fd2790a83a21f11e9b9e333255a2728 | |
parent | b9a05206d6927c2238a666ae798285fee6b50e41 (diff) | |
download | mu-554ac51249633f529860ffd902af6969ef73b209.tar.gz |
148 - better idiom for generic functions
-rw-r--r-- | mu.arc | 19 | ||||
-rw-r--r-- | mu.arc.t | 197 |
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) |