about summary refs log tree commit diff stats
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/020run23
-rw-r--r--cpp/021arithmetic52
-rw-r--r--cpp/022boolean26
-rw-r--r--cpp/023jump16
-rw-r--r--cpp/024compare50
-rw-r--r--cpp/025trace8
-rw-r--r--cpp/030container24
-rw-r--r--cpp/032array20
-rw-r--r--cpp/033length4
-rw-r--r--cpp/034exclusive_container12
-rw-r--r--cpp/035call10
-rw-r--r--cpp/036call_ingredient30
-rw-r--r--cpp/037call_reply4
-rw-r--r--cpp/042new20
-rw-r--r--cpp/070display10
-rw-r--r--cpp/090debug8
16 files changed, 162 insertions, 155 deletions
diff --git a/cpp/020run b/cpp/020run
index e4ffafc7..41b62f80 100644
--- a/cpp/020run
+++ b/cpp/020run
@@ -52,26 +52,25 @@ void run_current_routine()
   while (!Current_routine->completed())  // later layers will modify condition
   {
     // Running One Instruction.
-    vector<instruction>& instructions = steps();
     size_t& pc = running_at();
 //?     trace("foo") << "2: " << pc << " " << &pc; //? 1
-    if (instructions[pc].is_label) { ++pc; continue; }
+    if (current_instruction().is_label) { ++pc; continue; }
 //?     cout << "AAA " << Trace_stream << " ^" << Trace_stream->dump_layer << "$\n"; //? 1
 //?     trace("foo") << "2.5: " << pc << " " << &pc; //? 1
     trace("run") << "instruction " << recipe_name() << '/' << pc;
-//?     cout << "operation " << instructions[pc].operation << '\n'; //? 3
-//?     if (!instructions[pc].products.empty()) trace("foo") << "AAA product 0 is " << instructions[pc].products[0].to_string(); //? 1
-    switch (instructions[pc].operation) {
+//?     cout << "operation " << current_instruction().operation << '\n'; //? 3
+//?     if (!current_instruction().products.empty()) trace("foo") << "AAA product 0 is " << current_instruction().products[0].to_string(); //? 1
+    switch (current_instruction().operation) {
       // Primitive Recipe Implementations
       case COPY: {
-        trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-        vector<int> data = read_memory(instructions[pc].ingredients[0]);
-        write_memory(instructions[pc].products[0], data);
+        trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+        vector<int> data = read_memory(current_instruction().ingredients[0]);
+        write_memory(current_instruction().products[0], data);
         break;
       }
       // End Primitive Recipe Implementations
       default: {
-        cout << "not a primitive op: " << instructions[pc].operation << '\n';
+        cout << "not a primitive op: " << current_instruction().operation << '\n';
       }
     }
 //?     trace("foo") << "3: " << pc << " " << &pc; //? 1
@@ -96,8 +95,12 @@ inline vector<instruction>& steps() {
   return Recipe[Current_routine->running_recipe].steps;
 }
 
+inline const instruction& current_instruction() {
+  return Recipe[Current_routine->running_recipe].steps[Current_routine->running_at];
+}
+
 inline bool routine::completed() const {
-  return running_step_index >= Recipe[running_recipe].steps.size();
+  return Current_routine->running_at >= Recipe[running_recipe].steps.size();
 }
 
 :(before "End Commandline Parsing")
diff --git a/cpp/021arithmetic b/cpp/021arithmetic
index 8f4b9c3b..7f7ab0f0 100644
--- a/cpp/021arithmetic
+++ b/cpp/021arithmetic
@@ -6,16 +6,16 @@ ADD,
 Recipe_number["add"] = ADD;
 :(before "End Primitive Recipe Implementations")
 case ADD: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] + arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -49,16 +49,16 @@ SUBTRACT,
 Recipe_number["subtract"] = SUBTRACT;
 :(before "End Primitive Recipe Implementations")
 case SUBTRACT: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] - arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -92,17 +92,17 @@ MULTIPLY,
 Recipe_number["multiply"] = MULTIPLY;
 :(before "End Primitive Recipe Implementations")
 case MULTIPLY: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   trace("run") << "ingredient 1 is " << arg1[0];
   vector<int> result;
   result.push_back(arg0[0] * arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -136,17 +136,17 @@ DIVIDE,
 Recipe_number["divide"] = DIVIDE;
 :(before "End Primitive Recipe Implementations")
 case DIVIDE: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   trace("run") << "ingredient 1 is " << arg1[0];
   vector<int> result;
   result.push_back(arg0[0] / arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -180,20 +180,20 @@ DIVIDE_WITH_REMAINDER,
 Recipe_number["divide-with-remainder"] = DIVIDE_WITH_REMAINDER;
 :(before "End Primitive Recipe Implementations")
 case DIVIDE_WITH_REMAINDER: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result0;
   result0.push_back(arg0[0] / arg1[0]);
   trace("run") << "product 0 is " << result0[0];
-  write_memory(instructions[pc].products[0], result0);
+  write_memory(current_instruction().products[0], result0);
   vector<int> result1;
   result1.push_back(arg0[0] % arg1[0]);
   trace("run") << "product 1 is " << result1[0];
-  write_memory(instructions[pc].products[1], result1);
+  write_memory(current_instruction().products[1], result1);
   break;
 }
 
diff --git a/cpp/022boolean b/cpp/022boolean
index 1aef69d9..014774db 100644
--- a/cpp/022boolean
+++ b/cpp/022boolean
@@ -6,16 +6,16 @@ AND,
 Recipe_number["and"] = AND;
 :(before "End Primitive Recipe Implementations")
 case AND: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] && arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -39,16 +39,16 @@ OR,
 Recipe_number["or"] = OR;
 :(before "End Primitive Recipe Implementations")
 case OR: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] || arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -72,13 +72,13 @@ NOT,
 Recipe_number["not"] = NOT;
 :(before "End Primitive Recipe Implementations")
 case NOT: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
   vector<int> result;
   result.push_back(!arg0[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
diff --git a/cpp/023jump b/cpp/023jump
index 2835e040..d4dd6094 100644
--- a/cpp/023jump
+++ b/cpp/023jump
@@ -6,8 +6,8 @@ JUMP,
 Recipe_number["jump"] = JUMP;
 :(before "End Primitive Recipe Implementations")
 case JUMP: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].value;
-  pc += instructions[pc].ingredients[0].value;
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].value;
+  pc += current_instruction().ingredients[0].value;
   trace("run") << "jumping to instruction " << pc+1;
   break;
 }
