about summary refs log tree commit diff stats
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/.traces/add4
-rw-r--r--cpp/.traces/add_literal2
-rw-r--r--cpp/.traces/and4
-rw-r--r--cpp/.traces/brace_conversion16
-rw-r--r--cpp/.traces/calling_recipe4
-rw-r--r--cpp/.traces/copy3
-rw-r--r--cpp/.traces/copy_array6
-rw-r--r--cpp/.traces/copy_indirect4
-rw-r--r--cpp/.traces/copy_literal2
-rw-r--r--cpp/.traces/copy_multiple_locations4
-rw-r--r--cpp/.traces/divide4
-rw-r--r--cpp/.traces/divide_literal2
-rw-r--r--cpp/.traces/divide_with_remainder4
-rw-r--r--cpp/.traces/divide_with_remainder_literal2
-rw-r--r--cpp/.traces/equal4
-rw-r--r--cpp/.traces/equal24
-rw-r--r--cpp/.traces/get4
-rw-r--r--cpp/.traces/get_address4
-rw-r--r--cpp/.traces/get_address_indirect5
-rw-r--r--cpp/.traces/get_handles_record_fields5
-rw-r--r--cpp/.traces/get_indirect5
-rw-r--r--cpp/.traces/greater_or_equal4
-rw-r--r--cpp/.traces/greater_or_equal24
-rw-r--r--cpp/.traces/greater_or_equal34
-rw-r--r--cpp/.traces/greater_than4
-rw-r--r--cpp/.traces/greater_than24
-rw-r--r--cpp/.traces/index6
-rw-r--r--cpp/.traces/index_address6
-rw-r--r--cpp/.traces/jump_backward4
-rw-r--r--cpp/.traces/jump_can_skip_instructions3
-rw-r--r--cpp/.traces/jump_if3
-rw-r--r--cpp/.traces/jump_if_fallthrough3
-rw-r--r--cpp/.traces/jump_unless3
-rw-r--r--cpp/.traces/jump_unless_fallthrough3
-rw-r--r--cpp/.traces/lesser_or_equal4
-rw-r--r--cpp/.traces/lesser_or_equal24
-rw-r--r--cpp/.traces/lesser_or_equal34
-rw-r--r--cpp/.traces/lesser_than4
-rw-r--r--cpp/.traces/lesser_than24
-rw-r--r--cpp/.traces/loop30
-rw-r--r--cpp/.traces/multiply4
-rw-r--r--cpp/.traces/multiply_literal2
-rw-r--r--cpp/.traces/next_ingredient5
-rw-r--r--cpp/.traces/not3
-rw-r--r--cpp/.traces/or4
-rw-r--r--cpp/.traces/parse_multiple_properties3
-rw-r--r--cpp/.traces/reply6
-rw-r--r--cpp/.traces/run_label18
-rw-r--r--cpp/.traces/store_indirect3
-rw-r--r--cpp/.traces/subtract4
-rw-r--r--cpp/.traces/subtract_literal2
-rw-r--r--cpp/011load1
-rw-r--r--cpp/012run10
-rw-r--r--cpp/020call2
-rw-r--r--cpp/023transform2
-rw-r--r--cpp/024brace113
56 files changed, 373 insertions, 2 deletions
diff --git a/cpp/.traces/add b/cpp/.traces/add
index c831e62a..59515bf1 100644
--- a/cpp/.traces/add
+++ b/cpp/.traces/add
@@ -8,6 +8,10 @@ parse/0: instruction: 2
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: add ...
 run/0: instruction main/0
 run/0: ingredient 0 is 23
 mem/0: storing in location 1
