about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-02 15:52:22 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-02 22:56:13 -0700
commit22b3069272c1a177e814a7c4e769e20858e2b368 (patch)
tree761199b26823fe5ba11af66108e95ece1bc4f02c
parenta316f1e4168a98ba8c1bbe7b091f8a7e7b3f03e6 (diff)
downloadmu-22b3069272c1a177e814a7c4e769e20858e2b368.tar.gz
1242 - simpler implementation for 'scenario'
Also now has the side effect that scenarios can have any number of 'run'
or check or any future blocks, in any order.
-rw-r--r--cpp/.traces/array-from-args57
-rw-r--r--cpp/.traces/buffer-append-works275
-rw-r--r--cpp/.traces/channel48
-rw-r--r--cpp/.traces/channel-initialization53
-rw-r--r--cpp/.traces/channel-new-empty-not-full53
-rw-r--r--cpp/.traces/channel-read-increments-full65
-rw-r--r--cpp/.traces/channel-read-not-full65
-rw-r--r--cpp/.traces/channel-wrap119
-rw-r--r--cpp/.traces/channel-write-full59
-rw-r--r--cpp/.traces/channel-write-increments-free59
-rw-r--r--cpp/.traces/channel-write-not-empty59
-rw-r--r--cpp/.traces/check_string_in_memory57
-rw-r--r--cpp/.traces/check_trace41
-rw-r--r--cpp/.traces/check_trace_instruction37
-rw-r--r--cpp/.traces/check_trace_negative41
-rw-r--r--cpp/.traces/clear-line-erases-printed-characters112
-rw-r--r--cpp/.traces/factorial-test210
-rw-r--r--cpp/.traces/first_scenario_checking_trace14
-rw-r--r--cpp/.traces/first_scenario_checking_trace_negative14
-rw-r--r--cpp/.traces/first_scenario_in_mu36
-rw-r--r--cpp/.traces/init-buffer-allocates204
-rw-r--r--cpp/.traces/integer-to-decimal-digit-negative52
-rw-r--r--cpp/.traces/integer-to-decimal-digit-positive45
-rw-r--r--cpp/.traces/integer-to-decimal-digit-zero43
-rw-r--r--cpp/.traces/interpolate-at-end64
-rw-r--r--cpp/.traces/interpolate-at-start70
-rw-r--r--cpp/.traces/interpolate-works61
-rw-r--r--cpp/.traces/jump7
-rw-r--r--cpp/.traces/parse_scenario_memory_expectation3
-rw-r--r--cpp/.traces/parse_scenario_memory_expectation_duplicate5
-rw-r--r--cpp/.traces/print-character-at-top-left68
-rw-r--r--cpp/.traces/scenario_block (renamed from cpp/.traces/run_handles_comments)24
-rw-r--r--cpp/.traces/scenario_check_memory_and_trace76
-rw-r--r--cpp/.traces/scenario_multiple_blocks80
-rw-r--r--cpp/.traces/scenario_trace_block4
-rw-r--r--cpp/.traces/scenario_with_comment_in_mu46
-rw-r--r--cpp/.traces/scenario_with_multiple_comments_in_mu50
-rw-r--r--cpp/.traces/string-append-167
-rw-r--r--cpp/.traces/string-equal-common-lengths-but-distinct54
-rw-r--r--cpp/.traces/string-equal-distinct-lengths80
-rw-r--r--cpp/.traces/string-equal-identical54
-rw-r--r--cpp/.traces/string-equal-reflexive48
-rw-r--r--cpp/.traces/string-equal-with-empty54
-rw-r--r--cpp/.traces/trace_in_mu10
-rw-r--r--cpp/.traces/trace_should_contain17
-rw-r--r--cpp/049scenario_helpers.cc11
-rw-r--r--cpp/050scenario.cc242
-rw-r--r--cpp/051scenario_test.mu52
-rw-r--r--cpp/052scenario_trace.cc122
-rw-r--r--cpp/053scenario_trace_test.mu28
-rw-r--r--cpp/060string.mu30
-rw-r--r--cpp/061channel.mu18
-rw-r--r--cpp/062array.mu2
-rw-r--r--cpp/071print.mu4
54 files changed, 2227 insertions, 1042 deletions
diff --git a/cpp/.traces/array-from-args b/cpp/.traces/array-from-args
index d999e006..292b6a44 100644
--- a/cpp/.traces/array-from-args
+++ b/cpp/.traces/array-from-args
@@ -1,3 +1,36 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:location <- init-array 0:literal, 1:literal, 2:literal
+    2:array:location <- copy 1:address:array:location/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:location <- init-array 0:literal, 1:literal, 2:literal
+    2:array:location <- copy 1:address:array:location/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 3  # array length
+    3 <- 0
+    4 <- 1
+    5 <- 2
+  ", value: 0, type: 0, properties: ["
+    2 <- 3  # array length
+    3 <- 0
+    4 <- 1
+    5 <- 2
+  ": "literal-string"]}
+after-brace/0: recipe array-from-args
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: array-from-args
+run/0: instruction array-from-args/0
+run/0: run {name: "
+    1:address:array:location <- init-array 0:literal, 1:literal, 2:literal
+    2:array:location <- copy 1:address:array:location/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:location <- init-array 0:literal, 1:literal, 2:literal
+    2:array:location <- copy 1:address:array:location/deref
+  ": "literal-string"]}
 parse/0: instruction: init-array
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "literal"]}
@@ -6,12 +39,10 @@ parse/0:   product: {name: "1", value: 0, type: 2-5-1, properties: ["1": "addres
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "1", value: 0, type: 2-5-1, properties: ["1": "address":"array":"location", "deref": ]}
 parse/0:   product: {name: "2", value: 0, type: 5-1, properties: ["2": "array":"location"]}
-after-brace/0: recipe test-array-from-args
+after-brace/0: recipe tmp0
 after-brace/0: init-array ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-array-from-args
-run/0: instruction test-array-from-args/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-1, properties: ["1": "address":"array":"location"]} <- init-array {name: "0", value: 0, type: 0, properties: ["0": "literal"]}, {name: "1", value: 1, type: 0, properties: ["1": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
 run/0: instruction init-array/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -268,7 +299,7 @@ run/0: reply {name: "result", value: 4, type: 2-5-1, properties: ["result": "add
 mem/0: location 1005 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-array-from-args/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 5-1, properties: ["2": "array":"location"]} <- copy {name: "1", value: 1, type: 2-5-1, properties: ["1": "address":"array":"location", "deref": ]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -280,3 +311,19 @@ mem/0: storing 3 in location 2
 mem/0: storing 0 in location 3
 mem/0: storing 1 in location 4
 mem/0: storing 2 in location 5
+run/0: instruction array-from-args/1
+run/0: memory-should-contain {name: "
+    2 <- 3  # array length
+    3 <- 0
+    4 <- 1
+    5 <- 2
+  ", value: 0, type: 0, properties: ["
+    2 <- 3  # array length
+    3 <- 0
+    4 <- 1
+    5 <- 2
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
diff --git a/cpp/.traces/buffer-append-works b/cpp/.traces/buffer-append-works
index 0cad1113..9cadf18c 100644
--- a/cpp/.traces/buffer-append-works
+++ b/cpp/.traces/buffer-append-works
@@ -1,3 +1,196 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:buffer <- init-buffer 3:literal
+    s1:address:array:character <- get x:address:buffer/deref, data:offset
+    x:address:buffer <- buffer-append x:address:buffer, 97:literal  # 'a'
+    x:address:buffer <- buffer-append x:address:buffer, 98:literal  # 'b'
+    x:address:buffer <- buffer-append x:address:buffer, 99:literal  # 'c'
+    s2:address:array:character <- get x:address:buffer/deref, data:offset
+    1:boolean/raw <- equal s1:address:array:character, s2:address:array:character
+#?     $print s2:address:array:character
+#?     $print [
+#? ]
+#?     $print 1060:integer/raw
+#?     $print [
+#? ]
+#?     $print 1061:integer/raw
+#?     $print [
+#? ]
+#?     $print 1062:integer/raw
+#?     $print [
+#? ]
+#?     $print 1063:integer/raw
+#?     $print [
+#? ]
+#?     $print 1064:integer/raw
+#?     $print [
+#? ]
+#?     $print 1065:integer/raw
+#?     $print [
+#? ]
+    2:array:character/raw <- copy s2:address:array:character/deref
+    +buffer-filled
+    x:address:buffer <- buffer-append x:address:buffer, 100:literal  # 'd'
+    s3:address:array:character <- get x:address:buffer/deref, data:offset
+    10:boolean/raw <- equal s1:address:array:character, s3:address:array:character
+    11:integer/raw <- get x:address:buffer/deref, length:offset
+    12:array:character/raw <- copy s3:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:buffer <- init-buffer 3:literal
+    s1:address:array:character <- get x:address:buffer/deref, data:offset
+    x:address:buffer <- buffer-append x:address:buffer, 97:literal  # 'a'
+    x:address:buffer <- buffer-append x:address:buffer, 98:literal  # 'b'
+    x:address:buffer <- buffer-append x:address:buffer, 99:literal  # 'c'
+    s2:address:array:character <- get x:address:buffer/deref, data:offset
+    1:boolean/raw <- equal s1:address:array:character, s2:address:array:character
+#?     $print s2:address:array:character
+#?     $print [
+#? ]
+#?     $print 1060:integer/raw
+#?     $print [
+#? ]
+#?     $print 1061:integer/raw
+#?     $print [
+#? ]
+#?     $print 1062:integer/raw
+#?     $print [
+#? ]
+#?     $print 1063:integer/raw
+#?     $print [
+#? ]
+#?     $print 1064:integer/raw
+#?     $print [
+#? ]
+#?     $print 1065:integer/raw
+#?     $print [
+#? ]
+    2:array:character/raw <- copy s2:address:array:character/deref
+    +buffer-filled
+    x:address:buffer <- buffer-append x:address:buffer, 100:literal  # 'd'
+    s3:address:array:character <- get x:address:buffer/deref, data:offset
+    10:boolean/raw <- equal s1:address:array:character, s3:address:array:character
+    11:integer/raw <- get x:address:buffer/deref, length:offset
+    12:array:character/raw <- copy s3:address:array:character/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    # before +buffer-filled
+    1 <- 1   # no change in data pointer
+    2 <- 3   # size of data
+    3 <- 97  # data
+    4 <- 98
+    5 <- 99
+    # in the end
+    10 <- 0   # data pointer has grown
+    11 <- 4   # final length
+    12 <- 6   # but data's capacity has doubled
+    13 <- 97  # data
+    14 <- 98
+    15 <- 99
+    16 <- 100
+    17 <- 0
+    18 <- 0
+  ", value: 0, type: 0, properties: ["
+    # before +buffer-filled
+    1 <- 1   # no change in data pointer
+    2 <- 3   # size of data
+    3 <- 97  # data
+    4 <- 98
+    5 <- 99
+    # in the end
+    10 <- 0   # data pointer has grown
+    11 <- 4   # final length
+    12 <- 6   # but data's capacity has doubled
+    13 <- 97  # data
+    14 <- 98
+    15 <- 99
+    16 <- 100
+    17 <- 0
+    18 <- 0
+  ": "literal-string"]}
+after-brace/0: recipe buffer-append-works
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: buffer-append-works
+run/0: instruction buffer-append-works/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:buffer <- init-buffer 3:literal
+    s1:address:array:character <- get x:address:buffer/deref, data:offset
+    x:address:buffer <- buffer-append x:address:buffer, 97:literal  # 'a'
+    x:address:buffer <- buffer-append x:address:buffer, 98:literal  # 'b'
+    x:address:buffer <- buffer-append x:address:buffer, 99:literal  # 'c'
+    s2:address:array:character <- get x:address:buffer/deref, data:offset
+    1:boolean/raw <- equal s1:address:array:character, s2:address:array:character
+#?     $print s2:address:array:character
+#?     $print [
+#? ]
+#?     $print 1060:integer/raw
+#?     $print [
+#? ]
+#?     $print 1061:integer/raw
+#?     $print [
+#? ]
+#?     $print 1062:integer/raw
+#?     $print [
+#? ]
+#?     $print 1063:integer/raw
+#?     $print [
+#? ]
+#?     $print 1064:integer/raw
+#?     $print [
+#? ]
+#?     $print 1065:integer/raw
+#?     $print [
+#? ]
+    2:array:character/raw <- copy s2:address:array:character/deref
+    +buffer-filled
+    x:address:buffer <- buffer-append x:address:buffer, 100:literal  # 'd'
+    s3:address:array:character <- get x:address:buffer/deref, data:offset
+    10:boolean/raw <- equal s1:address:array:character, s3:address:array:character
+    11:integer/raw <- get x:address:buffer/deref, length:offset
+    12:array:character/raw <- copy s3:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:buffer <- init-buffer 3:literal
+    s1:address:array:character <- get x:address:buffer/deref, data:offset
+    x:address:buffer <- buffer-append x:address:buffer, 97:literal  # 'a'
+    x:address:buffer <- buffer-append x:address:buffer, 98:literal  # 'b'
+    x:address:buffer <- buffer-append x:address:buffer, 99:literal  # 'c'
+    s2:address:array:character <- get x:address:buffer/deref, data:offset
+    1:boolean/raw <- equal s1:address:array:character, s2:address:array:character
+#?     $print s2:address:array:character
+#?     $print [
+#? ]
+#?     $print 1060:integer/raw
+#?     $print [
+#? ]
+#?     $print 1061:integer/raw
+#?     $print [
+#? ]
+#?     $print 1062:integer/raw
+#?     $print [
+#? ]
+#?     $print 1063:integer/raw
+#?     $print [
+#? ]
+#?     $print 1064:integer/raw
+#?     $print [
+#? ]
+#?     $print 1065:integer/raw
+#?     $print [
+#? ]
+    2:array:character/raw <- copy s2:address:array:character/deref
+    +buffer-filled
+    x:address:buffer <- buffer-append x:address:buffer, 100:literal  # 'd'
+    s3:address:array:character <- get x:address:buffer/deref, data:offset
+    10:boolean/raw <- equal s1:address:array:character, s3:address:array:character
+    11:integer/raw <- get x:address:buffer/deref, length:offset
+    12:array:character/raw <- copy s3:address:array:character/deref
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -61,7 +254,7 @@ name/0: assign s2 3
 name/0: element data of type buffer is at offset 1
 name/0: assign s3 4
 name/0: element length of type buffer is at offset 0
-after-brace/0: recipe test-buffer-append-works
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: init-buffer ...
 after-brace/0: get ...
@@ -76,13 +269,11 @@ after-brace/0: get ...
 after-brace/0: equal ...
 after-brace/0: get ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-buffer-append-works
-run/0: instruction test-buffer-append-works/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-buffer-append-works/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]} <- init-buffer {name: "3", value: 3, type: 0, properties: ["3": "literal"]}
 run/0: instruction init-buffer/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -129,7 +320,7 @@ run/0: reply {name: "result", value: 1, type: 2-9, properties: ["result": "addre
 mem/0: location 1033 is 1062
 run/0: result 0 is 1062
 mem/0: storing 1062 in location 1002
-run/0: instruction test-buffer-append-works/2
+run/0: instruction tmp0/2
 run/0: {name: "s1", value: 2, type: 2-5-4, properties: ["s1": "address":"array":"character"]} <- get {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer", "deref": ]}, {name: "data", value: 1, type: 0, properties: ["data": "offset"]}
 run/0: ingredient 0 is x
 mem/0: location 1002 is 1062
@@ -139,7 +330,7 @@ run/0: its type is 2
 mem/0: location 1063 is 1064
 run/0: product 0 is 1064
 mem/0: storing 1064 in location 1003
-run/0: instruction test-buffer-append-works/3
+run/0: instruction tmp0/3
 run/0: {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]} <- buffer-append {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]}, {name: "97", value: 97, type: 0, properties: ["97": "literal"]}
 mem/0: location 1002 is 1062
 run/0: instruction buffer-append/0
@@ -256,7 +447,7 @@ run/0: reply {name: "in", value: 1, type: 2-9, properties: ["in": "address":"buf
 mem/0: location 1070 is 1062
 run/0: result 0 is 1062
 mem/0: storing 1062 in location 1002
-run/0: instruction test-buffer-append-works/4
+run/0: instruction tmp0/4
 run/0: {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]} <- buffer-append {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]}, {name: "98", value: 98, type: 0, properties: ["98": "literal"]}
 mem/0: location 1002 is 1062
 run/0: instruction buffer-append/0
@@ -373,7 +564,7 @@ run/0: reply {name: "in", value: 1, type: 2-9, properties: ["in": "address":"buf
 mem/0: location 1132 is 1062
 run/0: result 0 is 1062
 mem/0: storing 1062 in location 1002
-run/0: instruction test-buffer-append-works/5
+run/0: instruction tmp0/5
 run/0: {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]} <- buffer-append {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]}, {name: "99", value: 99, type: 0, properties: ["99": "literal"]}
 mem/0: location 1002 is 1062
 run/0: instruction buffer-append/0
@@ -490,7 +681,7 @@ run/0: reply {name: "in", value: 1, type: 2-9, properties: ["in": "address":"buf
 mem/0: location 1194 is 1062
 run/0: result 0 is 1062
 mem/0: storing 1062 in location 1002
-run/0: instruction test-buffer-append-works/6
+run/0: instruction tmp0/6
 run/0: {name: "s2", value: 3, type: 2-5-4, properties: ["s2": "address":"array":"character"]} <- get {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer", "deref": ]}, {name: "data", value: 1, type: 0, properties: ["data": "offset"]}
 run/0: ingredient 0 is x
 mem/0: location 1002 is 1062
@@ -500,7 +691,7 @@ run/0: its type is 2
 mem/0: location 1063 is 1064
 run/0: product 0 is 1064
 mem/0: storing 1064 in location 1004
-run/0: instruction test-buffer-append-works/7
+run/0: instruction tmp0/7
 run/0: {name: "1", value: 1, type: 3, properties: ["1": "boolean", "raw": ]} <- equal {name: "s1", value: 2, type: 2-5-4, properties: ["s1": "address":"array":"character"]}, {name: "s2", value: 3, type: 2-5-4, properties: ["s2": "address":"array":"character"]}
 run/0: ingredient 0 is s1
 mem/0: location 1003 is 1064
@@ -508,7 +699,7 @@ run/0: ingredient 1 is s2
 mem/0: location 1004 is 1064
 run/0: product 0 is 1
 mem/0: storing 1 in location 1
-run/0: instruction test-buffer-append-works/8
+run/0: instruction tmp0/8
 run/0: {name: "2", value: 2, type: 5-4, properties: ["2": "array":"character", "raw": ]} <- copy {name: "s2", value: 3, type: 2-5-4, properties: ["s2": "address":"array":"character", "deref": ]}
 run/0: ingredient 0 is s2
 mem/0: location 1004 is 1064
@@ -520,7 +711,7 @@ mem/0: storing 3 in location 2
 mem/0: storing 97 in location 3
 mem/0: storing 98 in location 4
 mem/0: storing 99 in location 5
-run/0: instruction test-buffer-append-works/10
+run/0: instruction tmp0/10
 run/0: {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]} <- buffer-append {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer"]}, {name: "100", value: 100, type: 0, properties: ["100": "literal"]}
 mem/0: location 1002 is 1062
 run/0: instruction buffer-append/0
@@ -857,7 +1048,7 @@ run/0: reply {name: "in", value: 1, type: 2-9, properties: ["in": "address":"buf
 mem/0: location 1256 is 1062
 run/0: result 0 is 1062
 mem/0: storing 1062 in location 1002
-run/0: instruction test-buffer-append-works/11
+run/0: instruction tmp0/11
 run/0: {name: "s3", value: 4, type: 2-5-4, properties: ["s3": "address":"array":"character"]} <- get {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer", "deref": ]}, {name: "data", value: 1, type: 0, properties: ["data": "offset"]}
 run/0: ingredient 0 is x
 mem/0: location 1002 is 1062
@@ -867,7 +1058,7 @@ run/0: its type is 2
 mem/0: location 1063 is 1347
 run/0: product 0 is 1347
 mem/0: storing 1347 in location 1005
-run/0: instruction test-buffer-append-works/12
+run/0: instruction tmp0/12
 run/0: {name: "10", value: 10, type: 3, properties: ["10": "boolean", "raw": ]} <- equal {name: "s1", value: 2, type: 2-5-4, properties: ["s1": "address":"array":"character"]}, {name: "s3", value: 4, type: 2-5-4, properties: ["s3": "address":"array":"character"]}
 run/0: ingredient 0 is s1
 mem/0: location 1003 is 1064
@@ -875,7 +1066,7 @@ run/0: ingredient 1 is s3
 mem/0: location 1005 is 1347
 run/0: product 0 is 0
 mem/0: storing 0 in location 10
-run/0: instruction test-buffer-append-works/13
+run/0: instruction tmp0/13
 run/0: {name: "11", value: 11, type: 1, properties: ["11": "integer", "raw": ]} <- get {name: "x", value: 1, type: 2-9, properties: ["x": "address":"buffer", "deref": ]}, {name: "length", value: 0, type: 0, properties: ["length": "offset"]}
 run/0: ingredient 0 is x
 mem/0: location 1002 is 1062
@@ -885,7 +1076,7 @@ run/0: its type is 1
 mem/0: location 1062 is 4
 run/0: product 0 is 4
 mem/0: storing 4 in location 11
-run/0: instruction test-buffer-append-works/14
+run/0: instruction tmp0/14
 run/0: {name: "12", value: 12, type: 5-4, properties: ["12": "array":"character", "raw": ]} <- copy {name: "s3", value: 4, type: 2-5-4, properties: ["s3": "address":"array":"character", "deref": ]}
 run/0: ingredient 0 is s3
 mem/0: location 1005 is 1347
@@ -903,3 +1094,53 @@ mem/0: storing 99 in location 15
 mem/0: storing 100 in location 16
 mem/0: storing 0 in location 17
 mem/0: storing 0 in location 18
+run/0: instruction buffer-append-works/1
+run/0: memory-should-contain {name: "
+    # before +buffer-filled
+    1 <- 1   # no change in data pointer
+    2 <- 3   # size of data
+    3 <- 97  # data
+    4 <- 98
+    5 <- 99
+    # in the end
+    10 <- 0   # data pointer has grown
+    11 <- 4   # final length
+    12 <- 6   # but data's capacity has doubled
+    13 <- 97  # data
+    14 <- 98
+    15 <- 99
+    16 <- 100
+    17 <- 0
+    18 <- 0
+  ", value: 0, type: 0, properties: ["
+    # before +buffer-filled
+    1 <- 1   # no change in data pointer
+    2 <- 3   # size of data
+    3 <- 97  # data
+    4 <- 98
+    5 <- 99
+    # in the end
+    10 <- 0   # data pointer has grown
+    11 <- 4   # final length
+    12 <- 6   # but data's capacity has doubled
+    13 <- 97  # data
+    14 <- 98
+    15 <- 99
+    16 <- 100
+    17 <- 0
+    18 <- 0
+  ": "literal-string"]}
+run/0: checking location 1
+run/0: checking location 2
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
+run/0: checking location 10
+run/0: checking location 11
+run/0: checking location 12
+run/0: checking location 13
+run/0: checking location 14
+run/0: checking location 15
+run/0: checking location 16
+run/0: checking location 17
+run/0: checking location 18
diff --git a/cpp/.traces/channel b/cpp/.traces/channel
index 50c7ae3b..ca6ea2d2 100644
--- a/cpp/.traces/channel
+++ b/cpp/.traces/channel
@@ -1,3 +1,34 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer, 1:address:channel <- read 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer, 1:address:channel <- read 1:address:channel
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 34
+  ", value: 0, type: 0, properties: ["
+    2 <- 34
+  ": "literal-string"]}
+after-brace/0: recipe channel
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel
+run/0: instruction channel/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer, 1:address:channel <- read 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer, 1:address:channel <- read 1:address:channel
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -9,13 +40,11 @@ parse/0: instruction: read
 parse/0:   ingredient: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
 parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
-after-brace/0: recipe test-channel
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: read ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel
-run/0: instruction test-channel/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -82,7 +111,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -265,7 +294,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1041 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel/2
+run/0: instruction tmp0/2
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]}, {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- read {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction read/0
@@ -392,3 +421,10 @@ run/0: result 0 is 34
 mem/0: storing 34 in location 2
 run/0: result 1 is 1031
 mem/0: storing 1031 in location 1
+run/0: instruction channel/1
+run/0: memory-should-contain {name: "
+    2 <- 34
+  ", value: 0, type: 0, properties: ["
+    2 <- 34
+  ": "literal-string"]}
+run/0: checking location 2
diff --git a/cpp/.traces/channel-initialization b/cpp/.traces/channel-initialization
index e04b4594..ad16bef2 100644
--- a/cpp/.traces/channel-initialization
+++ b/cpp/.traces/channel-initialization
@@ -1,3 +1,36 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 0  # first-full
+    3 <- 0  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # first-full
+    3 <- 0  # first-free
+  ": "literal-string"]}
+after-brace/0: recipe channel-initialization
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-initialization
+run/0: instruction channel-initialization/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -11,13 +44,11 @@ parse/0:   ingredient: {name: "first-free", value: 0, type: 0, properties: ["fir
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
 name/0: element first-full of type channel is at offset 0
 name/0: element first-free of type channel is at offset 1
-after-brace/0: recipe test-channel-initialization
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: get ...
 after-brace/0: get ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-initialization
-run/0: instruction test-channel-initialization/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -84,7 +115,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-initialization/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-full", value: 0, type: 0, properties: ["first-full": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -94,7 +125,7 @@ run/0: its type is 1
 mem/0: location 1031 is 0
 run/0: product 0 is 0
 mem/0: storing 0 in location 2
-run/0: instruction test-channel-initialization/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -104,3 +135,13 @@ run/0: its type is 1
 mem/0: location 1032 is 0
 run/0: product 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction channel-initialization/1
+run/0: memory-should-contain {name: "
+    2 <- 0  # first-full
+    3 <- 0  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # first-full
+    3 <- 0  # first-free
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-new-empty-not-full b/cpp/.traces/channel-new-empty-not-full
index 74584d36..b852e4f6 100644
--- a/cpp/.traces/channel-new-empty-not-full
+++ b/cpp/.traces/channel-new-empty-not-full
@@ -1,3 +1,36 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+after-brace/0: recipe channel-new-empty-not-full
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-new-empty-not-full
+run/0: instruction channel-new-empty-not-full/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -7,13 +40,11 @@ parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
 parse/0: instruction: channel-full?
 parse/0:   ingredient: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
-after-brace/0: recipe test-channel-new-empty-not-full
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: channel-empty? ...
 after-brace/0: channel-full? ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-new-empty-not-full
-run/0: instruction test-channel-new-empty-not-full/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -80,7 +111,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-new-empty-not-full/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- channel-empty? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-empty?/0
@@ -124,7 +155,7 @@ run/0: reply {name: "result", value: 4, type: 3, properties: ["result": "boolean
 mem/0: location 1044 is 1
 run/0: result 0 is 1
 mem/0: storing 1 in location 2
-run/0: instruction test-channel-new-empty-not-full/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- channel-full? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-full?/0
@@ -219,3 +250,13 @@ run/0: reply {name: "result", value: 6, type: 3, properties: ["result": "boolean
 mem/0: location 1077 is 0
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction channel-new-empty-not-full/1
+run/0: memory-should-contain {name: "
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-read-increments-full b/cpp/.traces/channel-read-increments-full
index ec0c90d1..37b0d3d9 100644
--- a/cpp/.traces/channel-read-increments-full
+++ b/cpp/.traces/channel-read-increments-full
@@ -1,3 +1,44 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 1  # first-full
+    3 <- 1  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # first-full
+    3 <- 1  # first-free
+  ": "literal-string"]}
+after-brace/0: recipe channel-read-increments-full
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-read-increments-full
+run/0: instruction channel-read-increments-full/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -19,15 +60,13 @@ parse/0:   ingredient: {name: "first-free", value: 0, type: 0, properties: ["fir
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
 name/0: element first-full of type channel is at offset 0
 name/0: element first-free of type channel is at offset 1
-after-brace/0: recipe test-channel-read-increments-full
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: read ...
 after-brace/0: get ...
 after-brace/0: get ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-read-increments-full
-run/0: instruction test-channel-read-increments-full/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -94,7 +133,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-increments-full/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -277,7 +316,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1041 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-increments-full/2
+run/0: instruction tmp0/2
 run/0: {name: "_", value: 0, type: 0, properties: ["_": "dummy"]}, {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- read {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction read/0
@@ -403,7 +442,7 @@ mem/0: location 1134 is 1031
 run/0: result 0 is 34
 run/0: result 1 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-increments-full/3
+run/0: instruction tmp0/3
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-full", value: 0, type: 0, properties: ["first-full": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -413,7 +452,7 @@ run/0: its type is 1
 mem/0: location 1031 is 1
 run/0: product 0 is 1
 mem/0: storing 1 in location 2
-run/0: instruction test-channel-read-increments-full/4
+run/0: instruction tmp0/4
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -423,3 +462,13 @@ run/0: its type is 1
 mem/0: location 1032 is 1
 run/0: product 0 is 1
 mem/0: storing 1 in location 3
+run/0: instruction channel-read-increments-full/1
+run/0: memory-should-contain {name: "
+    2 <- 1  # first-full
+    3 <- 1  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # first-full
+    3 <- 1  # first-free
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-read-not-full b/cpp/.traces/channel-read-not-full
index d05be04b..07b46cdd 100644
--- a/cpp/.traces/channel-read-not-full
+++ b/cpp/.traces/channel-read-not-full
@@ -1,3 +1,44 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+after-brace/0: recipe channel-read-not-full
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-read-not-full
+run/0: instruction channel-read-not-full/0
+run/0: run {name: "
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -15,15 +56,13 @@ parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
 parse/0: instruction: channel-full?
 parse/0:   ingredient: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
-after-brace/0: recipe test-channel-read-not-full
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: read ...
 after-brace/0: channel-empty? ...
 after-brace/0: channel-full? ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-read-not-full
-run/0: instruction test-channel-read-not-full/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "1", value: 1, type: 0, properties: ["1": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -90,7 +129,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-not-full/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -273,7 +312,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1039 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-not-full/2
+run/0: instruction tmp0/2
 run/0: {name: "_", value: 0, type: 0, properties: ["_": "dummy"]}, {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- read {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction read/0
@@ -399,7 +438,7 @@ mem/0: location 1132 is 1031
 run/0: result 0 is 34
 run/0: result 1 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-read-not-full/3
+run/0: instruction tmp0/3
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- channel-empty? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-empty?/0
@@ -443,7 +482,7 @@ run/0: reply {name: "result", value: 4, type: 3, properties: ["result": "boolean
 mem/0: location 1197 is 1
 run/0: result 0 is 1
 mem/0: storing 1 in location 2
-run/0: instruction test-channel-read-not-full/4
+run/0: instruction tmp0/4
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- channel-full? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-full?/0
@@ -541,3 +580,13 @@ run/0: reply {name: "result", value: 6, type: 3, properties: ["result": "boolean
 mem/0: location 1230 is 0
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction channel-read-not-full/1
+run/0: memory-should-contain {name: "
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-wrap b/cpp/.traces/channel-wrap
index fc196654..9595e80e 100644
--- a/cpp/.traces/channel-wrap
+++ b/cpp/.traces/channel-wrap
@@ -1,3 +1,84 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    # channel with just 1 slot
+    1:address:channel <- init-channel 1:literal/capacity
+    # write and read a value
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    # first-free will now be 1
+    2:integer <- get 1:address:channel/deref, first-free:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+    # write second value, verify that first-free wraps
+    1:address:channel <- write 1:address:channel, 34:literal
+    4:integer <- get 1:address:channel/deref, first-free:offset
+    # read second value, verify that first-full wraps
+    _, 1:address:channel <- read 1:address:channel
+    5:integer <- get 1:address:channel/deref, first-full:offset
+  ", value: 0, type: 0, properties: ["
+    # channel with just 1 slot
+    1:address:channel <- init-channel 1:literal/capacity
+    # write and read a value
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    # first-free will now be 1
+    2:integer <- get 1:address:channel/deref, first-free:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+    # write second value, verify that first-free wraps
+    1:address:channel <- write 1:address:channel, 34:literal
+    4:integer <- get 1:address:channel/deref, first-free:offset
+    # read second value, verify that first-full wraps
+    _, 1:address:channel <- read 1:address:channel
+    5:integer <- get 1:address:channel/deref, first-full:offset
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 1  # first-free after first write
+    3 <- 1  # first-full after first read
+    4 <- 0  # first-free after second write, wrapped
+    5 <- 0  # first-full after second read, wrapped
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # first-free after first write
+    3 <- 1  # first-full after first read
+    4 <- 0  # first-free after second write, wrapped
+    5 <- 0  # first-full after second read, wrapped
+  ": "literal-string"]}
+after-brace/0: recipe channel-wrap
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-wrap
+run/0: instruction channel-wrap/0
+run/0: run {name: "
+    # channel with just 1 slot
+    1:address:channel <- init-channel 1:literal/capacity
+    # write and read a value
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    # first-free will now be 1
+    2:integer <- get 1:address:channel/deref, first-free:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+    # write second value, verify that first-free wraps
+    1:address:channel <- write 1:address:channel, 34:literal
+    4:integer <- get 1:address:channel/deref, first-free:offset
+    # read second value, verify that first-full wraps
+    _, 1:address:channel <- read 1:address:channel
+    5:integer <- get 1:address:channel/deref, first-full:offset
+  ", value: 0, type: 0, properties: ["
+    # channel with just 1 slot
+    1:address:channel <- init-channel 1:literal/capacity
+    # write and read a value
+    1:address:channel <- write 1:address:channel, 34:literal
+    _, 1:address:channel <- read 1:address:channel
+    # first-free will now be 1
+    2:integer <- get 1:address:channel/deref, first-free:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+    # write second value, verify that first-free wraps
+    1:address:channel <- write 1:address:channel, 34:literal
+    4:integer <- get 1:address:channel/deref, first-free:offset
+    # read second value, verify that first-full wraps
+    _, 1:address:channel <- read 1:address:channel
+    5:integer <- get 1:address:channel/deref, first-full:offset
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -37,7 +118,7 @@ name/0: element first-free of type channel is at offset 1
 name/0: element first-free of type channel is at offset 1
 name/0: element first-free of type channel is at offset 1
 name/0: element first-full of type channel is at offset 0
-after-brace/0: recipe test-channel-wrap
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: read ...
@@ -47,9 +128,7 @@ after-brace/0: write ...
 after-brace/0: get ...
 after-brace/0: read ...
 after-brace/0: get ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-wrap
-run/0: instruction test-channel-wrap/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "1", value: 1, type: 0, properties: ["1": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -116,7 +195,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-wrap/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -299,7 +378,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1039 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-wrap/2
+run/0: instruction tmp0/2
 run/0: {name: "_", value: 0, type: 0, properties: ["_": "dummy"]}, {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- read {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction read/0
@@ -425,7 +504,7 @@ mem/0: location 1132 is 1031
 run/0: result 0 is 34
 run/0: result 1 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-wrap/3
+run/0: instruction tmp0/3
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -435,7 +514,7 @@ run/0: its type is 1
 mem/0: location 1032 is 1
 run/0: product 0 is 1
 mem/0: storing 1 in location 2
-run/0: instruction test-channel-wrap/4
+run/0: instruction tmp0/4
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -445,7 +524,7 @@ run/0: its type is 1
 mem/0: location 1032 is 1
 run/0: product 0 is 1
 mem/0: storing 1 in location 3
-run/0: instruction test-channel-wrap/5
+run/0: instruction tmp0/5
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -635,7 +714,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1194 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-wrap/6
+run/0: instruction tmp0/6
 run/0: {name: "4", value: 4, type: 1, properties: ["4": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -645,7 +724,7 @@ run/0: its type is 1
 mem/0: location 1032 is 0
 run/0: product 0 is 0
 mem/0: storing 0 in location 4
-run/0: instruction test-channel-wrap/7
+run/0: instruction tmp0/7
 run/0: {name: "_", value: 0, type: 0, properties: ["_": "dummy"]}, {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- read {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction read/0
@@ -775,7 +854,7 @@ mem/0: location 1287 is 1031
 run/0: result 0 is 34
 run/0: result 1 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-wrap/8
+run/0: instruction tmp0/8
 run/0: {name: "5", value: 5, type: 1, properties: ["5": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-full", value: 0, type: 0, properties: ["first-full": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -785,3 +864,19 @@ run/0: its type is 1
 mem/0: location 1031 is 0
 run/0: product 0 is 0
 mem/0: storing 0 in location 5
+run/0: instruction channel-wrap/1
+run/0: memory-should-contain {name: "
+    2 <- 1  # first-free after first write
+    3 <- 1  # first-full after first read
+    4 <- 0  # first-free after second write, wrapped
+    5 <- 0  # first-full after second read, wrapped
+  ", value: 0, type: 0, properties: ["
+    2 <- 1  # first-free after first write
+    3 <- 1  # first-full after first read
+    4 <- 0  # first-free after second write, wrapped
+    5 <- 0  # first-full after second read, wrapped
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
diff --git a/cpp/.traces/channel-write-full b/cpp/.traces/channel-write-full
index 121c73bf..130657a2 100644
--- a/cpp/.traces/channel-write-full
+++ b/cpp/.traces/channel-write-full
@@ -1,3 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 0  # empty?
+    3 <- 1  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # empty?
+    3 <- 1  # full?
+  ": "literal-string"]}
+after-brace/0: recipe channel-write-full
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-write-full
+run/0: instruction channel-write-full/0
+run/0: run {name: "
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 1:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "1", value: 0, type: 0, properties: ["1": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -11,14 +48,12 @@ parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
 parse/0: instruction: channel-full?
 parse/0:   ingredient: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
-after-brace/0: recipe test-channel-write-full
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: channel-empty? ...
 after-brace/0: channel-full? ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-write-full
-run/0: instruction test-channel-write-full/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "1", value: 1, type: 0, properties: ["1": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -85,7 +120,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-full/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -268,7 +303,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1039 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-full/2
+run/0: instruction tmp0/2
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- channel-empty? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-empty?/0
@@ -312,7 +347,7 @@ run/0: reply {name: "result", value: 4, type: 3, properties: ["result": "boolean
 mem/0: location 1135 is 0
 run/0: result 0 is 0
 mem/0: storing 0 in location 2
-run/0: instruction test-channel-write-full/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- channel-full? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-full?/0
@@ -410,3 +445,13 @@ run/0: reply {name: "result", value: 6, type: 3, properties: ["result": "boolean
 mem/0: location 1168 is 1
 run/0: result 0 is 1
 mem/0: storing 1 in location 3
+run/0: instruction channel-write-full/1
+run/0: memory-should-contain {name: "
+    2 <- 0  # empty?
+    3 <- 1  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # empty?
+    3 <- 1  # full?
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-write-increments-free b/cpp/.traces/channel-write-increments-free
index 397bd2b9..c1a8362d 100644
--- a/cpp/.traces/channel-write-increments-free
+++ b/cpp/.traces/channel-write-increments-free
@@ -1,3 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 0  # first-full
+    3 <- 1  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # first-full
+    3 <- 1  # first-free
+  ": "literal-string"]}
+after-brace/0: recipe channel-write-increments-free
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-write-increments-free
+run/0: instruction channel-write-increments-free/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- get 1:address:channel/deref, first-full:offset
+    3:integer <- get 1:address:channel/deref, first-free:offset
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -15,14 +52,12 @@ parse/0:   ingredient: {name: "first-free", value: 0, type: 0, properties: ["fir
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
 name/0: element first-full of type channel is at offset 0
 name/0: element first-free of type channel is at offset 1
-after-brace/0: recipe test-channel-write-increments-free
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: get ...
 after-brace/0: get ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-write-increments-free
-run/0: instruction test-channel-write-increments-free/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -89,7 +124,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-increments-free/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -272,7 +307,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1041 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-increments-free/2
+run/0: instruction tmp0/2
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-full", value: 0, type: 0, properties: ["first-full": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -282,7 +317,7 @@ run/0: its type is 1
 mem/0: location 1031 is 0
 run/0: product 0 is 0
 mem/0: storing 0 in location 2
-run/0: instruction test-channel-write-increments-free/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- get {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel", "deref": ]}, {name: "first-free", value: 1, type: 0, properties: ["first-free": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -292,3 +327,13 @@ run/0: its type is 1
 mem/0: location 1032 is 1
 run/0: product 0 is 1
 mem/0: storing 1 in location 3
+run/0: instruction channel-write-increments-free/1
+run/0: memory-should-contain {name: "
+    2 <- 0  # first-full
+    3 <- 1  # first-free
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # first-full
+    3 <- 1  # first-free
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/channel-write-not-empty b/cpp/.traces/channel-write-not-empty
index bf541002..997ad716 100644
--- a/cpp/.traces/channel-write-not-empty
+++ b/cpp/.traces/channel-write-not-empty
@@ -1,3 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 0  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+after-brace/0: recipe channel-write-not-empty
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: channel-write-not-empty
+run/0: instruction channel-write-not-empty/0
+run/0: run {name: "
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ", value: 0, type: 0, properties: ["
+    1:address:channel <- init-channel 3:literal/capacity
+    1:address:channel <- write 1:address:channel, 34:literal
+    2:integer <- channel-empty? 1:address:channel
+    3:integer <- channel-full? 1:address:channel
+  ": "literal-string"]}
 parse/0: instruction: init-channel
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "capacity": ]}
 parse/0:   product: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
@@ -11,14 +48,12 @@ parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
 parse/0: instruction: channel-full?
 parse/0:   ingredient: {name: "1", value: 0, type: 2-10, properties: ["1": "address":"channel"]}
 parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
-after-brace/0: recipe test-channel-write-not-empty
+after-brace/0: recipe tmp0
 after-brace/0: init-channel ...
 after-brace/0: write ...
 after-brace/0: channel-empty? ...
 after-brace/0: channel-full? ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-channel-write-not-empty
-run/0: instruction test-channel-write-not-empty/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- init-channel {name: "3", value: 3, type: 0, properties: ["3": "literal", "capacity": ]}
 run/0: instruction init-channel/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -85,7 +120,7 @@ run/0: reply {name: "result", value: 1, type: 2-10, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-not-empty/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]} <- write {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}, {name: "34", value: 34, type: 0, properties: ["34": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction write/0
@@ -268,7 +303,7 @@ run/0: reply {name: "chan", value: 1, type: 2-10, properties: ["chan": "address"
 mem/0: location 1041 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-channel-write-not-empty/2
+run/0: instruction tmp0/2
 run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- channel-empty? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-empty?/0
@@ -312,7 +347,7 @@ run/0: reply {name: "result", value: 4, type: 3, properties: ["result": "boolean
 mem/0: location 1137 is 0
 run/0: result 0 is 0
 mem/0: storing 0 in location 2
-run/0: instruction test-channel-write-not-empty/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 1, properties: ["3": "integer"]} <- channel-full? {name: "1", value: 1, type: 2-10, properties: ["1": "address":"channel"]}
 mem/0: location 1 is 1031
 run/0: instruction channel-full?/0
@@ -407,3 +442,13 @@ run/0: reply {name: "result", value: 6, type: 3, properties: ["result": "boolean
 mem/0: location 1170 is 0
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction channel-write-not-empty/1
+run/0: memory-should-contain {name: "
+    2 <- 0  # empty?
+    3 <- 0  # full?
+  ", value: 0, type: 0, properties: ["
+    2 <- 0  # empty?
+    3 <- 0  # full?
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
diff --git a/cpp/.traces/check_string_in_memory b/cpp/.traces/check_string_in_memory
index 635a5557..895976e2 100644
--- a/cpp/.traces/check_string_in_memory
+++ b/cpp/.traces/check_string_in_memory
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- copy 3:literal
+    2:character <- copy 97:literal  # 'a'
+    3:character <- copy 98:literal  # 'b'
+    4:character <- copy 99:literal  # 'c'
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 3:literal
+    2:character <- copy 97:literal  # 'a'
+    3:character <- copy 98:literal  # 'b'
+    4:character <- copy 99:literal  # 'c'
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1:string <- [abc]
+  ", value: 0, type: 0, properties: ["
+    1:string <- [abc]
+  ": "literal-string"]}
+after-brace/0: recipe check_string_in_memory
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: check_string_in_memory
+run/0: instruction check_string_in_memory/0
+run/0: run {name: "
+    1:integer <- copy 3:literal
+    2:character <- copy 97:literal  # 'a'
+    3:character <- copy 98:literal  # 'b'
+    4:character <- copy 99:literal  # 'c'
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 3:literal
+    2:character <- copy 97:literal  # 'a'
+    3:character <- copy 98:literal  # 'b'
+    4:character <- copy 99:literal  # 'c'
+  ": "literal-string"]}
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal"]}
 parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
@@ -10,26 +45,34 @@ parse/0:   product: {name: "3", value: 0, type: 4, properties: ["3": "character"
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "99", value: 0, type: 0, properties: ["99": "literal"]}
 parse/0:   product: {name: "4", value: 0, type: 4, properties: ["4": "character"]}
-after-brace/0: recipe test-check_string_in_memory
+after-brace/0: recipe tmp0
 after-brace/0: copy ...
 after-brace/0: copy ...
 after-brace/0: copy ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-check_string_in_memory
-run/0: instruction test-check_string_in_memory/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- copy {name: "3", value: 3, type: 0, properties: ["3": "literal"]}
 run/0: ingredient 0 is 3
 mem/0: storing 3 in location 1
-run/0: instruction test-check_string_in_memory/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 4, properties: ["2": "character"]} <- copy {name: "97", value: 97, type: 0, properties: ["97": "literal"]}
 run/0: ingredient 0 is 97
 mem/0: storing 97 in location 2
-run/0: instruction test-check_string_in_memory/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 4, properties: ["3": "character"]} <- copy {name: "98", value: 98, type: 0, properties: ["98": "literal"]}
 run/0: ingredient 0 is 98
 mem/0: storing 98 in location 3
-run/0: instruction test-check_string_in_memory/3
+run/0: instruction tmp0/3
 run/0: {name: "4", value: 4, type: 4, properties: ["4": "character"]} <- copy {name: "99", value: 99, type: 0, properties: ["99": "literal"]}
 run/0: ingredient 0 is 99
 mem/0: storing 99 in location 4
+run/0: instruction check_string_in_memory/1
+run/0: memory-should-contain {name: "
+    1:string <- [abc]
+  ", value: 0, type: 0, properties: ["
+    1:string <- [abc]
+  ": "literal-string"]}
+run/0: checking array length at 1
+run/0: checking location 2
+run/0: checking location 3
+run/0: checking location 4
diff --git a/cpp/.traces/check_trace b/cpp/.traces/check_trace
new file mode 100644
index 00000000..fd611d77
--- /dev/null
+++ b/cpp/.traces/check_trace
@@ -0,0 +1,41 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    mem: storing 4 in location 1
+  ", value: 0, type: 0, properties: ["
+    mem: storing 4 in location 1
+  ": "literal-string"]}
+after-brace/0: recipe check_trace
+after-brace/0: run ...
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: check_trace
+run/0: instruction check_trace/0
+run/0: run {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: add
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe tmp0
+after-brace/0: add ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
+run/0: instruction check_trace/1
+run/0: trace-should-contain {name: "
+    mem: storing 4 in location 1
+  ", value: 0, type: 0, properties: ["
+    mem: storing 4 in location 1
+  ": "literal-string"]}
diff --git a/cpp/.traces/check_trace_instruction b/cpp/.traces/check_trace_instruction
new file mode 100644
index 00000000..5849ff41
--- /dev/null
+++ b/cpp/.traces/check_trace_instruction
@@ -0,0 +1,37 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    trace [foo], [aaa]
+  ", value: 0, type: 0, properties: ["
+    trace [foo], [aaa]
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    foo: aaa
+  ", value: 0, type: 0, properties: ["
+    foo: aaa
+  ": "literal-string"]}
+after-brace/0: recipe check_trace_instruction
+after-brace/0: run ...
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: check_trace_instruction
+run/0: instruction check_trace_instruction/0
+run/0: run {name: "
+    trace [foo], [aaa]
+  ", value: 0, type: 0, properties: ["
+    trace [foo], [aaa]
+  ": "literal-string"]}
+parse/0: instruction: trace
+parse/0:   ingredient: {name: "foo", value: 0, type: 0, properties: ["foo": "literal-string"]}
+parse/0:   ingredient: {name: "aaa", value: 0, type: 0, properties: ["aaa": "literal-string"]}
+after-brace/0: recipe tmp0
+after-brace/0: trace ...
+run/0: instruction tmp0/0
+run/0: trace {name: "foo", value: 0, type: 0, properties: ["foo": "literal-string"]}, {name: "aaa", value: 0, type: 0, properties: ["aaa": "literal-string"]}
+foo/0: aaa
+run/0: instruction check_trace_instruction/1
+run/0: trace-should-contain {name: "
+    foo: aaa
+  ", value: 0, type: 0, properties: ["
+    foo: aaa
+  ": "literal-string"]}
diff --git a/cpp/.traces/check_trace_negative b/cpp/.traces/check_trace_negative
new file mode 100644
index 00000000..c9289d57
--- /dev/null
+++ b/cpp/.traces/check_trace_negative
@@ -0,0 +1,41 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: trace-should-not-contain
+parse/0:   ingredient: {name: "
+    mem: storing 5 in location 1
+  ", value: 0, type: 0, properties: ["
+    mem: storing 5 in location 1
+  ": "literal-string"]}
+after-brace/0: recipe check_trace_negative
+after-brace/0: run ...
+after-brace/0: trace-should-not-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: check_trace_negative
+run/0: instruction check_trace_negative/0
+run/0: run {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: add
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe tmp0
+after-brace/0: add ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
+run/0: instruction check_trace_negative/1
+run/0: trace-should-not-contain {name: "
+    mem: storing 5 in location 1
+  ", value: 0, type: 0, properties: ["
+    mem: storing 5 in location 1
+  ": "literal-string"]}
diff --git a/cpp/.traces/clear-line-erases-printed-characters b/cpp/.traces/clear-line-erases-printed-characters
index 4aacb7e0..9aae7db2 100644
--- a/cpp/.traces/clear-line-erases-printed-characters
+++ b/cpp/.traces/clear-line-erases-printed-characters
@@ -1,3 +1,74 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    # print a character
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    # move cursor to start of line
+    1:address:screen <- move-cursor 1:address:screen, 0:literal/row, 0:literal/column
+    # clear line
+    1:address:screen <- clear-line 1:address:screen
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    # print a character
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    # move cursor to start of line
+    1:address:screen <- move-cursor 1:address:screen, 0:literal/row, 0:literal/column
+    # clear line
+    1:address:screen <- clear-line 1:address:screen
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 6  # width*height
+    4 <- 0
+    5 <- 0
+    6 <- 0
+    7 <- 0
+    8 <- 0
+    9 <- 0
+  ", value: 0, type: 0, properties: ["
+    3 <- 6  # width*height
+    4 <- 0
+    5 <- 0
+    6 <- 0
+    7 <- 0
+    8 <- 0
+    9 <- 0
+  ": "literal-string"]}
+after-brace/0: recipe clear-line-erases-printed-characters
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: clear-line-erases-printed-characters
+run/0: instruction clear-line-erases-printed-characters/0
+run/0: run {name: "
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    # print a character
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    # move cursor to start of line
+    1:address:screen <- move-cursor 1:address:screen, 0:literal/row, 0:literal/column
+    # clear line
+    1:address:screen <- clear-line 1:address:screen
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    # print a character
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    # move cursor to start of line
+    1:address:screen <- move-cursor 1:address:screen, 0:literal/row, 0:literal/column
+    # clear line
+    1:address:screen <- clear-line 1:address:screen
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ": "literal-string"]}
 parse/0: instruction: init-fake-screen
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "width": ]}
 parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal", "height": ]}
@@ -22,16 +93,14 @@ parse/0: instruction: copy
 parse/0:   ingredient: {name: "2", value: 0, type: 2-5-4, properties: ["2": "address":"array":"character", "deref": ]}
 parse/0:   product: {name: "3", value: 0, type: 5-4, properties: ["3": "array":"character"]}
 name/0: element data of type screen is at offset 4
-after-brace/0: recipe test-clear-line-erases-printed-characters
+after-brace/0: recipe tmp0
 after-brace/0: init-fake-screen ...
 after-brace/0: print-character ...
 after-brace/0: move-cursor ...
 after-brace/0: clear-line ...
 after-brace/0: get ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-clear-line-erases-printed-characters
-run/0: instruction test-clear-line-erases-printed-characters/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- init-fake-screen {name: "3", value: 3, type: 0, properties: ["3": "literal", "width": ]}, {name: "2", value: 2, type: 0, properties: ["2": "literal", "height": ]}
 run/0: instruction init-fake-screen/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal", "capacity": ]}
@@ -403,7 +472,7 @@ run/0: reply {name: "result", value: 1, type: 2-11, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-clear-line-erases-printed-characters/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- print-character {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]}, {name: "97", value: 97, type: 0, properties: ["97": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction print-character/0
@@ -521,7 +590,7 @@ run/0: reply {name: "x", value: 1, type: 2-11, properties: ["x": "address":"scre
 mem/0: location 1076 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-clear-line-erases-printed-characters/2
+run/0: instruction tmp0/2
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- move-cursor {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]}, {name: "0", value: 0, type: 0, properties: ["0": "literal", "row": ]}, {name: "0", value: 0, type: 0, properties: ["0": "literal", "column": ]}
 mem/0: location 1 is 1031
 run/0: instruction move-cursor/0
@@ -578,7 +647,7 @@ run/0: reply {name: "x", value: 1, type: 2-11, properties: ["x": "address":"scre
 mem/0: location 1107 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-clear-line-erases-printed-characters/3
+run/0: instruction tmp0/3
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- clear-line {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]}
 mem/0: location 1 is 1031
 run/0: instruction clear-line/0
@@ -1046,7 +1115,7 @@ run/0: reply {name: "x", value: 1, type: 2-11, properties: ["x": "address":"scre
 mem/0: location 1138 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-clear-line-erases-printed-characters/4
+run/0: instruction tmp0/4
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character"]} <- get {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen", "deref": ]}, {name: "data", value: 4, type: 0, properties: ["data": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -1056,7 +1125,7 @@ run/0: its type is 2
 mem/0: location 1035 is 1036
 run/0: product 0 is 1036
 mem/0: storing 1036 in location 2
-run/0: instruction test-clear-line-erases-printed-characters/5
+run/0: instruction tmp0/5
 run/0: {name: "3", value: 3, type: 5-4, properties: ["3": "array":"character"]} <- copy {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "deref": ]}
 run/0: ingredient 0 is 2
 mem/0: location 2 is 1036
@@ -1074,3 +1143,28 @@ mem/0: storing 0 in location 6
 mem/0: storing 0 in location 7
 mem/0: storing 0 in location 8
 mem/0: storing 0 in location 9
+run/0: instruction clear-line-erases-printed-characters/1
+run/0: memory-should-contain {name: "
+    3 <- 6  # width*height
+    4 <- 0
+    5 <- 0
+    6 <- 0
+    7 <- 0
+    8 <- 0
+    9 <- 0
+  ", value: 0, type: 0, properties: ["
+    3 <- 6  # width*height
+    4 <- 0
+    5 <- 0
+    6 <- 0
+    7 <- 0
+    8 <- 0
+    9 <- 0
+  ": "literal-string"]}
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
+run/0: checking location 6
+run/0: checking location 7
+run/0: checking location 8
+run/0: checking location 9
diff --git a/cpp/.traces/factorial-test b/cpp/.traces/factorial-test
deleted file mode 100644
index 1729d718..00000000
--- a/cpp/.traces/factorial-test
+++ /dev/null
@@ -1,210 +0,0 @@
-parse/0: instruction: 108
-parse/0:   ingredient: {name: "5", value: 0, type: 0, properties: ["5": "literal"]}
-parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
-after-brace/0: recipe test-factorial-test
-after-brace/0: factorial ...
-run/0: instruction test-factorial-test/0
-run/0: instruction factorial/0
-mem/0: new alloc: 1000
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 5
-mem/0: storing 5 in location 1002
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1002 is 5
-run/0: ingredient 1 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1003
-run/0: instruction factorial/4
-mem/0: location 1003 is 0
-run/0: ingredient 0 is 0
-run/0: ingredient 1 is 
-run/0: jumping to instruction 6
-run/0: instruction factorial/7
-run/0: ingredient 0 is n
-mem/0: location 1002 is 5
-run/0: ingredient 1 is 1
-run/0: product 0 is 4
-mem/0: storing 4 in location 1004
-run/0: instruction factorial/8
-mem/0: location 1004 is 4
-run/0: instruction factorial/0
-mem/0: new alloc: 1030
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 4
-mem/0: storing 4 in location 1032
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1032 is 4
-run/0: ingredient 1 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1033
-run/0: instruction factorial/4
-mem/0: location 1033 is 0
-run/0: ingredient 0 is 0
-run/0: ingredient 1 is 
-run/0: jumping to instruction 6
-run/0: instruction factorial/7
-run/0: ingredient 0 is n
-mem/0: location 1032 is 4
-run/0: ingredient 1 is 1
-run/0: product 0 is 3
-mem/0: storing 3 in location 1034
-run/0: instruction factorial/8
-mem/0: location 1034 is 3
-run/0: instruction factorial/0
-mem/0: new alloc: 1060
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 3
-mem/0: storing 3 in location 1062
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1062 is 3
-run/0: ingredient 1 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1063
-run/0: instruction factorial/4
-mem/0: location 1063 is 0
-run/0: ingredient 0 is 0
-run/0: ingredient 1 is 
-run/0: jumping to instruction 6
-run/0: instruction factorial/7
-run/0: ingredient 0 is n
-mem/0: location 1062 is 3
-run/0: ingredient 1 is 1
-run/0: product 0 is 2
-mem/0: storing 2 in location 1064
-run/0: instruction factorial/8
-mem/0: location 1064 is 2
-run/0: instruction factorial/0
-mem/0: new alloc: 1090
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 2
-mem/0: storing 2 in location 1092
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1092 is 2
-run/0: ingredient 1 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1093
-run/0: instruction factorial/4
-mem/0: location 1093 is 0
-run/0: ingredient 0 is 0
-run/0: ingredient 1 is 
-run/0: jumping to instruction 6
-run/0: instruction factorial/7
-run/0: ingredient 0 is n
-mem/0: location 1092 is 2
-run/0: ingredient 1 is 1
-run/0: product 0 is 1
-mem/0: storing 1 in location 1094
-run/0: instruction factorial/8
-mem/0: location 1094 is 1
-run/0: instruction factorial/0
-mem/0: new alloc: 1120
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 1
-mem/0: storing 1 in location 1122
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1122 is 1
-run/0: ingredient 1 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1123
-run/0: instruction factorial/4
-mem/0: location 1123 is 0
-run/0: ingredient 0 is 0
-run/0: ingredient 1 is 
-run/0: jumping to instruction 6
-run/0: instruction factorial/7
-run/0: ingredient 0 is n
-mem/0: location 1122 is 1
-run/0: ingredient 1 is 1
-run/0: product 0 is 0
-mem/0: storing 0 in location 1124
-run/0: instruction factorial/8
-mem/0: location 1124 is 0
-run/0: instruction factorial/0
-mem/0: new alloc: 1150
-mem/0: array size is 30
-run/0: instruction factorial/1
-run/0: product 0 is 0
-mem/0: storing 0 in location 1152
-run/0: instruction factorial/3
-run/0: ingredient 0 is n
-mem/0: location 1152 is 0
-run/0: ingredient 1 is 0
-run/0: product 0 is 1
-mem/0: storing 1 in location 1153
-run/0: instruction factorial/4
-mem/0: location 1153 is 1
-run/0: ingredient 0 is 1
-run/0: jump-unless fell through
-run/0: instruction factorial/5
-run/0: result 0 is 1
-mem/0: storing 1 in location 1125
-run/0: instruction factorial/9
-run/0: ingredient 0 is subresult
-mem/0: location 1125 is 1
-run/0: ingredient 1 is n
-mem/0: location 1122 is 1
-run/0: ingredient 1 is 1
-run/0: product 0 is 1
-mem/0: storing 1 in location 1126
-run/0: instruction factorial/10
-mem/0: location 1126 is 1
-run/0: result 0 is 1
-mem/0: storing 1 in location 1095
-run/0: instruction factorial/9
-run/0: ingredient 0 is subresult
-mem/0: location 1095 is 1
-run/0: ingredient 1 is n
-mem/0: location 1092 is 2
-run/0: ingredient 1 is 2
-run/0: product 0 is 2
-mem/0: storing 2 in location 1096
-run/0: instruction factorial/10
-mem/0: location 1096 is 2
-run/0: result 0 is 2
-mem/0: storing 2 in location 1065
-run/0: instruction factorial/9
-run/0: ingredient 0 is subresult
-mem/0: location 1065 is 2
-run/0: ingredient 1 is n
-mem/0: location 1062 is 3
-run/0: ingredient 1 is 3
-run/0: product 0 is 6
-mem/0: storing 6 in location 1066
-run/0: instruction factorial/10
-mem/0: location 1066 is 6
-run/0: result 0 is 6
-mem/0: storing 6 in location 1035
-run/0: instruction factorial/9
-run/0: ingredient 0 is subresult
-mem/0: location 1035 is 6
-run/0: ingredient 1 is n
-mem/0: location 1032 is 4
-run/0: ingredient 1 is 4
-run/0: product 0 is 24
-mem/0: storing 24 in location 1036
-run/0: instruction factorial/10
-mem/0: location 1036 is 24
-run/0: result 0 is 24
-mem/0: storing 24 in location 1005
-run/0: instruction factorial/9
-run/0: ingredient 0 is subresult
-mem/0: location 1005 is 24
-run/0: ingredient 1 is n
-mem/0: location 1002 is 5
-run/0: ingredient 1 is 5
-run/0: product 0 is 120
-mem/0: storing 120 in location 1006
-run/0: instruction factorial/10
-mem/0: location 1006 is 120
-run/0: result 0 is 120
-mem/0: storing 120 in location 1
diff --git a/cpp/.traces/first_scenario_checking_trace b/cpp/.traces/first_scenario_checking_trace
deleted file mode 100644
index 109fed69..00000000
--- a/cpp/.traces/first_scenario_checking_trace
+++ /dev/null
@@ -1,14 +0,0 @@
-parse/0: instruction: add
-parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
-parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
-parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
-after-brace/0: recipe test-first_scenario_checking_trace
-after-brace/0: add ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-first_scenario_checking_trace
-run/0: instruction test-first_scenario_checking_trace/0
-run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
-run/0: ingredient 0 is 2
-run/0: ingredient 1 is 2
-run/0: product 0 is 4
-mem/0: storing 4 in location 1
diff --git a/cpp/.traces/first_scenario_checking_trace_negative b/cpp/.traces/first_scenario_checking_trace_negative
deleted file mode 100644
index 0214db4e..00000000
--- a/cpp/.traces/first_scenario_checking_trace_negative
+++ /dev/null
@@ -1,14 +0,0 @@
-parse/0: instruction: add
-parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
-parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
-parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
-after-brace/0: recipe test-first_scenario_checking_trace_negative
-after-brace/0: add ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-first_scenario_checking_trace_negative
-run/0: instruction test-first_scenario_checking_trace_negative/0
-run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
-run/0: ingredient 0 is 2
-run/0: ingredient 1 is 2
-run/0: product 0 is 4
-mem/0: storing 4 in location 1
diff --git a/cpp/.traces/first_scenario_in_mu b/cpp/.traces/first_scenario_in_mu
index 9e02c432..090585b8 100644
--- a/cpp/.traces/first_scenario_in_mu
+++ b/cpp/.traces/first_scenario_in_mu
@@ -1,14 +1,42 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+after-brace/0: recipe first_scenario_in_mu
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: first_scenario_in_mu
+run/0: instruction first_scenario_in_mu/0
+run/0: run {name: "
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
 parse/0: instruction: add
 parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
 parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
 parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
-after-brace/0: recipe test-first_scenario_in_mu
+after-brace/0: recipe tmp0
 after-brace/0: add ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-first_scenario_in_mu
-run/0: instruction test-first_scenario_in_mu/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
 run/0: ingredient 0 is 2
 run/0: ingredient 1 is 2
 run/0: product 0 is 4
 mem/0: storing 4 in location 1
+run/0: instruction first_scenario_in_mu/1
+run/0: memory-should-contain {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+run/0: checking location 1
diff --git a/cpp/.traces/init-buffer-allocates b/cpp/.traces/init-buffer-allocates
deleted file mode 100644
index 2730df91..00000000
--- a/cpp/.traces/init-buffer-allocates
+++ /dev/null
@@ -1,204 +0,0 @@
-parse/0: instruction: 33
-parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
-parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
-parse/0:   product: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]}
-parse/0: instruction: 100
-parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal"]}
-parse/0:   product: {name: "x", value: 0, type: 2-9, properties: ["x": "address":"buffer"]}
-parse/0: instruction: 19
-parse/0:   ingredient: {name: "x", value: 0, type: 2-9, properties: ["x": "address":"buffer", "deref": ]}
-parse/0:   ingredient: {name: "data", value: 0, type: 0, properties: ["data": "offset"]}
-parse/0:   product: {name: "s1", value: 0, type: 2-5-4, properties: ["s1": "address":"array":"character"]}
-parse/0: instruction: 23
-parse/0:   ingredient: {name: "s1", value: 0, type: 2-5-4, properties: ["s1": "address":"array":"character", "deref": ]}
-parse/0:   product: {name: "len1", value: 0, type: 1, properties: ["len1": "integer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "len1", value: 0, type: 1, properties: ["len1": "integer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: " ", value: 0, type: 0, properties: [" ": "literal-string"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "x", value: 0, type: 2-9, properties: ["x": "address":"buffer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "
-", value: 0, type: 0, properties: ["
-": "literal-string"]}
-parse/0: instruction: 100
-parse/0:   ingredient: {name: "4", value: 0, type: 0, properties: ["4": "literal"]}
-parse/0:   product: {name: "y", value: 0, type: 2-9, properties: ["y": "address":"buffer"]}
-parse/0: instruction: 19
-parse/0:   ingredient: {name: "y", value: 0, type: 2-9, properties: ["y": "address":"buffer", "deref": ]}
-parse/0:   ingredient: {name: "data", value: 0, type: 0, properties: ["data": "offset"]}
-parse/0:   product: {name: "s2", value: 0, type: 2-5-4, properties: ["s2": "address":"array":"character"]}
-parse/0: instruction: 23
-parse/0:   ingredient: {name: "s2", value: 0, type: 2-5-4, properties: ["s2": "address":"array":"character", "deref": ]}
-parse/0:   product: {name: "len2", value: 0, type: 1, properties: ["len2": "integer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "len2", value: 0, type: 1, properties: ["len2": "integer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: " ", value: 0, type: 0, properties: [" ": "literal-string"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "y", value: 0, type: 2-9, properties: ["y": "address":"buffer"]}
-parse/0: instruction: 99
-parse/0:   ingredient: {name: "
-", value: 0, type: 0, properties: ["
-": "literal-string"]}
-parse/0: instruction: 3
-parse/0:   ingredient: {name: "y", value: 0, type: 2-9, properties: ["y": "address":"buffer"]}
-parse/0:   ingredient: {name: "x", value: 0, type: 2-9, properties: ["x": "address":"buffer"]}
-parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer", "raw": ]}
-new/0: location -> 1
-name/0: assign x 1
-name/0: element data of type buffer is at offset 1
-name/0: assign s1 2
-name/0: assign len1 3
-name/0: assign y 4
-name/0: element data of type buffer is at offset 1
-name/0: assign s2 5
-name/0: assign len2 6
-after-brace/0: recipe test-init-buffer-allocates
-after-brace/0: new ...
-after-brace/0: init-buffer ...
-after-brace/0: get ...
-after-brace/0: length ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: init-buffer ...
-after-brace/0: get ...
-after-brace/0: length ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: $print ...
-after-brace/0: subtract ...
-run/0: instruction test-init-buffer-allocates/0
-mem/0: new alloc: 1000
-mem/0: array size is 30
-run/0: instruction test-init-buffer-allocates/1
-run/0: instruction init-buffer/0
-mem/0: new alloc: 1030
-mem/0: array size is 30
-run/0: instruction init-buffer/1
-mem/0: new alloc: 1060
-mem/0: storing 1060 in location 1032
-run/0: instruction init-buffer/2
-run/0: ingredient 0 is result
-mem/0: location 1032 is 1060
-run/0: ingredient 1 is length
-run/0: address to copy is 1060
-run/0: product 0 is 1060
-mem/0: storing 1060 in location 1033
-run/0: instruction init-buffer/3
-run/0: ingredient 0 is 0
-mem/0: location 1033 is 1060
-mem/0: storing 0 in location 1060
-run/0: instruction init-buffer/4
-run/0: ingredient 0 is result
-mem/0: location 1032 is 1060
-run/0: ingredient 1 is data
-run/0: address to copy is 1061
-run/0: product 0 is 1061
-mem/0: storing 1061 in location 1034
-run/0: instruction init-buffer/5
-run/0: product 0 is 3
-mem/0: storing 3 in location 1035
-run/0: instruction init-buffer/6
-mem/0: new alloc: 1062
-mem/0: location 1034 is 1061
-mem/0: storing 1062 in location 1061
-mem/0: location 1035 is 3
-mem/0: array size is 3
-run/0: instruction init-buffer/7
-mem/0: location 1032 is 1060
-run/0: result 0 is 1060
-mem/0: storing 1060 in location 1002
-run/0: instruction test-init-buffer-allocates/2
-run/0: ingredient 0 is x
-mem/0: location 1002 is 1060
-run/0: ingredient 1 is data
-run/0: address to copy is 1061
-run/0: its type is 2
-mem/0: location 2062 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1003
-run/0: instruction test-init-buffer-allocates/3
-mem/0: location 1003 is 0
-mem/0: storing 0 in location 1004
-run/0: instruction test-init-buffer-allocates/4
-mem/0: location 1004 is 0
-run/0: $print: 0
-run/0: instruction test-init-buffer-allocates/5
-run/0: $print:  
-run/0: instruction test-init-buffer-allocates/6
-mem/0: location 1002 is 1060
-run/0: $print: 1060
-run/0: instruction test-init-buffer-allocates/7
-run/0: $print: 
-run/0: instruction test-init-buffer-allocates/8
-run/0: instruction init-buffer/0
-mem/0: new alloc: 1065
-mem/0: array size is 30
-run/0: instruction init-buffer/1
-mem/0: new alloc: 1095
-mem/0: storing 1095 in location 1067
-run/0: instruction init-buffer/2
-run/0: ingredient 0 is result
-mem/0: location 1067 is 1095
-run/0: ingredient 1 is length
-run/0: address to copy is 1095
-run/0: product 0 is 1095
-mem/0: storing 1095 in location 1068
-run/0: instruction init-buffer/3
-run/0: ingredient 0 is 0
-mem/0: location 1068 is 1095
-mem/0: storing 0 in location 1095
-run/0: instruction init-buffer/4
-run/0: ingredient 0 is result
-mem/0: location 1067 is 1095
-run/0: ingredient 1 is data
-run/0: address to copy is 1096
-run/0: product 0 is 1096
-mem/0: storing 1096 in location 1069
-run/0: instruction init-buffer/5
-run/0: product 0 is 4
-mem/0: storing 4 in location 1070
-run/0: instruction init-buffer/6
-mem/0: new alloc: 1097
-mem/0: location 1069 is 1096
-mem/0: storing 1097 in location 1096
-mem/0: location 1070 is 4
-mem/0: array size is 4
-run/0: instruction init-buffer/7
-mem/0: location 1067 is 1095
-run/0: result 0 is 1095
-mem/0: storing 1095 in location 1005
-run/0: instruction test-init-buffer-allocates/9
-run/0: ingredient 0 is y
-mem/0: location 1005 is 1095
-run/0: ingredient 1 is data
-run/0: address to copy is 1096
-run/0: its type is 2
-mem/0: location 2097 is 0
-run/0: product 0 is 0
-mem/0: storing 0 in location 1006
-run/0: instruction test-init-buffer-allocates/10
-mem/0: location 1006 is 0
-mem/0: storing 0 in location 1007
-run/0: instruction test-init-buffer-allocates/11
-mem/0: location 1007 is 0
-run/0: $print: 0
-run/0: instruction test-init-buffer-allocates/12
-run/0: $print:  
-run/0: instruction test-init-buffer-allocates/13
-mem/0: location 1005 is 1095
-run/0: $print: 1095
-run/0: instruction test-init-buffer-allocates/14
-run/0: $print: 
-run/0: instruction test-init-buffer-allocates/15
-run/0: ingredient 0 is y
-mem/0: location 1005 is 1095
-run/0: ingredient 1 is x
-mem/0: location 1002 is 1060
-run/0: product 0 is 35
-mem/0: storing 35 in location 1
diff --git a/cpp/.traces/integer-to-decimal-digit-negative b/cpp/.traces/integer-to-decimal-digit-negative
index ef47b493..fac1a708 100644
--- a/cpp/.traces/integer-to-decimal-digit-negative
+++ b/cpp/.traces/integer-to-decimal-digit-negative
@@ -1,15 +1,44 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- integer-to-decimal-string -1:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string -1:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2 <- 2
+    3 <- 45  # '-'
+    4 <- 49  # '1'
+  ", value: 0, type: 0, properties: ["
+    2 <- 2
+    3 <- 45  # '-'
+    4 <- 49  # '1'
+  ": "literal-string"]}
+after-brace/0: recipe integer-to-decimal-digit-negative
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: integer-to-decimal-digit-negative
+run/0: instruction integer-to-decimal-digit-negative/0
+run/0: run {name: "
+    1:address:array:character/raw <- integer-to-decimal-string -1:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string -1:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
 parse/0: instruction: integer-to-decimal-string
 parse/0:   ingredient: {name: "-1", value: 0, type: 0, properties: ["-1": "literal"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 parse/0:   product: {name: "2", value: 0, type: 5-4, properties: ["2": "array":"character", "raw": ]}
-after-brace/0: recipe test-integer-to-decimal-digit-negative
+after-brace/0: recipe tmp0
 after-brace/0: integer-to-decimal-string ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-integer-to-decimal-digit-negative
-run/0: instruction test-integer-to-decimal-digit-negative/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- integer-to-decimal-string {name: "-1", value: -1, type: 0, properties: ["-1": "literal"]}
 run/0: instruction integer-to-decimal-string/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -557,7 +586,7 @@ run/0: reply {name: "result", value: 2, type: 2-5-4, properties: ["result": "add
 mem/0: location 1003 is 1219
 run/0: result 0 is 1219
 mem/0: storing 1219 in location 1
-run/0: instruction test-integer-to-decimal-digit-negative/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 5-4, properties: ["2": "array":"character", "raw": ]} <- copy {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1219
@@ -567,3 +596,16 @@ mem/0: location 1221 is 49
 mem/0: storing 2 in location 2
 mem/0: storing 45 in location 3
 mem/0: storing 49 in location 4
+run/0: instruction integer-to-decimal-digit-negative/1
+run/0: memory-should-contain {name: "
+    2 <- 2
+    3 <- 45  # '-'
+    4 <- 49  # '1'
+  ", value: 0, type: 0, properties: ["
+    2 <- 2
+    3 <- 45  # '-'
+    4 <- 49  # '1'
+  ": "literal-string"]}
+run/0: checking location 2
+run/0: checking location 3
+run/0: checking location 4
diff --git a/cpp/.traces/integer-to-decimal-digit-positive b/cpp/.traces/integer-to-decimal-digit-positive
index df2d858d..69bbc01c 100644
--- a/cpp/.traces/integer-to-decimal-digit-positive
+++ b/cpp/.traces/integer-to-decimal-digit-positive
@@ -1,15 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- integer-to-decimal-string 234:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string 234:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2:string <- [234]
+  ", value: 0, type: 0, properties: ["
+    2:string <- [234]
+  ": "literal-string"]}
+after-brace/0: recipe integer-to-decimal-digit-positive
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: integer-to-decimal-digit-positive
+run/0: instruction integer-to-decimal-digit-positive/0
+run/0: run {name: "
+    1:address:array:character/raw <- integer-to-decimal-string 234:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string 234:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
 parse/0: instruction: integer-to-decimal-string
 parse/0:   ingredient: {name: "234", value: 0, type: 0, properties: ["234": "literal"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 parse/0:   product: {name: "2", value: 0, type: 5-4, properties: ["2": "array":"character", "raw": ]}
-after-brace/0: recipe test-integer-to-decimal-digit-positive
+after-brace/0: recipe tmp0
 after-brace/0: integer-to-decimal-string ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-integer-to-decimal-digit-positive
-run/0: instruction test-integer-to-decimal-digit-positive/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- integer-to-decimal-string {name: "234", value: 234, type: 0, properties: ["234": "literal"]}
 run/0: instruction integer-to-decimal-string/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -788,7 +813,7 @@ run/0: reply {name: "result", value: 2, type: 2-5-4, properties: ["result": "add
 mem/0: location 1003 is 1281
 run/0: result 0 is 1281
 mem/0: storing 1281 in location 1
-run/0: instruction test-integer-to-decimal-digit-positive/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 5-4, properties: ["2": "array":"character", "raw": ]} <- copy {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1281
@@ -800,3 +825,13 @@ mem/0: storing 3 in location 2
 mem/0: storing 50 in location 3
 mem/0: storing 51 in location 4
 mem/0: storing 52 in location 5
+run/0: instruction integer-to-decimal-digit-positive/1
+run/0: memory-should-contain {name: "
+    2:string <- [234]
+  ", value: 0, type: 0, properties: ["
+    2:string <- [234]
+  ": "literal-string"]}
+run/0: checking array length at 2
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
diff --git a/cpp/.traces/integer-to-decimal-digit-zero b/cpp/.traces/integer-to-decimal-digit-zero
index e80db30e..e4731f30 100644
--- a/cpp/.traces/integer-to-decimal-digit-zero
+++ b/cpp/.traces/integer-to-decimal-digit-zero
@@ -1,15 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- integer-to-decimal-string 0:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string 0:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    2:string <- [0]
+  ", value: 0, type: 0, properties: ["
+    2:string <- [0]
+  ": "literal-string"]}
+after-brace/0: recipe integer-to-decimal-digit-zero
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: integer-to-decimal-digit-zero
+run/0: instruction integer-to-decimal-digit-zero/0
+run/0: run {name: "
+    1:address:array:character/raw <- integer-to-decimal-string 0:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- integer-to-decimal-string 0:literal
+    2:array:character/raw <- copy 1:address:array:character/deref/raw
+  ": "literal-string"]}
 parse/0: instruction: integer-to-decimal-string
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
 parse/0: instruction: copy
 parse/0:   ingredient: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 parse/0:   product: {name: "2", value: 0, type: 5-4, properties: ["2": "array":"character", "raw": ]}
-after-brace/0: recipe test-integer-to-decimal-digit-zero
+after-brace/0: recipe tmp0
 after-brace/0: integer-to-decimal-string ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-integer-to-decimal-digit-zero
-run/0: instruction test-integer-to-decimal-digit-zero/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- integer-to-decimal-string {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 run/0: instruction integer-to-decimal-string/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
@@ -32,7 +57,7 @@ run/0: reply {name: "result", value: 2, type: 2-5-4, properties: ["result": "add
 mem/0: location 1003 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-integer-to-decimal-digit-zero/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 5-4, properties: ["2": "array":"character", "raw": ]} <- copy {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "deref": , "raw": ]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -40,3 +65,11 @@ mem/0: location 1031 is 1
 mem/0: location 1032 is 48
 mem/0: storing 1 in location 2
 mem/0: storing 48 in location 3
+run/0: instruction integer-to-decimal-digit-zero/1
+run/0: memory-should-contain {name: "
+    2:string <- [0]
+  ", value: 0, type: 0, properties: ["
+    2:string <- [0]
+  ": "literal-string"]}
+run/0: checking array length at 2
+run/0: checking location 3
diff --git a/cpp/.traces/interpolate-at-end b/cpp/.traces/interpolate-at-end
index 35fc4746..061a4d3f 100644
--- a/cpp/.traces/interpolate-at-end
+++ b/cpp/.traces/interpolate-at-end
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- new [hello, _]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [hello, _]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    4:string <- [hello, abc]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [hello, abc]
+  ": "literal-string"]}
+after-brace/0: recipe interpolate-at-end
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: interpolate-at-end
+run/0: instruction interpolate-at-end/0
+run/0: run {name: "
+    1:address:array:character/raw <- new [hello, _]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [hello, _]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "hello, _", value: 0, type: 0, properties: ["hello, _": "literal-string"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
@@ -13,20 +48,18 @@ parse/0:   ingredient: {name: "3", value: 0, type: 2-5-4, properties: ["3": "add
 parse/0:   product: {name: "4", value: 0, type: 5-4, properties: ["4": "array":"character", "raw": ]}
 new/0: hello, _ -> 0
 new/0: abc -> 0
-after-brace/0: recipe test-interpolate-at-end
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: interpolate ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-interpolate-at-end
-run/0: instruction test-interpolate-at-end/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- new {name: "hello, _", value: 0, type: 0, properties: ["hello, _": "literal-string"]}
 mem/0: storing 1000 in location 1
-run/0: instruction test-interpolate-at-end/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1009 in location 2
-run/0: instruction test-interpolate-at-end/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": ]} <- interpolate {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}, {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]}
 mem/0: location 1 is 1000
 mem/0: location 2 is 1009
@@ -866,7 +899,7 @@ run/0: reply {name: "result", value: 7, type: 2-5-4, properties: ["result": "add
 mem/0: location 1021 is 1074
 run/0: result 0 is 1074
 mem/0: storing 1074 in location 3
-run/0: instruction test-interpolate-at-end/3
+run/0: instruction tmp0/3
 run/0: {name: "4", value: 4, type: 5-4, properties: ["4": "array":"character", "raw": ]} <- copy {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": , "deref": ]}
 run/0: ingredient 0 is 3
 mem/0: location 3 is 1074
@@ -892,3 +925,20 @@ mem/0: storing 32 in location 11
 mem/0: storing 97 in location 12
 mem/0: storing 98 in location 13
 mem/0: storing 99 in location 14
+run/0: instruction interpolate-at-end/1
+run/0: memory-should-contain {name: "
+    4:string <- [hello, abc]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [hello, abc]
+  ": "literal-string"]}
+run/0: checking array length at 4
+run/0: checking location 5
+run/0: checking location 6
+run/0: checking location 7
+run/0: checking location 8
+run/0: checking location 9
+run/0: checking location 10
+run/0: checking location 11
+run/0: checking location 12
+run/0: checking location 13
+run/0: checking location 14
diff --git a/cpp/.traces/interpolate-at-start b/cpp/.traces/interpolate-at-start
index 47c1d8c0..fb228fb8 100644
--- a/cpp/.traces/interpolate-at-start
+++ b/cpp/.traces/interpolate-at-start
@@ -1,3 +1,40 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- new [_, hello!]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [_, hello!]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    4:string <- [abc, hello!]
+    16 <- 0  # out of bounds
+  ", value: 0, type: 0, properties: ["
+    4:string <- [abc, hello!]
+    16 <- 0  # out of bounds
+  ": "literal-string"]}
+after-brace/0: recipe interpolate-at-start
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: interpolate-at-start
+run/0: instruction interpolate-at-start/0
+run/0: run {name: "
+    1:address:array:character/raw <- new [_, hello!]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [_, hello!]
+    2:address:array:character/raw <- new [abc]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "_, hello!", value: 0, type: 0, properties: ["_, hello!": "literal-string"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
@@ -13,20 +50,18 @@ parse/0:   ingredient: {name: "3", value: 0, type: 2-5-4, properties: ["3": "add
 parse/0:   product: {name: "4", value: 0, type: 5-4, properties: ["4": "array":"character", "raw": ]}
 new/0: _, hello! -> 0
 new/0: abc -> 0
-after-brace/0: recipe test-interpolate-at-start
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: interpolate ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-interpolate-at-start
-run/0: instruction test-interpolate-at-start/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- new {name: "_, hello!", value: 0, type: 0, properties: ["_, hello!": "literal-string"]}
 mem/0: storing 1000 in location 1
-run/0: instruction test-interpolate-at-start/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1010 in location 2
-run/0: instruction test-interpolate-at-start/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": ]} <- interpolate {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}, {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]}
 mem/0: location 1 is 1000
 mem/0: location 2 is 1010
@@ -839,7 +874,7 @@ run/0: reply {name: "result", value: 7, type: 2-5-4, properties: ["result": "add
 mem/0: location 1022 is 1075
 run/0: result 0 is 1075
 mem/0: storing 1075 in location 3
-run/0: instruction test-interpolate-at-start/3
+run/0: instruction tmp0/3
 run/0: {name: "4", value: 4, type: 5-4, properties: ["4": "array":"character", "raw": ]} <- copy {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": , "deref": ]}
 run/0: ingredient 0 is 3
 mem/0: location 3 is 1075
@@ -867,3 +902,24 @@ mem/0: storing 108 in location 12
 mem/0: storing 108 in location 13
 mem/0: storing 111 in location 14
 mem/0: storing 33 in location 15
+run/0: instruction interpolate-at-start/1
+run/0: memory-should-contain {name: "
+    4:string <- [abc, hello!]
+    16 <- 0  # out of bounds
+  ", value: 0, type: 0, properties: ["
+    4:string <- [abc, hello!]
+    16 <- 0  # out of bounds
+  ": "literal-string"]}
+run/0: checking array length at 4
+run/0: checking location 5
+run/0: checking location 6
+run/0: checking location 7
+run/0: checking location 8
+run/0: checking location 9
+run/0: checking location 10
+run/0: checking location 11
+run/0: checking location 12
+run/0: checking location 13
+run/0: checking location 14
+run/0: checking location 15
+run/0: checking location 16
diff --git a/cpp/.traces/interpolate-works b/cpp/.traces/interpolate-works
index c093cc14..265b48b3 100644
--- a/cpp/.traces/interpolate-works
+++ b/cpp/.traces/interpolate-works
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- new [abc _]
+    2:address:array:character/raw <- new [def]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [abc _]
+    2:address:array:character/raw <- new [def]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    4:string <- [abc def]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [abc def]
+  ": "literal-string"]}
+after-brace/0: recipe interpolate-works
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: interpolate-works
+run/0: instruction interpolate-works/0
+run/0: run {name: "
+    1:address:array:character/raw <- new [abc _]
+    2:address:array:character/raw <- new [def]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [abc _]
+    2:address:array:character/raw <- new [def]
+    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "abc _", value: 0, type: 0, properties: ["abc _": "literal-string"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
@@ -13,20 +48,18 @@ parse/0:   ingredient: {name: "3", value: 0, type: 2-5-4, properties: ["3": "add
 parse/0:   product: {name: "4", value: 0, type: 5-4, properties: ["4": "array":"character", "raw": ]}
 new/0: abc _ -> 0
 new/0: def -> 0
-after-brace/0: recipe test-interpolate-works
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: interpolate ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-interpolate-works
-run/0: instruction test-interpolate-works/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- new {name: "abc _", value: 0, type: 0, properties: ["abc _": "literal-string"]}
 mem/0: storing 1000 in location 1
-run/0: instruction test-interpolate-works/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]} <- new {name: "def", value: 0, type: 0, properties: ["def": "literal-string"]}
 mem/0: storing 1006 in location 2
-run/0: instruction test-interpolate-works/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": ]} <- interpolate {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}, {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]}
 mem/0: location 1 is 1000
 mem/0: location 2 is 1006
@@ -659,7 +692,7 @@ run/0: reply {name: "result", value: 7, type: 2-5-4, properties: ["result": "add
 mem/0: location 1018 is 1071
 run/0: result 0 is 1071
 mem/0: storing 1071 in location 3
-run/0: instruction test-interpolate-works/3
+run/0: instruction tmp0/3
 run/0: {name: "4", value: 4, type: 5-4, properties: ["4": "array":"character", "raw": ]} <- copy {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": , "deref": ]}
 run/0: ingredient 0 is 3
 mem/0: location 3 is 1071
@@ -679,3 +712,17 @@ mem/0: storing 32 in location 8
 mem/0: storing 100 in location 9
 mem/0: storing 101 in location 10
 mem/0: storing 102 in location 11
+run/0: instruction interpolate-works/1
+run/0: memory-should-contain {name: "
+    4:string <- [abc def]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [abc def]
+  ": "literal-string"]}
+run/0: checking array length at 4
+run/0: checking location 5
+run/0: checking location 6
+run/0: checking location 7
+run/0: checking location 8
+run/0: checking location 9
+run/0: checking location 10
+run/0: checking location 11
diff --git a/cpp/.traces/jump b/cpp/.traces/jump
deleted file mode 100644
index e1c0f664..00000000
--- a/cpp/.traces/jump
+++ /dev/null
@@ -1,7 +0,0 @@
-parse/0: instruction: 10
-parse/0:   ingredient: {name: "1", type: 0}
-parse/0: instruction: 1
-parse/0:   ingredient: {name: "1", type: 0}
-parse/0:   product: {name: "1", type: 1}
-run/0: instruction 0
-run/0: ingredient 0 is 1
diff --git a/cpp/.traces/parse_scenario_memory_expectation b/cpp/.traces/parse_scenario_memory_expectation
deleted file mode 100644
index ad2621ec..00000000
--- a/cpp/.traces/parse_scenario_memory_expectation
+++ /dev/null
@@ -1,3 +0,0 @@
-parse/0: reading scenario foo
-parse/0: scenario will run: a <- b
-parse/0: memory expectation: *1 == 0
diff --git a/cpp/.traces/parse_scenario_memory_expectation_duplicate b/cpp/.traces/parse_scenario_memory_expectation_duplicate
deleted file mode 100644
index b167144e..00000000
--- a/cpp/.traces/parse_scenario_memory_expectation_duplicate
+++ /dev/null
@@ -1,5 +0,0 @@
-parse/0: reading scenario foo
-parse/0: scenario will run: a <- b
-parse/0: memory expectation: *1 == 0
-warn/0: duplicate expectation for location 1: 0 -> 1
-parse/0: memory expectation: *1 == 1
diff --git a/cpp/.traces/print-character-at-top-left b/cpp/.traces/print-character-at-top-left
index 65bf6f98..f8ae92ce 100644
--- a/cpp/.traces/print-character-at-top-left
+++ b/cpp/.traces/print-character-at-top-left
@@ -1,3 +1,46 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 6  # width*height
+    4 <- 97  # 'a'
+    5 <- 0
+  ", value: 0, type: 0, properties: ["
+    3 <- 6  # width*height
+    4 <- 97  # 'a'
+    5 <- 0
+  ": "literal-string"]}
+after-brace/0: recipe print-character-at-top-left
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: print-character-at-top-left
+run/0: instruction print-character-at-top-left/0
+run/0: run {name: "
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ", value: 0, type: 0, properties: ["
+#?     $start-tracing #? 3
+    1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height
+    1:address:screen <- print-character 1:address:screen, 97:literal  # 'a'
+    2:address:array:character <- get 1:address:screen/deref, data:offset
+    3:array:character <- copy 2:address:array:character/deref
+  ": "literal-string"]}
 parse/0: instruction: init-fake-screen
 parse/0:   ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal", "width": ]}
 parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal", "height": ]}
@@ -14,14 +57,12 @@ parse/0: instruction: copy
 parse/0:   ingredient: {name: "2", value: 0, type: 2-5-4, properties: ["2": "address":"array":"character", "deref": ]}
 parse/0:   product: {name: "3", value: 0, type: 5-4, properties: ["3": "array":"character"]}
 name/0: element data of type screen is at offset 4
-after-brace/0: recipe test-print-character-at-top-left
+after-brace/0: recipe tmp0
 after-brace/0: init-fake-screen ...
 after-brace/0: print-character ...
 after-brace/0: get ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-print-character-at-top-left
-run/0: instruction test-print-character-at-top-left/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- init-fake-screen {name: "3", value: 3, type: 0, properties: ["3": "literal", "width": ]}, {name: "2", value: 2, type: 0, properties: ["2": "literal", "height": ]}
 run/0: instruction init-fake-screen/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal", "capacity": ]}
@@ -393,7 +434,7 @@ run/0: reply {name: "result", value: 1, type: 2-11, properties: ["result": "addr
 mem/0: location 1002 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-print-character-at-top-left/1
+run/0: instruction tmp0/1
 run/0: {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]} <- print-character {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen"]}, {name: "97", value: 97, type: 0, properties: ["97": "literal"]}
 mem/0: location 1 is 1031
 run/0: instruction print-character/0
@@ -511,7 +552,7 @@ run/0: reply {name: "x", value: 1, type: 2-11, properties: ["x": "address":"scre
 mem/0: location 1076 is 1031
 run/0: result 0 is 1031
 mem/0: storing 1031 in location 1
-run/0: instruction test-print-character-at-top-left/2
+run/0: instruction tmp0/2
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character"]} <- get {name: "1", value: 1, type: 2-11, properties: ["1": "address":"screen", "deref": ]}, {name: "data", value: 4, type: 0, properties: ["data": "offset"]}
 run/0: ingredient 0 is 1
 mem/0: location 1 is 1031
@@ -521,7 +562,7 @@ run/0: its type is 2
 mem/0: location 1035 is 1036
 run/0: product 0 is 1036
 mem/0: storing 1036 in location 2
-run/0: instruction test-print-character-at-top-left/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 5-4, properties: ["3": "array":"character"]} <- copy {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "deref": ]}
 run/0: ingredient 0 is 2
 mem/0: location 2 is 1036
@@ -539,3 +580,16 @@ mem/0: storing 0 in location 6
 mem/0: storing 0 in location 7
 mem/0: storing 0 in location 8
 mem/0: storing 0 in location 9
+run/0: instruction print-character-at-top-left/1
+run/0: memory-should-contain {name: "
+    3 <- 6  # width*height
+    4 <- 97  # 'a'
+    5 <- 0
+  ", value: 0, type: 0, properties: ["
+    3 <- 6  # width*height
+    4 <- 97  # 'a'
+    5 <- 0
+  ": "literal-string"]}
+run/0: checking location 3
+run/0: checking location 4
+run/0: checking location 5
diff --git a/cpp/.traces/run_handles_comments b/cpp/.traces/scenario_block
index 7043fa31..9f5870a2 100644
--- a/cpp/.traces/run_handles_comments
+++ b/cpp/.traces/scenario_block
@@ -1,21 +1,24 @@
 parse/0: instruction: run
 parse/0:   ingredient: {name: "
-    # comment
     1:integer <- copy 13:literal
   ", value: 0, type: 0, properties: ["
-    # comment
     1:integer <- copy 13:literal
   ": "literal-string"]}
-after-brace/0: recipe main
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+after-brace/0: recipe foo
 after-brace/0: run ...
+after-brace/0: memory-should-contain ...
 new/0: routine allocated memory from 1000 to 101000
-schedule/0: main
-run/0: instruction main/0
+schedule/0: foo
+run/0: instruction foo/0
 run/0: run {name: "
-    # comment
     1:integer <- copy 13:literal
   ", value: 0, type: 0, properties: ["
-    # comment
     1:integer <- copy 13:literal
   ": "literal-string"]}
 parse/0: instruction: copy
@@ -27,3 +30,10 @@ run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- copy {name: "13", value: 13, type: 0, properties: ["13": "literal"]}
 run/0: ingredient 0 is 13
 mem/0: storing 13 in location 1
+run/0: instruction foo/1
+run/0: memory-should-contain {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+run/0: checking location 1
diff --git a/cpp/.traces/scenario_check_memory_and_trace b/cpp/.traces/scenario_check_memory_and_trace
new file mode 100644
index 00000000..7803bb73
--- /dev/null
+++ b/cpp/.traces/scenario_check_memory_and_trace
@@ -0,0 +1,76 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    a: a b c
+  ", value: 0, type: 0, properties: ["
+    a: a b c
+  ": "literal-string"]}
+parse/0: instruction: trace-should-not-contain
+parse/0:   ingredient: {name: "
+    a: x y z
+  ", value: 0, type: 0, properties: ["
+    a: x y z
+  ": "literal-string"]}
+after-brace/0: recipe foo
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+after-brace/0: trace-should-contain ...
+after-brace/0: trace-should-not-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: foo
+run/0: instruction foo/0
+run/0: run {name: "
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
+  ": "literal-string"]}
+parse/0: instruction: copy
+parse/0:   ingredient: {name: "13", value: 0, type: 0, properties: ["13": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+parse/0: instruction: trace
+parse/0:   ingredient: {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}
+parse/0:   ingredient: {name: "a b c", value: 0, type: 0, properties: ["a b c": "literal-string"]}
+after-brace/0: recipe tmp0
+after-brace/0: copy ...
+after-brace/0: trace ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- copy {name: "13", value: 13, type: 0, properties: ["13": "literal"]}
+run/0: ingredient 0 is 13
+mem/0: storing 13 in location 1
+run/0: instruction tmp0/1
+run/0: trace {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}, {name: "a b c", value: 0, type: 0, properties: ["a b c": "literal-string"]}
+a/0: a b c
+run/0: instruction foo/1
+run/0: memory-should-contain {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+run/0: checking location 1
+run/0: instruction foo/2
+run/0: trace-should-contain {name: "
+    a: a b c
+  ", value: 0, type: 0, properties: ["
+    a: a b c
+  ": "literal-string"]}
+run/0: instruction foo/3
+run/0: trace-should-not-contain {name: "
+    a: x y z
+  ", value: 0, type: 0, properties: ["
+    a: x y z
+  ": "literal-string"]}
diff --git a/cpp/.traces/scenario_multiple_blocks b/cpp/.traces/scenario_multiple_blocks
new file mode 100644
index 00000000..c5f8946a
--- /dev/null
+++ b/cpp/.traces/scenario_multiple_blocks
@@ -0,0 +1,80 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:integer <- copy 13:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 13:literal
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    2:integer <- copy 13:literal
+  ", value: 0, type: 0, properties: ["
+    2:integer <- copy 13:literal
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 13
+    2 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+    2 <- 13
+  ": "literal-string"]}
+after-brace/0: recipe foo
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: foo
+run/0: instruction foo/0
+run/0: run {name: "
+    1:integer <- copy 13:literal
+  ", value: 0, type: 0, properties: ["
+    1:integer <- copy 13:literal
+  ": "literal-string"]}
+parse/0: instruction: copy
+parse/0:   ingredient: {name: "13", value: 0, type: 0, properties: ["13": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe tmp0
+after-brace/0: copy ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- copy {name: "13", value: 13, type: 0, properties: ["13": "literal"]}
+run/0: ingredient 0 is 13
+mem/0: storing 13 in location 1
+run/0: instruction foo/1
+run/0: memory-should-contain {name: "
+    1 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+  ": "literal-string"]}
+run/0: checking location 1
+run/0: instruction foo/2
+run/0: run {name: "
+    2:integer <- copy 13:literal
+  ", value: 0, type: 0, properties: ["
+    2:integer <- copy 13:literal
+  ": "literal-string"]}
+parse/0: instruction: copy
+parse/0:   ingredient: {name: "13", value: 0, type: 0, properties: ["13": "literal"]}
+parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
+after-brace/0: recipe tmp1
+after-brace/0: copy ...
+run/0: instruction tmp1/0
+run/0: {name: "2", value: 2, type: 1, properties: ["2": "integer"]} <- copy {name: "13", value: 13, type: 0, properties: ["13": "literal"]}
+run/0: ingredient 0 is 13
+mem/0: storing 13 in location 2
+run/0: instruction foo/3
+run/0: memory-should-contain {name: "
+    1 <- 13
+    2 <- 13
+  ", value: 0, type: 0, properties: ["
+    1 <- 13
+    2 <- 13
+  ": "literal-string"]}
+run/0: checking location 1
+run/0: checking location 2
diff --git a/cpp/.traces/scenario_trace_block b/cpp/.traces/scenario_trace_block
deleted file mode 100644
index 8729af2c..00000000
--- a/cpp/.traces/scenario_trace_block
+++ /dev/null
@@ -1,4 +0,0 @@
-parse/0: reading scenario foo
-scenario/0: +bar: baz
-scenario/0: +bar: floo
-scenario/0: -bar: abc
diff --git a/cpp/.traces/scenario_with_comment_in_mu b/cpp/.traces/scenario_with_comment_in_mu
new file mode 100644
index 00000000..29e72e98
--- /dev/null
+++ b/cpp/.traces/scenario_with_comment_in_mu
@@ -0,0 +1,46 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    # comment
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    # comment
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+after-brace/0: recipe scenario_with_comment_in_mu
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: scenario_with_comment_in_mu
+run/0: instruction scenario_with_comment_in_mu/0
+run/0: run {name: "
+    # comment
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    # comment
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: add
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe tmp0
+after-brace/0: add ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
+run/0: instruction scenario_with_comment_in_mu/1
+run/0: memory-should-contain {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+run/0: checking location 1
diff --git a/cpp/.traces/scenario_with_multiple_comments_in_mu b/cpp/.traces/scenario_with_multiple_comments_in_mu
new file mode 100644
index 00000000..941ad837
--- /dev/null
+++ b/cpp/.traces/scenario_with_multiple_comments_in_mu
@@ -0,0 +1,50 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    # comment1
+    # comment2
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    # comment1
+    # comment2
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+after-brace/0: recipe scenario_with_multiple_comments_in_mu
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: scenario_with_multiple_comments_in_mu
+run/0: instruction scenario_with_multiple_comments_in_mu/0
+run/0: run {name: "
+    # comment1
+    # comment2
+    1:integer <- add 2:literal, 2:literal
+  ", value: 0, type: 0, properties: ["
+    # comment1
+    # comment2
+    1:integer <- add 2:literal, 2:literal
+  ": "literal-string"]}
+parse/0: instruction: add
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe tmp0
+after-brace/0: add ...
+run/0: instruction tmp0/0
+run/0: {name: "1", value: 1, type: 1, properties: ["1": "integer"]} <- add {name: "2", value: 2, type: 0, properties: ["2": "literal"]}, {name: "2", value: 2, type: 0, properties: ["2": "literal"]}
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
+run/0: instruction scenario_with_multiple_comments_in_mu/1
+run/0: memory-should-contain {name: "
+    1 <- 4
+  ", value: 0, type: 0, properties: ["
+    1 <- 4
+  ": "literal-string"]}
+run/0: checking location 1
diff --git a/cpp/.traces/string-append-1 b/cpp/.traces/string-append-1
index 16645ab7..b05fbe2c 100644
--- a/cpp/.traces/string-append-1
+++ b/cpp/.traces/string-append-1
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    1:address:array:character/raw <- new [hello,]
+    2:address:array:character/raw <- new [ world!]
+    3:address:array:character/raw <- string-append 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [hello,]
+    2:address:array:character/raw <- new [ world!]
+    3:address:array:character/raw <- string-append 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    4:string <- [hello, world!]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [hello, world!]
+  ": "literal-string"]}
+after-brace/0: recipe string-append-1
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-append-1
+run/0: instruction string-append-1/0
+run/0: run {name: "
+    1:address:array:character/raw <- new [hello,]
+    2:address:array:character/raw <- new [ world!]
+    3:address:array:character/raw <- string-append 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ", value: 0, type: 0, properties: ["
+    1:address:array:character/raw <- new [hello,]
+    2:address:array:character/raw <- new [ world!]
+    3:address:array:character/raw <- string-append 1:address:array:character/raw, 2:address:array:character/raw
+    4:array:character/raw <- copy 3:address:array:character/raw/deref
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "hello,", value: 0, type: 0, properties: ["hello,": "literal-string"]}
 parse/0:   product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}
@@ -13,20 +48,18 @@ parse/0:   ingredient: {name: "3", value: 0, type: 2-5-4, properties: ["3": "add
 parse/0:   product: {name: "4", value: 0, type: 5-4, properties: ["4": "array":"character", "raw": ]}
 new/0: hello, -> 0
 new/0:  world! -> 0
-after-brace/0: recipe test-string-append-1
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-append ...
 after-brace/0: copy ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-append-1
-run/0: instruction test-string-append-1/0
+run/0: instruction tmp0/0
 run/0: {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]} <- new {name: "hello,", value: 0, type: 0, properties: ["hello,": "literal-string"]}
 mem/0: storing 1000 in location 1
-run/0: instruction test-string-append-1/1
+run/0: instruction tmp0/1
 run/0: {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]} <- new {name: " world!", value: 0, type: 0, properties: [" world!": "literal-string"]}
 mem/0: storing 1007 in location 2
-run/0: instruction test-string-append-1/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": ]} <- string-append {name: "1", value: 1, type: 2-5-4, properties: ["1": "address":"array":"character", "raw": ]}, {name: "2", value: 2, type: 2-5-4, properties: ["2": "address":"array":"character", "raw": ]}
 mem/0: location 1 is 1000
 mem/0: location 2 is 1007
@@ -850,7 +883,7 @@ run/0: reply {name: "result", value: 6, type: 2-5-4, properties: ["result": "add
 mem/0: location 1022 is 1046
 run/0: result 0 is 1046
 mem/0: storing 1046 in location 3
-run/0: instruction test-string-append-1/3
+run/0: instruction tmp0/3
 run/0: {name: "4", value: 4, type: 5-4, properties: ["4": "array":"character", "raw": ]} <- copy {name: "3", value: 3, type: 2-5-4, properties: ["3": "address":"array":"character", "raw": , "deref": ]}
 run/0: ingredient 0 is 3
 mem/0: location 3 is 1046
@@ -882,3 +915,23 @@ mem/0: storing 114 in location 14
 mem/0: storing 108 in location 15
 mem/0: storing 100 in location 16
 mem/0: storing 33 in location 17
+run/0: instruction string-append-1/1
+run/0: memory-should-contain {name: "
+    4:string <- [hello, world!]
+  ", value: 0, type: 0, properties: ["
+    4:string <- [hello, world!]
+  ": "literal-string"]}
+run/0: checking array length at 4
+run/0: checking location 5
+run/0: checking location 6
+run/0: checking location 7
+run/0: checking location 8
+run/0: checking location 9
+run/0: checking location 10
+run/0: checking location 11
+run/0: checking location 12
+run/0: checking location 13
+run/0: checking location 14
+run/0: checking location 15
+run/0: checking location 16
+run/0: checking location 17
diff --git a/cpp/.traces/string-equal-common-lengths-but-distinct b/cpp/.traces/string-equal-common-lengths-but-distinct
index 82244da9..96313dbb 100644
--- a/cpp/.traces/string-equal-common-lengths-but-distinct
+++ b/cpp/.traces/string-equal-common-lengths-but-distinct
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 0  # abc != abd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # abc != abd
+  ": "literal-string"]}
+after-brace/0: recipe string-equal-common-lengths-but-distinct
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-equal-common-lengths-but-distinct
+run/0: instruction string-equal-common-lengths-but-distinct/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -17,24 +52,22 @@ new/0: abc -> 0
 name/0: assign x 1
 new/0: abd -> 0
 name/0: assign y 2
-after-brace/0: recipe test-string-equal-common-lengths-but-distinct
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-equal ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-equal-common-lengths-but-distinct
-run/0: instruction test-string-equal-common-lengths-but-distinct/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-string-equal-common-lengths-but-distinct/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1031 in location 1002
-run/0: instruction test-string-equal-common-lengths-but-distinct/2
+run/0: instruction tmp0/2
 run/0: {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]} <- new {name: "abd", value: 0, type: 0, properties: ["abd": "literal-string"]}
 mem/0: storing 1035 in location 1003
-run/0: instruction test-string-equal-common-lengths-but-distinct/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 3, properties: ["3": "boolean", "raw": ]} <- string-equal {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}, {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]}
 mem/0: location 1002 is 1031
 mem/0: location 1003 is 1035
@@ -254,3 +287,10 @@ run/0: instruction string-equal/21
 run/0: reply {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction string-equal-common-lengths-but-distinct/1
+run/0: memory-should-contain {name: "
+    3 <- 0  # abc != abd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # abc != abd
+  ": "literal-string"]}
+run/0: checking location 3
diff --git a/cpp/.traces/string-equal-distinct-lengths b/cpp/.traces/string-equal-distinct-lengths
index 72ff3a0c..87501fe9 100644
--- a/cpp/.traces/string-equal-distinct-lengths
+++ b/cpp/.traces/string-equal-distinct-lengths
@@ -1,3 +1,52 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 0  # abc != abcd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # abc != abcd
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    string-equal: comparing lengths
+  ", value: 0, type: 0, properties: ["
+    string-equal: comparing lengths
+  ": "literal-string"]}
+parse/0: instruction: trace-should-not-contain
+parse/0:   ingredient: {name: "
+    string-equal: comparing characters
+  ", value: 0, type: 0, properties: ["
+    string-equal: comparing characters
+  ": "literal-string"]}
+after-brace/0: recipe string-equal-distinct-lengths
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+after-brace/0: trace-should-contain ...
+after-brace/0: trace-should-not-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-equal-distinct-lengths
+run/0: instruction string-equal-distinct-lengths/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -17,24 +66,22 @@ new/0: abc -> 0
 name/0: assign x 1
 new/0: abcd -> 0
 name/0: assign y 2
-after-brace/0: recipe test-string-equal-distinct-lengths
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-equal ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-equal-distinct-lengths
-run/0: instruction test-string-equal-distinct-lengths/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-string-equal-distinct-lengths/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1031 in location 1002
-run/0: instruction test-string-equal-distinct-lengths/2
+run/0: instruction tmp0/2
 run/0: {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]} <- new {name: "abcd", value: 0, type: 0, properties: ["abcd": "literal-string"]}
 mem/0: storing 1035 in location 1003
-run/0: instruction test-string-equal-distinct-lengths/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 3, properties: ["3": "boolean", "raw": ]} <- string-equal {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}, {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]}
 mem/0: location 1002 is 1031
 mem/0: location 1003 is 1035
@@ -78,3 +125,22 @@ run/0: instruction string-equal/9
 run/0: reply {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction string-equal-distinct-lengths/1
+run/0: memory-should-contain {name: "
+    3 <- 0  # abc != abcd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # abc != abcd
+  ": "literal-string"]}
+run/0: checking location 3
+run/0: instruction string-equal-distinct-lengths/2
+run/0: trace-should-contain {name: "
+    string-equal: comparing lengths
+  ", value: 0, type: 0, properties: ["
+    string-equal: comparing lengths
+  ": "literal-string"]}
+run/0: instruction string-equal-distinct-lengths/3
+run/0: trace-should-not-contain {name: "
+    string-equal: comparing characters
+  ", value: 0, type: 0, properties: ["
+    string-equal: comparing characters
+  ": "literal-string"]}
diff --git a/cpp/.traces/string-equal-identical b/cpp/.traces/string-equal-identical
index 57f3afa8..80de07e8 100644
--- a/cpp/.traces/string-equal-identical
+++ b/cpp/.traces/string-equal-identical
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 1  # abc == abc
+  ", value: 0, type: 0, properties: ["
+    3 <- 1  # abc == abc
+  ": "literal-string"]}
+after-brace/0: recipe string-equal-identical
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-equal-identical
+run/0: instruction string-equal-identical/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    y:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -17,24 +52,22 @@ new/0: abc -> 0
 name/0: assign x 1
 new/0: abc -> 0
 name/0: assign y 2
-after-brace/0: recipe test-string-equal-identical
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-equal ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-equal-identical
-run/0: instruction test-string-equal-identical/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-string-equal-identical/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1031 in location 1002
-run/0: instruction test-string-equal-identical/2
+run/0: instruction tmp0/2
 run/0: {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1035 in location 1003
-run/0: instruction test-string-equal-identical/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 3, properties: ["3": "boolean", "raw": ]} <- string-equal {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}, {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]}
 mem/0: location 1002 is 1031
 mem/0: location 1003 is 1035
@@ -280,3 +313,10 @@ run/0: instruction string-equal/26
 run/0: reply {name: "1", value: 1, type: 0, properties: ["1": "literal"]}
 run/0: result 0 is 1
 mem/0: storing 1 in location 3
+run/0: instruction string-equal-identical/1
+run/0: memory-should-contain {name: "
+    3 <- 1  # abc == abc
+  ", value: 0, type: 0, properties: ["
+    3 <- 1  # abc == abc
+  ": "literal-string"]}
+run/0: checking location 3
diff --git a/cpp/.traces/string-equal-reflexive b/cpp/.traces/string-equal-reflexive
index b13664f2..efb93b6a 100644
--- a/cpp/.traces/string-equal-reflexive
+++ b/cpp/.traces/string-equal-reflexive
@@ -1,3 +1,34 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, x:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, x:address:array:character
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 1  # x == x for all x
+  ", value: 0, type: 0, properties: ["
+    3 <- 1  # x == x for all x
+  ": "literal-string"]}
+after-brace/0: recipe string-equal-reflexive
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-equal-reflexive
+run/0: instruction string-equal-reflexive/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, x:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new [abc]
+    3:boolean/raw <- string-equal x:address:array:character, x:address:array:character
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -12,20 +43,18 @@ parse/0:   product: {name: "3", value: 0, type: 3, properties: ["3": "boolean",
 new/0: location -> 1
 new/0: abc -> 0
 name/0: assign x 1
-after-brace/0: recipe test-string-equal-reflexive
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-equal ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-equal-reflexive
-run/0: instruction test-string-equal-reflexive/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-string-equal-reflexive/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]} <- new {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}
 mem/0: storing 1031 in location 1002
-run/0: instruction test-string-equal-reflexive/2
+run/0: instruction tmp0/2
 run/0: {name: "3", value: 3, type: 3, properties: ["3": "boolean", "raw": ]} <- string-equal {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}, {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}
 mem/0: location 1002 is 1031
 mem/0: location 1002 is 1031
@@ -271,3 +300,10 @@ run/0: instruction string-equal/26
 run/0: reply {name: "1", value: 1, type: 0, properties: ["1": "literal"]}
 run/0: result 0 is 1
 mem/0: storing 1 in location 3
+run/0: instruction string-equal-reflexive/1
+run/0: memory-should-contain {name: "
+    3 <- 1  # x == x for all x
+  ", value: 0, type: 0, properties: ["
+    3 <- 1  # x == x for all x
+  ": "literal-string"]}
+run/0: checking location 3
diff --git a/cpp/.traces/string-equal-with-empty b/cpp/.traces/string-equal-with-empty
index ff241a4c..6d867557 100644
--- a/cpp/.traces/string-equal-with-empty
+++ b/cpp/.traces/string-equal-with-empty
@@ -1,3 +1,38 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new []
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new []
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
+parse/0: instruction: memory-should-contain
+parse/0:   ingredient: {name: "
+    3 <- 0  # "" != abcd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # "" != abcd
+  ": "literal-string"]}
+after-brace/0: recipe string-equal-with-empty
+after-brace/0: run ...
+after-brace/0: memory-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: string-equal-with-empty
+run/0: instruction string-equal-with-empty/0
+run/0: run {name: "
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new []
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ", value: 0, type: 0, properties: ["
+    default-space:address:array:location <- new location:type, 30:literal
+    x:address:array:character <- new []
+    y:address:array:character <- new [abcd]
+    3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
+  ": "literal-string"]}
 parse/0: instruction: new
 parse/0:   ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]}
 parse/0:   ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]}
@@ -17,24 +52,22 @@ new/0:  -> 0
 name/0: assign x 1
 new/0: abcd -> 0
 name/0: assign y 2
-after-brace/0: recipe test-string-equal-with-empty
+after-brace/0: recipe tmp0
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: new ...
 after-brace/0: string-equal ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-string-equal-with-empty
-run/0: instruction test-string-equal-with-empty/0
+run/0: instruction tmp0/0
 run/0: {name: "default-space", value: 0, type: 2-5-1, properties: ["default-space": "address":"array":"location"]} <- new {name: "location", value: 1, type: 0, properties: ["location": "type"]}, {name: "30", value: 30, type: 0, properties: ["30": "literal"]}
 mem/0: array size is 30
 mem/0: new alloc: 1000
-run/0: instruction test-string-equal-with-empty/1
+run/0: instruction tmp0/1
 run/0: {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]} <- new {name: "", value: 0, type: 0, properties: ["": "literal-string"]}
 mem/0: storing 1031 in location 1002
-run/0: instruction test-string-equal-with-empty/2
+run/0: instruction tmp0/2
 run/0: {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]} <- new {name: "abcd", value: 0, type: 0, properties: ["abcd": "literal-string"]}
 mem/0: storing 1032 in location 1003
-run/0: instruction test-string-equal-with-empty/3
+run/0: instruction tmp0/3
 run/0: {name: "3", value: 3, type: 3, properties: ["3": "boolean", "raw": ]} <- string-equal {name: "x", value: 1, type: 2-5-4, properties: ["x": "address":"array":"character"]}, {name: "y", value: 2, type: 2-5-4, properties: ["y": "address":"array":"character"]}
 mem/0: location 1002 is 1031
 mem/0: location 1003 is 1032
@@ -78,3 +111,10 @@ run/0: instruction string-equal/9
 run/0: reply {name: "0", value: 0, type: 0, properties: ["0": "literal"]}
 run/0: result 0 is 0
 mem/0: storing 0 in location 3
+run/0: instruction string-equal-with-empty/1
+run/0: memory-should-contain {name: "
+    3 <- 0  # "" != abcd
+  ", value: 0, type: 0, properties: ["
+    3 <- 0  # "" != abcd
+  ": "literal-string"]}
+run/0: checking location 3
diff --git a/cpp/.traces/trace_in_mu b/cpp/.traces/trace_in_mu
deleted file mode 100644
index 468f0880..00000000
--- a/cpp/.traces/trace_in_mu
+++ /dev/null
@@ -1,10 +0,0 @@
-parse/0: instruction: trace
-parse/0:   ingredient: {name: "foo", value: 0, type: 0, properties: ["foo": "literal-string"]}
-parse/0:   ingredient: {name: "aaa", value: 0, type: 0, properties: ["aaa": "literal-string"]}
-after-brace/0: recipe test-trace_in_mu
-after-brace/0: trace ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: test-trace_in_mu
-run/0: instruction test-trace_in_mu/0
-run/0: trace {name: "foo", value: 0, type: 0, properties: ["foo": "literal-string"]}, {name: "aaa", value: 0, type: 0, properties: ["aaa": "literal-string"]}
-foo/0: aaa
diff --git a/cpp/.traces/trace_should_contain b/cpp/.traces/trace_should_contain
deleted file mode 100644
index 471d332e..00000000
--- a/cpp/.traces/trace_should_contain
+++ /dev/null
@@ -1,17 +0,0 @@
-parse/0: instruction: trace-should-contain
-parse/0:   ingredient: {name: "
-    a: b
-  ", value: 0, type: 0, properties: ["
-    a: b
-  ": "literal-string"]}
-after-brace/0: recipe main
-after-brace/0: trace-should-contain ...
-new/0: routine allocated memory from 1000 to 101000
-schedule/0: main
-run/0: instruction main/0
-run/0: trace-should-contain {name: "
-    a: b
-  ", value: 0, type: 0, properties: ["
-    a: b
-  ": "literal-string"]}
-warn/0: undefined operation 1001: trace-should-contain
diff --git a/cpp/049scenario_helpers.cc b/cpp/049scenario_helpers.cc
index fa584565..d5b755f2 100644
--- a/cpp/049scenario_helpers.cc
+++ b/cpp/049scenario_helpers.cc
@@ -12,15 +12,6 @@ recipe main [
 ]
 +mem: storing 13 in location 1
 
-:(scenario run_handles_comments)
-recipe main [
-  run [
-    # comment
-    1:integer <- copy 13:literal
-  ]
-]
-+mem: storing 13 in location 1
-
 :(before "End Globals")
 size_t Num_temporary_recipes = 0;
 :(before "End Setup")
@@ -208,6 +199,7 @@ bool check_trace(const string& expected) {
 
   raise << "missing [" << expected_lines[curr_expected_line].second << "] "
         << "in trace layer " << expected_lines[curr_expected_line].first << '\n';
+  Passed = false;
   return false;
 }
 
@@ -293,6 +285,7 @@ bool check_trace_missing(const string& in) {
   for (size_t i = 0; i < lines.size(); ++i) {
     if (trace_count(lines[i].first, lines[i].second) != 0) {
       raise << "unexpected [" << lines[i].second << "] in trace layer " << lines[i].first << '\n';
+      Passed = false;
       return false;
     }
   }
diff --git a/cpp/050scenario.cc b/cpp/050scenario.cc
index 5dbc940a..dc839a10 100644
--- a/cpp/050scenario.cc
+++ b/cpp/050scenario.cc
@@ -4,10 +4,7 @@
 :(before "End Types")
 struct scenario {
   string name;
-  string dump_layer;
   string to_run;
-  map<int, int> memory_expectations;
-  // End scenario Fields
 };
 
 :(before "End Globals")
@@ -15,178 +12,111 @@ vector<scenario> Scenarios;
 
 //:: How we check Scenarios.
 
-:(before "End Tests")
-time_t mu_time; time(&mu_time);
-cerr << "\nMu tests: " << ctime(&mu_time);
-for (size_t i = 0; i < Scenarios.size(); ++i) {
-  run_mu_test(i);
-}
-
-:(code)
-void run_mu_test(size_t i) {
-  setup();
-  Trace_file = Scenarios[i].name;
-  START_TRACING_UNTIL_END_OF_SCOPE
-  if (!Scenarios[i].dump_layer.empty())
-    Trace_stream->dump_layer = Scenarios[i].dump_layer;
-//?   cerr << "AAA " << Scenarios[i].name << '\n'; //? 1
-//?   cout << Scenarios[i].to_run; //? 2
-  run(Scenarios[i].to_run);
-//?   cout << "after: " << Memory[1] << '\n'; //? 1
-//?   cout << "after:\n";  dump_memory(); //? 1
-  for (map<int, int>::iterator p = Scenarios[i].memory_expectations.begin();
-       p != Scenarios[i].memory_expectations.end();
-       ++p) {
-    if (Memory[p->first] != p->second) {
-      // todo: unit tests for the test parsing infrastructure; use raise?
-      cerr << Scenarios[i].name << ": Expected location " << p->first << " to contain " << p->second << " but saw " << Memory[p->first] << '\n';
-      Passed = false;
-    }
-  }
-  // End Scenario Checks
-  teardown();
-  if (Passed) cerr << ".";
-}
-
-//:: How we create Scenarios.
+:(scenarios run_mu_scenario)
+:(scenario scenario_block)
+scenario foo [
+  run [
+    1:integer <- copy 13:literal
+  ]
+  memory-should-contain [
+    1 <- 13
+  ]
+]
+# checks are inside scenario
 
-:(scenarios "parse_scenario")
-:(scenario parse_scenario_memory_expectation)
+:(scenario scenario_multiple_blocks)
 scenario foo [
   run [
-    a <- b
+    1:integer <- copy 13:literal
+  ]
+  memory-should-contain [
+    1 <- 13
+  ]
+  run [
+    2:integer <- copy 13:literal
   ]
-  memory should contain [
-    1 <- 0
+  memory-should-contain [
+    1 <- 13
+    2 <- 13
   ]
 ]
-+parse: scenario will run: a <- b
 
-:(scenario parse_scenario_memory_expectation_duplicate)
-% Hide_warnings = true;
+:(scenario scenario_check_memory_and_trace)
 scenario foo [
   run [
-    a <- b
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
   ]
-  memory should contain [
-    1 <- 0
-    1 <- 1
+  memory-should-contain [
+    1 <- 13
+  ]
+  trace-should-contain [
+    a: a b c
+  ]
+  trace-should-not-contain [
+    a: x y z
   ]
 ]
-+warn: duplicate expectation for location 1: 0 -> 1
 
-:(before "End Command Handlers")
-else if (command == "scenario") {
-//?   cout << "AAA scenario\n"; //? 1
-  Scenarios.push_back(parse_scenario(in));
+:(code)
+// just for tests
+void run_mu_scenario(const string& form) {
+  istringstream in(form);
+  in >> std::noskipws;
+  assert(next_word(in) == "scenario");
+  scenario s = parse_scenario(in);
+  run_mu_scenario(s);
 }
 
-:(code)
 scenario parse_scenario(istream& in) {
-  scenario x;
-  x.name = next_word(in);
-  trace("parse") << "reading scenario " << x.name;
+  scenario result;
+  result.name = next_word(in);
   skip_bracket(in, "'scenario' must begin with '['");
   ostringstream buffer;
   slurp_until_matching_bracket(in, buffer);
-//?   cout << "inner buffer: ^" << buffer.str() << "$\n"; //? 1
-  istringstream inner(buffer.str());
-  inner >> std::noskipws;
-  while (!inner.eof()) {
-    skip_whitespace_and_comments(inner);
-    string scenario_command = next_word(inner);
-    if (scenario_command.empty() && inner.eof()) break;
-    // Scenario Command Handlers
-    if (scenario_command == "run") {
-      handle_scenario_run_directive(inner, x);
-    }
-    else if (scenario_command == "memory") {
-      handle_scenario_memory_directive(inner, x);
-    }
-    else if (scenario_command == "dump") {
-      skip_whitespace_and_comments(inner);
-      x.dump_layer = next_word(inner);
-    }
-    // End Scenario Command Handlers
-    else {
-      raise << "unknown command in scenario: ^" << scenario_command << "$\n";
-    }
-  }
-  return x;
+  result.to_run = buffer.str();
+  return result;
 }
 
-void handle_scenario_run_directive(istream& in, scenario& result) {
-  skip_bracket(in, "'run' inside scenario must begin with '['");
-  ostringstream buffer;
-  slurp_until_matching_bracket(in, buffer);
-  string trace_result = buffer.str();  // temporary copy
-  trace("parse") << "scenario will run: " << trim(trace_result);
-//?   cout << buffer.str() << '\n'; //? 1
-  result.to_run = "recipe test-"+result.name+" [" + buffer.str() + "]";
+void run_mu_scenario(const scenario& s) {
+  setup();
+  // In this layer we're writing tangle scenarios about mu scenarios.
+  // Don't need to set Trace_file and Trace_stream in that situation.
+  // Hackily simulate a conditional START_TRACING_UNTIL_END_OF_SCOPE.
+  bool temporary_trace_file = Trace_file.empty();
+  if (temporary_trace_file) Trace_file = s.name;
+  cerr << Trace_file << '\n';
+  bool delete_trace_stream = !Trace_stream;
+  if (delete_trace_stream) Trace_stream = new trace_stream;
+//?   START_TRACING_UNTIL_END_OF_SCOPE;
+  run("recipe "+s.name+" [ " + s.to_run + " ]");
+  teardown();
+  if (delete_trace_stream) {
+    ofstream fout((Trace_dir+Trace_file).c_str());
+    fout << Trace_stream->readable_contents("");
+    fout.close();
+    delete Trace_stream;
+    Trace_stream = NULL;
+  }
+  if (temporary_trace_file) Trace_file = "";
 }
 
-void handle_scenario_memory_directive(istream& in, scenario& out) {
-  if (next_word(in) != "should") {
-    raise << "'memory' directive inside scenario must continue 'memory should'\n";
-  }
-  if (next_word(in) != "contain") {
-    raise << "'memory' directive inside scenario must continue 'memory should contain'\n";
-  }
-  skip_bracket(in, "'memory' directive inside scenario must begin with 'memory should contain ['\n");
-  while (true) {
-    skip_whitespace_and_comments(in);
-    if (in.eof()) break;
-//?     cout << "a: " << in.peek() << '\n'; //? 1
-    if (in.peek() == ']') break;
-    string lhs = next_word(in);
-    if (!is_number(lhs)) {
-      handle_type(lhs, in, out);
-      continue;
-    }
-    int address = to_int(lhs);
-//?     cout << "address: " << address << '\n'; //? 2
-//?     cout << "b: " << in.peek() << '\n'; //? 1
-    skip_whitespace_and_comments(in);
-//?     cout << "c: " << in.peek() << '\n'; //? 1
-    string _assign;  in >> _assign;  assert(_assign == "<-");
-    skip_whitespace_and_comments(in);
-    int value = 0;  in >> value;
-    if (out.memory_expectations.find(address) != out.memory_expectations.end())
-      raise << "duplicate expectation for location " << address << ": " << out.memory_expectations[address] << " -> " << value << '\n';
-    out.memory_expectations[address] = value;
-    trace("parse") << "memory expectation: *" << address << " == " << value;
-  }
-  skip_whitespace(in);
-  assert(in.get() == ']');
+:(before "End Command Handlers")
+else if (command == "scenario") {
+  Scenarios.push_back(parse_scenario(in));
 }
 
-void handle_type(const string& lhs, istream& in, scenario& out) {
-  reagent x(lhs);
-  if (x.properties[0].second[0] == "string") {
-    x.set_value(to_int(x.name));
-//?     cerr << x.name << ' ' << x.value << '\n'; //? 1
-    skip_whitespace_and_comments(in);
-    string _assign = next_word(in);
-//?     cerr << _assign << '\n'; //? 1
-    assert(_assign == "<-");
-    skip_whitespace_and_comments(in);
-    string literal = next_word(in);
-//?     cerr << literal << '\n'; //? 1
-    size_t address = x.value;
-    out.memory_expectations[address] = literal.size()-2;  // exclude quoting brackets
-    ++address;
-    for (size_t i = 1; i < literal.size()-1; ++i) {
-//?       cerr << "checking " << address << ": " << literal[i] << '\n'; //? 1
-      out.memory_expectations[address] = literal[i];
-      ++address;
-    }
-    return;
-  }
-  raise << "scenario doesn't know how to parse memory expectation on " << lhs << '\n';
+:(before "End Tests")
+time_t mu_time; time(&mu_time);
+cerr << "\nMu tests: " << ctime(&mu_time);
+for (size_t i = 0; i < Scenarios.size(); ++i) {
+  run_mu_scenario(Scenarios[i]);
+  if (Passed) cerr << ".";
 }
 
 //:: Helpers
 
+:(code)
 void slurp_until_matching_bracket(istream& in, ostream& out) {
   int brace_depth = 1;  // just scanned '['
   char c;
@@ -197,23 +127,3 @@ void slurp_until_matching_bracket(istream& in, ostream& out) {
     out << c;
   }
 }
-
-:(code)
-// for tests
-void parse_scenario(const string& s) {
-  istringstream in(s);
-  in >> std::noskipws;
-  skip_whitespace_and_comments(in);
-  string _scenario = next_word(in);
-//?   cout << _scenario << '\n'; //? 1
-  assert(_scenario == "scenario");
-  parse_scenario(in);
-}
-
-:(before "End Includes")
-#include <sys/stat.h>
-:(code)
-bool file_exists(const string& filename) {
-  struct stat buffer;
-  return stat(filename.c_str(), &buffer) == 0;
-}
diff --git a/cpp/051scenario_test.mu b/cpp/051scenario_test.mu
index d401c62b..5064f8a5 100644
--- a/cpp/051scenario_test.mu
+++ b/cpp/051scenario_test.mu
@@ -4,7 +4,28 @@ scenario first_scenario_in_mu [
   run [
     1:integer <- add 2:literal, 2:literal
   ]
-  memory should contain [
+  memory-should-contain [
+    1 <- 4
+  ]
+]
+
+scenario scenario_with_comment_in_mu [
+  run [
+    # comment
+    1:integer <- add 2:literal, 2:literal
+  ]
+  memory-should-contain [
+    1 <- 4
+  ]
+]
+
+scenario scenario_with_multiple_comments_in_mu [
+  run [
+    # comment1
+    # comment2
+    1:integer <- add 2:literal, 2:literal
+  ]
+  memory-should-contain [
     1 <- 4
   ]
 ]
@@ -16,7 +37,34 @@ scenario check_string_in_memory [
     3:character <- copy 98:literal  # 'b'
     4:character <- copy 99:literal  # 'c'
   ]
-  memory should contain [
+  memory-should-contain [
     1:string <- [abc]
   ]
 ]
+
+scenario check_trace [
+  run [
+    1:integer <- add 2:literal, 2:literal
+  ]
+  trace-should-contain [
+    mem: storing 4 in location 1
+  ]
+]
+
+scenario check_trace_negative [
+  run [
+    1:integer <- add 2:literal, 2:literal
+  ]
+  trace-should-not-contain [
+    mem: storing 5 in location 1
+  ]
+]
+
+scenario check_trace_instruction [
+  run [
+    trace [foo], [aaa]
+  ]
+  trace-should-contain [
+    foo: aaa
+  ]
+]
diff --git a/cpp/052scenario_trace.cc b/cpp/052scenario_trace.cc
deleted file mode 100644
index cf782835..00000000
--- a/cpp/052scenario_trace.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-//: Support a trace block inside scenario blocks.
-//: Allows two kinds of assertions:
-//:   trace must contain [ ... ]
-//:   trace must not contain [ ... ]
-
-:(scenarios "parse_scenario")
-:(scenario scenario_trace_block)
-scenario foo [
-  trace should contain [
-    bar: baz
-    bar: floo
-  ]
-  trace should not contain [
-    bar: abc
-  ]
-
-]
-+scenario: +bar: baz
-+scenario: +bar: floo
-+scenario: -bar: abc
-
-:(before "End scenario Fields")
-vector<pair<string, string> > trace_checks;
-vector<pair<string, string> > trace_negative_checks;
-
-:(before "End Scenario Command Handlers")
-else if (scenario_command == "trace") {
-  handle_scenario_trace_directive(inner, x);
-}
-
-:(before "End Scenario Checks")
-check_trace_contents(Scenarios[i]);
-check_trace_negative_contents(Scenarios[i]);
-
-:(code)
-void handle_scenario_trace_directive(istream& in, scenario& out) {
-  if (next_word(in) != "should") {
-    raise << "'trace' directive inside scenario must continue 'trace should'\n";
-  }
-  string s = next_word(in);
-  if (s == "not") {
-    handle_scenario_trace_negative_directive(in, out);
-    return;
-  }
-  if (s != "contain") {
-    raise << "'trace' directive inside scenario must continue 'trace should [not] contain'\n";
-  }
-  skip_bracket(in, "'trace' directive inside scenario must begin with 'trace should contain ['\n");
-  while (true) {
-    skip_whitespace_and_comments(in);
-    if (in.eof()) break;
-    if (in.peek() == ']') break;
-    string curr_line;
-    getline(in, curr_line);
-    istringstream tmp(curr_line);
-    tmp >> std::noskipws;
-    string label = slurp_until(tmp, ':');
-    if (tmp.get() != ' ') {
-      raise << "'trace' directive inside scenario should contain lines of the form 'label: message', instead got " << curr_line;
-      continue;
-    }
-    string message = slurp_rest(tmp);
-    out.trace_checks.push_back(pair<string, string>(label, message));
-    trace("scenario") << '+' << label << ": " << message << '\n';
-  }
-  skip_whitespace(in);
-  assert(in.get() == ']');
-}
-
-void handle_scenario_trace_negative_directive(istream& in, scenario& out) {
-  // 'not' already slurped
-  if (next_word(in) != "contain") {
-    raise << "'trace' directive inside scenario must continue 'trace should not contain'\n";
-  }
-  skip_bracket(in, "'trace' directive inside scenario must begin with 'trace should not contain ['\n");
-  while (true) {
-    skip_whitespace_and_comments(in);
-    if (in.eof()) break;
-    if (in.peek() == ']') break;
-    string curr_line;
-    getline(in, curr_line);
-    istringstream tmp(curr_line);
-    tmp >> std::noskipws;
-    string label = slurp_until(tmp, ':');
-    if (tmp.get() != ' ') {
-      raise << "'trace' directive inside scenario should contain lines of the form 'label: message', instead got " << curr_line;
-      continue;
-    }
-    string message = slurp_rest(tmp);
-    out.trace_negative_checks.push_back(pair<string, string>(label, message));
-    trace("scenario") << '-' << label << ": " << message << '\n';
-  }
-  skip_whitespace(in);
-  assert(in.get() == ']');
-}
-
-string slurp_rest(istream& in) {
-  ostringstream out;
-  char c;
-  while (in >> c) {
-    out << c;
-  }
-  return out.str();
-}
-
-void check_trace_contents(const scenario& s) {
-  if (s.trace_checks.empty()) return;
-  ostringstream contents;
-  for (size_t i = 0; i < s.trace_checks.size(); ++i) {
-    contents << s.trace_checks[i].first << ": " << s.trace_checks[i].second << "";
-  }
-  CHECK_TRACE_CONTENTS(contents.str());
-}
-
-void check_trace_negative_contents(const scenario& s) {
-  for (size_t i = 0; i < s.trace_negative_checks.size(); ++i) {
-    if (trace_count(s.trace_negative_checks[i].first, s.trace_negative_checks[i].second) > 0) {
-      raise << "trace shouldn't contain " << s.trace_negative_checks[i].first << ": " << s.trace_negative_checks[i].second << '\n';
-      Passed = false;
-    }
-  }
-}
diff --git a/cpp/053scenario_trace_test.mu b/cpp/053scenario_trace_test.mu
deleted file mode 100644
index 8016bbfb..00000000
--- a/cpp/053scenario_trace_test.mu
+++ /dev/null
@@ -1,28 +0,0 @@
-# tests for trace-checking scenario in previous layer
-
-scenario first_scenario_checking_trace [
-  run [
-    1:integer <- add 2:literal, 2:literal
-  ]
-  trace should contain [
-    mem: storing 4 in location 1
-  ]
-]
-
-scenario first_scenario_checking_trace_negative [
-  run [
-    1:integer <- add 2:literal, 2:literal
-  ]
-  trace should not contain [
-    mem: storing 5 in location 1
-  ]
-]
-
-scenario trace_in_mu [
-  run [
-    trace [foo], [aaa]
-  ]
-  trace should contain [
-    foo: aaa
-  ]
-]
diff --git a/cpp/060string.mu b/cpp/060string.mu
index e4d78932..e6705a65 100644
--- a/cpp/060string.mu
+++ b/cpp/060string.mu
@@ -38,7 +38,7 @@ scenario string-equal-reflexive [
     x:address:array:character <- new [abc]
     3:boolean/raw <- string-equal x:address:array:character, x:address:array:character
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 1  # x == x for all x
   ]
 ]
@@ -50,7 +50,7 @@ scenario string-equal-identical [
     y:address:array:character <- new [abc]
     3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 1  # abc == abc
   ]
 ]
@@ -62,13 +62,13 @@ scenario string-equal-distinct-lengths [
     y:address:array:character <- new [abcd]
     3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 0  # abc != abcd
   ]
-  trace should contain [
+  trace-should-contain [
     string-equal: comparing lengths
   ]
-  trace should not contain [
+  trace-should-not-contain [
     string-equal: comparing characters
   ]
 ]
@@ -80,7 +80,7 @@ scenario string-equal-with-empty [
     y:address:array:character <- new [abcd]
     3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 0  # "" != abcd
   ]
 ]
@@ -92,7 +92,7 @@ scenario string-equal-common-lengths-but-distinct [
     y:address:array:character <- new [abd]
     3:boolean/raw <- string-equal x:address:array:character, y:address:array:character
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 0  # abc != abd
   ]
 ]
@@ -211,7 +211,7 @@ scenario buffer-append-works [
     11:integer/raw <- get x:address:buffer/deref, length:offset
     12:array:character/raw <- copy s3:address:array:character/deref
   ]
-  memory should contain [
+  memory-should-contain [
     # before +buffer-filled
     1 <- 1   # no change in data pointer
     2 <- 3   # size of data
@@ -293,7 +293,7 @@ scenario integer-to-decimal-digit-zero [
     1:address:array:character/raw <- integer-to-decimal-string 0:literal
     2:array:character/raw <- copy 1:address:array:character/deref/raw
   ]
-  memory should contain [
+  memory-should-contain [
     2:string <- [0]
   ]
 ]
@@ -303,7 +303,7 @@ scenario integer-to-decimal-digit-positive [
     1:address:array:character/raw <- integer-to-decimal-string 234:literal
     2:array:character/raw <- copy 1:address:array:character/deref/raw
   ]
-  memory should contain [
+  memory-should-contain [
     2:string <- [234]
   ]
 ]
@@ -313,7 +313,7 @@ scenario integer-to-decimal-digit-negative [
     1:address:array:character/raw <- integer-to-decimal-string -1:literal
     2:array:character/raw <- copy 1:address:array:character/deref/raw
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 2
     3 <- 45  # '-'
     4 <- 49  # '1'
@@ -372,7 +372,7 @@ scenario string-append-1 [
     3:address:array:character/raw <- string-append 1:address:array:character/raw, 2:address:array:character/raw
     4:array:character/raw <- copy 3:address:array:character/raw/deref
   ]
-  memory should contain [
+  memory-should-contain [
     4:string <- [hello, world!]
   ]
 ]
@@ -475,7 +475,7 @@ scenario interpolate-works [
     3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
     4:array:character/raw <- copy 3:address:array:character/raw/deref
   ]
-  memory should contain [
+  memory-should-contain [
     4:string <- [abc def]
   ]
 ]
@@ -487,7 +487,7 @@ scenario interpolate-at-start [
     3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
     4:array:character/raw <- copy 3:address:array:character/raw/deref
   ]
-  memory should contain [
+  memory-should-contain [
     4:string <- [abc, hello!]
     16 <- 0  # out of bounds
   ]
@@ -500,7 +500,7 @@ scenario interpolate-at-end [
     3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
     4:array:character/raw <- copy 3:address:array:character/raw/deref
   ]
-  memory should contain [
+  memory-should-contain [
     4:string <- [hello, abc]
   ]
 ]
diff --git a/cpp/061channel.mu b/cpp/061channel.mu
index 83596961..bee6b785 100644
--- a/cpp/061channel.mu
+++ b/cpp/061channel.mu
@@ -14,7 +14,7 @@ scenario channel [
     1:address:channel <- write 1:address:channel, 34:literal
     2:integer, 1:address:channel <- read 1:address:channel
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 34
   ]
 ]
@@ -112,7 +112,7 @@ scenario channel-initialization [
     2:integer <- get 1:address:channel/deref, first-full:offset
     3:integer <- get 1:address:channel/deref, first-free:offset
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 0  # first-full
     3 <- 0  # first-free
   ]
@@ -125,7 +125,7 @@ scenario channel-write-increments-free [
     2:integer <- get 1:address:channel/deref, first-full:offset
     3:integer <- get 1:address:channel/deref, first-free:offset
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 0  # first-full
     3 <- 1  # first-free
   ]
@@ -139,7 +139,7 @@ scenario channel-read-increments-full [
     2:integer <- get 1:address:channel/deref, first-full:offset
     3:integer <- get 1:address:channel/deref, first-free:offset
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 1  # first-full
     3 <- 1  # first-free
   ]
@@ -162,7 +162,7 @@ scenario channel-wrap [
     _, 1:address:channel <- read 1:address:channel
     5:integer <- get 1:address:channel/deref, first-full:offset
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 1  # first-free after first write
     3 <- 1  # first-full after first read
     4 <- 0  # first-free after second write, wrapped
@@ -219,7 +219,7 @@ scenario channel-new-empty-not-full [
     2:integer <- channel-empty? 1:address:channel
     3:integer <- channel-full? 1:address:channel
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 1  # empty?
     3 <- 0  # full?
   ]
@@ -232,7 +232,7 @@ scenario channel-write-not-empty [
     2:integer <- channel-empty? 1:address:channel
     3:integer <- channel-full? 1:address:channel
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 0  # empty?
     3 <- 0  # full?
   ]
@@ -245,7 +245,7 @@ scenario channel-write-full [
     2:integer <- channel-empty? 1:address:channel
     3:integer <- channel-full? 1:address:channel
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 0  # empty?
     3 <- 1  # full?
   ]
@@ -259,7 +259,7 @@ scenario channel-read-not-full [
     2:integer <- channel-empty? 1:address:channel
     3:integer <- channel-full? 1:address:channel
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 1  # empty?
     3 <- 0  # full?
   ]
diff --git a/cpp/062array.mu b/cpp/062array.mu
index 3afecf5c..95af1412 100644
--- a/cpp/062array.mu
+++ b/cpp/062array.mu
@@ -3,7 +3,7 @@ scenario array-from-args [
     1:address:array:location <- init-array 0:literal, 1:literal, 2:literal
     2:array:location <- copy 1:address:array:location/deref
   ]
-  memory should contain [
+  memory-should-contain [
     2 <- 3  # array length
     3 <- 0
     4 <- 1
diff --git a/cpp/071print.mu b/cpp/071print.mu
index b34f9844..6789ff89 100644
--- a/cpp/071print.mu
+++ b/cpp/071print.mu
@@ -89,7 +89,7 @@ scenario print-character-at-top-left [
     2:address:array:character <- get 1:address:screen/deref, data:offset
     3:array:character <- copy 2:address:array:character/deref
   ]
-  memory should contain [
+  memory-should-contain [
     3 <- 6  # width*height
     4 <- 97  # 'a'
     5 <- 0
@@ -168,7 +168,7 @@ scenario clear-line-erases-printed-characters [
     3:array:character <- copy 2:address:array:character/deref
   ]
   # screen should be blank
-  memory should contain [
+  memory-should-contain [
     3 <- 6  # width*height
     4 <- 0
     5 <- 0