about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--010vm.cc44
-rw-r--r--011load.cc8
-rw-r--r--014literal_string.cc6
-rw-r--r--020run.cc8
-rw-r--r--021check_instruction.cc2
-rw-r--r--022arithmetic.cc56
-rw-r--r--023boolean.cc2
-rw-r--r--024jump.cc6
-rw-r--r--025compare.cc10
-rw-r--r--029tools.cc4
-rw-r--r--030container.cc30
-rw-r--r--031address.cc4
-rw-r--r--032array.cc18
-rw-r--r--033exclusive_container.cc8
-rw-r--r--034call.cc2
-rw-r--r--035call_ingredient.cc4
-rw-r--r--036call_reply.cc6
-rw-r--r--037new.cc6
-rw-r--r--038location_array.cc2
-rw-r--r--042name.cc6
-rw-r--r--043space.cc4
-rw-r--r--045closure_name.cc6
-rw-r--r--050scenario.cc2
-rw-r--r--056recipe_header.cc14
-rw-r--r--057static_dispatch.cc10
-rw-r--r--059shape_shifting_recipe.cc10
-rw-r--r--060immutable.cc8
-rw-r--r--061recipe.cc4
-rw-r--r--062scheduler.cc8
-rw-r--r--063wait.cc4
-rw-r--r--074random.cc2
-rw-r--r--077hash.cc4
-rw-r--r--080display.cc4
-rw-r--r--091run_interactive.cc6
-rw-r--r--092persist.cc10
35 files changed, 162 insertions, 166 deletions
diff --git a/010vm.cc b/010vm.cc
index 970b88c5..ae262e42 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -21,7 +21,6 @@ struct recipe {
   vector<instruction> steps;
   // End recipe Fields
   recipe();
-  string to_string() const;
 };
 
 :(before "struct recipe")
@@ -43,7 +42,6 @@ struct instruction {
   instruction();
   void clear();
   bool is_clear();
-  string to_string() const;
 };
 
 :(before "struct instruction")
@@ -65,7 +63,6 @@ struct reagent {
   reagent(const reagent& old);
   reagent& operator=(const reagent& old);
   void set_value(double v) { value = v; initialized = true; }
-  string to_string() const;
 };
 
 :(before "struct reagent")
@@ -102,7 +99,6 @@ struct string_tree {
   // advanced: tree containing strings
   string_tree(string_tree* l, string_tree* r) :left(l), right(r) {}
   // print as s-expression
-  string to_string() const;
 };
 
 :(before "End Globals")
@@ -354,13 +350,13 @@ reagent::reagent() :value(0), initialized(false), type(NULL) {
   properties.push_back(pair<string, string_tree*>("", NULL));
 }
 
