(load "mu.arc")
(reset)
(new-trace "literal")
(add-fns
'((main
((1 integer) <- copy (23 literal)))))
(run 'main)
(if (~is memory*.1 23)
(prn "F - 'copy' writes its lone 'arg' after the instruction name to its lone 'oarg' or output arg before the arrow. After this test, the value 23 is stored in memory address 1."))
(reset)
(new-trace "add")
(add-fns
'((main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
((3 integer) <- add (1 integer) (2 integer)))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4))
(prn "F - 'add' operates on two addresses"))
(reset)
(new-trace "add-literal")
(add-fns
'((main
((1 integer) <- add (2 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 5)
(prn "F - ops can take 'literal' operands (but not return them)"))
(reset)
(new-trace "sub-literal")
(add-fns
'((main
((1 integer) <- sub (1 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 -2)
(prn "F - 'sub' subtracts the second arg from the first"))
(reset)
(new-trace "mul-literal")
(add-fns
'((main
((1 integer) <- mul (2 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 6)
(prn "F - 'mul' multiplies like 'add' adds"))
(reset)
(new-trace "div-literal")
(add-fns
'((main
((1 integer) <- div (8 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 (/ real.8 3))
(prn "F - 'div' divides like 'sub' subtracts"))
(reset)
(new-trace "idiv-literal")
(add-fns
'((main
((1 integer) (2 integer) <- idiv (23 literal) (6 literal)))))
(run 'main)
(if (~iso memory* (obj 1 3 2 5))
(prn "F - 'idiv' performs integer division, returning quotient and remainder"))
(reset)
(new-trace "and-literal")
(add-fns
'((main
((1 boolean) <- and (t literal) (t literal)))))
(run 'main)
(if (~is memory*.1 nil)
(prn "F - logical 'and' for booleans"))
(reset)
(new-trace "lt-literal")
(add-fns
'((main
((1 boolean) <- lt (4 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 nil)
(prn "F - 'lt' is the less-than inequality operator"))
(reset)
(new-trace "le-literal-false")
(add-fns
'((main
((1 boolean) <- le (4 literal) (3 literal)))))
(run 'main)
(if (~is memory*.1 nil)
(prn "F - 'le' is the <= inequality operator"))
(reset)
(new-trace "le-literal-true")
(add-fns
'((main
((1 boolean) <- le (4 literal) (4 literal)))))
(run 'main)
(if (~is memory*.1 t)
(prn "F - 'le' returns true for equal operands"))
(reset)
(new-trace "le-literal-true-2")
(add-fns
'((main
((1 boolean) <- le (4 literal) (5 literal)))))
(run 'main)
(if (~is memory*.1 t)
(prn "F - le is the <= inequality operator - 2"))
(reset)
(new-trace "jump-skip")
(add-fns
'((main
((1 integer) <- copy (8 literal))
(jump (1 offset))
((2 integer) <- copy (3 literal))
(reply))))
(run 'main)
(if (~iso memory* (obj 1 8))
(prn "F - 'jump' skips some instructions"))
(reset)
(new-trace "jump-target")
(add-fns
'((main
((1 integer) <- copy (8 literal))
(jump (1 offset))
((2 integer) <- copy (3 literal))
(reply)
((3 integer) <- copy (34 literal)))))
(run 'main)
(if (~iso memory* (obj 1 8))
(prn "F - 'jump' doesn't skip too many instructions"))
(reset)
(new-trace "jump-if-skip")
(add-fns
'((main
((2 integer) <- copy (1 literal))
((1 boolean) <- eq (1 literal) (2 integer))
(jump-if (1 boolean) (1 offset))
((2 integer) <- copy (3 literal))
(reply)
((3 integer) <- copy (34 literal)))))
(run 'main)
(if (~iso memory* (obj 1 t 2 1))
(prn "F - 'jump-if' is a conditional 'jump'"))
(reset)
(new-trace "jump-if-fallthrough")
(add-fns
'((main
((1 boolean) <- eq (1 literal) (2 literal))
(jump-if (3 boolean) (1 offset))
((2 integer) <- copy (3 literal))
(reply)
((3 integer) <- copy (34 literal)))))
(run 'main)
(if (~iso memory* (obj 1 nil 2 3))
(prn "F - if 'jump-if's first arg is false, it doesn't skip any instructions"))
(reset)
(new-trace "jump-if-backward")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (1 literal))
((2 integer) <- add (2 integer) (2 integer))
((3 boolean) <- eq (1 integer) (2 integer))
(jump-if (3 boolean) (-3 offset))
((4 integer) <- copy (3 literal))
(reply)
((3 integer) <- copy (34 literal)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 4 3 nil 4 3))
(prn "F - 'jump-if' can take a negative offset to make backward jumps"))
(reset)
(new-trace "direct-addressing")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 integer) <- copy (1 integer)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 34))
(prn "F - 'copy' performs direct addressing"))
(reset)
(new-trace "indirect-addressing")
(add-fns
'((main
((1 integer-address) <- copy (2 literal))
((2 integer) <- copy (34 literal))
((3 integer) <- copy (1 integer-address deref)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 34 3 34))
(prn "F - 'copy' performs indirect addressing"))
(reset)
(new-trace "indirect-addressing-oarg")
(add-fns
'((main
((1 integer-address) <- copy (2 literal))
((2 integer) <- copy (34 literal))
((1 integer-address deref) <- add (2 integer) (2 literal)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 36))
(prn "F - instructions can perform indirect addressing on output arg"))
(reset)
(new-trace "get-record")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((3 boolean) <- get (1 integer-boolean-pair) (1 offset))
((4 integer) <- get (1 integer-boolean-pair) (0 offset)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 nil 3 nil 4 34))
(prn "F - 'get' accesses fields of records"))
(reset)
(new-trace "get-indirect")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((3 integer-boolean-pair-address) <- copy (1 literal))
((4 boolean) <- get (3 integer-boolean-pair-address deref) (1 offset))
((5 integer) <- get (3 integer-boolean-pair-address deref) (0 offset)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 nil 3 1 4 nil 5 34))
(prn "F - 'get' accesses fields of record address"))
(reset)
(new-trace "get-compound-field")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 integer) <- copy (35 literal))
((3 integer) <- copy (36 literal))
((4 integer-integer-pair) <- get (1 integer-point-pair) (1 offset)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 35 3 36 4 35 5 36))
(prn "F - 'get' accesses fields spanning multiple locations"))
(reset)
(new-trace "get-address")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((3 boolean-address) <- get-address (1 integer-boolean-pair) (1 offset)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 t 3 2))
(prn "F - 'get-address' returns address of fields of records"))
(reset)
(new-trace "get-address-indirect")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((3 integer-boolean-pair-address) <- copy (1 literal))
((4 boolean-address) <- get-address (3 integer-boolean-pair-address deref) (1 offset)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 t 3 1 4 2))
(prn "F - 'get-address' accesses fields of record address"))
(reset)
(new-trace "index-literal")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer-boolean-pair) <- index (1 integer-boolean-pair-array) (1 literal)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 24 7 t))
(prn "F - 'index' accesses indices of arrays"))
(reset)
(new-trace "index-direct")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer) <- copy (1 literal))
((7 integer-boolean-pair) <- index (1 integer-boolean-pair-array) (6 integer)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 1 7 24 8 t))
(prn "F - 'index' accesses indices of arrays"))
(reset)
(new-trace "index-indirect")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer) <- copy (1 literal))
((7 integer-boolean-pair-array-address) <- copy (1 literal))
((8 integer-boolean-pair) <- index (7 integer-boolean-pair-array-address deref) (6 integer)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 1 7 1 8 24 9 t))
(prn "F - 'index' accesses indices of array address"))
(reset)
(new-trace "index-address")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer) <- copy (1 literal))
((7 integer-boolean-pair-address) <- index-address (1 integer-boolean-pair-array) (6 integer)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 1 7 4))
(prn "F - 'index-address' returns addresses of indices of arrays"))
(reset)
(new-trace "index-address-indirect")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer) <- copy (1 literal))
((7 integer-boolean-pair-array-address) <- copy (1 literal))
((8 integer-boolean-pair-address) <- index-address (7 integer-boolean-pair-array-address deref) (6 integer)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 1 7 1 8 4))
(prn "F - 'index-address' returns addresses of indices of array addresses"))
(reset)
(new-trace "len-array")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer) <- len (1 integer-boolean-pair-array)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 2))
(prn "F - 'len' accesses length of array"))
(reset)
(new-trace "len-array-indirect")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 boolean) <- copy (t literal))
((4 integer) <- copy (24 literal))
((5 boolean) <- copy (t literal))
((6 integer-address) <- copy (1 literal))
((7 integer) <- len (6 integer-boolean-pair-array-address deref)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 23 3 nil 4 24 5 t 6 1 7 2))
(prn "F - 'len' accesses length of array address"))
(reset)
(new-trace "sizeof-record")
(add-fns
'((main
((1 integer) <- sizeof (integer-boolean-pair literal)))))
(run 'main)
(if (~is memory*.1 2)
(prn "F - 'sizeof' returns space required by arg"))
(reset)
(new-trace "sizeof-record-not-len")
(add-fns
'((main
((1 integer) <- sizeof (integer-point-pair literal)))))
(run 'main)
(if (~is memory*.1 3)
(prn "F - 'sizeof' is different from number of elems"))
(reset)
(new-trace "compound-operand-copy")
(add-fns
'((main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((4 boolean) <- copy (t literal))
((3 integer-boolean-pair) <- copy (1 integer-boolean-pair)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 nil 3 34 4 nil))
(prn "F - ops can operate on records spanning multiple locations"))
(reset)
(new-trace "compound-arg")
(add-fns
'((test1
((4 integer-boolean-pair) <- arg))
(main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
(test1 (1 integer-boolean-pair)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 nil 4 34 5 nil))
(prn "F - 'arg' can copy records spanning multiple locations"))
(reset)
(new-trace "compound-arg-indirect")
(add-fns
'((test1
((4 integer-boolean-pair) <- arg))
(main
((1 integer) <- copy (34 literal))
((2 boolean) <- copy (t literal))
((3 integer-boolean-pair-address) <- copy (1 literal))
(test1 (3 integer-boolean-pair-address deref)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 nil 3 1 4 34 5 nil))
(prn "F - 'arg' can copy records spanning multiple locations in indirect mode"))
(reset)
(new-trace "tagged-value")
(add-fns
'((main
((1 type) <- copy (integer-address literal))
((2 integer-address) <- copy (34 literal))
((3 integer-address) (4 boolean) <- maybe-coerce (1 tagged-value) (integer-address literal)))))
(run 'main)
(let last-routine (deq completed-routines*)
(aif rep.last-routine!error (prn "error - " it)))
(if (or (~is memory*.3 34) (~is memory*.4 t))
(prn "F - 'maybe-coerce' copies value only if type tag matches"))
(reset)
(new-trace "tagged-value-2")
(add-fns
'((main
((1 type) <- copy (integer-address literal))
((2 integer-address) <- copy (34 literal))
((3 integer-address) (4 boolean) <- maybe-coerce (1 tagged-value) (boolean-address literal)))))
(run 'main)
(if (or (~is memory*.3 0) (~is memory*.4 nil))
(prn "F - 'maybe-coerce' doesn't copy value when type tag doesn't match"))
(reset)
(new-trace "save-type")
(add-fns
'((main
((1 integer-address) <- copy (34 literal))
((2 tagged-value) <- save-type (1 integer-address)))))
(run 'main)
(if (~iso memory* (obj 1 34 2 'integer-address 3 34))
(prn "F - 'save-type' saves the type of a value at runtime, turning it into a tagged-value"))
(reset)
(new-trace "new-tagged-value")
(add-fns
'((main
((1 integer-address) <- copy (34 literal))
((2 tagged-value-address) <- new-tagged-value (integer-address literal) (1 integer-address))
((3 integer-address) (4 boolean) <- maybe-coerce (2 tagged-value-address deref) (integer-address literal)))))
(run 'main)
(if (or (~is memory*.3 34) (~is memory*.4 t))
(prn "F - 'new-tagged-value' is the converse of 'maybe-coerce'"))
(reset)
(new-trace "list")
(add-fns
'((test1
((1 list-address) <- new (list literal))
((2 tagged-value-address) <- list-value-address (1 list-address))
((3 type-address) <- get-address (2 tagged-value-address deref) (0 offset))
((3 type-address deref) <- copy (integer literal))
((4 location) <- get-address (2 tagged-value-address deref) (1 offset))
((4 location deref) <- copy (34 literal))
((5 list-address-address) <- get-address (1 list-address deref) (1 offset))
((5 list-address-address deref) <- new (list literal))
((6 list-address) <- copy (5 list-address-address deref))
((7 tagged-value-address) <- list-value-address (6 list-address))
((8 type-address) <- get-address (7 tagged-value-address deref) (0 offset))
((8 type-address deref) <- copy (boolean literal))
((9 location) <- get-address (7 tagged-value-address deref) (1 offset))
((9 location deref) <- copy (t literal))
((10 list-address) <- get (6 list-address deref) (1 offset))
)))
(let first Memory-in-use-until
(run 'test1)
(if (or (~all first (map memory* '(1 2 3)))
(~is memory*.first 'integer)
(~is memory*.4 (+ first 1))
(~is (memory* (+ first 1)) 34)
(~is memory*.5 (+ first 2))
(let second memory*.6
(or
(~is (memory* (+ first 2)) second)
(~all second (map memory* '(6 7 8)))
(~is memory*.second 'boolean)
(~is memory*.9 (+ second 1))
(~is (memory* (+ second 1)) t)
(~is memory*.10 nil))))
(prn "F - lists can contain elements of different types")))
(add-fns
'((test2
((10 list-address) <- list-next (1 list-address)))))
(run 'test2)
(if (~is memory*.10 memory*.6)
(prn "F - 'list-next can move a list pointer to the next node"))
(reset)
(new-trace "new-list")
(add-fns
'((main
((1 integer) <- new-list (3 literal) (4 literal) (5 literal)))))
(run 'main)
(let first memory*.1
(if (or (~is memory*.first 'integer)
(~is (memory* (+ first 1)) 3)
(let second (memory* (+ first 2))
(or (~is memory*.second 'integer)
(~is (memory* (+ second 1)) 4)
(let third (memory* (+ second 2))
(or (~is memory*.third 'integer)
(~is (memory* (+ third 1)) 5)
(~is (memory* (+ third 2) nil)))))))
(prn "F - 'new-list' can construct a list of integers")))
(reset)
(new-trace "new-fn")
(add-fns
'((test1
((3 integer) <- add (1 integer) (2 integer)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
(test1))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4))
(prn "F - calling a user-defined function runs its instructions"))
(reset)
(new-trace "new-fn-once")
(add-fns
'((test1
((1 integer) <- copy (1 literal)))
(main
(test1))))
(if (~is 2 (run 'main))
(prn "F - calling a user-defined function runs its instructions exactly once"))
(reset)
(new-trace "new-fn-reply")
(add-fns
'((test1
((3 integer) <- add (1 integer) (2 integer))
(reply)
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
(test1))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4))
(prn "F - 'reply' stops executing the current function"))
(reset)
(new-trace "new-fn-reply-nested")
(add-fns
`((test1
((3 integer) <- test2))
(test2
(reply (2 integer)))
(main
((2 integer) <- copy (34 literal))
(test1))))
(run 'main)
(if (~iso memory* (obj 2 34 3 34))
(prn "F - 'reply' stops executing any callers as necessary"))
(reset)
(new-trace "new-fn-reply-once")
(add-fns
'((test1
((3 integer) <- add (1 integer) (2 integer))
(reply)
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
(test1))))
(if (~is 4 (run 'main))
(prn "F - 'reply' executes instructions exactly once"))
(reset)
(new-trace "new-fn-arg-sequential")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- arg)
((3 integer) <- add (4 integer) (5 integer))
(reply)
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
(test1 (1 integer) (2 integer))
)))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4
4 1 5 3))
(prn "F - 'arg' accesses in order the operands of the most recent function call (the caller)"))
(reset)
(new-trace "new-fn-arg-random-access")
(add-fns
'((test1
((5 integer) <- arg (1 literal))
((4 integer) <- arg (0 literal))
((3 integer) <- add (4 integer) (5 integer))
(reply)
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
(test1 (1 integer) (2 integer))
)))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4
4 1 5 3))
(prn "F - 'arg' with index can access function call arguments out of order"))
(reset)
(new-trace "new-fn-arg-status")
(add-fns
'((test1
((4 integer) (5 boolean) <- arg))
(main
(test1 (1 literal))
)))
(run 'main)
(if (~iso memory* (obj 4 1 5 t))
(prn "F - 'arg' sets a second oarg when arg exists"))
(reset)
(new-trace "new-fn-arg-missing")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- arg))
(main
(test1 (1 literal))
)))
(run 'main)
(if (~iso memory* (obj 4 1))
(prn "F - missing 'arg' doesn't cause error"))
(reset)
(new-trace "new-fn-arg-missing-2")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) (6 boolean) <- arg))
(main
(test1 (1 literal))
)))
(run 'main)
(if (~iso memory* (obj 4 1 6 nil))
(prn "F - missing 'arg' wipes second oarg when provided"))
(reset)
(new-trace "new-fn-arg-missing-3")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- copy (34 literal))
((5 integer) (6 boolean) <- arg))
(main
(test1 (1 literal))
)))
(run 'main)
(if (~iso memory* (obj 4 1 6 nil))
(prn "F - missing 'arg' consistently wipes its oarg"))
(reset)
(new-trace "new-fn-arg-missing-4")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) (6 boolean) <- arg)
{ begin
(break-if (6 boolean))
((5 integer) <- copy (1 literal))
}
((7 integer) <- add (4 integer) (5 integer)))
(main
(test1 (34 literal))
)))
(run 'main)
(if (~iso memory* (obj 4 34 5 1 6 nil 7 35))
(prn "F - function with optional second arg"))
(reset)
(new-trace "new-fn-arg-by-value")
(add-fns
'((test1
((1 integer) <- copy (0 literal))
((2 integer) <- arg))
(main
((1 integer) <- copy (34 literal))
(test1 (1 integer)))))
(run 'main)
(if (~iso memory* (obj 1 0 2 34))
(prn "F - 'arg' passes by value"))
(reset)
(new-trace "new-fn-reply-oarg")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- arg)
((6 integer) <- add (4 integer) (5 integer))
(reply (6 integer))
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
((3 integer) <- test1 (1 integer) (2 integer)))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4
4 1 5 3 6 4))
(prn "F - 'reply' can take aguments that are returned, or written back into output args of caller"))
(reset)
(new-trace "new-fn-reply-oarg-multiple")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- arg)
((6 integer) <- add (4 integer) (5 integer))
(reply (6 integer) (5 integer))
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
((3 integer) (7 integer) <- test1 (1 integer) (2 integer)))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4 7 3
4 1 5 3 6 4))
(prn "F - 'reply' permits a function to return multiple values at once"))
(reset)
(new-trace "new-fn-prepare-reply")
(add-fns
'((test1
((4 integer) <- arg)
((5 integer) <- arg)
((6 integer) <- add (4 integer) (5 integer))
(prepare-reply (6 integer) (5 integer))
(reply)
((4 integer) <- copy (34 literal)))
(main
((1 integer) <- copy (1 literal))
((2 integer) <- copy (3 literal))
((3 integer) (7 integer) <- test1 (1 integer) (2 integer)))))
(run 'main)
(if (~iso memory* (obj 1 1 2 3 3 4 7 3
4 1 5 3 6 4))
(prn "F - without args, 'reply' returns values from previous 'prepare-reply'."))
(reset)
(new-trace "convert-braces")
(if (~iso (convert-braces
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
{ begin
((4 boolean) <- neq (1 integer) (3 integer))
(break-if (4 boolean))
((5 integer) <- copy (34 literal))
}
(reply)))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
((4 boolean) <- neq (1 integer) (3 integer))
(jump-if (4 boolean) (1 offset))
((5 integer) <- copy (34 literal))
(reply)))
(prn "F - convert-braces replaces break-if with a jump-if to after the next close-curly"))
(reset)
(new-trace "convert-braces-empty-block")
(if (~iso (convert-braces
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
{ begin
(break)
}
(reply)))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
(jump (0 offset))
(reply)))
(prn "F - convert-braces works for degenerate blocks"))
(reset)
(new-trace "convert-braces-nested-break")
(if (~iso (convert-braces
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
{ begin
((4 boolean) <- neq (1 integer) (3 integer))
(break-if (4 boolean))
{ begin
((5 integer) <- copy (34 literal))
}
}
(reply)))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
((4 boolean) <- neq (1 integer) (3 integer))
(jump-if (4 boolean) (1 offset))
((5 integer) <- copy (34 literal))
(reply)))
(prn "F - convert-braces balances curlies when converting break"))
(reset)
(new-trace "convert-braces-nested-continue")
(if (~iso (convert-braces
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
{ begin
((3 integer) <- add (2 integer) (2 integer))
{ begin
((4 boolean) <- neq (1 integer) (3 integer))
}
(continue-if (4 boolean))
((5 integer) <- copy (34 literal))
}
(reply)))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (2 integer) (2 integer))
((4 boolean) <- neq (1 integer) (3 integer))
(jump-if (4 boolean) (-3 offset))
((5 integer) <- copy (34 literal))
(reply)))
(prn "F - convert-braces balances curlies when converting continue"))
(reset)
(new-trace "continue")
(add-fns
'((main
((1 integer) <- copy (4 literal))
((2 integer) <- copy (1 literal))
{ begin
((2 integer) <- add (2 integer) (2 integer))
((3 boolean) <- neq (1 integer) (2 integer))
(continue-if (3 boolean))
((4 integer) <- copy (34 literal))
}
(reply))))
(run 'main)
(if (~iso memory* (obj 1 4 2 4 3 nil 4 34))
(prn "F - continue correctly loops"))
(reset)
(new-trace "continue-nested")
(add-fns
'((main
((1 integer) <- copy (4 literal))
((2 integer) <- copy (1 literal))
{ begin
((2 integer) <- add (2 integer) (2 integer))
{ begin
((3 boolean) <- neq (1 integer) (2 integer))
}
(continue-if (3 boolean))
((4 integer) <- copy (34 literal))
}
(reply))))
(run 'main)
(if (~iso memory* (obj 1 4 2 4 3 nil 4 34))
(prn "F - continue correctly loops"))
(reset)
(new-trace "continue-fail")
(add-fns
'((main
((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
{ begin
((2 integer) <- add (2 integer) (2 integer))
{ begin
((3 boolean) <- neq (1 integer) (2 integer))
}
(continue-if (3 boolean))
((4 integer) <- copy (34 literal))
}
(reply))))
(run 'main)
(if (~iso memory* (obj 1 4 2 4 3 nil 4 34))
(prn "F - continue might never trigger"))
(reset)
(new-trace "convert-names")
(if (~iso (convert-names
'(((x integer) <- copy (4 literal))
((y integer) <- copy (2 literal))
((z integer) <- add (x integer) (y integer))))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((3 integer) <- add (1 integer) (2 integer))))
(prn "F - convert-names renames symbolic names to integer locations"))
(reset)
(new-trace "convert-names-nil")
(if (~iso (convert-names
'(((x integer) <- copy (4 literal))
((y integer) <- copy (2 literal))
((nil integer) <- add (x integer) (y integer))))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((nil integer) <- add (1 integer) (2 integer))))
(prn "F - convert-names never renames nil"))
(reset)
(new-trace "new-primitive")
(add-fns
'((main
((1 integer-address) <- new (integer literal)))))
(let before Memory-in-use-until
(run 'main)
(if (~iso memory*.1 before)
(prn "F - 'new' returns current high-water mark"))
(if (~iso Memory-in-use-until (+ before 1))
(prn "F - 'new' on primitive types increments high-water mark by their size")))
(reset)
(new-trace "new-array-literal")
(add-fns
'((main
((1 type-array-address) <- new (type-array literal) (5 literal)))))
(let before Memory-in-use-until
(run 'main)
(if (~iso memory*.1 before)
(prn "F - 'new' on array with literal size returns current high-water mark"))
(if (~iso Memory-in-use-until (+ before 6))
(prn "F - 'new' on primitive arrays increments high-water mark by their size")))
(reset)
(new-trace "new-array-direct")
(add-fns
'((main
((1 integer) <- copy (5 literal))
((2 type-array-address) <- new (type-array literal) (1 integer)))))
(let before Memory-in-use-until
(run 'main)
(if (~iso memory*.2 before)
(prn "F - 'new' on array with variable size returns current high-water mark"))
(if (~iso Memory-in-use-until (+ before 6))
(prn "F - 'new' on primitive arrays increments high-water mark by their (variable) size")))
(reset)
(new-trace "set-default-scope")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (2 literal))
((1 integer) <- copy (23 literal)))))
(let before Memory-in-use-until
(run 'main)
(if (~and (~is 23 memory*.1)
(is 23 (memory* (+ before 1))))
(prn "F - default-scope implicitly modifies variable locations")))
(reset)
(new-trace "set-default-scope-skips-offset")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (2 literal))
((1 integer) <- copy (23 offset)))))
(let before Memory-in-use-until
(run 'main)
(if (~and (~is 23 memory*.1)
(is 23 (memory* (+ before 1))))
(prn "F - default-scope skips 'offset' types just like literals")))
(reset)
(new-trace "default-scope-bounds-check")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (2 literal))
((2 integer) <- copy (23 literal)))))
(run 'main)
(let last-routine (deq completed-routines*)
(if (no rep.last-routine!error)
(prn "F - default-scope checks bounds")))
(reset)
(new-trace "default-scope-and-get-indirect")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (5 literal))
((1 integer-boolean-pair-address) <- new (integer-boolean-pair literal))
((2 integer-address) <- get-address (1 integer-boolean-pair-address deref) (0 offset))
((2 integer-address deref) <- copy (34 literal))
((3 integer global) <- get (1 integer-boolean-pair-address deref) (0 offset)))))
(run 'main)
(let last-routine (deq completed-routines*)
(aif rep.last-routine!error (prn "error - " it)))
(if (~is 34 memory*.3)
(prn "F - indirect 'get' works in the presence of default-scope"))
(reset)
(new-trace "default-scope-and-index-indirect")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (5 literal))
((1 integer-array-address) <- new (integer-array literal) (4 literal))
((2 integer-address) <- index-address (1 integer-array-address deref) (2 offset))
((2 integer-address deref) <- copy (34 literal))
((3 integer global) <- index (1 integer-array-address deref) (2 offset)))))
(run 'main)
(let last-routine (deq completed-routines*)
(aif rep.last-routine!error (prn "error - " it)))
(if (~is 34 memory*.3)
(prn "F - indirect 'index' works in the presence of default-scope"))
(reset)
(new-trace "convert-names-default-scope")
(if (~iso (convert-names
'(((x integer) <- copy (4 literal))
((y integer) <- copy (2 literal))
((default-scope integer) <- add (x integer) (y integer))))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (2 literal))
((default-scope integer) <- add (1 integer) (2 integer))))
(prn "F - convert-names never renames default-scope"))
(reset)
(new-trace "suppress-default-scope")
(add-fns
'((main
((default-scope scope-address) <- new (scope literal) (2 literal))
((1 integer global) <- copy (23 literal)))))
(let before Memory-in-use-until
(run 'main)
(if (~and (is 23 memory*.1)
(~is 23 (memory* (+ before 1))))
(prn "F - default-scope skipped for locations with metadata 'global'")))
(reset)
(new-trace "convert-names-global")
(if (~iso (convert-names
'(((x integer) <- copy (4 literal))
((y integer global) <- copy (2 literal))
((default-scope integer) <- add (x integer) (y integer global))))
'(((1 integer) <- copy (4 literal))
((y integer global) <- copy (2 literal))
((default-scope integer) <- add (1 integer) (y integer global))))
(prn "F - convert-names never renames global operands"))
(reset)
(new-trace "dispatch-clause")
(add-fns
'((test1
((default-scope scope-address) <- new (scope literal) (20 literal))
((first-arg-box tagged-value-address) <- arg)
{ begin
((first-arg integer) (match? boolean) <- maybe-coerce (first-arg-box tagged-value-address deref) (integer literal))
(break-unless (match? boolean))
((second-arg-box tagged-value-address) <- arg)
((second-arg integer) <- maybe-coerce (second-arg-box tagged-value-address deref) (integer literal))
((result integer) <- add (first-arg integer) (second-arg integer))
(reply (result integer))
}
(reply (t literal)))
(main
((1 tagged-value-address) <- new-tagged-value (integer literal) (34 literal))
((2 tagged-value-address) <- new-tagged-value (integer literal) (3 literal))
((3 integer) <- test1 (1 tagged-value-address) (2 tagged-value-address)))))
(run 'main)
(if (~is memory*.3 37)
(prn "F - an example function that checks that its oarg is an integer"))
(reset)
(new-trace "dispatch-multiple-clauses")
(add-fns
'((test1
((default-scope scope-address) <- new (scope literal) (20 literal))
((first-arg-box tagged-value-address) <- arg)
{ begin
((first-arg integer) (match? boolean) <- maybe-coerce (first-arg-box tagged-value-address deref) (integer literal))
(break-unless (match? boolean))
((second-arg-box tagged-value-address) <- arg)
((second-arg integer) <- maybe-coerce (second-arg-box tagged-value-address deref) (integer literal))
((result integer) <- add (first-arg integer) (second-arg integer))
(reply (result integer))
}
{ begin
((first-arg boolean) (match? boolean) <- maybe-coerce (first-arg-box tagged-value-address deref) (boolean literal))
(break-unless (match? boolean))
((second-arg-box tagged-value-address) <- arg)
((second-arg boolean) <- maybe-coerce (second-arg-box tagged-value-address deref) (boolean literal))
((result boolean) <- or (first-arg boolean) (second-arg boolean))
(reply (result integer))
}
(reply (t literal)))
(main
((1 tagged-value-address) <- new-tagged-value (boolean literal) (t literal))
((2 tagged-value-address) <- new-tagged-value (boolean literal) (t literal))
((3 boolean) <- test1 (1 tagged-value-address) (2 tagged-value-address)))))
(run 'main)
(if (~is memory*.3 t)
(prn "F - an example function that can do different things (dispatch) based on the type of its args or oargs"))
(reset)
(new-trace "dispatch-multiple-calls")
(add-fns
'((test1
((default-scope scope-address) <- new (scope literal) (20 literal))
((first-arg-box tagged-value-address) <- arg)
{ begin
((first-arg integer) (match? boolean) <- maybe-coerce (first-arg-box tagged-value-address deref) (integer literal))
(break-unless (match? boolean))
((second-arg-box tagged-value-address) <- arg)
((second-arg integer) <- maybe-coerce (second-arg-box tagged-value-address deref) (integer literal))
((result integer) <- add (first-arg integer) (second-arg integer))
(reply (result integer))
}
{ begin
((first-arg boolean) (match? boolean) <- maybe-coerce (first-arg-box tagged-value-address deref) (boolean literal))
(break-unless (match? boolean))
((second-arg-box tagged-value-address) <- arg)
((second-arg boolean) <- maybe-coerce (second-arg-box tagged-value-address deref) (boolean literal))
((result boolean) <- or (first-arg boolean) (second-arg boolean))
(reply (result integer))
}
(reply (t literal)))
(main
((1 tagged-value-address) <- new-tagged-value (boolean literal) (t literal))
((2 tagged-value-address) <- new-tagged-value (boolean literal) (t literal))
((3 boolean) <- test1 (1 tagged-value-address) (2 tagged-value-address))
((10 tagged-value-address) <- new-tagged-value (integer literal) (34 literal))
((11 tagged-value-address) <- new-tagged-value (integer literal) (3 literal))
((12 integer) <- test1 (10 tagged-value-address) (11 tagged-value-address)))))
(run 'main)
(if (~and (is memory*.3 t) (is memory*.12 37))
(prn "F - different calls can exercise different clauses of the same function"))
(reset)
(new-trace "scheduler")
(add-fns
'((f1
((1 integer) <- copy (3 literal)))
(f2
((2 integer) <- copy (4 literal)))))
(let ninsts (run 'f1 'f2)
(when (~iso 2 ninsts)
(prn "F - scheduler didn't run the right number of instructions: " ninsts)))
(if (~iso memory* (obj 1 3 2 4))
(prn "F - scheduler runs multiple functions: " memory*))
(check-trace-contents "scheduler orders functions correctly"
'(("schedule" "f1")
("schedule" "f2")
))
(check-trace-contents "scheduler orders schedule and run events correctly"
'(("schedule" "f1")
("run" "f1 0")
("schedule" "f2")
("run" "f2 0")
))
(reset)
(new-trace "array-bounds-check")
(add-fns
'((main
((1 integer) <- copy (2 literal))
((2 integer) <- copy (23 literal))
((3 integer) <- copy (24 literal))
((4 integer) <- index (1 integer-array) (2 literal)))))
(run 'main)
(let last-routine (deq completed-routines*)
(if (no rep.last-routine!error)
(prn "F - 'index' throws an error if out of bounds")))
(reset)
(new-trace "convert-quotes-defer")
(if (~iso (convert-quotes
'(((1 integer) <- copy (4 literal))
(defer [
((3 integer) <- copy (6 literal))
])
((2 integer) <- copy (5 literal))))
'(((1 integer) <- copy (4 literal))
((2 integer) <- copy (5 literal))
((3 integer) <- copy (6 literal))))
(prn "F - convert-quotes can handle 'defer'"))
(reset)