about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-05-06 00:46:39 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-05-06 00:46:39 -0700
commit3473c63ad94756d6f79ddd5c48813e79d87429ca (patch)
tree9825e9a1c4fecf3f52697364bae17d7572bf5cdf
parentce9616a77fc4e1c22e913308c8ea55ef05203211 (diff)
downloadmu-3473c63ad94756d6f79ddd5c48813e79d87429ca.tar.gz
2931 - be explicit about making copies
-rw-r--r--010vm.cc2
-rw-r--r--020run.cc10
-rw-r--r--021check_instruction.cc19
-rw-r--r--027call_ingredient.cc4
-rw-r--r--028call_reply.cc4
-rw-r--r--030container.cc26
-rw-r--r--031merge.cc4
-rw-r--r--032array.cc28
-rw-r--r--033exclusive_container.cc26
-rw-r--r--034address.cc8
-rw-r--r--035lookup.cc30
-rw-r--r--036refcount.cc4
-rw-r--r--039location_array.cc2
-rw-r--r--040brace.cc2
-rw-r--r--043space.cc66
-rw-r--r--046global.cc32
-rw-r--r--058shape_shifting_recipe.cc6
-rw-r--r--061recipe.cc2
-rw-r--r--062scheduler.cc2
-rw-r--r--063wait.cc8
-rw-r--r--071rewrite_stash.cc6
-rw-r--r--078hash.cc10
22 files changed, 154 insertions, 147 deletions
diff --git a/010vm.cc b/010vm.cc
index d46719ad..8565c09d 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -388,7 +388,7 @@ string slurp_until(istream& in, char delim) {
   return out.str();
 }
 
