diff options
-rw-r--r-- | 030container.cc | 26 | ||||
-rw-r--r-- | 058generic_container.cc | 46 |
2 files changed, 61 insertions, 11 deletions
diff --git a/030container.cc b/030container.cc index 1bece91d..9618dd2a 100644 --- a/030container.cc +++ b/030container.cc @@ -152,10 +152,9 @@ case GET: { raise_error << maybe(Recipe[r].name) << "invalid offset " << offset_value << " for " << Type[base_type].name << '\n' << end(); break; } - reagent product = inst.products.at(0); + reagent& product = inst.products.at(0); // Update GET product in Check - reagent element; - element.type = new type_tree(*Type[base_type].elements.at(offset_value)); + const reagent element = element_type(base, offset_value); if (!types_match(product, element)) { raise_error << maybe(Recipe[r].name) << "'get' " << offset.original_string << " (" << offset_value << ") on " << Type[base_type].name << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); break; @@ -180,15 +179,25 @@ case GET: { src += size_of(Type[base_type].elements.at(i)); } trace(9998, "run") << "address to copy is " << src << end(); - type_ordinal src_type = Type[base_type].elements.at(offset)->value; - trace(9998, "run") << "its type is " << Type[src_type].name << end(); - reagent tmp; + reagent tmp = element_type(base, offset); tmp.set_value(src); - tmp.type = new type_tree(src_type); + trace(9998, "run") << "its type is " << dump_types(tmp) << end(); products.push_back(read_memory(tmp)); break; } +:(code) +const reagent element_type(const reagent& canonized_base, long long int offset_value) { + assert(offset_value >= 0); + assert(Type.find(canonized_base.type->value) != Type.end()); + const type_info& info = Type[canonized_base.type->value]; + assert(info.kind == CONTAINER); + reagent element; + element.type = new type_tree(*info.elements.at(offset_value)); + // End element_type Special-cases + return element; +} + :(scenario get_handles_nested_container_elements) recipe main [ 12:number <- copy 34 @@ -273,9 +282,8 @@ case GET_ADDRESS: { } reagent product = inst.products.at(0); // Update GET_ADDRESS product in Check - reagent element; // same type as for GET.. - element.type = new type_tree(*Type[base_type].elements.at(offset_value)); + reagent element = element_type(base, offset_value); // ..except for an address at the start element.type = new type_tree(Type_ordinal["address"], element.type); if (!types_match(product, element)) { diff --git a/058generic_container.cc b/058generic_container.cc index b192dbc3..d5368765 100644 --- a/058generic_container.cc +++ b/058generic_container.cc @@ -91,7 +91,7 @@ long long int size_of_type_ingredient(const type_tree* element_template, const t } assert(curr); assert(!curr->left); // unimplemented - trace(9999, "type") << "type deduced to be " << Type[curr->value].name << "$\n"; + trace(9999, "type") << "type deduced to be " << Type[curr->value].name << "$"; type_tree tmp(curr->value); if (curr->right) tmp.right = new type_tree(*curr->right); @@ -105,7 +105,7 @@ container foo:_t [ ] recipe main [ 1:foo:point <- merge 14, 15, 16 - 2:number <- get 1:foo:point, 1:offset + 2:number <- get 1:foo:point, y:offset ] +mem: storing 16 in location 2 @@ -115,6 +115,48 @@ if (Type[base_type].elements.at(i)->value >= START_TYPE_INGREDIENTS) { continue; } +:(scenario get_on_generic_container_2) +container foo:_t [ + x:_t + y:number +] +recipe main [ + 1:foo:point <- merge 14, 15, 16 + 2:point <- get 1:foo:point, x:offset +] ++mem: storing 14 in location 2 ++mem: storing 15 in location 3 + +:(before "End element_type Special-cases") +if (contains_type_ingredient(element)) { + replace_type_ingredients(element.type, canonized_base.type->right); +} + +:(code) +bool contains_type_ingredient(const reagent& x) { + return contains_type_ingredient(x.type); +} + +bool contains_type_ingredient(const type_tree* type) { + if (!type) return false; + if (type->value >= START_TYPE_INGREDIENTS) return true; + return contains_type_ingredient(type->left) || contains_type_ingredient(type->right); +} + +void replace_type_ingredients(type_tree* element_type, type_tree* callsite_type) { + if (!element_type) return; + if (element_type->value >= START_TYPE_INGREDIENTS) { + element_type->value = nth_type(callsite_type, element_type->value-START_TYPE_INGREDIENTS); + } + replace_type_ingredients(element_type->right, callsite_type->right); +} + +type_ordinal nth_type(type_tree* base, long long int n) { + assert(n >= 0); + if (n == 0) return base->value; // todo: base->left + return nth_type(base->right, n-1); +} + :(scenario get_address_on_generic_container) container foo:_t [ x:_t |