-string reagent::to_string() const {
+string to_string(const reagent& r) {
   ostringstream out;
-  if (!properties.empty()) {
+  if (!r.properties.empty()) {
     out << "{";
-    for (long long int i = 0; i < SIZE(properties); ++i) {
+    for (long long int i = 0; i < SIZE(r.properties); ++i) {
       if (i > 0) out << ", ";
-      out << "\"" << properties.at(i).first << "\": " << debug_string(properties.at(i).second);
+      out << "\"" << r.properties.at(i).first << "\": " << debug_string(r.properties.at(i).second);
     }
     out << "}";
   }
@@ -369,7 +365,7 @@ string reagent::to_string() const {
 
 string debug_string(const reagent& x) {
   ostringstream out;
-  out << x.name << ": " << debug_string(x.type) << " -- " << x.to_string();
+  out << x.name << ": " << debug_string(x.type) << " -- " << to_string(x);
   return out.str();
 }
 
@@ -430,18 +426,18 @@ void dump_type_name(type_ordinal type, ostream& out) {
     out << "?" << type;
 }
 
-string instruction::to_string() const {
-  if (is_label) return label;
+string to_string(const instruction& inst) {
+  if (inst.is_label) return inst.label;
   ostringstream out;
-  for (long long int i = 0; i < SIZE(products); ++i) {
+  for (long long int i = 0; i < SIZE(inst.products); ++i) {
     if (i > 0) out << ", ";
-    out << products.at(i).original_string;
+    out << inst.products.at(i).original_string;
   }
-  if (!products.empty()) out << " <- ";
-  out << name << ' ';
-  for (long long int i = 0; i < SIZE(ingredients); ++i) {
+  if (!inst.products.empty()) out << " <- ";
+  out << inst.name << ' ';
+  for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
     if (i > 0) out << ", ";
-    out << ingredients.at(i).original_string;
+    out << inst.ingredients.at(i).original_string;
   }
   return out.str();
 }
@@ -452,7 +448,7 @@ string debug_string(const recipe& x) {
   // Begin debug_string(recipe x)
   for (long long int index = 0; index < SIZE(x.steps); ++index) {
     const instruction& inst = x.steps.at(index);
-    out << "inst: " << inst.to_string() << '\n';
+    out << "inst: " << to_string(inst) << '\n';
     out << "  ingredients\n";
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i)
       out << "    " << debug_string(inst.ingredients.at(i)) << '\n';
@@ -497,18 +493,18 @@ void dump_memory() {
   }
 }
 
-string recipe::to_string() const {
+string to_string(const recipe& r) {
   ostringstream out;
-  out << "recipe " << name << " [\n";
-  for (long long int i = 0; i < SIZE(steps); ++i)
-    out << "  " << steps.at(i).to_string() << '\n';
+  out << "recipe " << r.name << " [\n";
+  for (long long int i = 0; i < SIZE(r.steps); ++i)
+    out << "  " << to_string(r.steps.at(i)) << '\n';
   out << "]\n";
   return out.str();
 }
 
-string string_tree::to_string() const {
+string to_string(const string_tree* x) {
   ostringstream out;
-  dump(this, out);
+  dump(x, out);
   return out.str();
 }
 
diff --git a/011load.cc b/011load.cc
index edde4044..2003eb7d 100644
--- a/011load.cc
+++ b/011load.cc
@@ -75,9 +75,9 @@ void slurp_body(istream& in, recipe& result) {
   instruction curr;
   while (next_instruction(in, &curr)) {
     // End Rewrite Instruction(curr, recipe result)
-    trace(9992, "load") << "after rewriting: " << curr.to_string() << end();
+    trace(9992, "load") << "after rewriting: " << to_string(curr) << end();
     if (!curr.is_clear()) {
-      curr.original_string = curr.to_string();
+      curr.original_string = to_string(curr);
       result.steps.push_back(curr);
     }
   }
@@ -140,10 +140,10 @@ bool next_instruction(istream& in, instruction* curr) {
   trace(9993, "parse") << "instruction: " << curr->name << end();
   trace(9993, "parse") << "  number of ingredients: " << SIZE(curr->ingredients) << end();
   for (vector<reagent>::iterator p = curr->ingredients.begin(); p != curr->ingredients.end(); ++p) {
-    trace(9993, "parse") << "  ingredient: " << p->to_string() << end();
+    trace(9993, "parse") << "  ingredient: " << to_string(*p) << end();
   }
   for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) {
-    trace(9993, "parse") << "  product: " << p->to_string() << end();
+    trace(9993, "parse") << "  product: " << to_string(*p) << end();
   }
   if (!has_data(in)) {
     raise_error << "9: unbalanced '[' for recipe\n" << end();
diff --git a/014literal_string.cc b/014literal_string.cc
index 209a6428..a94d5451 100644
--- a/014literal_string.cc
+++ b/014literal_string.cc
@@ -118,9 +118,9 @@ if (s.at(0) == '[') {
 //: Unlike other reagents, escape newlines in literal strings to make them
 //: more friendly to trace().
 
-:(after "string reagent::to_string()")
-  if (is_literal_string(*this))
-    return emit_literal_string(name);
+:(after "string to_string(const reagent& r)")
+  if (is_literal_string(r))
+    return emit_literal_string(r.name);
 
 :(code)
 bool is_literal_string(const reagent& x) {
diff --git a/020run.cc b/020run.cc
index 60c1c428..c6617607 100644
--- a/020run.cc
+++ b/020run.cc
@@ -61,7 +61,7 @@ void run_current_routine()
   {
     // Running One Instruction
     if (current_instruction().is_label) { ++current_step_index(); continue; }
-    trace(Initial_callstack_depth + Trace_stream->callstack_depth, "run") << current_instruction().to_string() << end();
+    trace(Initial_callstack_depth + Trace_stream->callstack_depth, "run") << to_string(current_instruction()) << end();
     if (get_or_insert(Memory, 0) != 0) {
       raise_error << "something wrote to location 0; this should never happen\n" << end();
       put(Memory, 0, 0);
@@ -86,7 +86,7 @@ void run_current_routine()
       }
     }
     if (SIZE(products) < SIZE(current_instruction().products)) {
-      raise_error << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products! " << current_instruction().to_string() << '\n' << end();
+      raise_error << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products! " << to_string(current_instruction()) << '\n' << end();
     }
     else {
       for (long long int i = 0; i < SIZE(current_instruction().products); ++i) {
@@ -267,7 +267,7 @@ vector<double> read_memory(reagent x) {
 
 void write_memory(reagent x, vector<double> data) {
   if (!x.type) {
-    raise_error << "can't write to " << x.to_string() << "; no type\n" << end();
+    raise_error << "can't write to " << to_string(x) << "; no type\n" << end();
     return;
   }
   if (is_dummy(x)) return;
@@ -275,7 +275,7 @@ void write_memory(reagent x, vector<double> data) {
   long long int base = x.value;
   if (base == 0) return;
   if (size_mismatch(x, data)) {
-    raise_error << maybe(current_recipe_name()) << "size mismatch in storing to " << x.original_string << " (" << size_of(x.type) << " vs " << SIZE(data) << ") at '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "size mismatch in storing to " << x.original_string << " (" << size_of(x.type) << " vs " << SIZE(data) << ") at '" << to_string(current_instruction()) << "'\n" << end();
     return;
   }
   // End write_memory(reagent x, long long int base) Special-cases
diff --git a/021check_instruction.cc b/021check_instruction.cc
index cf0a8d74..63d933f3 100644
--- a/021check_instruction.cc
+++ b/021check_instruction.cc
@@ -23,7 +23,7 @@ void check_instruction(const recipe_ordinal r) {
       // Primitive Recipe Checks
       case COPY: {
         if (SIZE(inst.products) != SIZE(inst.ingredients)) {
-          raise_error << "ingredients and products should match in '" << inst.to_string() << "'\n" << end();
+          raise_error << "ingredients and products should match in '" << to_string(inst) << "'\n" << end();
           break;
         }
         for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
diff --git a/022arithmetic.cc b/022arithmetic.cc
index 5f158517..8389074e 100644
--- a/022arithmetic.cc
+++ b/022arithmetic.cc
@@ -14,7 +14,7 @@ case ADD: {
     }
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'add' yields exactly one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'add' yields exactly one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -86,7 +86,7 @@ case SUBTRACT: {
     }
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'subtract' yields exactly one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'subtract' yields exactly one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -142,7 +142,7 @@ case MULTIPLY: {
     }
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'multiply' yields exactly one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'multiply' yields exactly one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -199,7 +199,7 @@ case DIVIDE: {
     }
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'divide' yields exactly one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'divide' yields exactly one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -247,15 +247,15 @@ put(Recipe_ordinal, "divide-with-remainder", DIVIDE_WITH_REMAINDER);
 :(before "End Primitive Recipe Checks")
 case DIVIDE_WITH_REMAINDER: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' yields two products in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'divide-with-remainder' yields two products in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.products); ++i) {
@@ -272,7 +272,7 @@ case DIVIDE_WITH_REMAINDER: {
   long long int a = static_cast<long long int>(ingredients.at(0).at(0));
   long long int b = static_cast<long long int>(ingredients.at(1).at(0));
   if (b == 0) {
-    raise_error << maybe(current_recipe_name()) << "divide by zero in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "divide by zero in '" << to_string(current_instruction()) << "'\n" << end();
     products.resize(2);
     products.at(0).push_back(0);
     products.at(1).push_back(0);
@@ -331,15 +331,15 @@ put(Recipe_ordinal, "shift-left", SHIFT_LEFT);
 :(before "End Primitive Recipe Checks")
 case SHIFT_LEFT: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-left' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-left' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -355,7 +355,7 @@ case SHIFT_LEFT: {
   long long int b = static_cast<long long int>(ingredients.at(1).at(0));
   products.resize(1);
   if (b < 0) {
-    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << to_string(current_instruction()) << "'\n" << end();
     products.at(0).push_back(0);
     break;
   }
@@ -402,15 +402,15 @@ put(Recipe_ordinal, "shift-right", SHIFT_RIGHT);
 :(before "End Primitive Recipe Checks")
 case SHIFT_RIGHT: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'shift-right' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'shift-right' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -426,7 +426,7 @@ case SHIFT_RIGHT: {
   long long int b = static_cast<long long int>(ingredients.at(1).at(0));
   products.resize(1);
   if (b < 0) {
-    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "second ingredient can't be negative in '" << to_string(current_instruction()) << "'\n" << end();
     products.at(0).push_back(0);
     break;
   }
@@ -473,15 +473,15 @@ put(Recipe_ordinal, "and-bits", AND_BITS);
 :(before "End Primitive Recipe Checks")
 case AND_BITS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'and-bits' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'and-bits' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'and-bits' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'and-bits' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'and-bits' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'and-bits' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -531,15 +531,15 @@ put(Recipe_ordinal, "or-bits", OR_BITS);
 :(before "End Primitive Recipe Checks")
 case OR_BITS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'or-bits' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'or-bits' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'or-bits' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'or-bits' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'or-bits' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'or-bits' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -583,15 +583,15 @@ put(Recipe_ordinal, "xor-bits", XOR_BITS);
 :(before "End Primitive Recipe Checks")
 case XOR_BITS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' requires number ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' requires number ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'xor-bits' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
@@ -635,15 +635,15 @@ put(Recipe_ordinal, "flip-bits", FLIP_BITS);
 :(before "End Primitive Recipe Checks")
 case FLIP_BITS: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' requires exactly one ingredient, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' requires exactly one ingredient, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
-    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' requires a number ingredient, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' requires a number ingredient, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (SIZE(inst.products) > 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' yields one product in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'flip-bits' yields one product in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) {
diff --git a/023boolean.cc b/023boolean.cc
index 13400c4c..fa962462 100644
--- a/023boolean.cc
+++ b/023boolean.cc
@@ -107,7 +107,7 @@ put(Recipe_ordinal, "not", NOT);
 :(before "End Primitive Recipe Checks")
 case NOT: {
   if (SIZE(inst.products) > SIZE(inst.ingredients)) {
-    raise_error << maybe(get(Recipe, r).name) << "'not' cannot have fewer ingredients than products in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'not' cannot have fewer ingredients than products in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
diff --git a/024jump.cc b/024jump.cc
index 95e31c55..f7228f08 100644
--- a/024jump.cc
+++ b/024jump.cc
@@ -16,7 +16,7 @@ put(Recipe_ordinal, "jump", JUMP);
 :(before "End Primitive Recipe Checks")
 case JUMP: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'jump' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'jump' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_scalar(inst.ingredients.at(0))) {
@@ -55,7 +55,7 @@ put(Recipe_ordinal, "jump-if", JUMP_IF);
 :(before "End Primitive Recipe Checks")
 case JUMP_IF: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'jump-if' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'jump-if' requires exactly two ingredients, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_scalar(inst.ingredients.at(0))) {
@@ -107,7 +107,7 @@ put(Recipe_ordinal, "jump-unless", JUMP_UNLESS);
 :(before "End Primitive Recipe Checks")
 case JUMP_UNLESS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'jump-unless' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'jump-unless' requires exactly two ingredients, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_scalar(inst.ingredients.at(0))) {
diff --git a/025compare.cc b/025compare.cc
index 056c859d..ca736ec9 100644
--- a/025compare.cc
+++ b/025compare.cc
@@ -7,7 +7,7 @@ put(Recipe_ordinal, "equal", EQUAL);
 :(before "End Primitive Recipe Checks")
 case EQUAL: {
   if (SIZE(inst.ingredients) <= 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'equal' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
     break;
   }
   break;
@@ -66,7 +66,7 @@ put(Recipe_ordinal, "greater-than", GREATER_THAN);
 :(before "End Primitive Recipe Checks")
 case GREATER_THAN: {
   if (SIZE(inst.ingredients) <= 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'greater-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'greater-than' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
@@ -125,7 +125,7 @@ put(Recipe_ordinal, "lesser-than", LESSER_THAN);
 :(before "End Primitive Recipe Checks")
 case LESSER_THAN: {
   if (SIZE(inst.ingredients) <= 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'lesser-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'lesser-than' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
@@ -184,7 +184,7 @@ put(Recipe_ordinal, "greater-or-equal", GREATER_OR_EQUAL);
 :(before "End Primitive Recipe Checks")
 case GREATER_OR_EQUAL: {
   if (SIZE(inst.ingredients) <= 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'greater-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'greater-or-equal' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
@@ -251,7 +251,7 @@ put(Recipe_ordinal, "lesser-or-equal", LESSER_OR_EQUAL);
 :(before "End Primitive Recipe Checks")
 case LESSER_OR_EQUAL: {
   if (SIZE(inst.ingredients) <= 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'lesser-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'lesser-or-equal' needs at least two ingredients to compare in '" << to_string(inst) << "'\n" << end();
     break;
   }
   for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
diff --git a/029tools.cc b/029tools.cc
index 7090abda..c379825a 100644
--- a/029tools.cc
+++ b/029tools.cc
@@ -13,7 +13,7 @@ put(Recipe_ordinal, "trace", TRACE);
 :(before "End Primitive Recipe Checks")
 case TRACE: {
   if (SIZE(inst.ingredients) < 3) {
-    raise_error << maybe(get(Recipe, r).name) << "'trace' takes three or more ingredients rather than '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'trace' takes three or more ingredients rather than '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -201,7 +201,7 @@ put(Recipe_ordinal, "assert", ASSERT);
 :(before "End Primitive Recipe Checks")
 case ASSERT: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'assert' takes exactly two ingredients rather than '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'assert' takes exactly two ingredients rather than '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_scalar(inst.ingredients.at(0))) {
diff --git a/030container.cc b/030container.cc
index 15e6471f..e88b0692 100644
--- a/030container.cc
+++ b/030container.cc
@@ -133,7 +133,7 @@ put(Recipe_ordinal, "get", GET);
 :(before "End Primitive Recipe Checks")
 case GET: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'get' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'get' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent base = inst.ingredients.at(0);  // new copy for every invocation
@@ -173,7 +173,7 @@ case GET: {
   // Update GET base in Run
   long long int base_address = base.value;
   if (base_address == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   type_ordinal base_type = base.type->value;
@@ -270,7 +270,7 @@ put(Recipe_ordinal, "get-address", GET_ADDRESS);
 :(before "End Primitive Recipe Checks")
 case GET_ADDRESS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'get-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'get-address' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent base = inst.ingredients.at(0);
@@ -314,7 +314,7 @@ case GET_ADDRESS: {
   // Update GET_ADDRESS base in Run
   long long int base_address = base.value;
   if (base_address == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   type_ordinal base_type = base.type->value;
@@ -550,11 +550,11 @@ void check_or_set_invalid_types(const recipe_ordinal r) {
     instruction& inst = caller.steps.at(index);
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
       check_or_set_invalid_types(inst.ingredients.at(i).type, inst.ingredients.at(i).properties.at(0).second,
-                                 maybe(caller.name), "'"+inst.to_string()+"'");
+                                 maybe(caller.name), "'"+to_string(inst)+"'");
     }
     for (long long int i = 0; i < SIZE(inst.products); ++i) {
       check_or_set_invalid_types(inst.products.at(i).type, inst.products.at(i).properties.at(0).second,
-                                 maybe(caller.name), "'"+inst.to_string()+"'");
+                                 maybe(caller.name), "'"+to_string(inst)+"'");
     }
   }
   // End check_or_set_invalid_types
@@ -613,11 +613,11 @@ void check_invalid_types(const recipe_ordinal r) {
     const instruction& inst = get(Recipe, r).steps.at(index);
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
       check_invalid_types(inst.ingredients.at(i).type,
-                          maybe(get(Recipe, r).name), "'"+inst.to_string()+"'");
+                          maybe(get(Recipe, r).name), "'"+to_string(inst)+"'");
     }
     for (long long int i = 0; i < SIZE(inst.products); ++i) {
       check_invalid_types(inst.products.at(i).type,
-                          maybe(get(Recipe, r).name), "'"+inst.to_string()+"'");
+                          maybe(get(Recipe, r).name), "'"+to_string(inst)+"'");
     }
   }
 }
@@ -752,19 +752,19 @@ void check_merge_calls(const recipe_ordinal r) {
     const instruction& inst = caller.steps.at(i);
     if (inst.name != "merge") continue;
     if (SIZE(inst.products) != 1) {
-      raise_error << maybe(caller.name) << "'merge' should yield a single product in '" << inst.to_string() << "'\n" << end();
+      raise_error << maybe(caller.name) << "'merge' should yield a single product in '" << to_string(inst) << "'\n" << end();
       continue;
     }
     reagent product = inst.products.at(0);
     // Update product While Type-checking Merge
     type_ordinal product_type = product.type->value;
     if (product_type == 0 || !contains_key(Type, product_type)) {
-      raise_error << maybe(caller.name) << "'merge' should yield a container in '" << inst.to_string() << "'\n" << end();
+      raise_error << maybe(caller.name) << "'merge' should yield a container in '" << to_string(inst) << "'\n" << end();
       continue;
     }
     const type_info& info = get(Type, product_type);
     if (info.kind != CONTAINER && info.kind != EXCLUSIVE_CONTAINER) {
-      raise_error << maybe(caller.name) << "'merge' should yield a container in '" << inst.to_string() << "'\n" << end();
+      raise_error << maybe(caller.name) << "'merge' should yield a container in '" << to_string(inst) << "'\n" << end();
       continue;
     }
     check_merge_call(inst.ingredients, product, caller, inst);
@@ -779,7 +779,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
     assert(!state.data.empty());
     trace(9999, "transform") << ingredient_index << " vs " << SIZE(ingredients) << end();
     if (ingredient_index >= SIZE(ingredients)) {
-      raise_error << maybe(caller.name) << "too few ingredients in '" << inst.to_string() << "'\n" << end();
+      raise_error << maybe(caller.name) << "too few ingredients in '" << to_string(inst) << "'\n" << end();
       return;
     }
     reagent& container = state.data.top().container;
@@ -796,7 +796,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
             state.data.pop();
             if (state.data.empty()) {
               if (ingredient_index < SIZE(ingredients))
-                raise_error << maybe(caller.name) << "too many ingredients in '" << inst.to_string() << "'\n" << end();
+                raise_error << maybe(caller.name) << "too many ingredients in '" << to_string(inst) << "'\n" << end();
               return;
             }
             ++state.data.top().container_element_index;
@@ -812,7 +812,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
       // End valid_merge Cases
       default: {
         if (!types_coercible(container, ingredients.at(ingredient_index))) {
-          raise_error << maybe(caller.name) << "incorrect type of ingredient " << ingredient_index << " in '" << inst.to_string() << "'\n" << end();
+          raise_error << maybe(caller.name) << "incorrect type of ingredient " << ingredient_index << " in '" << to_string(inst) << "'\n" << end();
           cerr << "  expected " << debug_string(container) << '\n';
           cerr << "  got " << debug_string(ingredients.at(ingredient_index)) << '\n';
           return;
@@ -823,7 +823,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
           state.data.pop();
           if (state.data.empty()) {
             if (ingredient_index < SIZE(ingredients))
-              raise_error << maybe(caller.name) << "too many ingredients in '" << inst.to_string() << "'\n" << end();
+              raise_error << maybe(caller.name) << "too many ingredients in '" << to_string(inst) << "'\n" << end();
             return;
           }
           ++state.data.top().container_element_index;
diff --git a/031address.cc b/031address.cc
index 5284dea1..be4dd8f8 100644
--- a/031address.cc
+++ b/031address.cc
@@ -25,7 +25,7 @@ recipe main [
 :(before "long long int base = x.value" following "void write_memory(reagent x, vector<double> data)")
 canonize(x);
 if (x.value == 0) {
-  raise_error << "can't write to location 0 in '" << current_instruction().to_string() << "'\n" << end();
+  raise_error << "can't write to location 0 in '" << to_string(current_instruction()) << "'\n" << end();
   return;
 }
 
@@ -91,7 +91,7 @@ if (!canonize_type(product)) continue;
 bool canonize_type(reagent& r) {
   while (has_property(r, "lookup")) {
     if (!r.type || r.type->value != get(Type_ordinal, "address")) {
-      raise_error << "can't lookup non-address: " << r.to_string() << ": " << debug_string(r.type) << '\n' << end();
+      raise_error << "can't lookup non-address: " << to_string(r) << ": " << debug_string(r.type) << '\n' << end();
       return false;
     }
     drop_from_type(r, "address");
diff --git a/032array.cc b/032array.cc
index b558d98f..d25ee7fa 100644
--- a/032array.cc
+++ b/032array.cc
@@ -20,7 +20,7 @@ put(Recipe_ordinal, "create-array", CREATE_ARRAY);
 :(before "End Primitive Recipe Checks")
 case CREATE_ARRAY: {
   if (inst.products.empty()) {
-    raise_error << maybe(get(Recipe, r).name) << "'create-array' needs one product and no ingredients but got '" << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'create-array' needs one product and no ingredients but got '" << to_string(inst) << '\n' << end();
     break;
   }
   reagent product = inst.products.at(0);
@@ -30,12 +30,12 @@ case CREATE_ARRAY: {
     break;
   }
   if (!product.type->right) {
-    raise_error << maybe(get(Recipe, r).name) << "create array of what? " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "create array of what? " << to_string(inst) << '\n' << end();
     break;
   }
   // 'create-array' will need to check properties rather than types
   if (!product.properties.at(0).second || !product.properties.at(0).second->right || !product.properties.at(0).second->right->right) {
-    raise_error << maybe(get(Recipe, r).name) << "create array of what size? " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "create array of what size? " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_integer(product.properties.at(0).second->right->right->value)) {
@@ -178,7 +178,7 @@ put(Recipe_ordinal, "index", INDEX);
 :(before "End Primitive Recipe Checks")
 case INDEX: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'index' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'index' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent base = inst.ingredients.at(0);
@@ -205,7 +205,7 @@ case INDEX: {
   long long int base_address = base.value;
   trace(9998, "run") << "base address is " << base_address << end();
   if (base_address == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   reagent offset = current_instruction().ingredients.at(1);
@@ -318,7 +318,7 @@ put(Recipe_ordinal, "index-address", INDEX_ADDRESS);
 :(before "End Primitive Recipe Checks")
 case INDEX_ADDRESS: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'index-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'index-address' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent base = inst.ingredients.at(0);
@@ -345,7 +345,7 @@ case INDEX_ADDRESS: {
   canonize(base);
   long long int base_address = base.value;
   if (base_address == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   reagent offset = current_instruction().ingredients.at(1);
@@ -426,7 +426,7 @@ put(Recipe_ordinal, "length", LENGTH);
 :(before "End Primitive Recipe Checks")
 case LENGTH: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'length' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'length' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent x = inst.ingredients.at(0);
@@ -442,7 +442,7 @@ case LENGTH: {
   reagent x = current_instruction().ingredients.at(0);
   canonize(x);
   if (x.value == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   products.resize(1);
diff --git a/033exclusive_container.cc b/033exclusive_container.cc
index ec77e639..b5116914 100644
--- a/033exclusive_container.cc
+++ b/033exclusive_container.cc
@@ -81,7 +81,7 @@ put(Recipe_ordinal, "maybe-convert", MAYBE_CONVERT);
 case MAYBE_CONVERT: {
   const recipe& caller = get(Recipe, r);
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(caller.name) << "'maybe-convert' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(caller.name) << "'maybe-convert' expects exactly 2 ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent base = inst.ingredients.at(0);
@@ -100,7 +100,7 @@ case MAYBE_CONVERT: {
   reagent& offset = inst.ingredients.at(1);
   populate_value(offset);
   if (offset.value >= SIZE(get(Type, base.type->value).elements)) {
-    raise_error << maybe(caller.name) << "invalid tag " << offset.value << " in '" << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "invalid tag " << offset.value << " in '" << to_string(inst) << '\n' << end();
     break;
   }
   reagent variant = variant_type(base, offset.value);
@@ -117,7 +117,7 @@ case MAYBE_CONVERT: {
   canonize(base);
   long long int base_address = base.value;
   if (base_address == 0) {
-    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end();
+    raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_string(current_instruction()) << "'\n" << end();
     break;
   }
   long long int tag = current_instruction().ingredients.at(1).value;
@@ -251,7 +251,7 @@ case EXCLUSIVE_CONTAINER: {
   reagent ingredient = ingredients.at(ingredient_index);  // unnecessary copy just to keep this function from modifying caller
   populate_value(ingredient);
   if (ingredient.value >= SIZE(container_info.elements)) {
-    raise_error << maybe(caller.name) << "invalid tag at " << ingredient_index << " for " << container_info.name << " in '" << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "invalid tag at " << ingredient_index << " for " << container_info.name << " in '" << to_string(inst) << '\n' << end();
     return;
   }
   reagent variant = variant_type(container, ingredient.value);
diff --git a/034call.cc b/034call.cc
index f9ba5def..6ab18ba4 100644
--- a/034call.cc
+++ b/034call.cc
@@ -97,7 +97,7 @@ inline const instruction& to_instruction(const call& call) {
 :(after "Defined Recipe Checks")
 // not a primitive; check that it's present in the book of recipes
 if (!contains_key(Recipe, inst.operation)) {
-  raise_error << maybe(get(Recipe, r).name) << "undefined operation in '" << inst.to_string() << "'\n" << end();
+  raise_error << maybe(get(Recipe, r).name) << "undefined operation in '" << to_string(inst) << "'\n" << end();
   break;
 }
 :(replace{} "default:" following "End Primitive Recipe Implementations")
diff --git a/035call_ingredient.cc b/035call_ingredient.cc
index f079f0c5..466078dc 100644
--- a/035call_ingredient.cc
+++ b/035call_ingredient.cc
@@ -42,7 +42,7 @@ put(Recipe_ordinal, "next-ingredient", NEXT_INGREDIENT);
 :(before "End Primitive Recipe Checks")
 case NEXT_INGREDIENT: {
   if (!inst.ingredients.empty()) {
-    raise_error << maybe(get(Recipe, r).name) << "'next-ingredient' didn't expect any ingredients in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'next-ingredient' didn't expect any ingredients in '" << to_string(inst) << "'\n" << end();
     break;
   }
   break;
@@ -141,7 +141,7 @@ put(Recipe_ordinal, "ingredient", INGREDIENT);
 :(before "End Primitive Recipe Checks")
 case INGREDIENT: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'ingredient' expects exactly one ingredient, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'ingredient' expects exactly one ingredient, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_literal(inst.ingredients.at(0)) && !is_mu_number(inst.ingredients.at(0))) {
diff --git a/036call_reply.cc b/036call_reply.cc
index eb4c1aba..ee295aa2 100644
--- a/036call_reply.cc
+++ b/036call_reply.cc
@@ -97,16 +97,16 @@ void check_types_of_reply_instructions(recipe_ordinal r) {
         if (has_property(reply_inst.ingredients.at(i), "same-as-ingredient")) {
           string_tree* tmp = property(reply_inst.ingredients.at(i), "same-as-ingredient");
           if (!tmp || tmp->right) {
-            raise_error << maybe(caller.name) << "'same-as-ingredient' metadata should take exactly one value in " << reply_inst.to_string() << '\n' << end();
+            raise_error << maybe(caller.name) << "'same-as-ingredient' metadata should take exactly one value in " << to_string(reply_inst) << '\n' << end();
             goto finish_reply_check;
           }
           long long int ingredient_index = to_integer(tmp->value);
           if (ingredient_index >= SIZE(caller_instruction.ingredients)) {
-            raise_error << maybe(caller.name) << "too few ingredients in '" << caller_instruction.to_string() << "'\n" << end();
+            raise_error << maybe(caller.name) << "too few ingredients in '" << to_string(caller_instruction) << "'\n" << end();
             goto finish_reply_check;
           }
           if (!is_dummy(caller_instruction.products.at(i)) && !is_literal(caller_instruction.ingredients.at(ingredient_index)) && caller_instruction.products.at(i).name != caller_instruction.ingredients.at(ingredient_index).name) {
-            raise_error << maybe(caller.name) << "'" << caller_instruction.to_string() << "' should write to " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end();
+            raise_error << maybe(caller.name) << "'" << to_string(caller_instruction) << "' should write to " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end();
           }
         }
       }
diff --git a/037new.cc b/037new.cc
index 95339edc..05d8a3e7 100644
--- a/037new.cc
+++ b/037new.cc
@@ -81,7 +81,7 @@ put(Recipe_ordinal, "new", NEW);
 case NEW: {
   const recipe& caller = get(Recipe, r);
   if (inst.ingredients.empty() || SIZE(inst.ingredients) > 2) {
-    raise_error << maybe(caller.name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "'new' requires one or two ingredients, but got " << to_string(inst) << '\n' << end();
     break;
   }
   // End NEW Check Special-cases
@@ -95,7 +95,7 @@ case NEW: {
     break;
   }
   if (!product_of_new_is_valid(inst)) {
-    raise_error << maybe(caller.name) << "product of 'new' has incorrect type: " << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "product of 'new' has incorrect type: " << to_string(inst) << '\n' << end();
     break;
   }
   break;
@@ -301,7 +301,7 @@ put(Recipe_ordinal, "abandon", ABANDON);
 :(before "End Primitive Recipe Checks")
 case ABANDON: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'abandon' requires one ingredient, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'abandon' requires one ingredient, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   reagent types = inst.ingredients.at(0);
diff --git a/038location_array.cc b/038location_array.cc
index b2ac48b1..cbb6d445 100644
--- a/038location_array.cc
+++ b/038location_array.cc
@@ -6,7 +6,7 @@ put(Recipe_ordinal, "to-location-array", TO_LOCATION_ARRAY);
 case TO_LOCATION_ARRAY: {
   const recipe& caller = get(Recipe, r);
   if (!is_shared_address_of_array_of_numbers(inst.products.at(0))) {
-    raise_error << maybe(caller.name) << "product of 'to-location-array' has incorrect type: " << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "product of 'to-location-array' has incorrect type: " << to_string(inst) << '\n' << end();
     break;
   }
   break;
diff --git a/042name.cc b/042name.cc
index bdaf50e9..733a8359 100644
--- a/042name.cc
+++ b/042name.cc
@@ -73,7 +73,7 @@ void transform_names(const recipe_ordinal r) {
 bool is_disqualified(/*mutable*/ reagent& x, const instruction& inst, const string& recipe_name) {
   if (!x.type) {
     // End Null-type is_disqualified Exceptions
-    raise_error << maybe(recipe_name) << "missing type for " << x.original_string << " in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(recipe_name) << "missing type for " << x.original_string << " in '" << to_string(inst) << "'\n" << end();
     return true;
   }
   if (is_raw(x)) return true;
@@ -196,7 +196,7 @@ recipe main [
 // replace element names of containers with offsets
 if (inst.name == "get" || inst.name == "get-address") {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "exactly 2 ingredients expected in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "exactly 2 ingredients expected in '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_literal(inst.ingredients.at(1)))
@@ -238,7 +238,7 @@ recipe main [
 // convert variant names of exclusive containers
 if (inst.name == "maybe-convert") {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "exactly 2 ingredients expected in '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "exactly 2 ingredients expected in '" << to_string(inst) << "'\n" << end();
     break;
   }
   assert(is_literal(inst.ingredients.at(1)));
diff --git a/043space.cc b/043space.cc
index 145fd816..497d87be 100644
--- a/043space.cc
+++ b/043space.cc
@@ -56,7 +56,7 @@ void absolutize(reagent& x) {
   if (is_raw(x) || is_dummy(x)) return;
   if (x.name == "default-space") return;
   if (!x.initialized) {
-    raise_error << current_instruction().to_string() << ": reagent not initialized: " << x.original_string << '\n' << end();
+    raise_error << to_string(current_instruction()) << ": reagent not initialized: " << x.original_string << '\n' << end();
   }
   x.set_value(address(x.value, space_base(x)));
   x.properties.push_back(pair<string, string_tree*>("raw", NULL));
@@ -235,7 +235,7 @@ void try_reclaim_locals() {
 
 void rewrite_default_space_instruction(instruction& curr) {
   if (!curr.ingredients.empty())
-    raise_error << curr.to_string() << " can't take any ingredients\n" << end();
+    raise_error << to_string(curr) << " can't take any ingredients\n" << end();
   curr.name = "new";
   curr.ingredients.push_back(reagent("location:type"));
   curr.ingredients.push_back(reagent("number-of-locals:literal"));
diff --git a/045closure_name.cc b/045closure_name.cc
index d16175b1..52e415fc 100644
--- a/045closure_name.cc
+++ b/045closure_name.cc
@@ -58,7 +58,7 @@ void collect_surrounding_spaces(const recipe_ordinal r) {
           || !type->right->right->right
           || type->right->right->right->value != get(Type_ordinal, "location")
           || type->right->right->right->right) {
-        raise_error << "slot 0 should always have type address:shared:array:location, but is " << inst.products.at(j).to_string() << '\n' << end();
+        raise_error << "slot 0 should always have type address:shared:array:location, but is " << to_string(inst.products.at(j)) << '\n' << end();
         continue;
       }
       string_tree* s = property(inst.products.at(j), "names");
@@ -66,7 +66,7 @@ void collect_surrounding_spaces(const recipe_ordinal r) {
         raise_error << "slot 0 requires a /names property in recipe " << get(Recipe, r).name << end();
         continue;
       }
-      if (s->right) raise_error << "slot 0 should have a single value in /names, but got " << inst.products.at(j).to_string() << '\n' << end();
+      if (s->right) raise_error << "slot 0 should have a single value in /names, but got " << to_string(inst.products.at(j)) << '\n' << end();
       const string& surrounding_recipe_name = s->value;
       if (surrounding_recipe_name.empty()) {
         raise_error << "slot 0 doesn't initialize its /names property in recipe " << get(Recipe, r).name << end();
@@ -112,7 +112,7 @@ long long int lookup_name(const reagent& x, const recipe_ordinal default_recipe)
 long long int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) {
   if (!Name[r].empty()) return Name[r][x.name];
   if (contains_key(done, r)) {
-    raise_error << "can't compute address of " << x.to_string() << " because " << end();
+    raise_error << "can't compute address of " << to_string(x) << " because " << end();
     for (long long int i = 1; i < SIZE(path); ++i) {
       raise_error << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end();
     }
diff --git a/050scenario.cc b/050scenario.cc
index 63c446ef..6606f09b 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -594,7 +594,7 @@ put(Recipe_ordinal, "check-trace-count-for-label", CHECK_TRACE_COUNT_FOR_LABEL);
 :(before "End Primitive Recipe Checks")
 case CHECK_TRACE_COUNT_FOR_LABEL: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'check-trace-for-label' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'check-trace-for-label' requires exactly two ingredients, but got '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
diff --git a/056recipe_header.cc b/056recipe_header.cc
index f55c2ba8..757e57fe 100644
--- a/056recipe_header.cc
+++ b/056recipe_header.cc
@@ -218,17 +218,17 @@ void check_calls_against_header(const recipe_ordinal r) {
     for (long int i = 0; i < min(SIZE(inst.ingredients), SIZE(callee.ingredients)); ++i) {
       // ingredients coerced from call to callee
       if (!types_coercible(callee.ingredients.at(i), inst.ingredients.at(i)))
-        raise_error << maybe(caller.name) << "ingredient " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+        raise_error << maybe(caller.name) << "ingredient " << i << " has the wrong type at '" << to_string(inst) << "'\n" << end();
       if (is_unique_address(inst.ingredients.at(i)))
-        raise << maybe(caller.name) << "try to avoid passing non-shared addresses into calls, like ingredient " << i << " at '" << inst.to_string() << "'\n" << end();
+        raise << maybe(caller.name) << "try to avoid passing non-shared addresses into calls, like ingredient " << i << " at '" << to_string(inst) << "'\n" << end();
     }
     for (long int i = 0; i < min(SIZE(inst.products), SIZE(callee.products)); ++i) {
       if (is_dummy(inst.products.at(i))) continue;
       // products coerced from callee to call
       if (!types_coercible(inst.products.at(i), callee.products.at(i)))
-        raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+        raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << to_string(inst) << "'\n" << end();
       if (is_unique_address(inst.products.at(i)))
-        raise << maybe(caller.name) << "try to avoid getting non-shared addresses out of calls, like product " << i << " at '" << inst.to_string() << "'\n" << end();
+        raise << maybe(caller.name) << "try to avoid getting non-shared addresses out of calls, like product " << i << " at '" << to_string(inst) << "'\n" << end();
     }
   }
 }
@@ -292,12 +292,12 @@ void check_reply_instructions_against_header(const recipe_ordinal r) {
     const instruction& inst = caller_recipe.steps.at(i);
     if (inst.name != "reply") continue;
     if (SIZE(caller_recipe.products) != SIZE(inst.ingredients)) {
-      raise_error << maybe(caller_recipe.name) << "replied with the wrong number of products at '" << inst.to_string() << "'\n" << end();
+      raise_error << maybe(caller_recipe.name) << "replied with the wrong number of products at '" << to_string(inst) << "'\n" << end();
       continue;
     }
     for (long long int i = 0; i < SIZE(caller_recipe.products); ++i) {
       if (!types_match(caller_recipe.products.at(i), inst.ingredients.at(i)))
-        raise_error << maybe(caller_recipe.name) << "replied with the wrong type at '" << inst.to_string() << "'\n" << end();
+        raise_error << maybe(caller_recipe.name) << "replied with the wrong type at '" << to_string(inst) << "'\n" << end();
     }
   }
 }
@@ -378,7 +378,7 @@ void deduce_types_from_header(const recipe_ordinal r) {
   }
   for (long long int i = 0; i < SIZE(caller_recipe.steps); ++i) {
     instruction& inst = caller_recipe.steps.at(i);
-    trace(9992, "transform") << "instruction: " << inst.to_string() << end();
+    trace(9992, "transform") << "instruction: " << to_string(inst) << end();
     for (long long int i = 0; i < SIZE(inst.ingredients); ++i) {
       if (inst.ingredients.at(i).type) continue;
       if (header_type.find(inst.ingredients.at(i).name) == header_type.end())
diff --git a/057static_dispatch.cc b/057static_dispatch.cc
index 9c71ac38..576ef35f 100644
--- a/057static_dispatch.cc
+++ b/057static_dispatch.cc
@@ -194,14 +194,14 @@ string best_variant(instruction& inst, const recipe& caller_recipe) {
 
   // error messages
   if (get(Recipe_ordinal, inst.name) >= MAX_PRIMITIVE_RECIPES) {  // we currently don't check types for primitive variants
-    raise_error << maybe(caller_recipe.name) << "failed to find a matching call for '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(caller_recipe.name) << "failed to find a matching call for '" << to_string(inst) << "'\n" << end();
     for (list<call>::iterator p = /*skip*/++resolve_stack.begin(); p != resolve_stack.end(); ++p) {
       const recipe& specializer_recipe = get(Recipe, p->running_recipe);
       const instruction& specializer_inst = specializer_recipe.steps.at(p->running_step_index);
       if (specializer_recipe.name != "interactive")
-        raise_error << "  (from '" << specializer_inst.to_string() << "' in " << specializer_recipe.name << ")\n" << end();
+        raise_error << "  (from '" << to_string(specializer_inst) << "' in " << specializer_recipe.name << ")\n" << end();
       else
-        raise_error << "  (from '" << specializer_inst.to_string() << "')\n" << end();
+        raise_error << "  (from '" << to_string(specializer_inst) << "')\n" << end();
       // One special-case to help with the rewrite_stash transform. (cross-layer)
       if (specializer_inst.products.at(0).name.find("stash_") == 0) {
         instruction stash_inst;
@@ -525,10 +525,10 @@ string header_label(recipe_ordinal r) {
   ostringstream out;
   out << "recipe " << caller.name;
   for (long long int i = 0; i < SIZE(caller.ingredients); ++i)
-    out << ' ' << caller.ingredients.at(i).to_string();
+    out << ' ' << to_string(caller.ingredients.at(i));
   if (!caller.products.empty()) out << " ->";
   for (long long int i = 0; i < SIZE(caller.products); ++i)
-    out << ' ' << caller.products.at(i).to_string();
+    out << ' ' << to_string(caller.products.at(i));
   return out.str();
 }
 
diff --git a/059shape_shifting_recipe.cc b/059shape_shifting_recipe.cc
index 5bb1126d..5784af16 100644
--- a/059shape_shifting_recipe.cc
+++ b/059shape_shifting_recipe.cc
@@ -301,7 +301,7 @@ void compute_type_names(recipe& variant) {
     save_or_deduce_type_name(variant.products.at(i), type_names, variant);
   for (long long int i = 0; i < SIZE(variant.steps); ++i) {
     instruction& inst = variant.steps.at(i);
-    trace(9993, "transform") << "  instruction: " << inst.to_string() << end();
+    trace(9993, "transform") << "  instruction: " << to_string(inst) << end();
     for (long long int in = 0; in < SIZE(inst.ingredients); ++in)
       save_or_deduce_type_name(inst.ingredients.at(in), type_names, variant);
     for (long long int out = 0; out < SIZE(inst.products); ++out)
@@ -310,7 +310,7 @@ void compute_type_names(recipe& variant) {
 }
 
 void save_or_deduce_type_name(reagent& x, map<string, string_tree*>& type_name, const recipe& variant) {
-  trace(9994, "transform") << "    checking " << x.to_string() << ": " << debug_string(x.properties.at(0).second) << end();
+  trace(9994, "transform") << "    checking " << to_string(x) << ": " << debug_string(x.properties.at(0).second) << end();
   if (!x.properties.at(0).second && contains_key(type_name, x.name)) {
     x.properties.at(0).second = new string_tree(*get(type_name, x.name));
     trace(9994, "transform") << "    deducing type to " << debug_string(x.properties.at(0).second) << end();
@@ -374,7 +374,7 @@ void accumulate_type_ingredients(const string_tree* exemplar_type, const string_
     }
     else {
       if (!deeply_equal_types(get(mappings, exemplar_type->value), refinement_type)) {
-        raise_error << maybe(caller_recipe.name) << "no call found for '" << call_instruction.to_string() << "'\n" << end();
+        raise_error << maybe(caller_recipe.name) << "no call found for '" << to_string(call_instruction) << "'\n" << end();
 //?         cerr << exemplar_type->value << ": " << debug_string(get(mappings, exemplar_type->value)) << " vs " << debug_string(refinement_type) << '\n';
         *error = true;
         return;
@@ -404,7 +404,7 @@ void replace_type_ingredients(recipe& new_recipe, const map<string, const string
   // update its body
   for (long long int i = 0; i < SIZE(new_recipe.steps); ++i) {
     instruction& inst = new_recipe.steps.at(i);
-    trace(9993, "transform") << "replacing in instruction '" << inst.to_string() << "'" << end();
+    trace(9993, "transform") << "replacing in instruction '" << to_string(inst) << "'" << end();
     for (long long int j = 0; j < SIZE(inst.ingredients); ++j)
       replace_type_ingredients(inst.ingredients.at(j), mappings, new_recipe);
     for (long long int j = 0; j < SIZE(inst.products); ++j)
@@ -413,7 +413,7 @@ void replace_type_ingredients(recipe& new_recipe, const map<string, const string
     if (inst.name == "new" && inst.ingredients.at(0).properties.at(0).second->value != "literal-string") {
       string_tree* type_name = parse_string_tree(inst.ingredients.at(0).name);
       replace_type_ingredients(type_name, mappings);
-      inst.ingredients.at(0).name = type_name->to_string();
+      inst.ingredients.at(0).name = to_string(type_name);
       delete type_name;
     }
   }
diff --git a/060immutable.cc b/060immutable.cc
index 4d637d6c..496e33c7 100644
--- a/060immutable.cc
+++ b/060immutable.cc
@@ -243,9 +243,9 @@ void check_immutable_ingredient_in_instruction(const instruction& inst, const se
       // primitive recipe
       if (inst.operation == GET_ADDRESS || inst.operation == INDEX_ADDRESS) {
         if (current_ingredient_name == original_ingredient_name)
-          raise << maybe(caller.name) << "cannot modify ingredient " << current_ingredient_name << " after instruction '" << inst.to_string() << "' because it's not also a product of " << caller.name << '\n' << end();
+          raise << maybe(caller.name) << "cannot modify ingredient " << current_ingredient_name << " after instruction '" << to_string(inst) << "' because it's not also a product of " << caller.name << '\n' << end();
         else
-          raise << maybe(caller.name) << "cannot modify " << current_ingredient_name << " after instruction '" << inst.to_string() << "' because that would modify ingredient " << original_ingredient_name << " which is not also a product of " << caller.name << '\n' << end();
+          raise << maybe(caller.name) << "cannot modify " << current_ingredient_name << " after instruction '" << to_string(inst) << "' because that would modify ingredient " << original_ingredient_name << " which is not also a product of " << caller.name << '\n' << end();
       }
     }
     else {
@@ -253,9 +253,9 @@ void check_immutable_ingredient_in_instruction(const instruction& inst, const se
       if (!is_mu_address(current_ingredient)) return;  // making a copy is ok
       if (is_modified_in_recipe(inst.operation, current_ingredient_index, caller)) {
         if (current_ingredient_name == original_ingredient_name)
-          raise << maybe(caller.name) << "cannot modify ingredient " << current_ingredient_name << " at instruction '" << inst.to_string() << "' because it's not also a product of " << caller.name << '\n' << end();
+          raise << maybe(caller.name) << "cannot modify ingredient " << current_ingredient_name << " at instruction '" << to_string(inst) << "' because it's not also a product of " << caller.name << '\n' << end();
         else
-          raise << maybe(caller.name) << "cannot modify " << current_ingredient_name << " after instruction '" << inst.to_string() << "' because that would modify ingredient " << original_ingredient_name << " which is not also a product of " << caller.name << '\n' << end();
+          raise << maybe(caller.name) << "cannot modify " << current_ingredient_name << " after instruction '" << to_string(inst) << "' because that would modify ingredient " << original_ingredient_name << " which is not also a product of " << caller.name << '\n' << end();
       }
     }
   }
diff --git a/061recipe.cc b/061recipe.cc
index 5798f4df..4e6f2b83 100644
--- a/061recipe.cc
+++ b/061recipe.cc
@@ -115,12 +115,12 @@ void check_indirect_calls_against_header(const recipe_ordinal r) {
     if (!callee_header.has_header) continue;
     for (long int i = /*skip callee*/1; i < min(SIZE(inst.ingredients), SIZE(callee_header.ingredients)+/*skip callee*/1); ++i) {
       if (!types_coercible(callee_header.ingredients.at(i-/*skip callee*/1), inst.ingredients.at(i)))
-        raise_error << maybe(caller.name) << "ingredient " << i-/*skip callee*/1 << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+        raise_error << maybe(caller.name) << "ingredient " << i-/*skip callee*/1 << " has the wrong type at '" << to_string(inst) << "'\n" << end();
     }
     for (long int i = 0; i < min(SIZE(inst.products), SIZE(callee_header.products)); ++i) {
       if (is_dummy(inst.products.at(i))) continue;
       if (!types_coercible(callee_header.products.at(i), inst.products.at(i)))
-        raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end();
+        raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << to_string(inst) << "'\n" << end();
     }
   }
 }
diff --git a/062scheduler.cc b/062scheduler.cc
index ca22caae..348024c2 100644
--- a/062scheduler.cc
+++ b/062scheduler.cc
@@ -343,7 +343,7 @@ put(Recipe_ordinal, "routine-state", ROUTINE_STATE);
 :(before "End Primitive Recipe Checks")
 case ROUTINE_STATE: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'routine-state' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'routine-state' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -376,7 +376,7 @@ put(Recipe_ordinal, "restart", RESTART);
 :(before "End Primitive Recipe Checks")
 case RESTART: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'restart' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'restart' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -404,7 +404,7 @@ put(Recipe_ordinal, "stop", STOP);
 :(before "End Primitive Recipe Checks")
 case STOP: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'stop' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'stop' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -486,7 +486,7 @@ put(Recipe_ordinal, "limit-time", LIMIT_TIME);
 :(before "End Primitive Recipe Checks")
 case LIMIT_TIME: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'limit-time' requires exactly two ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'limit-time' requires exactly two ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
diff --git a/063wait.cc b/063wait.cc
index 888edcdf..37fbabb1 100644
--- a/063wait.cc
+++ b/063wait.cc
@@ -96,7 +96,7 @@ put(Recipe_ordinal, "wait-for-routine", WAIT_FOR_ROUTINE);
 :(before "End Primitive Recipe Checks")
 case WAIT_FOR_ROUTINE: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'wait-for-routine' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'wait-for-routine' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -108,7 +108,7 @@ case WAIT_FOR_ROUTINE: {
 :(before "End Primitive Recipe Implementations")
 case WAIT_FOR_ROUTINE: {
   if (ingredients.at(0).at(0) == Current_routine->id) {
-    raise_error << maybe(current_recipe_name()) << "routine can't wait for itself! " << current_instruction().to_string() << '\n' << end();
+    raise_error << maybe(current_recipe_name()) << "routine can't wait for itself! " << to_string(current_instruction()) << '\n' << end();
     break;
   }
   Current_routine->state = WAITING;
diff --git a/074random.cc b/074random.cc
index 69ed8b2c..fd70b71e 100644
--- a/074random.cc
+++ b/074random.cc
@@ -36,7 +36,7 @@ put(Recipe_ordinal, "round", ROUND);
 :(before "End Primitive Recipe Checks")
 case ROUND: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'round' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'round' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
diff --git a/077hash.cc b/077hash.cc
index a42b439a..88a5d1f7 100644
--- a/077hash.cc
+++ b/077hash.cc
@@ -15,7 +15,7 @@ put(Recipe_ordinal, "hash", HASH);
 :(before "End Primitive Recipe Checks")
 case HASH: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'hash' takes exactly one ingredient rather than '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'hash' takes exactly one ingredient rather than '" << to_string(inst) << "'\n" << end();
     break;
   }
   break;
@@ -363,7 +363,7 @@ put(Recipe_ordinal, "hash_old", HASH_OLD);
 :(before "End Primitive Recipe Checks")
 case HASH_OLD: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'hash_old' takes exactly one ingredient rather than '" << inst.to_string() << "'\n" << end();
+    raise_error << maybe(get(Recipe, r).name) << "'hash_old' takes exactly one ingredient rather than '" << to_string(inst) << "'\n" << end();
     break;
   }
   if (!is_mu_string(inst.ingredients.at(0))) {
diff --git a/080display.cc b/080display.cc
index 7a807c62..79fcc697 100644
--- a/080display.cc
+++ b/080display.cc
@@ -100,7 +100,7 @@ put(Recipe_ordinal, "print-character-to-display", PRINT_CHARACTER_TO_DISPLAY);
 :(before "End Primitive Recipe Checks")
 case PRINT_CHARACTER_TO_DISPLAY: {
   if (inst.ingredients.empty()) {
-    raise_error << maybe(get(Recipe, r).name) << "'print-character-to-display' requires at least one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'print-character-to-display' requires at least one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
@@ -186,7 +186,7 @@ put(Recipe_ordinal, "move-cursor-on-display", MOVE_CURSOR_ON_DISPLAY);
 :(before "End Primitive Recipe Checks")
 case MOVE_CURSOR_ON_DISPLAY: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'move-cursor-on-display' requires two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'move-cursor-on-display' requires two ingredients, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_number(inst.ingredients.at(0))) {
diff --git a/091run_interactive.cc b/091run_interactive.cc
index 9ad77ebb..8930c935 100644
--- a/091run_interactive.cc
+++ b/091run_interactive.cc
@@ -30,11 +30,11 @@ put(Recipe_ordinal, "run-interactive", RUN_INTERACTIVE);
 :(before "End Primitive Recipe Checks")
 case RUN_INTERACTIVE: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'run-interactive' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'run-interactive' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_string(inst.ingredients.at(0))) {
-    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'run-interactive' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'run-interactive' should be a string, but got " << to_string(inst.ingredients.at(0)) << '\n' << end();
     break;
   }
   break;
@@ -449,7 +449,7 @@ put(Recipe_ordinal, "reload", RELOAD);
 :(before "End Primitive Recipe Checks")
 case RELOAD: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'reload' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'reload' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (!is_mu_string(inst.ingredients.at(0))) {
diff --git a/092persist.cc b/092persist.cc
index e0201cd0..ce7be5d3 100644
--- a/092persist.cc
+++ b/092persist.cc
@@ -9,7 +9,7 @@ put(Recipe_ordinal, "restore", RESTORE);
 :(before "End Primitive Recipe Checks")
 case RESTORE: {
   if (SIZE(inst.ingredients) != 1) {
-    raise_error << maybe(get(Recipe, r).name) << "'restore' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'restore' requires exactly one ingredient, but got " << to_string(inst) << '\n' << end();
     break;
   }
   string filename;
@@ -20,7 +20,7 @@ case RESTORE: {
     ;
   }
   else {
-    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'restore' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'restore' should be a string, but got " << to_string(inst.ingredients.at(0)) << '\n' << end();
     break;
   }
   break;
@@ -73,7 +73,7 @@ put(Recipe_ordinal, "save", SAVE);
 :(before "End Primitive Recipe Checks")
 case SAVE: {
   if (SIZE(inst.ingredients) != 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'save' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "'save' requires exactly two ingredients, but got " << to_string(inst) << '\n' << end();
     break;
   }
   if (is_literal_string(inst.ingredients.at(0))) {
@@ -83,11 +83,11 @@ case SAVE: {
     ;
   }
   else {
-    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'save' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'save' should be a string, but got " << to_string(inst.ingredients.at(0)) << '\n' << end();
     break;
   }
   if (!is_mu_string(inst.ingredients.at(1))) {
-    raise_error << maybe(get(Recipe, r).name) << "second ingredient of 'save' should be an address:array:character, but got " << inst.ingredients.at(1).to_string() << '\n' << end();
+    raise_error << maybe(get(Recipe, r).name) << "second ingredient of 'save' should be an address:array:character, but got " << to_string(inst.ingredients.at(1)) << '\n' << end();
     break;
   }
   break;