@@ -39,15 +39,15 @@ JUMP_IF,
 Recipe_number["jump-if"] = JUMP_IF;
 :(before "End Primitive Recipe Implementations")
 case JUMP_IF: {
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
   trace("run") << "ingredient 0 is " << arg0[0];
   if (!arg0[0]) {
     trace("run") << "jump-if fell through";
     break;
   }
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  pc += instructions[pc].ingredients[1].value;
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  pc += current_instruction().ingredients[1].value;
   trace("run") << "jumping to instruction " << pc+1;
   break;
 }
@@ -79,15 +79,15 @@ JUMP_UNLESS,
 Recipe_number["jump-unless"] = JUMP_UNLESS;
 :(before "End Primitive Recipe Implementations")
 case JUMP_UNLESS: {
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
   trace("run") << "ingredient 0 is " << arg0[0];
   if (arg0[0]) {
     trace("run") << "jump-unless fell through";
     break;
   }
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  pc += instructions[pc].ingredients[1].value;
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  pc += current_instruction().ingredients[1].value;
   trace("run") << "jumping to instruction " << pc+1;
   break;
 }
diff --git a/cpp/024compare b/cpp/024compare
index c536b23e..3445809c 100644
--- a/cpp/024compare
+++ b/cpp/024compare
@@ -6,14 +6,14 @@ EQUAL,
 Recipe_number["equal"] = EQUAL;
 :(before "End Primitive Recipe Implementations")
 case EQUAL: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   vector<int> result;
   result.push_back(equal(arg0.begin(), arg0.end(), arg1.begin()));
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -51,16 +51,16 @@ GREATER_THAN,
 Recipe_number["greater-than"] = GREATER_THAN;
 :(before "End Primitive Recipe Implementations")
 case GREATER_THAN: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] > arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -98,16 +98,16 @@ LESSER_THAN,
 Recipe_number["lesser-than"] = LESSER_THAN;
 :(before "End Primitive Recipe Implementations")
 case LESSER_THAN: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] < arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -145,16 +145,16 @@ GREATER_OR_EQUAL,
 Recipe_number["greater-or-equal"] = GREATER_OR_EQUAL;
 :(before "End Primitive Recipe Implementations")
 case GREATER_OR_EQUAL: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] >= arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -206,16 +206,16 @@ LESSER_OR_EQUAL,
 Recipe_number["lesser-or-equal"] = LESSER_OR_EQUAL;
 :(before "End Primitive Recipe Implementations")
 case LESSER_OR_EQUAL: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  vector<int> arg0 = read_memory(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  vector<int> arg0 = read_memory(current_instruction().ingredients[0]);
   assert(arg0.size() == 1);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  vector<int> arg1 = read_memory(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  vector<int> arg1 = read_memory(current_instruction().ingredients[1]);
   assert(arg1.size() == 1);
   vector<int> result;
   result.push_back(arg0[0] <= arg1[0]);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
diff --git a/cpp/025trace b/cpp/025trace
index 017c24b9..ae06cb8b 100644
--- a/cpp/025trace
+++ b/cpp/025trace
@@ -12,10 +12,10 @@ TRACE,
 Recipe_number["trace"] = TRACE;
 :(before "End Primitive Recipe Implementations")
 case TRACE: {
-  assert(isa_literal(instructions[pc].ingredients[0]));
-  string label = instructions[pc].ingredients[0].name;
-  assert(isa_literal(instructions[pc].ingredients[1]));
-  string message = instructions[pc].ingredients[1].name;
+  assert(isa_literal(current_instruction().ingredients[0]));
+  string label = current_instruction().ingredients[0].name;
+  assert(isa_literal(current_instruction().ingredients[1]));
+  string message = current_instruction().ingredients[1].name;
   trace(label) << message;
   break;
 }
diff --git a/cpp/030container b/cpp/030container
index 9069f576..1741af1b 100644
--- a/cpp/030container
+++ b/cpp/030container
@@ -81,14 +81,14 @@ GET,
 Recipe_number["get"] = GET;
 :(before "End Primitive Recipe Implementations")
 case GET: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  reagent base = instructions[pc].ingredients[0];
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  reagent base = current_instruction().ingredients[0];
   int base_address = base.value;
   int base_type = base.types[0];
   assert(Type[base_type].kind == container);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  assert(isa_literal(instructions[pc].ingredients[1]));
-  size_t offset = instructions[pc].ingredients[1].value;
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  assert(isa_literal(current_instruction().ingredients[1]));
+  size_t offset = current_instruction().ingredients[1].value;
   int src = base_address;
   for (size_t i = 0; i < offset; ++i) {
     src += size_of(Type[base_type].elements[i]);
@@ -103,7 +103,7 @@ case GET: {
   tmp.types.push_back(src_type);
   vector<int> result(read_memory(tmp));
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
 
@@ -148,14 +148,14 @@ GET_ADDRESS,
 Recipe_number["get-address"] = GET_ADDRESS;
 :(before "End Primitive Recipe Implementations")
 case GET_ADDRESS: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  reagent base = instructions[pc].ingredients[0];
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  reagent base = current_instruction().ingredients[0];
   int base_address = base.value;
   int base_type = base.types[0];
   assert(Type[base_type].kind == container);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  assert(isa_literal(instructions[pc].ingredients[1]));
-  size_t offset = instructions[pc].ingredients[1].value;
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  assert(isa_literal(current_instruction().ingredients[1]));
+  size_t offset = current_instruction().ingredients[1].value;
   int src = base_address;
   for (size_t i = 0; i < offset; ++i) {
     src += size_of(Type[base_type].elements[i]);
@@ -164,6 +164,6 @@ case GET_ADDRESS: {
   vector<int> result;
   result.push_back(src);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
diff --git a/cpp/032array b/cpp/032array
index 1c5c58c4..9ea08a16 100644
--- a/cpp/032array
+++ b/cpp/032array
@@ -97,13 +97,13 @@ Recipe_number["index"] = INDEX;
 case INDEX: {
   static const int ARRAY = Type_number["array"];
 //?   if (Trace_stream) Trace_stream->dump_layer = "run"; //? 1
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].to_string();
-  reagent base = canonize(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].to_string();
+  reagent base = canonize(current_instruction().ingredients[0]);
 //?   trace("run") << "ingredient 0 after canonize: " << base.to_string(); //? 1
   int base_address = base.value;
   assert(base.types[0] == ARRAY);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].to_string();
-  reagent offset = canonize(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].to_string();
+  reagent offset = canonize(current_instruction().ingredients[1]);
 //?   trace("run") << "ingredient 1 after canonize: " << offset.to_string(); //? 1
   vector<int> offset_val(read_memory(offset));
   vector<type_number> element_type = array_element(base.types);
@@ -118,7 +118,7 @@ case INDEX: {
 //?   trace("run") << "AAA: " << tmp.to_string() << '\n'; //? 3
   vector<int> result(read_memory(tmp));
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
 //?   if (Trace_stream) Trace_stream->dump_layer = ""; //? 1
   break;
 }
@@ -162,12 +162,12 @@ Recipe_number["index-address"] = INDEX_ADDRESS;
 :(before "End Primitive Recipe Implementations")
 case INDEX_ADDRESS: {
   static const int ARRAY = Type_number["array"];
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  reagent base = canonize(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  reagent base = canonize(current_instruction().ingredients[0]);
   int base_address = base.value;
   assert(base.types[0] == ARRAY);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].to_string();
-  reagent offset = canonize(instructions[pc].ingredients[1]);
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].to_string();
+  reagent offset = canonize(current_instruction().ingredients[1]);
   vector<int> offset_val(read_memory(offset));
   vector<type_number> element_type = array_element(base.types);
   int src = base_address + 1 + offset_val[0]*size_of(element_type);
@@ -175,6 +175,6 @@ case INDEX_ADDRESS: {
   vector<int> result;
   result.push_back(src);
   trace("run") << "product 0 is " << result[0];
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
diff --git a/cpp/033length b/cpp/033length
index 01199ce6..5281287d 100644
--- a/cpp/033length
+++ b/cpp/033length
@@ -17,7 +17,7 @@ LENGTH,
 Recipe_number["length"] = LENGTH;
 :(before "End Primitive Recipe Implementations")
 case LENGTH: {
-  reagent x = canonize(instructions[pc].ingredients[0]);
+  reagent x = canonize(current_instruction().ingredients[0]);
   if (x.types[0] != Type_number["array"]) {
     raise << "tried to calculate length of non-array " << x.to_string() << '\n';
     break;
@@ -25,6 +25,6 @@ case LENGTH: {
   vector<int> result;
 //?   cout << "length: " << x.value << '\n'; //? 1
   result.push_back(Memory[x.value]);
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
diff --git a/cpp/034exclusive_container b/cpp/034exclusive_container
index d9f266c0..89a4f921 100644
--- a/cpp/034exclusive_container
+++ b/cpp/034exclusive_container
@@ -88,14 +88,14 @@ MAYBE_CONVERT,
 Recipe_number["maybe-convert"] = MAYBE_CONVERT;
 :(before "End Primitive Recipe Implementations")
 case MAYBE_CONVERT: {
-  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
-  reagent base = canonize(instructions[pc].ingredients[0]);
+  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
+  reagent base = canonize(current_instruction().ingredients[0]);
   int base_address = base.value;
   int base_type = base.types[0];
   assert(Type[base_type].kind == exclusive_container);
-  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
-  assert(isa_literal(instructions[pc].ingredients[1]));
-  size_t tag = instructions[pc].ingredients[1].value;
+  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
+  assert(isa_literal(current_instruction().ingredients[1]));
+  size_t tag = current_instruction().ingredients[1].value;
   vector<int> result;
   if (tag == static_cast<size_t>(Memory[base_address])) {
     result.push_back(base_address+1);
@@ -103,6 +103,6 @@ case MAYBE_CONVERT: {
   else {
     result.push_back(0);
   }
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   break;
 }
diff --git a/cpp/035call b/cpp/035call
index c7052e62..799cb739 100644
--- a/cpp/035call
+++ b/cpp/035call
@@ -65,15 +65,19 @@ inline string recipe_name() {
 inline vector<instruction>& steps() {
   return Recipe[Current_routine->calls.top().running_recipe].steps;
 }
+:(replace{} "inline const instruction& current_instruction()")
+inline const instruction& current_instruction() {
+  return Recipe[Current_routine->calls.top().running_recipe].steps[Current_routine->calls.top().pc];
+}
 
 :(replace{} "default:" following "End Primitive Recipe Implementations")
 default: {
   // not a primitive; try to look up the book of recipes
-  if (Recipe.find(instructions[pc].operation) == Recipe.end()) {
-    raise << "undefined operation " << instructions[pc].operation << ": " << instructions[pc].name << '\n';
+  if (Recipe.find(current_instruction().operation) == Recipe.end()) {
+    raise << "undefined operation " << current_instruction().operation << ": " << current_instruction().name << '\n';
     break;
   }
-  Current_routine->calls.push(call(instructions[pc].operation));
+  Current_routine->calls.push(call(current_instruction().operation));
   continue;  // not done with caller; don't increment pc
 }
 
diff --git a/cpp/036call_ingredient b/cpp/036call_ingredient
index 5c222fc4..08894690 100644
--- a/cpp/036call_ingredient
+++ b/cpp/036call_ingredient
@@ -28,9 +28,9 @@ size_t next_ingredient_to_process;
 :(replace{} "call(recipe_number r)")
 call(recipe_number r) :running_recipe(r), pc(0), next_ingredient_to_process(0) {}
 
-:(replace "Current_routine->calls.push(call(instructions[pc].operation))" following "End Primitive Recipe Implementations")
-call callee(instructions[pc].operation);
-for (vector<reagent>::iterator p = instructions[pc].ingredients.begin(); p != instructions[pc].ingredients.end(); ++p) {
+:(replace "Current_routine->calls.push(call(current_instruction().operation))" following "End Primitive Recipe Implementations")
+call callee(current_instruction().operation);
+for (vector<reagent>::const_iterator p = current_instruction().ingredients.begin(); p != current_instruction().ingredients.end(); ++p) {
   callee.ingredient_atoms.push_back(read_memory(*p));
 }
 Current_routine->calls.push(callee);
@@ -44,20 +44,20 @@ case NEXT_INGREDIENT: {
   if (Current_routine->calls.top().next_ingredient_to_process < Current_routine->calls.top().ingredient_atoms.size()) {
     trace("run") << "product 0 is "
         << Current_routine->calls.top().ingredient_atoms[Current_routine->calls.top().next_ingredient_to_process][0];
-    write_memory(instructions[pc].products[0],
+    write_memory(current_instruction().products[0],
         Current_routine->calls.top().ingredient_atoms[Current_routine->calls.top().next_ingredient_to_process]);
-    if (instructions[pc].products.size() > 1) {
+    if (current_instruction().products.size() > 1) {
       vector<int> ingredient_exists;
       ingredient_exists.push_back(1);
-      write_memory(instructions[pc].products[1], ingredient_exists);
+      write_memory(current_instruction().products[1], ingredient_exists);
     }
     ++Current_routine->calls.top().next_ingredient_to_process;
   }
   else {
-    if (instructions[pc].products.size() > 1) {
+    if (current_instruction().products.size() > 1) {
       vector<int> no_ingredient;
       no_ingredient.push_back(0);
-      write_memory(instructions[pc].products[1], no_ingredient);
+      write_memory(current_instruction().products[1], no_ingredient);
     }
   }
   break;
@@ -105,24 +105,24 @@ INGREDIENT,
 Recipe_number["ingredient"] = INGREDIENT;
 :(before "End Primitive Recipe Implementations")
 case INGREDIENT: {
-  if (static_cast<size_t>(instructions[pc].ingredients[0].value) < Current_routine->calls.top().ingredient_atoms.size()) {
-    Current_routine->calls.top().next_ingredient_to_process = instructions[pc].ingredients[0].value;
+  if (static_cast<size_t>(current_instruction().ingredients[0].value) < Current_routine->calls.top().ingredient_atoms.size()) {
+    Current_routine->calls.top().next_ingredient_to_process = current_instruction().ingredients[0].value;
     trace("run") << "product 0 is "
         << Current_routine->calls.top().ingredient_atoms[Current_routine->calls.top().next_ingredient_to_process][0];
-    write_memory(instructions[pc].products[0],
+    write_memory(current_instruction().products[0],
         Current_routine->calls.top().ingredient_atoms[Current_routine->calls.top().next_ingredient_to_process]);
-    if (instructions[pc].products.size() > 1) {
+    if (current_instruction().products.size() > 1) {
       vector<int> ingredient_exists;
       ingredient_exists.push_back(1);
-      write_memory(instructions[pc].products[1], ingredient_exists);
+      write_memory(current_instruction().products[1], ingredient_exists);
     }
     ++Current_routine->calls.top().next_ingredient_to_process;
   }
   else {
-    if (instructions[pc].products.size() > 1) {
+    if (current_instruction().products.size() > 1) {
       vector<int> no_ingredient;
       no_ingredient.push_back(0);
-      write_memory(instructions[pc].products[1], no_ingredient);
+      write_memory(current_instruction().products[1], no_ingredient);
     }
   }
   break;
diff --git a/cpp/037call_reply b/cpp/037call_reply
index 76e0ab9f..97e93fe3 100644
--- a/cpp/037call_reply
+++ b/cpp/037call_reply
@@ -22,8 +22,8 @@ Recipe_number["reply"] = REPLY;
 :(before "End Primitive Recipe Implementations")
 case REPLY: {
   vector<vector<int> > callee_results;
-  for (size_t i = 0; i < instructions[pc].ingredients.size(); ++i) {
-    callee_results.push_back(read_memory(instructions[pc].ingredients[i]));
+  for (size_t i = 0; i < current_instruction().ingredients.size(); ++i) {
+    callee_results.push_back(read_memory(current_instruction().ingredients[i]));
   }
   Current_routine->calls.pop();
   assert(!Current_routine->calls.empty());
diff --git a/cpp/042new b/cpp/042new
index 0fa7e16a..d45a7c56 100644
--- a/cpp/042new
+++ b/cpp/042new
@@ -47,12 +47,12 @@ case NEW: {
   vector<int> result;
   trace("mem") << "new alloc: " << Current_routine->alloc;
   result.push_back(Current_routine->alloc);
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   vector<int> types;
-  types.push_back(instructions[pc].ingredients[0].value);
-  if (instructions[pc].ingredients.size() > 1) {
+  types.push_back(current_instruction().ingredients[0].value);
+  if (current_instruction().ingredients.size() > 1) {
     // array
-    vector<int> capacity = read_memory(instructions[pc].ingredients[1]);
+    vector<int> capacity = read_memory(current_instruction().ingredients[1]);
     trace("mem") << "array size is " << capacity[0];
     Memory[Current_routine->alloc] = capacity[0];
     Current_routine->alloc += capacity[0]*size_of(types);
@@ -87,16 +87,16 @@ recipe main [
 +mem: storing 101 in location 2
 
 :(after "case NEW" following "Primitive Recipe Implementations")
-if (instructions[pc].ingredients[0].properties[0].second[0] == "literal-string") {
+if (current_instruction().ingredients[0].properties[0].second[0] == "literal-string") {
   // allocate an array just large enough for it
   vector<int> result;
   result.push_back(Current_routine->alloc);
-  write_memory(instructions[pc].products[0], result);
+  write_memory(current_instruction().products[0], result);
   // assume that all characters fit in a single location
-//?   cout << "new string literal: " << instructions[pc].ingredients[0].name << '\n'; //? 1
-  Memory[Current_routine->alloc++] = instructions[pc].ingredients[0].name.size();
-  for (size_t i = 0; i < instructions[pc].ingredients[0].name.size(); ++i) {
-    Memory[Current_routine->alloc++] = instructions[pc].ingredients[0].name[i];
+//?   cout << "new string literal: " << current_instruction().ingredients[0].name << '\n'; //? 1
+  Memory[Current_routine->alloc++] = current_instruction().ingredients[0].name.size();
+  for (size_t i = 0; i < current_instruction().ingredients[0].name.size(); ++i) {
+    Memory[Current_routine->alloc++] = current_instruction().ingredients[0].name[i];
   }
   // mu strings are not null-terminated in memory
   break;
diff --git a/cpp/070display b/cpp/070display
index feb16fe1..bf2ff85f 100644
--- a/cpp/070display
+++ b/cpp/070display
@@ -58,7 +58,7 @@ PRINT_CHARACTER_TO_DISPLAY,
 Recipe_number["print-character-to-display"] = PRINT_CHARACTER_TO_DISPLAY;
 :(before "End Primitive Recipe Implementations")
 case PRINT_CHARACTER_TO_DISPLAY: {
-  vector<int> arg = read_memory(instructions[pc].ingredients[0]);
+  vector<int> arg = read_memory(current_instruction().ingredients[0]);
   int h=tb_height(), w=tb_width();
   size_t height = (h >= 0) ? h : 0;
   size_t width = (w >= 0) ? w : 0;
@@ -88,10 +88,10 @@ Recipe_number["cursor-position-on-display"] = CURSOR_POSITION_ON_DISPLAY;
 case CURSOR_POSITION_ON_DISPLAY: {
   vector<int> row;
   row.push_back(Display_row);
-  write_memory(instructions[pc].products[0], row);
+  write_memory(current_instruction().products[0], row);
   vector<int> column;
   column.push_back(Display_column);
-  write_memory(instructions[pc].products[1], column);
+  write_memory(current_instruction().products[1], column);
   break;
 }
 
@@ -101,8 +101,8 @@ MOVE_CURSOR_ON_DISPLAY,
 Recipe_number["move-cursor-on-display"] = MOVE_CURSOR_ON_DISPLAY;
 :(before "End Primitive Recipe Implementations")
 case MOVE_CURSOR_ON_DISPLAY: {
-  vector<int> row = read_memory(instructions[pc].ingredients[0]);
-  vector<int> column = read_memory(instructions[pc].ingredients[1]);
+  vector<int> row = read_memory(current_instruction().ingredients[0]);
+  vector<int> column = read_memory(current_instruction().ingredients[1]);
   Display_row = row[0];
   Display_column = column[0];
   tb_set_cursor(Display_column, Display_row);
diff --git a/cpp/090debug b/cpp/090debug
index 4f1a0796..d81071e9 100644
--- a/cpp/090debug
+++ b/cpp/090debug
@@ -6,12 +6,12 @@ _PRINT,
 Recipe_number["$print"] = _PRINT;
 :(before "End Primitive Recipe Implementations")
 case _PRINT: {
-  if (isa_literal(instructions[pc].ingredients[0])) {
-    trace("run") << "$print: " << instructions[pc].ingredients[0].name;
-    cout << instructions[pc].ingredients[0].name;
+  if (isa_literal(current_instruction().ingredients[0])) {
+    trace("run") << "$print: " << current_instruction().ingredients[0].name;
+    cout << current_instruction().ingredients[0].name;
     break;
   }
-  vector<int> result(read_memory(instructions[pc].ingredients[0]));
+  vector<int> result(read_memory(current_instruction().ingredients[0]));
   for (size_t i = 0; i < result.size(); ++i) {
     trace("run") << "$print: " << result[i];
     if (i > 0) cout << " ";