diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-03-21 02:53:34 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-03-21 02:53:34 -0700 |
commit | d57bf669c20f1936af8674d549bfb01c01f68f4f (patch) | |
tree | 0d10ba2f55f1d7725c193871900ffb3152564d66 | |
parent | acc4792d2f7c787aad064876a1eb2d00bdf076b2 (diff) | |
download | mu-d57bf669c20f1936af8674d549bfb01c01f68f4f.tar.gz |
2804 - support stashing arrays
Now to extend 'stash' for arrays, just extend array-to-text-line instead and perform the lookup inside it.
-rw-r--r-- | 042name.cc | 11 | ||||
-rw-r--r-- | 047check_type_by_name.cc | 12 | ||||
-rw-r--r-- | 070text.mu | 7 | ||||
-rw-r--r-- | 071rewrite_stash.cc | 33 |
4 files changed, 50 insertions, 13 deletions
diff --git a/042name.cc b/042name.cc index 6a9858a6..8cd6cd4f 100644 --- a/042name.cc +++ b/042name.cc @@ -110,14 +110,13 @@ int lookup_name(const reagent& r, const recipe_ordinal default_recipe) { return Name[default_recipe][r.name]; } -type_ordinal skip_addresses(type_tree* type, const string& recipe_name) { +type_ordinal skip_addresses(type_tree* type) { type_ordinal address = get(Type_ordinal, "address"); type_ordinal shared = get(Type_ordinal, "shared"); for (; type; type = type->right) { if (type->value != address && type->value != shared) return type->value; } - raise << maybe(recipe_name) << "expected a container" << '\n' << end(); return -1; } @@ -220,7 +219,9 @@ if (inst.name == "get" || inst.name == "get-address") { raise << maybe(get(Recipe, r).name) << "expected ingredient 1 of " << (inst.name == "get" ? "'get'" : "'get-address'") << " to have type 'offset'; got " << inst.ingredients.at(1).original_string << '\n' << end(); if (inst.ingredients.at(1).name.find_first_not_of("0123456789") != string::npos) { // since first non-address in base type must be a container, we don't have to canonize - type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type, get(Recipe, r).name); + type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type); + if (base_type == -1) + raise << maybe(get(Recipe, r).name) << "expected a container in '" << to_original_string(inst) << "'\n" << end(); if (contains_key(Type, base_type)) { // otherwise we'll raise an error elsewhere inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name, get(Recipe, r).name)); trace(9993, "name") << "element " << inst.ingredients.at(1).name << " of type " << get(Type, base_type).name << " is at offset " << no_scientific(inst.ingredients.at(1).value) << end(); @@ -261,7 +262,9 @@ if (inst.name == "maybe-convert") { assert(is_literal(inst.ingredients.at(1))); if (inst.ingredients.at(1).name.find_first_not_of("0123456789") != string::npos) { // since first non-address in base type must be an exclusive container, we don't have to canonize - type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type, get(Recipe, r).name); + type_ordinal base_type = skip_addresses(inst.ingredients.at(0).type); + if (base_type == -1) + raise << maybe(get(Recipe, r).name) << "expected an exclusive-container in '" << to_original_string(inst) << "'\n" << end(); if (contains_key(Type, base_type)) { // otherwise we'll raise an error elsewhere inst.ingredients.at(1).set_value(find_element_name(base_type, inst.ingredients.at(1).name, get(Recipe, r).name)); trace(9993, "name") << "variant " << inst.ingredients.at(1).name << " of type " << get(Type, base_type).name << " has tag " << no_scientific(inst.ingredients.at(1).value) << end(); diff --git a/047check_type_by_name.cc b/047check_type_by_name.cc index a1970915..ed45119f 100644 --- a/047check_type_by_name.cc +++ b/047check_type_by_name.cc @@ -26,11 +26,11 @@ void check_or_set_types_by_name(const recipe_ordinal r) { instruction& inst = caller.steps.at(i); for (int in = 0; in < SIZE(inst.ingredients); ++in) { deduce_missing_type(known, inst.ingredients.at(in)); - check_type(known, inst.ingredients.at(in), r); + check_type(known, inst.ingredients.at(in), caller); } for (int out = 0; out < SIZE(inst.products); ++out) { deduce_missing_type(known, inst.products.at(out)); - check_type(known, inst.products.at(out), r); + check_type(known, inst.products.at(out), caller); } } } @@ -42,7 +42,7 @@ void deduce_missing_type(set<reagent>& known, reagent& x) { trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end(); } -void check_type(set<reagent>& known, const reagent& x, const recipe_ordinal r) { +void check_type(set<reagent>& known, const reagent& x, const recipe& caller) { if (is_literal(x)) return; if (is_integer(x.name)) return; // if you use raw locations you're probably doing something unsafe if (!x.type) return; // might get filled in by other logic later @@ -51,16 +51,16 @@ void check_type(set<reagent>& known, const reagent& x, const recipe_ordinal r) { known.insert(x); } if (!types_strictly_match(known.find(x)->type, x.type)) { - raise << maybe(get(Recipe, r).name) << x.name << " used with multiple types\n" << end(); + raise << maybe(caller.name) << x.name << " used with multiple types\n" << end(); return; } if (x.type->name == "array") { if (!x.type->right) { - raise << maybe(get(Recipe, r).name) << x.name << " can't be just an array. What is it an array of?\n" << end(); + raise << maybe(caller.name) << x.name << " can't be just an array. What is it an array of?\n" << end(); return; } if (!x.type->right->right) { - raise << get(Recipe, r).name << " can't determine the size of array variable " << x.name << ". Either allocate it separately and make the type of " << x.name << " address:shared:..., or specify the length of the array in the type of " << x.name << ".\n" << end(); + raise << caller.name << " can't determine the size of array variable " << x.name << ". Either allocate it separately and make the type of " << x.name << " address:shared:..., or specify the length of the array in the type of " << x.name << ".\n" << end(); return; } } diff --git a/070text.mu b/070text.mu index b69db18a..24317a59 100644 --- a/070text.mu +++ b/070text.mu @@ -8,6 +8,13 @@ def to-text-line x:_elem -> y:address:shared:array:character [ y <- to-text x ] +# variant for arrays (since we can't pass them around otherwise) +def array-to-text-line x:address:shared:array:_elem -> y:address:shared:array:character [ + local-scope + load-ingredients + y <- to-text *x +] + # to-text on text is just the identity function def to-text x:address:shared:array:character -> y:address:shared:array:character [ local-scope diff --git a/071rewrite_stash.cc b/071rewrite_stash.cc index a41fa72f..a1a3deef 100644 --- a/071rewrite_stash.cc +++ b/071rewrite_stash.cc @@ -8,7 +8,19 @@ recipe main [ n:number <- copy 34 stash n ] -+transform: {stash_2_0: ("address" "shared" "array" "character")} <- to-text-line {n: ()} ++transform: {stash_2_0: ("address" "shared" "array" "character")} <- to-text-line {n: "number"} ++transform: stash {stash_2_0: ("address" "shared" "array" "character")} + +//: special case: rewrite attempts to stash contents of most arrays to avoid +//: passing addresses around + +:(scenario rewrite_stashes_of_arrays) +recipe main [ + local-scope + n:address:shared:array:number <- new number:type, 3 + stash *n +] ++transform: {stash_2_0: ("address" "shared" "array" "character")} <- array-to-text-line {n: ("address" "shared" "array" "number")} +transform: stash {stash_2_0: ("address" "shared" "array" "character")} :(before "End Instruction Inserting/Deleting Transforms") @@ -20,6 +32,7 @@ void rewrite_stashes_to_text(recipe_ordinal r) { trace(9991, "transform") << "--- rewrite 'stash' instructions in recipe " << caller.name << end(); // in recipes without named locations, 'stash' is still not extensible if (contains_numeric_locations(caller)) return; + check_or_set_types_by_name(r); // prerequisite rewrite_stashes_to_text(caller); } @@ -29,11 +42,20 @@ void rewrite_stashes_to_text(recipe& caller) { instruction& inst = caller.steps.at(i); if (inst.name == "stash") { for (int j = 0; j < SIZE(inst.ingredients); ++j) { + assert(inst.ingredients.at(j).type); if (is_literal(inst.ingredients.at(j))) continue; if (is_mu_string(inst.ingredients.at(j))) continue; instruction def; - def.name = "to-text-line"; - def.ingredients.push_back(inst.ingredients.at(j)); + if (is_address_of_array(inst.ingredients.at(j))) { + def.name = "array-to-text-line"; + reagent tmp = inst.ingredients.at(j); + drop_one_lookup(tmp); + def.ingredients.push_back(tmp); + } + else { + def.name = "to-text-line"; + def.ingredients.push_back(inst.ingredients.at(j)); + } ostringstream ingredient_name; ingredient_name << "stash_" << i << '_' << j << ":address:shared:array:character"; def.products.push_back(reagent(ingredient_name.str())); @@ -49,6 +71,11 @@ void rewrite_stashes_to_text(recipe& caller) { caller.steps.swap(new_instructions); } +bool is_address_of_array(reagent x) { + if (!canonize_type(x)) return false; + return x.type->name == "array"; +} + //: Make sure that the new system is strictly better than just the 'stash' //: primitive by itself. |