(load "mu.arc")
(on-init
(= types* (obj
type (obj size 1)
type-address (obj size 1 address t elem 'type)
type-array (obj array t elem 'type)
type-array-address (obj size 1 address t elem 'type-array)
location (obj size 1 address t elem 'location)
integer (obj size 1)
boolean (obj size 1)
boolean-address (obj size 1 address t)
byte (obj size 1)
character (obj size 1)
character-address (obj size 1 address t elem 'character)
string (obj size 1)
integer-array (obj array t elem 'integer)
integer-address (obj size 1 address t elem 'integer)
integer-boolean-pair (obj size 2 record t elems '(integer boolean))
integer-boolean-pair-address (obj size 1 address t elem 'integer-boolean-pair)
integer-boolean-pair-array (obj array t elem 'integer-boolean-pair)
integer-integer-pair (obj size 2 record t elems '(integer integer))
integer-point-pair (obj size 2 record t elems '(integer integer-integer-pair))
tagged-value (obj size 2 record t elems '(type location))
tagged-value-address (obj size 1 address t elem 'tagged-value)
list (obj size 2 record t elems '(tagged-value list-address))
list-address (obj size 1 address t elem 'list)
list-address-address (obj size 1 address t elem 'list-address)
)))
(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 (8 literal) (3 literal)))))
(run 'main)
(if (~iso memory* (obj 1 2 2 2))
(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 integer) <- 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 integer) <- 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-array-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-array-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-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 "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 "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")
(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)
(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 "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 type))
((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 type))
((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)))))
(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
(~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)))
(prn "F - 'list' constructs a heterogeneous list, which 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-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)
((4 integer) <- arg 0)
((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-3")
(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-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 "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 "dispatch-clause")
(add-fns
'((test1
((4 tagged-value-address) <- arg)
{ begin
((5 integer) (6 boolean) <- maybe-coerce (4 tagged-value-address deref) (integer literal))
(break-unless (6 boolean))
((7 tagged-value-address) <- arg)
((8 integer) (9 boolean) <- maybe-coerce (7 tagged-value-address deref) (integer literal))
((9 integer) <- add (5 integer) (8 integer))
(reply (9 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
((4 tagged-value-address) <- arg)
{ begin
((5 integer) (6 boolean) <- maybe-coerce (4 tagged-value-address deref) (integer literal))
(break-unless (6 boolean))
((7 tagged-value-address) <- arg)
((8 integer) (9 boolean) <- maybe-coerce (7 tagged-value-address deref) (integer literal))
((9 integer) <- add (5 integer) (8 integer))
(reply (9 integer))
}
{ begin
((5 boolean) (6 boolean) <- maybe-coerce (4 tagged-value-address deref) (boolean literal))
(break-unless (6 boolean))
((7 tagged-value-address) <- arg)
((8 boolean) (9 boolean) <- maybe-coerce (7 tagged-value-address deref) (boolean literal))
((9 boolean) <- or (5 boolean) (8 boolean))
(reply (9 boolean))
}
(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
((4 tagged-value-address) <- arg)
{ begin
((5 integer) (6 boolean) <- maybe-coerce (4 tagged-value-address deref) (integer literal))
(break-unless (6 boolean))
((7 tagged-value-address) <- arg)
((8 integer) (9 boolean) <- maybe-coerce (7 tagged-value-address deref) (integer literal))
((9 integer) <- add (5 integer) (8 integer))
(reply (9 integer))
}
{ begin
((5 boolean) (6 boolean) <- maybe-coerce (4 tagged-value-address deref) (boolean literal))
(break-unless (6 boolean))
((7 tagged-value-address) <- arg)
((8 boolean) (9 boolean) <- maybe-coerce (7 tagged-value-address deref) (boolean literal))
((9 boolean) <- or (5 boolean) (8 boolean))
(reply (9 boolean))
}
(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 "new-primitive")
(let before Memory-in-use-until
(add-fns
'((main
((1 integer-address) <- new (integer type)))))
(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")
(let before Memory-in-use-until
(add-fns
'((main
((1 type-array-address) <- new (type-array type) (5 literal)))))
(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")
(let before Memory-in-use-until
(add-fns
'((main
((1 integer) <- copy (5 literal))
((2 type-array-address) <- new (type-array type) (1 integer)))))
(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 "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)