diff --git a/cpp/.traces/add_literal b/cpp/.traces/add_literal
index b9879031..dc2755f2 100644
--- a/cpp/.traces/add_literal
+++ b/cpp/.traces/add_literal
@@ -2,6 +2,8 @@ parse/0: instruction: 2
 parse/0:   ingredient: {name: "23", value: 23, type: 0, properties: [23: literal]}
 parse/0:   ingredient: {name: "34", value: 34, type: 0, properties: [34: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: add ...
 run/0: instruction main/0
 run/0: ingredient 0 is 23
 run/0: ingredient 1 is 34
diff --git a/cpp/.traces/and b/cpp/.traces/and
index b487c4e4..0b259036 100644
--- a/cpp/.traces/and
+++ b/cpp/.traces/and
@@ -8,6 +8,10 @@ parse/0: instruction: 7
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: and ...
 run/0: instruction main/0
 run/0: ingredient 0 is 1
 mem/0: storing in location 1
diff --git a/cpp/.traces/brace_conversion b/cpp/.traces/brace_conversion
new file mode 100644
index 00000000..b00da286
--- /dev/null
+++ b/cpp/.traces/brace_conversion
@@ -0,0 +1,16 @@
+parse/0: label: {
+parse/0: instruction: 25
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
+parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+parse/0: label: }
+brace/0: 24: push (open, 0)
+brace/0: push (close, 3)
+after-brace/0: recipe main
+after-brace/0: jump 1:offset
+after-brace/0: copy ...
+run/0: instruction main/1
+run/0: ingredient 0 is 
+run/0: instruction main/2
+run/0: ingredient 0 is 0
+mem/0: storing in location 1
diff --git a/cpp/.traces/calling_recipe b/cpp/.traces/calling_recipe
index e8e3f1f3..078963f6 100644
--- a/cpp/.traces/calling_recipe
+++ b/cpp/.traces/calling_recipe
@@ -3,6 +3,10 @@ parse/0: instruction: 2
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: f ...
+after-brace/0: recipe f
+after-brace/0: add ...
 run/0: instruction main/0
 run/0: instruction f/0
 run/0: ingredient 0 is 2
diff --git a/cpp/.traces/copy b/cpp/.traces/copy
index 9a52d9d6..3c12980d 100644
--- a/cpp/.traces/copy
+++ b/cpp/.traces/copy
@@ -4,6 +4,9 @@ parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 23
 mem/0: storing in location 1
diff --git a/cpp/.traces/copy_array b/cpp/.traces/copy_array
index 967a9ed9..0cd0074a 100644
--- a/cpp/.traces/copy_array
+++ b/cpp/.traces/copy_array
@@ -13,6 +13,12 @@ parse/0:   product: {name: "4", value: 4, type: 1, properties: [4: integer]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 6, properties: [1: integer-array]}
 parse/0:   product: {name: "5", value: 5, type: 6, properties: [5: integer-array]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 3
 mem/0: storing in location 1
diff --git a/cpp/.traces/copy_indirect b/cpp/.traces/copy_indirect
index e55c5c42..aa429126 100644
--- a/cpp/.traces/copy_indirect
+++ b/cpp/.traces/copy_indirect
@@ -7,6 +7,10 @@ parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 2-1, properties: [1: address:integer, deref: ]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 2
 mem/0: storing in location 1
diff --git a/cpp/.traces/copy_literal b/cpp/.traces/copy_literal
index cbb53fbc..a5a1dd6c 100644
--- a/cpp/.traces/copy_literal
+++ b/cpp/.traces/copy_literal
@@ -1,6 +1,8 @@
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "23", value: 23, type: 0, properties: [23: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 23
 mem/0: storing in location 1
diff --git a/cpp/.traces/copy_multiple_locations b/cpp/.traces/copy_multiple_locations
index f03d3573..c4b8edb6 100644
--- a/cpp/.traces/copy_multiple_locations
+++ b/cpp/.traces/copy_multiple_locations
@@ -7,6 +7,10 @@ parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 4, properties: [1: point]}
 parse/0:   product: {name: "3", value: 3, type: 4, properties: [3: point]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/divide b/cpp/.traces/divide
index 0bfb1741..c521ccd8 100644
--- a/cpp/.traces/divide
+++ b/cpp/.traces/divide
@@ -8,6 +8,10 @@ parse/0: instruction: 5
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: divide ...
 run/0: instruction main/0
 run/0: ingredient 0 is 27
 mem/0: storing in location 1
diff --git a/cpp/.traces/divide_literal b/cpp/.traces/divide_literal
index 41552683..85335d47 100644
--- a/cpp/.traces/divide_literal
+++ b/cpp/.traces/divide_literal
@@ -2,6 +2,8 @@ parse/0: instruction: 5
 parse/0:   ingredient: {name: "8", value: 8, type: 0, properties: [8: literal]}
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: divide ...
 run/0: instruction main/0
 run/0: ingredient 0 is 8
 run/0: ingredient 1 is 2
diff --git a/cpp/.traces/divide_with_remainder b/cpp/.traces/divide_with_remainder
index a9f36a48..8ae52475 100644
--- a/cpp/.traces/divide_with_remainder
+++ b/cpp/.traces/divide_with_remainder
@@ -9,6 +9,10 @@ parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
 parse/0:   product: {name: "4", value: 4, type: 1, properties: [4: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: divide_with_remainder ...
 run/0: instruction main/0
 run/0: ingredient 0 is 27
 mem/0: storing in location 1
diff --git a/cpp/.traces/divide_with_remainder_literal b/cpp/.traces/divide_with_remainder_literal
index 4d3a3784..be1f8f85 100644
--- a/cpp/.traces/divide_with_remainder_literal
+++ b/cpp/.traces/divide_with_remainder_literal
@@ -3,6 +3,8 @@ parse/0:   ingredient: {name: "9", value: 9, type: 0, properties: [9: literal]}
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
+after-brace/0: recipe main
+after-brace/0: divide_with_remainder ...
 run/0: instruction main/0
 run/0: ingredient 0 is 9
 run/0: ingredient 1 is 2
diff --git a/cpp/.traces/equal b/cpp/.traces/equal
index 4d445657..e852c144 100644
--- a/cpp/.traces/equal
+++ b/cpp/.traces/equal
@@ -8,6 +8,10 @@ parse/0: instruction: 13
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/equal2 b/cpp/.traces/equal2
index ce3b54b5..3435ba18 100644
--- a/cpp/.traces/equal2
+++ b/cpp/.traces/equal2
@@ -8,6 +8,10 @@ parse/0: instruction: 13
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/get b/cpp/.traces/get
index ff2c96b8..7043c0ef 100644
--- a/cpp/.traces/get
+++ b/cpp/.traces/get
@@ -8,6 +8,10 @@ parse/0: instruction: 18
 parse/0:   ingredient: {name: "12", value: 12, type: 4, properties: [12: point]}
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0:   product: {name: "15", value: 15, type: 1, properties: [15: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: get ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 12
diff --git a/cpp/.traces/get_address b/cpp/.traces/get_address
index 1156f7cd..2011a897 100644
--- a/cpp/.traces/get_address
+++ b/cpp/.traces/get_address
@@ -8,6 +8,10 @@ parse/0: instruction: 19
 parse/0:   ingredient: {name: "12", value: 12, type: 4, properties: [12: point]}
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0:   product: {name: "15", value: 15, type: 2-1, properties: [15: address:integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: get-address ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 12
diff --git a/cpp/.traces/get_address_indirect b/cpp/.traces/get_address_indirect
index 16f3f56a..398e28d1 100644
--- a/cpp/.traces/get_address_indirect
+++ b/cpp/.traces/get_address_indirect
@@ -11,6 +11,11 @@ parse/0: instruction: 19
 parse/0:   ingredient: {name: "1", value: 1, type: 2-4, properties: [1: address:point, deref: ]}
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: offset]}
 parse/0:   product: {name: "4", value: 4, type: 1, properties: [4: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: get-address ...
 run/0: instruction main/0
 run/0: ingredient 0 is 2
 mem/0: storing in location 1
diff --git a/cpp/.traces/get_handles_record_fields b/cpp/.traces/get_handles_record_fields
index 85fdec38..a5e4b6eb 100644
--- a/cpp/.traces/get_handles_record_fields
+++ b/cpp/.traces/get_handles_record_fields
@@ -11,6 +11,11 @@ parse/0: instruction: 18
 parse/0:   ingredient: {name: "12", value: 12, type: 5, properties: [12: point-integer]}
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0:   product: {name: "15", value: 15, type: 1, properties: [15: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: get ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 12
diff --git a/cpp/.traces/get_indirect b/cpp/.traces/get_indirect
index a3daab86..8aa7606c 100644
--- a/cpp/.traces/get_indirect
+++ b/cpp/.traces/get_indirect
@@ -11,6 +11,11 @@ parse/0: instruction: 18
 parse/0:   ingredient: {name: "1", value: 1, type: 2-4, properties: [1: address:point, deref: ]}
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: offset]}
 parse/0:   product: {name: "4", value: 4, type: 1, properties: [4: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: get ...
 run/0: instruction main/0
 run/0: ingredient 0 is 2
 mem/0: storing in location 1
diff --git a/cpp/.traces/greater_or_equal b/cpp/.traces/greater_or_equal
index f9065713..d625a3f7 100644
--- a/cpp/.traces/greater_or_equal
+++ b/cpp/.traces/greater_or_equal
@@ -8,6 +8,10 @@ parse/0: instruction: 16
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: greater-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/greater_or_equal2 b/cpp/.traces/greater_or_equal2
index 00ff6059..eb68b27a 100644
--- a/cpp/.traces/greater_or_equal2
+++ b/cpp/.traces/greater_or_equal2
@@ -8,6 +8,10 @@ parse/0: instruction: 16
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: greater-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/greater_or_equal3 b/cpp/.traces/greater_or_equal3
index 8795fd99..e78e6178 100644
--- a/cpp/.traces/greater_or_equal3
+++ b/cpp/.traces/greater_or_equal3
@@ -8,6 +8,10 @@ parse/0: instruction: 16
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: greater-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/greater_than b/cpp/.traces/greater_than
index ce7c3e5c..9c3a2523 100644
--- a/cpp/.traces/greater_than
+++ b/cpp/.traces/greater_than
@@ -8,6 +8,10 @@ parse/0: instruction: 14
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: greater-than ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/greater_than2 b/cpp/.traces/greater_than2
index 17f6c6fa..31203a57 100644
--- a/cpp/.traces/greater_than2
+++ b/cpp/.traces/greater_than2
@@ -8,6 +8,10 @@ parse/0: instruction: 14
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: greater-than ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/index b/cpp/.traces/index
index 0e60606f..20460ed5 100644
--- a/cpp/.traces/index
+++ b/cpp/.traces/index
@@ -14,6 +14,12 @@ parse/0: instruction: 20
 parse/0:   ingredient: {name: "1", value: 1, type: 6, properties: [1: integer-array]}
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
 parse/0:   product: {name: "5", value: 5, type: 1, properties: [5: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: index ...
 run/0: instruction main/0
 run/0: ingredient 0 is 3
 mem/0: storing in location 1
diff --git a/cpp/.traces/index_address b/cpp/.traces/index_address
index 297fcfc9..d00a6a7c 100644
--- a/cpp/.traces/index_address
+++ b/cpp/.traces/index_address
@@ -14,6 +14,12 @@ parse/0: instruction: 21
 parse/0:   ingredient: {name: "1", value: 1, type: 6, properties: [1: integer-array]}
 parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
 parse/0:   product: {name: "5", value: 5, type: 1, properties: [5: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: index-address ...
 run/0: instruction main/0
 run/0: ingredient 0 is 3
 mem/0: storing in location 1
diff --git a/cpp/.traces/jump_backward b/cpp/.traces/jump_backward
index e592f74c..2fc0f399 100644
--- a/cpp/.traces/jump_backward
+++ b/cpp/.traces/jump_backward
@@ -4,6 +4,10 @@ parse/0: instruction: 10
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 10
 parse/0:   ingredient: {name: "-2", value: -2, type: 0, properties: [-2: offset]}
+after-brace/0: recipe main
+after-brace/0: jump ...
+after-brace/0: jump ...
+after-brace/0: jump ...
 run/0: instruction main/0
 run/0: ingredient 0 is 1
 run/0: instruction main/2
diff --git a/cpp/.traces/jump_can_skip_instructions b/cpp/.traces/jump_can_skip_instructions
index 8372bbdb..8dbf5748 100644
--- a/cpp/.traces/jump_can_skip_instructions
+++ b/cpp/.traces/jump_can_skip_instructions
@@ -3,5 +3,8 @@ parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: jump ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 1
diff --git a/cpp/.traces/jump_if b/cpp/.traces/jump_if
index d126aa33..c56b028b 100644
--- a/cpp/.traces/jump_if
+++ b/cpp/.traces/jump_if
@@ -4,6 +4,9 @@ parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: jump-if ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 999
 run/0: ingredient 1 is 1
diff --git a/cpp/.traces/jump_if_fallthrough b/cpp/.traces/jump_if_fallthrough
index 056b67d8..601bbc3d 100644
--- a/cpp/.traces/jump_if_fallthrough
+++ b/cpp/.traces/jump_if_fallthrough
@@ -4,6 +4,9 @@ parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   product: {name: "123", value: 123, type: 1, properties: [123: integer]}
+after-brace/0: recipe main
+after-brace/0: jump-if ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 0
 run/0: jump-if fell through
diff --git a/cpp/.traces/jump_unless b/cpp/.traces/jump_unless
index d294faa3..15587ff0 100644
--- a/cpp/.traces/jump_unless
+++ b/cpp/.traces/jump_unless
@@ -4,6 +4,9 @@ parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: jump-unless ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 0
 run/0: ingredient 1 is 1
diff --git a/cpp/.traces/jump_unless_fallthrough b/cpp/.traces/jump_unless_fallthrough
index 59e87f18..e87ac12e 100644
--- a/cpp/.traces/jump_unless_fallthrough
+++ b/cpp/.traces/jump_unless_fallthrough
@@ -4,6 +4,9 @@ parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: offset]}
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   product: {name: "123", value: 123, type: 1, properties: [123: integer]}
+after-brace/0: recipe main
+after-brace/0: jump-unless ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 999
 run/0: jump-unless fell through
diff --git a/cpp/.traces/lesser_or_equal b/cpp/.traces/lesser_or_equal
index aadc8a0c..6898935d 100644
--- a/cpp/.traces/lesser_or_equal
+++ b/cpp/.traces/lesser_or_equal
@@ -8,6 +8,10 @@ parse/0: instruction: 17
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: lesser-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 32
 mem/0: storing in location 1
diff --git a/cpp/.traces/lesser_or_equal2 b/cpp/.traces/lesser_or_equal2
index 1beafca9..2434a4de 100644
--- a/cpp/.traces/lesser_or_equal2
+++ b/cpp/.traces/lesser_or_equal2
@@ -8,6 +8,10 @@ parse/0: instruction: 17
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: lesser-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 33
 mem/0: storing in location 1
diff --git a/cpp/.traces/lesser_or_equal3 b/cpp/.traces/lesser_or_equal3
index 9dcb4092..74e5f592 100644
--- a/cpp/.traces/lesser_or_equal3
+++ b/cpp/.traces/lesser_or_equal3
@@ -8,6 +8,10 @@ parse/0: instruction: 17
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: lesser-or-equal ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/lesser_than b/cpp/.traces/lesser_than
index 2b7b2763..d7b086e7 100644
--- a/cpp/.traces/lesser_than
+++ b/cpp/.traces/lesser_than
@@ -8,6 +8,10 @@ parse/0: instruction: 15
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: lesser-than ...
 run/0: instruction main/0
 run/0: ingredient 0 is 32
 mem/0: storing in location 1
diff --git a/cpp/.traces/lesser_than2 b/cpp/.traces/lesser_than2
index 6ee339a9..48967738 100644
--- a/cpp/.traces/lesser_than2
+++ b/cpp/.traces/lesser_than2
@@ -8,6 +8,10 @@ parse/0: instruction: 15
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: lesser-than ...
 run/0: instruction main/0
 run/0: ingredient 0 is 34
 mem/0: storing in location 1
diff --git a/cpp/.traces/loop b/cpp/.traces/loop
new file mode 100644
index 00000000..48f94a4e
--- /dev/null
+++ b/cpp/.traces/loop
@@ -0,0 +1,30 @@
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
+parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
+parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
+parse/0: label: {
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "0", value: 0, type: 0, properties: [0: literal]}
+parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+parse/0: instruction: 25
+parse/0: label: }
+brace/0: 24: push (open, 2)
+brace/0: push (close, 5)
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: jump -2:offset
+run/0: instruction main/0
+run/0: ingredient 0 is 0
+mem/0: storing in location 1
+run/0: instruction main/1
+run/0: ingredient 0 is 0
+mem/0: storing in location 2
+run/0: instruction main/3
+run/0: ingredient 0 is 0
+mem/0: storing in location 3
+run/0: instruction main/4
+run/0: ingredient 0 is 
diff --git a/cpp/.traces/multiply b/cpp/.traces/multiply
index 24ad673f..ce15063f 100644
--- a/cpp/.traces/multiply
+++ b/cpp/.traces/multiply
@@ -8,6 +8,10 @@ parse/0: instruction: 4
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: multiply ...
 run/0: instruction main/0
 run/0: ingredient 0 is 4
 mem/0: storing in location 1
diff --git a/cpp/.traces/multiply_literal b/cpp/.traces/multiply_literal
index c190e1ef..9c18759b 100644
--- a/cpp/.traces/multiply_literal
+++ b/cpp/.traces/multiply_literal
@@ -2,6 +2,8 @@ parse/0: instruction: 4
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   ingredient: {name: "3", value: 3, type: 0, properties: [3: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: multiply ...
 run/0: instruction main/0
 run/0: ingredient 0 is 2
 run/0: ingredient 1 is 3
diff --git a/cpp/.traces/next_ingredient b/cpp/.traces/next_ingredient
index ac0de44c..9c779fcd 100644
--- a/cpp/.traces/next_ingredient
+++ b/cpp/.traces/next_ingredient
@@ -6,6 +6,11 @@ parse/0: instruction: 2
 parse/0:   ingredient: {name: "1", value: 1, type: 0, properties: [1: literal]}
 parse/0:   ingredient: {name: "12", value: 12, type: 1, properties: [12: integer]}
 parse/0:   product: {name: "13", value: 13, type: 1, properties: [13: integer]}
+after-brace/0: recipe main
+after-brace/0: f ...
+after-brace/0: recipe f
+after-brace/0: next-ingredient ...
+after-brace/0: add ...
 run/0: instruction main/0
 run/0: instruction f/0
 run/0: product 0 is 2
diff --git a/cpp/.traces/not b/cpp/.traces/not
index a5196acc..d0f35946 100644
--- a/cpp/.traces/not
+++ b/cpp/.traces/not
@@ -4,6 +4,9 @@ parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0: instruction: 9
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: not ...
 run/0: instruction main/0
 run/0: ingredient 0 is 1
 mem/0: storing in location 1
diff --git a/cpp/.traces/or b/cpp/.traces/or
index b9b9c0cf..bf8bf538 100644
--- a/cpp/.traces/or
+++ b/cpp/.traces/or
@@ -8,6 +8,10 @@ parse/0: instruction: 8
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: or ...
 run/0: instruction main/0
 run/0: ingredient 0 is 1
 mem/0: storing in location 1
diff --git a/cpp/.traces/parse_multiple_properties b/cpp/.traces/parse_multiple_properties
new file mode 100644
index 00000000..c3c79ae2
--- /dev/null
+++ b/cpp/.traces/parse_multiple_properties
@@ -0,0 +1,3 @@
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "23", value: 23, type: 0, properties: [23: literal, foo: bar:baz]}
+parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
diff --git a/cpp/.traces/reply b/cpp/.traces/reply
index 170c4dcf..e94e9610 100644
--- a/cpp/.traces/reply
+++ b/cpp/.traces/reply
@@ -11,6 +11,12 @@ parse/0:   product: {name: "13", value: 13, type: 1, properties: [13: integer]}
 parse/0: instruction: 23
 parse/0:   ingredient: {name: "12", value: 12, type: 1, properties: [12: integer]}
 parse/0:   ingredient: {name: "13", value: 13, type: 1, properties: [13: integer]}
+after-brace/0: recipe main
+after-brace/0: f ...
+after-brace/0: recipe f
+after-brace/0: next-ingredient ...
+after-brace/0: add ...
+after-brace/0: reply ...
 run/0: instruction main/0
 run/0: instruction f/0
 run/0: product 0 is 2
diff --git a/cpp/.traces/run_label b/cpp/.traces/run_label
new file mode 100644
index 00000000..e1b62185
--- /dev/null
+++ b/cpp/.traces/run_label
@@ -0,0 +1,18 @@
+parse/0: label: +foo
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "23", value: 23, type: 0, properties: [23: literal]}
+parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
+parse/0:   product: {name: "2", value: 2, type: 1, properties: [2: integer]}
+after-brace/0: recipe main
+after-brace/0: jump 0:offset
+after-brace/0: copy ...
+after-brace/0: copy ...
+run/0: instruction main/1
+run/0: ingredient 0 is 23
+mem/0: storing in location 1
+run/0: instruction main/2
+run/0: ingredient 0 is 1
+mem/0: location 1 is 23
+mem/0: storing in location 2
diff --git a/cpp/.traces/store_indirect b/cpp/.traces/store_indirect
index 97ba5164..44c5f10c 100644
--- a/cpp/.traces/store_indirect
+++ b/cpp/.traces/store_indirect
@@ -4,6 +4,9 @@ parse/0:   product: {name: "1", value: 1, type: 2-1, properties: [1: address:int
 parse/0: instruction: 1
 parse/0:   ingredient: {name: "34", value: 34, type: 0, properties: [34: literal]}
 parse/0:   product: {name: "1", value: 1, type: 2-1, properties: [1: address:integer, deref: ]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
 run/0: instruction main/0
 run/0: ingredient 0 is 2
 mem/0: storing in location 1
diff --git a/cpp/.traces/subtract b/cpp/.traces/subtract
index 5f1a946a..4275117e 100644
--- a/cpp/.traces/subtract
+++ b/cpp/.traces/subtract
@@ -8,6 +8,10 @@ parse/0: instruction: 3
 parse/0:   ingredient: {name: "1", value: 1, type: 1, properties: [1: integer]}
 parse/0:   ingredient: {name: "2", value: 2, type: 1, properties: [2: integer]}
 parse/0:   product: {name: "3", value: 3, type: 1, properties: [3: integer]}
+after-brace/0: recipe main
+after-brace/0: copy ...
+after-brace/0: copy ...
+after-brace/0: subtract ...
 run/0: instruction main/0
 run/0: ingredient 0 is 23
 mem/0: storing in location 1
diff --git a/cpp/.traces/subtract_literal b/cpp/.traces/subtract_literal
index 48c3866a..5bd95f68 100644
--- a/cpp/.traces/subtract_literal
+++ b/cpp/.traces/subtract_literal
@@ -2,6 +2,8 @@ parse/0: instruction: 3
 parse/0:   ingredient: {name: "5", value: 5, type: 0, properties: [5: literal]}
 parse/0:   ingredient: {name: "2", value: 2, type: 0, properties: [2: literal]}
 parse/0:   product: {name: "1", value: 1, type: 1, properties: [1: integer]}
+after-brace/0: recipe main
+after-brace/0: subtract ...
 run/0: instruction main/0
 run/0: ingredient 0 is 5
 run/0: ingredient 1 is 2
diff --git a/cpp/011load b/cpp/011load
index 3d75c9ac..97483e93 100644
--- a/cpp/011load
+++ b/cpp/011load
@@ -86,6 +86,7 @@ bool next_instruction(istream& in, instruction* curr) {
     ++p;  // skip <-
   }
 
+  curr->name = *p;
   if (Recipe_number.find(*p) == Recipe_number.end())
     Recipe_number[*p] = Next_recipe_number++;
   curr->operation = Recipe_number[*p];  ++p;
diff --git a/cpp/012run b/cpp/012run
index 8ae164c3..f4dd6390 100644
--- a/cpp/012run
+++ b/cpp/012run
@@ -36,6 +36,7 @@ void run(routine rr) {
     vector<instruction>& instructions = steps(rr);
     size_t& pc = running_at(rr);
     // Running one instruction.
+    if (instructions[pc].is_label) { ++pc; continue; }
     trace("run") << "instruction " << recipe_name(rr) << '/' << pc;
     switch (instructions[pc].operation) {
       // Primitive Recipe Implementations.
@@ -140,3 +141,12 @@ size_t size_of(reagent r) {
   if (!t.is_record && !t.is_array) return t.size;
   return t.size;  // TODO
 }
+
+:(scenario run_label)
+recipe main [
+  +foo
+  1:integer <- copy 23:literal
+  2:integer <- copy 1:integer
+]
++run: instruction main/1
++run: instruction main/2
diff --git a/cpp/020call b/cpp/020call
index 22548b8d..2e0000c0 100644
--- a/cpp/020call
+++ b/cpp/020call
@@ -45,7 +45,7 @@ inline vector<instruction>& steps(routine& rr) {
 default: {
   // not a primitive; try to look for a matching recipe
   if (Recipe.find(instructions[pc].operation) == Recipe.end()) {
-    raise << "undefined operation " << instructions[pc].operation << '\n';
+    raise << "undefined operation " << instructions[pc].operation << ": " << instructions[pc].name << '\n';
     break;
   }
   rr.calls.push(call(instructions[pc].operation));
diff --git a/cpp/023transform b/cpp/023transform
index 3ab2cdbb..faada76e 100644
--- a/cpp/023transform
+++ b/cpp/023transform
@@ -14,7 +14,7 @@ void run(string form) {
 
 :(before "End Recipe Fields")
 size_t transformed_until;
-  recipe() :transformed_until(0) {}
+  recipe() :transformed_until(-1) {}
 
 :(before "End Types")
 typedef void (*transform_fn)(recipe_number);
diff --git a/cpp/024brace b/cpp/024brace
new file mode 100644
index 00000000..5a2d346f
--- /dev/null
+++ b/cpp/024brace
@@ -0,0 +1,113 @@
+//: Structured programming
+//:
+//: Our jump operators are quite inconvenient to use, so mu provides a
+//: lightweight tool called 'transform_braces' to work in a slightly more
+//: convenient format with nested braces:
+//:
+//:   {
+//:     some instructions
+//:     {
+//:       more instructions
+//:     }
+//:   }
+//:
+//: Braces are just labels, they require no special parsing. The operations
+//: 'loop' and 'break' jump to just after the enclosing '{' and '}'
+//: respectively.
+//:
+//: Conditional and unconditional 'loop' and 'break' should give us 80% of the
+//: benefits of the control-flow primitives we're used to in other languages,
+//: like 'if', 'while', 'for', etc.
+
+:(scenario "brace_conversion")
+recipe main [
+  {
+    break
+    1:integer <- copy 0:literal
+  }
+]
++after-brace: recipe main
++after-brace: jump 1:offset
++after-brace: copy ...
+
+//: one-time setup
+:(after "int main")
+Transform.push_back(transform_braces);
+
+:(code)
+void transform_braces(const recipe_number r) {
+  const int OPEN = 0, CLOSE = 1;
+  list<pair<int/*OPEN/CLOSE*/, size_t/*step index*/> > braces;
+  for (size_t index = 0; index < Recipe[r].steps.size(); ++index) {
+    const instruction& inst = Recipe[r].steps[index];
+    if (inst.label == "{") {
+      trace("brace") << r << ": push (open, " << index << ")";
+      braces.push_back(pair<int,size_t>(OPEN, index));
+    }
+    if (inst.label == "}") {
+      trace("brace") << "push (close, " << index << ")";
+      braces.push_back(pair<int,size_t>(CLOSE, index));
+    }
+  }
+  stack<size_t/*step index*/> open_braces;
+  trace("after-brace") << "recipe " << Recipe[r].name;
+  for (size_t index = 0; index < Recipe[r].steps.size(); ++index) {
+    instruction& inst = Recipe[r].steps[index];
+    if (inst.label == "{") open_braces.push(index);
+    else if (inst.label == "}") open_braces.pop();
+    else if (inst.operation == Recipe_number["loop"]) {
+      inst.operation = Recipe_number["jump"];
+      if (inst.ingredients.size() > 0 && inst.ingredients[0].types[0] == 0) {
+        // explicit target; a later phase will handle it
+        ;
+      }
+      else {
+        reagent ing(0);  // literal
+        ing.value = open_braces.top()-index;
+        inst.ingredients.push_back(ing);
+        trace("after-brace") << "jump " << ing.value << ":offset";
+      }
+    }
+    else if (inst.operation == Recipe_number["break"]) {
+      inst.operation = Recipe_number["jump"];
+      if (inst.ingredients.size() > 0 && inst.ingredients[0].types[0] == 0) {
+        // explicit target; a later phase will handle it
+        ;
+      }
+      else {
+        reagent ing(0);  // literal
+        ing.value = index - matching_brace(open_braces.top(), braces) - 1;
+        inst.ingredients.push_back(ing);
+        trace("after-brace") << "jump " << ing.value << ":offset";
+      }
+    }
+    else {
+      trace("after-brace") << inst.name << " ...";
+    }
+  }
+}
+
+size_t matching_brace(size_t index, const list<pair<int, size_t> >& braces) {
+  int stacksize;
+  for (list<pair<int, size_t> >::const_iterator p = braces.begin(); p != braces.end(); ++p) {
+    if (p->second <= index) continue;
+    stacksize += (p->first ? 1 : -1);
+    if (stacksize == -1) return p->second;
+  }
+  return -1;
+}
+
+:(scenario "loop")
+recipe main [
+  1:integer <- copy 0:literal
+  2:integer <- copy 0:literal
+  {
+    3:integer <- copy 0:literal
+    loop
+  }
+]
++after-brace: recipe main
++after-brace: copy ...
++after-brace: copy ...
++after-brace: copy ...
++after-brace: jump -2:offset