2931 - be explicit about making copies

This commit is contained in:
Kartik K. Agaram 2016-05-06 00:46:39 -07:00
parent ce9616a77f
commit 3473c63ad9
22 changed files with 154 additions and 147 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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";

View File

@ -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

View File

@ -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();

View File

@ -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) {

View File

@ -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))) {

View File

@ -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();

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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))

View File

@ -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");

View File

@ -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()));

View File

@ -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

View File

@ -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)")

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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";
}

View File

@ -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();