about summary refs log tree commit diff stats
path: root/cpp
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 /cpp
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.
Diffstat (limited to 'cpp')
-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