-bool has_property(reagent x, string name) {
+bool has_property(const reagent& x, const string& name) {
   for (int i = 0; i < SIZE(x.properties); ++i) {
     if (x.properties.at(i).first == name) return true;
   }
diff --git a/020run.cc b/020run.cc
index a94eb668..5bfbc34b 100644
--- a/020run.cc
+++ b/020run.cc
@@ -250,13 +250,14 @@ void load_all(string dir) {
 //:: Reading from memory, writing to memory.
 
 :(code)
-vector<double> read_memory(reagent x) {
+vector<double> read_memory(reagent/*copy*/ x) {
+  // Begin Preprocess read_memory(reagent x)
   vector<double> result;
   if (is_literal(x)) {
     result.push_back(x.value);
     return result;
   }
-  // End Preprocess read_memory(x)
+  // End Preprocess read_memory(reagent x)
   int size = size_of(x);
   for (int offset = 0; offset < size; ++offset) {
     double val = get_or_insert(Memory, x.value+offset);
@@ -266,14 +267,15 @@ vector<double> read_memory(reagent x) {
   return result;
 }
 
-void write_memory(reagent x, const vector<double>& data) {
+void write_memory(reagent/*copy*/ x, const vector<double>& data) {
+  // Begin Preprocess write_memory(reagent x, vector<double> data)
   if (!x.type) {
     raise << "can't write to " << to_string(x) << "; no type\n" << end();
     return;
   }
   if (is_dummy(x)) return;
   if (is_literal(x)) return;
-  // End Preprocess write_memory(x)
+  // End Preprocess write_memory(reagent x, vector<double> data)
   if (x.value == 0) return;
   if (size_mismatch(x, data)) {
     raise << maybe(current_recipe_name()) << "size mismatch in storing to " << x.original_string << " (" << size_of(x.type) << " vs " << SIZE(data) << ") at '" << to_original_string(current_instruction()) << "'\n" << end();
diff --git a/021check_instruction.cc b/021check_instruction.cc
index 599fa6c9..2bf0d97a 100644
--- a/021check_instruction.cc
+++ b/021check_instruction.cc
@@ -132,7 +132,8 @@ bool boolean_matches_literal(const reagent& to, const reagent& from) {
 
 // copy arguments because later layers will want to make changes to them
 // without perturbing the caller
-bool types_strictly_match(reagent to, reagent from) {
+bool types_strictly_match(reagent/*copy*/ to, reagent/*copy*/ from) {
+  // End Preprocess types_strictly_match(reagent to, reagent from)
   if (is_literal(from) && to.type->value == get(Type_ordinal, "number")) return true;
   // to sidestep type-checking, use /unsafe in the source.
   // this will be highlighted in red inside vim. just for setting up some tests.
@@ -145,7 +146,7 @@ bool types_strictly_match(reagent to, reagent from) {
 
 // two types match if the second begins like the first
 // (trees perform the same check recursively on each subtree)
-bool types_strictly_match(type_tree* to, type_tree* from) {
+bool types_strictly_match(const type_tree* to, const type_tree* from) {
   if (!to) return true;
   if (!from) return to->value == 0;
   if (from->value == -1) return from->name == to->name;
@@ -169,25 +170,29 @@ bool is_unsafe(const reagent& r) {
   return has_property(r, "unsafe");
 }
 
-bool is_mu_array(reagent r) {
+bool is_mu_array(reagent/*copy*/ r) {
+  // End Preprocess is_mu_array(reagent r)
   if (!r.type) return false;
   if (is_literal(r)) return false;
   return r.type->value == get(Type_ordinal, "array");
 }
 
-bool is_mu_address(reagent r) {
+bool is_mu_address(reagent/*copy*/ r) {
+  // End Preprocess is_mu_address(reagent r)
   if (!r.type) return false;
   if (is_literal(r)) return false;
   return r.type->value == get(Type_ordinal, "address");
 }
 
-bool is_mu_boolean(reagent r) {
+bool is_mu_boolean(reagent/*copy*/ r) {
+  // End Preprocess is_mu_boolean(reagent r)
   if (!r.type) return false;
   if (is_literal(r)) return false;
   return r.type->value == get(Type_ordinal, "boolean");
 }
 
-bool is_mu_number(reagent r) {
+bool is_mu_number(reagent/*copy*/ r) {
+  // End Preprocess is_mu_number(reagent r)
   if (!r.type) return false;
   if (is_literal(r)) {
     if (!r.type) return false;
@@ -198,7 +203,7 @@ bool is_mu_number(reagent r) {
   return r.type->value == get(Type_ordinal, "number");
 }
 
-bool is_mu_scalar(reagent r) {
+bool is_mu_scalar(reagent/*copy*/ r) {
   if (!r.type) return false;
   if (is_literal(r))
     return !r.type || r.type->name != "literal-string";
diff --git a/027call_ingredient.cc b/027call_ingredient.cc
index 21f9f7ff..739815ed 100644
--- a/027call_ingredient.cc
+++ b/027call_ingredient.cc
@@ -30,7 +30,7 @@ next_ingredient_to_process = 0;
 :(before "End Call Housekeeping")
 for (int i = 0; i < SIZE(ingredients); ++i) {
   current_call().ingredient_atoms.push_back(ingredients.at(i));
-  reagent ingredient = call_instruction.ingredients.at(i);
+  reagent/*copy*/ ingredient = call_instruction.ingredients.at(i);
   // End Compute Call Ingredient
   current_call().ingredients.push_back(ingredient);
 }
@@ -51,7 +51,7 @@ case NEXT_INGREDIENT: {
 case NEXT_INGREDIENT: {
   assert(!Current_routine->calls.empty());
   if (current_call().next_ingredient_to_process < SIZE(current_call().ingredient_atoms)) {
-    reagent product = current_instruction().products.at(0);
+    reagent/*copy*/ product = current_instruction().products.at(0);
     // End Preprocess NEXT_INGREDIENT product
     if (current_recipe_name() == "main") {
       // no ingredient types since the call might be implicit; assume ingredients are always strings
diff --git a/028call_reply.cc b/028call_reply.cc
index 0f320aa0..5632668f 100644
--- a/028call_reply.cc
+++ b/028call_reply.cc
@@ -68,8 +68,8 @@ void check_types_of_reply_instructions(recipe_ordinal r) {
         break;
       }
       for (int i = 0; i < SIZE(caller_instruction.products); ++i) {
-        reagent lhs = reply_inst.ingredients.at(i);
-        reagent rhs = caller_instruction.products.at(i);
+        reagent/*copy*/ lhs = reply_inst.ingredients.at(i);
+        reagent/*copy*/ rhs = caller_instruction.products.at(i);
         // End Check RETURN Copy(lhs, rhs)
         if (!types_coercible(rhs, lhs)) {
           raise << maybe(callee.name) << reply_inst.name << " ingredient " << lhs.original_string << " can't be saved in " << rhs.original_string << '\n' << end();
diff --git a/030container.cc b/030container.cc
index 8018cb91..3e779871 100644
--- a/030container.cc
+++ b/030container.cc
@@ -180,7 +180,7 @@ void compute_container_metadata(const type_tree* type, set<type_ordinal>& pendin
   if (info.kind == CONTAINER) {
     container_metadata metadata;
     for (int i = 0; i < SIZE(info.elements); ++i) {
-      reagent element = info.elements.at(i);
+      reagent/*copy*/ element = info.elements.at(i);
       // Compute Container Metadata(element)
       compute_container_metadata(element.type, pending_metadata);
       metadata.offset.push_back(metadata.size);  // save previous size as offset
@@ -244,14 +244,14 @@ case GET: {
     raise << maybe(get(Recipe, r).name) << "'get' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);  // new copy for every invocation
+  reagent/*copy*/ base = inst.ingredients.at(0);  // new copy for every invocation
   // Update GET base in Check
   if (!base.type || !base.type->value || !contains_key(Type, base.type->value) || get(Type, base.type->value).kind != CONTAINER) {
     raise << maybe(get(Recipe, r).name) << "first ingredient of 'get' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end();
     break;
   }
   type_ordinal base_type = base.type->value;
-  reagent offset = inst.ingredients.at(1);
+  const reagent& offset = inst.ingredients.at(1);
   if (!is_literal(offset) || !is_mu_scalar(offset)) {
     raise << maybe(get(Recipe, r).name) << "second ingredient of 'get' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end();
     break;
@@ -266,9 +266,9 @@ case GET: {
     break;
   }
   if (inst.products.empty()) break;
-  reagent product = inst.products.at(0);
+  reagent/*copy*/ product = inst.products.at(0);
   // Update GET product in Check
-  const reagent element = element_type(base.type, offset_value);
+  const reagent& element = element_type(base.type, offset_value);
   if (!types_coercible(product, element)) {
     raise << maybe(get(Recipe, r).name) << "'get " << base.original_string << ", " << offset.original_string << "' should write to " << names_to_string_without_quotes(element.type) << " but " << product.name << " has type " << names_to_string_without_quotes(product.type) << '\n' << end();
     break;
@@ -277,7 +277,7 @@ case GET: {
 }
 :(before "End Primitive Recipe Implementations")
 case GET: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   // Update GET base in Run
   int base_address = base.value;
   if (base_address == 0) {
@@ -290,7 +290,7 @@ case GET: {
   assert(base.metadata.size);
   int src = base_address + base.metadata.offset.at(offset);
   trace(9998, "run") << "address to copy is " << src << end();
-  reagent element = element_type(base.type, offset);
+  reagent/*copy*/ element = element_type(base.type, offset);
   element.set_value(src);
   trace(9998, "run") << "its type is " << names_to_string(element.type) << end();
   // Read element
@@ -305,7 +305,7 @@ const reagent element_type(const type_tree* type, int offset_value) {
   assert(!get(Type, type->value).name.empty());
   const type_info& info = get(Type, type->value);
   assert(info.kind == CONTAINER);
-  reagent element = info.elements.at(offset_value);
+  reagent/*copy*/ element = info.elements.at(offset_value);
   // End element_type Special-cases
   return element;
 }
@@ -381,14 +381,14 @@ case PUT: {
     raise << maybe(get(Recipe, r).name) << "'put' expects exactly 3 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);
+  reagent/*copy*/ base = inst.ingredients.at(0);
   // Update PUT base in Check
   if (!base.type || !base.type->value || !contains_key(Type, base.type->value) || get(Type, base.type->value).kind != CONTAINER) {
     raise << maybe(get(Recipe, r).name) << "first ingredient of 'put' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end();
     break;
   }
   type_ordinal base_type = base.type->value;
-  reagent offset = inst.ingredients.at(1);
+  reagent/*copy*/ offset = inst.ingredients.at(1);
   // Update PUT offset in Check
   if (!is_literal(offset) || !is_mu_scalar(offset)) {
     raise << maybe(get(Recipe, r).name) << "second ingredient of 'put' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end();
@@ -405,8 +405,8 @@ case PUT: {
   else {
     offset_value = offset.value;
   }
-  reagent& value = inst.ingredients.at(2);
-  reagent element = element_type(base.type, offset_value);
+  const reagent& value = inst.ingredients.at(2);
+  const reagent& element = element_type(base.type, offset_value);
   if (!types_coercible(element, value)) {
     raise << maybe(get(Recipe, r).name) << "'put " << base.original_string << ", " << offset.original_string << "' should store " << names_to_string_without_quotes(element.type) << " but " << value.name << " has type " << names_to_string_without_quotes(value.type) << '\n' << end();
     break;
@@ -415,7 +415,7 @@ case PUT: {
 }
 :(before "End Primitive Recipe Implementations")
 case PUT: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   // Update PUT base in Run
   int base_address = base.value;
   if (base_address == 0) {
diff --git a/031merge.cc b/031merge.cc
index 168510ed..dea86982 100644
--- a/031merge.cc
+++ b/031merge.cc
@@ -123,7 +123,7 @@ void check_merge_calls(const recipe_ordinal r) {
       raise << maybe(caller.name) << "'merge' should yield a single product in '" << to_original_string(inst) << "'\n" << end();
       continue;
     }
-    reagent product = inst.products.at(0);
+    reagent/*copy*/ 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)) {
@@ -157,7 +157,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
         // degenerate case: merge with the same type always succeeds
         if (state.data.top().container_element_index == 0 && types_coercible(container, inst.ingredients.at(ingredient_index)))
           return;
-        reagent expected_ingredient = element_type(container.type, state.data.top().container_element_index);
+        const reagent& expected_ingredient = element_type(container.type, state.data.top().container_element_index);
         trace(9999, "transform") << "checking container " << to_string(container) << " || " << to_string(expected_ingredient) << " vs ingredient " << ingredient_index << end();
         // if the current element is the ingredient we expect, move on to the next element/ingredient
         if (types_coercible(expected_ingredient, ingredients.at(ingredient_index))) {
diff --git a/032array.cc b/032array.cc
index 485f403f..51f8e0b4 100644
--- a/032array.cc
+++ b/032array.cc
@@ -23,7 +23,7 @@ case CREATE_ARRAY: {
     raise << maybe(get(Recipe, r).name) << "'create-array' needs one product and no ingredients but got '" << to_original_string(inst) << '\n' << end();
     break;
   }
-  reagent product = inst.products.at(0);
+  reagent/*copy*/ product = inst.products.at(0);
   // Update CREATE_ARRAY product in Check
   if (!is_mu_array(product)) {
     raise << maybe(get(Recipe, r).name) << "'create-array' cannot create non-array " << product.original_string << '\n' << end();
@@ -46,7 +46,7 @@ case CREATE_ARRAY: {
 }
 :(before "End Primitive Recipe Implementations")
 case CREATE_ARRAY: {
-  reagent product = current_instruction().products.at(0);
+  reagent/*copy*/ product = current_instruction().products.at(0);
   // Update CREATE_ARRAY product in Run
   int base_address = product.value;
   int array_length = to_integer(product.type->right->right->name);
@@ -173,20 +173,20 @@ case INDEX: {
     raise << maybe(get(Recipe, r).name) << "'index' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);
+  reagent/*copy*/ base = inst.ingredients.at(0);
   // Update INDEX base in Check
   if (!is_mu_array(base)) {
     raise << maybe(get(Recipe, r).name) << "'index' on a non-array " << base.original_string << '\n' << end();
     break;
   }
-  reagent index = inst.ingredients.at(1);
+  reagent/*copy*/ index = inst.ingredients.at(1);
   // Update INDEX index in Check
   if (!is_mu_number(index)) {
     raise << maybe(get(Recipe, r).name) << "second ingredient of 'index' should be a number, but got " << index.original_string << '\n' << end();
     break;
   }
   if (inst.products.empty()) break;
-  reagent product = inst.products.at(0);
+  reagent/*copy*/ product = inst.products.at(0);
   // Update INDEX product in Check
   reagent element;
   element.type = copy_array_element(base.type);
@@ -198,7 +198,7 @@ case INDEX: {
 }
 :(before "End Primitive Recipe Implementations")
 case INDEX: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   // Update INDEX base in Run
   int base_address = base.value;
   trace(9998, "run") << "base address is " << base_address << end();
@@ -206,7 +206,7 @@ case INDEX: {
     raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
     break;
   }
-  reagent index = current_instruction().ingredients.at(1);
+  reagent/*copy*/ index = current_instruction().ingredients.at(1);
   // Update INDEX index in Run
   vector<double> index_val(read_memory(index));
   if (index_val.at(0) < 0 || index_val.at(0) >= get_or_insert(Memory, base_address)) {
@@ -335,19 +335,19 @@ case PUT_INDEX: {
     raise << maybe(get(Recipe, r).name) << "'put-index' expects exactly 3 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);
+  reagent/*copy*/ base = inst.ingredients.at(0);
   // Update PUT_INDEX base in Check
   if (!is_mu_array(base)) {
     raise << maybe(get(Recipe, r).name) << "'put-index' on a non-array " << base.original_string << '\n' << end();
     break;
   }
-  reagent index = inst.ingredients.at(1);
+  reagent/*copy*/ index = inst.ingredients.at(1);
   // Update PUT_INDEX index in Check
   if (!is_mu_number(index)) {
     raise << maybe(get(Recipe, r).name) << "second ingredient of 'put-index' should have type 'number', but got " << inst.ingredients.at(1).original_string << '\n' << end();
     break;
   }
-  reagent value = inst.ingredients.at(2);
+  reagent/*copy*/ value = inst.ingredients.at(2);
   // Update PUT_INDEX value in Check
   reagent element;
   element.type = copy_array_element(base.type);
@@ -359,14 +359,14 @@ case PUT_INDEX: {
 }
 :(before "End Primitive Recipe Implementations")
 case PUT_INDEX: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   // Update PUT_INDEX base in Run
   int base_address = base.value;
   if (base_address == 0) {
     raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
     break;
   }
-  reagent index = current_instruction().ingredients.at(1);
+  reagent/*copy*/ index = current_instruction().ingredients.at(1);
   // Update PUT_INDEX index in Run
   vector<double> index_val(read_memory(index));
   if (index_val.at(0) < 0 || index_val.at(0) >= get_or_insert(Memory, base_address)) {
@@ -441,7 +441,7 @@ case LENGTH: {
     raise << maybe(get(Recipe, r).name) << "'length' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent array = inst.ingredients.at(0);
+  reagent/*copy*/ array = inst.ingredients.at(0);
   // Update LENGTH array in Check
   if (!is_mu_array(array)) {
     raise << "tried to calculate length of non-array " << array.original_string << '\n' << end();
@@ -451,7 +451,7 @@ case LENGTH: {
 }
 :(before "End Primitive Recipe Implementations")
 case LENGTH: {
-  reagent array = current_instruction().ingredients.at(0);
+  reagent/*copy*/ array = current_instruction().ingredients.at(0);
   // Update LENGTH array in Run
   if (array.value == 0) {
     raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
diff --git a/033exclusive_container.cc b/033exclusive_container.cc
index e41e3f34..e978ca80 100644
--- a/033exclusive_container.cc
+++ b/033exclusive_container.cc
@@ -42,7 +42,7 @@ if (info.kind == EXCLUSIVE_CONTAINER) {
   // (So like containers, it can't contain arrays.)
   int size = 0;
   for (int i = 0; i < SIZE(info.elements); ++i) {
-    reagent element = info.elements.at(i);
+    reagent/*copy*/ element = info.elements.at(i);
     // Compute Exclusive Container Metadata(element)
     compute_container_metadata(element);
     int variant_size = size_of(element);
@@ -98,7 +98,7 @@ case MAYBE_CONVERT: {
     raise << maybe(caller.name) << "'maybe-convert' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);
+  reagent/*copy*/ base = inst.ingredients.at(0);
   // Update MAYBE_CONVERT base in Check
   if (!base.type || !base.type->value || get(Type, base.type->value).kind != EXCLUSIVE_CONTAINER) {
     raise << maybe(caller.name) << "first ingredient of 'maybe-convert' should be an exclusive-container, but got " << base.original_string << '\n' << end();
@@ -113,7 +113,7 @@ case MAYBE_CONVERT: {
     raise << maybe(caller.name) << "'maybe-convert' expects exactly 2 products in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent product = inst.products.at(0);
+  reagent/*copy*/ product = inst.products.at(0);
   // Update MAYBE_CONVERT product in Check
   reagent& offset = inst.ingredients.at(1);
   populate_value(offset);
@@ -121,12 +121,12 @@ case MAYBE_CONVERT: {
     raise << maybe(caller.name) << "invalid tag " << offset.value << " in '" << to_original_string(inst) << '\n' << end();
     break;
   }
-  reagent variant = variant_type(base, offset.value);
+  const reagent& variant = variant_type(base, offset.value);
   if (!types_coercible(product, variant)) {
     raise << maybe(caller.name) << "'maybe-convert " << base.original_string << ", " << inst.ingredients.at(1).original_string << "' should write to " << to_string(variant.type) << " but " << product.name << " has type " << to_string(product.type) << '\n' << end();
     break;
   }
-  reagent status = inst.products.at(1);
+  reagent/*copy*/ status = inst.products.at(1);
   // Update MAYBE_CONVERT status in Check
   if (!is_mu_boolean(status)) {
     raise << maybe(get(Recipe, r).name) << "second product yielded by 'maybe-convert' should be a boolean, but tried to write to " << inst.products.at(1).original_string << '\n' << end();
@@ -136,7 +136,7 @@ case MAYBE_CONVERT: {
 }
 :(before "End Primitive Recipe Implementations")
 case MAYBE_CONVERT: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   // Update MAYBE_CONVERT base in Run
   int base_address = base.value;
   if (base_address == 0) {
@@ -144,13 +144,13 @@ case MAYBE_CONVERT: {
     break;
   }
   int tag = current_instruction().ingredients.at(1).value;
-  reagent product = current_instruction().products.at(0);
+  reagent/*copy*/ product = current_instruction().products.at(0);
   // Update MAYBE_CONVERT product in Run
-  reagent status = current_instruction().products.at(1);
+  reagent/*copy*/ status = current_instruction().products.at(1);
   // Update MAYBE_CONVERT status in Run
   // optimization: directly write results to only update first product when necessary
   if (tag == static_cast<int>(get_or_insert(Memory, base_address))) {
-    const reagent variant = variant_type(base, tag);
+    const reagent& variant = variant_type(base, tag);
     trace(9999, "mem") << "storing 1 in location " << status.value << end();
     put(Memory, status.value, 1);
     // Write Memory in Successful MAYBE_CONVERT in Run
@@ -174,7 +174,7 @@ const reagent variant_type(const reagent& base, int tag) {
   assert(!get(Type, base.type->value).name.empty());
   const type_info& info = get(Type, base.type->value);
   assert(info.kind == EXCLUSIVE_CONTAINER);
-  reagent element = info.elements.at(tag);
+  reagent/*copy*/ element = info.elements.at(tag);
   // End variant_type Special-cases
   return element;
 }
@@ -279,13 +279,13 @@ case EXCLUSIVE_CONTAINER: {
     raise << maybe(caller.name) << "ingredient " << ingredient_index << " of 'merge' should be a literal, for the tag of exclusive-container " << container_info.name << '\n' << end();
     return;
   }
-  reagent ingredient = ingredients.at(ingredient_index);  // unnecessary copy just to keep this function from modifying caller
+  reagent/*copy*/ 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 << maybe(caller.name) << "invalid tag at " << ingredient_index << " for " << container_info.name << " in '" << to_original_string(inst) << '\n' << end();
     return;
   }
-  reagent variant = variant_type(container, ingredient.value);
+  const reagent& variant = variant_type(container, ingredient.value);
   trace(9999, "transform") << "tag: " << ingredient.value << end();
   // replace union with its variant
   state.data.pop();
@@ -394,7 +394,7 @@ if (current_step_index() < SIZE(Current_routine->steps())
     && current_instruction().operation == MERGE
     && !current_instruction().products.empty()
     && current_instruction().products.at(0).type) {
-  reagent x = current_instruction().products.at(0);
+  reagent/*copy*/ x = current_instruction().products.at(0);
   // Update size_mismatch Check for MERGE(x)
   if (get(Type, x.type->value).kind == EXCLUSIVE_CONTAINER)
     return size_of(x) < SIZE(data);
diff --git a/034address.cc b/034address.cc
index 17e89a85..8966d9bf 100644
--- a/034address.cc
+++ b/034address.cc
@@ -136,7 +136,7 @@ def main [
 :(before "End Mu Types Initialization")
 put(Type_ordinal, "type", 0);
 :(code)
-bool is_mu_type_literal(reagent r) {
+bool is_mu_type_literal(const reagent& r) {
   return is_literal(r) && r.type && r.type->name == "type";
 }
 
@@ -152,7 +152,7 @@ case NEW: {
     break;
   }
   // End NEW Check Special-cases
-  reagent type = inst.ingredients.at(0);
+  const reagent& type = inst.ingredients.at(0);
   if (!is_mu_type_literal(type)) {
     raise << maybe(caller.name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end();
     break;
@@ -169,7 +169,7 @@ case NEW: {
 }
 :(code)
 bool product_of_new_is_valid(const instruction& inst) {
-  reagent product = inst.products.at(0);
+  reagent/*copy*/ product = inst.products.at(0);
   // Update NEW product in Check
   if (!product.type || product.type->value != get(Type_ordinal, "address"))
     return false;
@@ -179,7 +179,7 @@ bool product_of_new_is_valid(const instruction& inst) {
     if (!product.type || product.type->value != get(Type_ordinal, "array")) return false;
     drop_from_type(product, "array");
   }
-  reagent expected_product("x:"+inst.ingredients.at(0).name);
+  reagent/*copy*/ expected_product("x:"+inst.ingredients.at(0).name);
   // End Post-processing(expected_product) When Checking 'new'
   return types_strictly_match(product, expected_product);
 }
diff --git a/035lookup.cc b/035lookup.cc
index 63897ba9..62802b00 100644
--- a/035lookup.cc
+++ b/035lookup.cc
@@ -42,7 +42,7 @@ def main [
 # 1 contains 10. Skip refcount and lookup location 11.
 +mem: storing 34 in location 2
 
-:(before "End Preprocess read_memory(x)")
+:(before "End Preprocess read_memory(reagent x)")
 canonize(x);
 
 //: similarly, write to addresses pointing at other locations using the
@@ -54,7 +54,7 @@ def main [
 ]
 +mem: storing 34 in location 11
 
-:(before "End Preprocess write_memory(x)")
+:(before "End Preprocess write_memory(reagent x, vector<double> data)")
 canonize(x);
 if (x.value == 0) {
   raise << "can't write to location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
@@ -117,20 +117,20 @@ void test_lookup_zero_address_does_not_skip_refcount() {
   CHECK_EQ(x.value, 0);
 }
 
-:(after "bool types_strictly_match(reagent to, reagent from)")
-  if (!canonize_type(to)) return false;
-  if (!canonize_type(from)) return false;
+:(before "End Preprocess types_strictly_match(reagent to, reagent from)")
+if (!canonize_type(to)) return false;
+if (!canonize_type(from)) return false;
 
-:(after "bool is_mu_array(reagent r)")
-  if (!canonize_type(r)) return false;
+:(before "End Preprocess is_mu_array(reagent r)")
+if (!canonize_type(r)) return false;
 
-:(after "bool is_mu_address(reagent r)")
-  if (!canonize_type(r)) return false;
+:(before "End Preprocess is_mu_address(reagent r)")
+if (!canonize_type(r)) return false;
 
-:(after "bool is_mu_number(reagent r)")
-  if (!canonize_type(r)) return false;
-:(after "bool is_mu_boolean(reagent r)")
-  if (!canonize_type(r)) return false;
+:(before "End Preprocess is_mu_number(reagent r)")
+if (!canonize_type(r)) return false;
+:(before "End Preprocess is_mu_boolean(reagent r)")
+if (!canonize_type(r)) return false;
 
 :(after "Update product While Type-checking Merge")
 if (!canonize_type(product)) continue;
@@ -431,7 +431,7 @@ _DUMP,
 put(Recipe_ordinal, "$dump", _DUMP);
 :(before "End Primitive Recipe Implementations")
 case _DUMP: {
-  reagent after_canonize = current_instruction().ingredients.at(0);
+  reagent/*copy*/ after_canonize = current_instruction().ingredients.at(0);
   canonize(after_canonize);
   cerr << maybe(current_recipe_name()) << current_instruction().ingredients.at(0).name << ' ' << no_scientific(current_instruction().ingredients.at(0).value) << " => " << no_scientific(after_canonize.value) << " => " << no_scientific(get_or_insert(Memory, after_canonize.value)) << '\n';
   break;
@@ -452,7 +452,7 @@ case _BAR: {
     else cerr << '\n';
   }
   else {
-    reagent tmp = current_instruction().ingredients.at(0);
+    reagent/*copy*/ tmp = current_instruction().ingredients.at(0);
     canonize(tmp);
     Bar = tmp.value;
   }
diff --git a/036refcount.cc b/036refcount.cc
index e684c723..a20e7c0e 100644
--- a/036refcount.cc
+++ b/036refcount.cc
@@ -55,7 +55,7 @@ void update_refcounts(int old_address, int new_address, int size) {
   }
 }
 
-int payload_size(/*copy*/ reagent x) {
+int payload_size(reagent/*copy*/ x) {
   // lookup_memory without drop_one_lookup
   if (x.value)
     x.set_value(get_or_insert(Memory, x.value)+/*skip refcount*/1);
@@ -113,7 +113,7 @@ def main [
 +mem: incrementing refcount of 1000: 1 -> 2
 
 :(after "Write Memory in PUT in Run")
-reagent element = element_type(base.type, offset);
+reagent/*copy*/ element = element_type(base.type, offset);
 assert(!has_property(element, "lookup"));
 element.value = address;
 if (is_mu_address(element))
diff --git a/039location_array.cc b/039location_array.cc
index 191e6d38..56e1b419 100644
--- a/039location_array.cc
+++ b/039location_array.cc
@@ -12,7 +12,7 @@ case TO_LOCATION_ARRAY: {
   break;
 }
 :(code)
-bool is_address_of_array_of_numbers(reagent product) {
+bool is_address_of_array_of_numbers(reagent/*copy*/ product) {
   canonize_type(product);
   if (!product.type || product.type->value != get(Type_ordinal, "address")) return false;
   drop_from_type(product, "address");
diff --git a/040brace.cc b/040brace.cc
index e9f83d5a..8cd7e622 100644
--- a/040brace.cc
+++ b/040brace.cc
@@ -419,7 +419,7 @@ if (curr.name == "return-unless" || curr.name == "reply-unless") {
 
 :(code)
 void emit_return_block(recipe& out, const string& break_command, const vector<reagent>& ingredients) {
-  reagent condition = ingredients.at(0);
+  reagent/*copy*/ condition = ingredients.at(0);
   vector<reagent> return_ingredients;
   copy(++ingredients.begin(), ingredients.end(), inserter(return_ingredients, return_ingredients.end()));
 
diff --git a/043space.cc b/043space.cc
index d29cf983..e4a39b7c 100644
--- a/043space.cc
+++ b/043space.cc
@@ -82,21 +82,21 @@ int address(int offset, int base) {
 
 //:: reads and writes to the 'default-space' variable have special behavior
 
-:(after "void write_memory(reagent x, const vector<double>& data)")
-  if (x.name == "default-space") {
-    if (!scalar(data)
-        || !x.type
-        || x.type->value != get(Type_ordinal, "address")
-        || !x.type->right
-        || x.type->right->value != get(Type_ordinal, "array")
-        || !x.type->right->right
-        || x.type->right->right->value != get(Type_ordinal, "location")
-        || x.type->right->right->right) {
-      raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
-    }
-    current_call().default_space = data.at(0);
-    return;
+:(after "Begin Preprocess write_memory(reagent x, vector<double> data)")
+if (x.name == "default-space") {
+  if (!scalar(data)
+      || !x.type
+      || x.type->value != get(Type_ordinal, "address")
+      || !x.type->right
+      || x.type->right->value != get(Type_ordinal, "array")
+      || !x.type->right->right
+      || x.type->right->right->value != get(Type_ordinal, "location")
+      || x.type->right->right->right) {
+    raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
   }
+  current_call().default_space = data.at(0);
+  return;
+}
 
 :(scenario get_default_space)
 def main [
@@ -105,12 +105,12 @@ def main [
 ]
 +mem: storing 10 in location 1
 
-:(after "vector<double> read_memory(reagent x)")
-  if (x.name == "default-space") {
-    vector<double> result;
-    result.push_back(current_call().default_space);
-    return result;
-  }
+:(after "Begin Preprocess read_memory(reagent x)")
+if (x.name == "default-space") {
+  vector<double> result;
+  result.push_back(current_call().default_space);
+  return result;
+}
 
 //:: fix 'get'
 
@@ -178,19 +178,19 @@ if (s == "number-of-locals") return true;
 if (curr.name == "new-default-space") {
   rewrite_default_space_instruction(curr);
 }
-:(after "vector<double> read_memory(reagent x)")
-  if (x.name == "number-of-locals") {
-    vector<double> result;
-    result.push_back(Name[get(Recipe_ordinal, current_recipe_name())][""]);
-    if (result.back() == 0)
-      raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end();
-    return result;
-  }
-:(after "void write_memory(reagent x, const vector<double>& data)")
-  if (x.name == "number-of-locals") {
-    raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end();
-    return;
-  }
+:(after "Begin Preprocess read_memory(reagent x)")
+if (x.name == "number-of-locals") {
+  vector<double> result;
+  result.push_back(Name[get(Recipe_ordinal, current_recipe_name())][""]);
+  if (result.back() == 0)
+    raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end();
+  return result;
+}
+:(after "Begin Preprocess write_memory(reagent x, vector<double> data)")
+if (x.name == "number-of-locals") {
+  raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end();
+  return;
+}
 
 //:: a little hook to automatically reclaim the default-space when returning
 //:: from a recipe
diff --git a/046global.cc b/046global.cc
index 40cef9d8..47706803 100644
--- a/046global.cc
+++ b/046global.cc
@@ -40,23 +40,23 @@ if (s == "global-space") return true;
 int global_space;
 :(before "End routine Constructor")
 global_space = 0;
-:(after "void write_memory(reagent x, const vector<double>& data)")
-  if (x.name == "global-space") {
-    if (!scalar(data)
-        || !x.type
-        || x.type->value != get(Type_ordinal, "address")
-        || !x.type->right
-        || x.type->right->value != get(Type_ordinal, "array")
-        || !x.type->right->right
-        || x.type->right->right->value != get(Type_ordinal, "location")
-        || x.type->right->right->right) {
-      raise << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
-    }
-    if (Current_routine->global_space)
-      raise << "routine already has a global-space; you can't over-write your globals" << end();
-    Current_routine->global_space = data.at(0);
-    return;
+:(after "Begin Preprocess write_memory(reagent x, vector<double> data)")
+if (x.name == "global-space") {
+  if (!scalar(data)
+      || !x.type
+      || x.type->value != get(Type_ordinal, "address")
+      || !x.type->right
+      || x.type->right->value != get(Type_ordinal, "array")
+      || !x.type->right->right
+      || x.type->right->right->value != get(Type_ordinal, "location")
+      || x.type->right->right->right) {
+    raise << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
   }
+  if (Current_routine->global_space)
+    raise << "routine already has a global-space; you can't over-write your globals" << end();
+  Current_routine->global_space = data.at(0);
+  return;
+}
 
 //: now marking variables as /space:global looks them up inside this field
 :(after "int space_base(const reagent& x)")
diff --git a/058shape_shifting_recipe.cc b/058shape_shifting_recipe.cc
index 5f87e6da..c64bc840 100644
--- a/058shape_shifting_recipe.cc
+++ b/058shape_shifting_recipe.cc
@@ -162,7 +162,7 @@ bool any_type_ingredient_in_header(recipe_ordinal variant) {
   return false;
 }
 
-bool concrete_type_names_strictly_match(reagent to, reagent from) {
+bool concrete_type_names_strictly_match(reagent/*copy*/ to, reagent/*copy*/ from) {
   canonize_type(to);
   canonize_type(from);
   return concrete_type_names_strictly_match(to.type, from.type, from);
@@ -293,7 +293,7 @@ void compute_type_ingredient_mappings(const recipe& exemplar, const instruction&
   int limit = min(SIZE(inst.ingredients), SIZE(exemplar.ingredients));
   for (int i = 0; i < limit; ++i) {
     const reagent& exemplar_reagent = exemplar.ingredients.at(i);
-    reagent ingredient = inst.ingredients.at(i);
+    reagent/*copy*/ ingredient = inst.ingredients.at(i);
     canonize_type(ingredient);
     if (is_mu_address(exemplar_reagent) && ingredient.name == "0") continue;  // assume it matches
     accumulate_type_ingredients(exemplar_reagent, ingredient, mappings, exemplar, inst, caller_recipe, error);
@@ -301,7 +301,7 @@ void compute_type_ingredient_mappings(const recipe& exemplar, const instruction&
   limit = min(SIZE(inst.products), SIZE(exemplar.products));
   for (int i = 0; i < limit; ++i) {
     const reagent& exemplar_reagent = exemplar.products.at(i);
-    reagent product = inst.products.at(i);
+    reagent/*copy*/ product = inst.products.at(i);
     if (is_dummy(product)) continue;
     canonize_type(product);
     accumulate_type_ingredients(exemplar_reagent, product, mappings, exemplar, inst, caller_recipe, error);
diff --git a/061recipe.cc b/061recipe.cc
index 18ff524c..93fe1bd2 100644
--- a/061recipe.cc
+++ b/061recipe.cc
@@ -143,7 +143,7 @@ recipe from_reagent(const reagent& r) {
   return result_header;
 }
 
-bool is_mu_recipe(reagent r) {
+bool is_mu_recipe(const reagent& r) {
   if (!r.type) return false;
   if (r.type->name == "recipe") return true;
   if (r.type->name == "recipe-literal") return true;
diff --git a/062scheduler.cc b/062scheduler.cc
index a1209738..a3d0baad 100644
--- a/062scheduler.cc
+++ b/062scheduler.cc
@@ -168,7 +168,7 @@ case START_RUNNING: {
   // populate ingredients
   for (int i = 1; i < SIZE(current_instruction().ingredients); ++i) {
     new_routine->calls.front().ingredient_atoms.push_back(ingredients.at(i));
-    reagent ingredient = current_instruction().ingredients.at(i);
+    reagent/*copy*/ ingredient = current_instruction().ingredients.at(i);
     canonize_type(ingredient);
     new_routine->calls.front().ingredients.push_back(ingredient);
   }
diff --git a/063wait.cc b/063wait.cc
index 4595d7c1..e07d658a 100644
--- a/063wait.cc
+++ b/063wait.cc
@@ -112,14 +112,14 @@ case GET_LOCATION: {
     raise << maybe(get(Recipe, r).name) << "'get-location' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
     break;
   }
-  reagent base = inst.ingredients.at(0);
+  reagent/*copy*/ base = inst.ingredients.at(0);
   if (!canonize_type(base)) break;
   if (!base.type || !base.type->value || !contains_key(Type, base.type->value) || get(Type, base.type->value).kind != CONTAINER) {
     raise << maybe(get(Recipe, r).name) << "first ingredient of 'get-location' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end();
     break;
   }
   type_ordinal base_type = base.type->value;
-  reagent offset = inst.ingredients.at(1);
+  const reagent& offset = inst.ingredients.at(1);
   if (!is_literal(offset) || !is_mu_scalar(offset)) {
     raise << maybe(get(Recipe, r).name) << "second ingredient of 'get-location' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end();
     break;
@@ -144,7 +144,7 @@ case GET_LOCATION: {
 }
 :(before "End Primitive Recipe Implementations")
 case GET_LOCATION: {
-  reagent base = current_instruction().ingredients.at(0);
+  reagent/*copy*/ base = current_instruction().ingredients.at(0);
   canonize(base);
   int base_address = base.value;
   if (base_address == 0) {
@@ -164,7 +164,7 @@ case GET_LOCATION: {
 }
 
 :(code)
-bool is_mu_location(reagent x) {
+bool is_mu_location(reagent/*copy*/ x) {
   if (!canonize_type(x)) return false;
   if (!x.type) return false;
   if (x.type->right) return false;
diff --git a/071rewrite_stash.cc b/071rewrite_stash.cc
index 6e2368e6..346cc132 100644
--- a/071rewrite_stash.cc
+++ b/071rewrite_stash.cc
@@ -61,7 +61,7 @@ void rewrite_stashes_to_text(recipe& caller) {
         instruction def;
         if (is_lookup_of_address_of_array(inst.ingredients.at(j))) {
           def.name = "array-to-text-line";
-          reagent tmp = inst.ingredients.at(j);
+          reagent/*copy*/ tmp = inst.ingredients.at(j);
           drop_one_lookup(tmp);
           def.ingredients.push_back(tmp);
         }
@@ -84,13 +84,13 @@ void rewrite_stashes_to_text(recipe& caller) {
   caller.steps.swap(new_instructions);
 }
 
-bool is_lookup_of_address_of_array(reagent x) {
+bool is_lookup_of_address_of_array(reagent/*copy*/ x) {
   if (x.type->name != "address") return false;
   if (!canonize_type(x)) return false;
   return x.type->name == "array";
 }
 
-bool is_static_array(reagent x) {
+bool is_static_array(const reagent& x) {
   // no canonize_type()
   return x.type->name == "array";
 }
diff --git a/078hash.cc b/078hash.cc
index 36de2fda..6577373d 100644
--- a/078hash.cc
+++ b/078hash.cc
@@ -22,7 +22,7 @@ case HASH: {
 }
 :(before "End Primitive Recipe Implementations")
 case HASH: {
-  reagent input = current_instruction().ingredients.at(0);  // copy
+  reagent/*copy*/ input = current_instruction().ingredients.at(0);
   products.resize(1);
   products.at(0).push_back(hash(0, input));
   break;
@@ -76,11 +76,11 @@ size_t hash_mu_string(size_t h, const reagent& r) {
 
 size_t hash_mu_array(size_t h, const reagent& r) {
   int size = get_or_insert(Memory, r.value);
-  reagent elem = r;
+  reagent/*copy*/ elem = r;
   delete elem.type;
   elem.type = copy_array_element(r.type);
   for (int i=0, address = r.value+1; i < size; ++i, address += size_of(elem)) {
-    reagent tmp = elem;
+    reagent/*copy*/ tmp = elem;
     tmp.value = address;
     h = hash(h, tmp);
 //?     cerr << i << " (" << address << "): " << h << '\n';
@@ -100,7 +100,7 @@ size_t hash_mu_container(size_t h, const reagent& r) {
   int address = r.value;
   int offset = 0;
   for (int i = 0; i < SIZE(info.elements); ++i) {
-    reagent element = element_type(r.type, i);
+    reagent/*copy*/ element = element_type(r.type, i);
     if (has_property(element, "ignore-for-hash")) continue;
     element.set_value(address+offset);
     h = hash(h, element);
@@ -119,7 +119,7 @@ bool is_mu_exclusive_container(const reagent& r) {
 size_t hash_mu_exclusive_container(size_t h, const reagent& r) {
   assert(r.type->value);
   int tag = get(Memory, r.value);
-  reagent variant = variant_type(r, tag);
+  reagent/*copy*/ variant = variant_type(r, tag);
   // todo: move this error to container definition time
   if (has_property(variant, "ignore-for-hash"))
     raise << get(Type, r.type->value).name << ": /ignore-for-hash won't work in exclusive containers\n" << end();