Follow-up to commit 3321: move get_base_type() more thoroughly to layer
55. The notion of a base_type doesn't really make sense before we
introduce type ingredients and shape-shifting containers, and it
simplifies early layers a *lot* even including the cost of that *ugly*
preamble in layer 55 to retrofit all the places.
This commit is contained in:
Kartik K. Agaram 2016-11-08 11:46:04 -08:00
parent 4ecab1821e
commit b55b15a920
8 changed files with 68 additions and 41 deletions

View File

@ -148,25 +148,19 @@ void clear_container_metadata() {
if (r.metadata.size) return r.metadata.size;
:(before "End size_of(type) Special-cases")
const type_tree* root = root_type(type);
if (!contains_key(Type, root->value)) {
raise << "no such type " << root->value << '\n' << end();
const type_tree* base_type = type;
// Update base_type in size_of(type)
if (!contains_key(Type, base_type->value)) {
raise << "no such type " << base_type->value << '\n' << end();
return 0;
}
type_info t = get(Type, root->value);
type_info t = get(Type, base_type->value);
if (t.kind == CONTAINER) {
// Compute size_of Container
if (!contains_key(Container_metadata, type)) return 1; // error raised elsewhere
return get(Container_metadata, type).size;
}
:(code)
const type_tree* root_type(const type_tree* t) {
const type_tree* result = t->atom ? t : t->left;
assert(result->atom);
return result;
}
//: precompute Container_metadata before we need size_of
//: also store a copy in each reagent in each instruction in each recipe
@ -421,10 +415,11 @@ case GET: {
:(code)
const reagent element_type(const type_tree* type, int offset_value) {
assert(offset_value >= 0);
const type_tree* root = root_type(type);
assert(contains_key(Type, root->value));
assert(!get(Type, root->value).name.empty());
const type_info& info = get(Type, root->value);
const type_tree* base_type = type;
// Update base_type in element_type
assert(contains_key(Type, base_type->value));
assert(!get(Type, base_type->value).name.empty());
const type_info& info = get(Type, base_type->value);
assert(info.kind == CONTAINER);
if (offset_value >= SIZE(info.elements)) return reagent(); // error handled elsewhere
reagent/*copy*/ element = info.elements.at(offset_value);

View File

@ -166,7 +166,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
if (types_coercible(expected_ingredient, ingredients.at(ingredient_index))) {
++ingredient_index;
++state.data.top().container_element_index;
while (state.data.top().container_element_index >= SIZE(get(Type, root_type(state.data.top().container.type)->value).elements)) {
while (state.data.top().container_element_index >= SIZE(get(Type, get_base_type(state.data.top().container.type)->value).elements)) {
state.data.pop();
if (state.data.empty()) {
if (ingredient_index < SIZE(ingredients))
@ -201,7 +201,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
return;
}
++state.data.top().container_element_index;
} while (state.data.top().container_element_index >= SIZE(get(Type, root_type(state.data.top().container.type)->value).elements));
} while (state.data.top().container_element_index >= SIZE(get(Type, get_base_type(state.data.top().container.type)->value).elements));
}
}
}
@ -209,6 +209,12 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
assert(false);
}
// replaced in a later layer
// todo: find some clean way to take this call completely out of this layer
const type_tree* get_base_type(const type_tree* t) {
return t;
}
:(scenario merge_check_product)
% Hide_errors = true;
def main [

View File

@ -321,8 +321,10 @@ void compute_container_address_offsets(const type_tree* type, const string& loca
compute_container_address_offsets(array_element(type), location_for_error_messages);
// End compute_container_address_offsets Non-atom Special-cases
}
if (!contains_key(Type, root_type(type)->value)) return; // error raised elsewhere
type_info& info = get(Type, root_type(type)->value);
const type_tree* base_type = type;
// Update base_type in compute_container_address_offsets
if (!contains_key(Type, base_type->value)) return; // error raised elsewhere
type_info& info = get(Type, base_type->value);
if (info.kind == CONTAINER) {
compute_container_address_offsets(info, type, location_for_error_messages);
}
@ -353,12 +355,13 @@ void append_addresses(int base_offset, const type_tree* type, map<set<tag_condit
get_or_insert(out, key).insert(address_element_info(base_offset, new type_tree(*type->right)));
return;
}
const type_tree* root = root_type(type);
const type_info& info = get(Type, root->value);
const type_tree* base_type = type;
// Update base_type in append_container_address_offsets
const type_info& info = get(Type, base_type->value);
if (info.kind == CONTAINER) {
for (int curr_index = 0, curr_offset = base_offset; curr_index < SIZE(info.elements); ++curr_index) {
trace(9993, "transform") << "checking container " << root->name << ", element " << curr_index << end();
reagent/*copy*/ element = element_type(type, curr_index); // not root
trace(9993, "transform") << "checking container " << base_type->name << ", element " << curr_index << end();
reagent/*copy*/ element = element_type(type, curr_index); // not base_type
// Compute Container Address Offset(element)
if (is_mu_address(element)) {
trace(9993, "transform") << "address at offset " << curr_offset << end();
@ -379,8 +382,9 @@ void append_addresses(int base_offset, const type_tree* type, map<set<tag_condit
curr_offset += size_of(element);
}
else if (is_mu_exclusive_container(element)) {
const type_tree* element_root_type = root_type(element.type);
const type_info& element_info = get(Type, element_root_type->value);
const type_tree* element_base_type = element.type;
// Update element_base_type For Exclusive Container in append_addresses
const type_info& element_info = get(Type, element_base_type->value);
for (int tag = 0; tag < SIZE(element_info.elements); ++tag) {
set<tag_condition_info> new_key = key;
new_key.insert(tag_condition_info(curr_offset, tag));

View File

@ -121,7 +121,9 @@ type_ordinal skip_addresses(type_tree* type) {
while (type && is_compound_type_starting_with(type, "address"))
type = type->right;
if (!type) return -1; // error handled elsewhere
return root_type(type)->value;
const type_tree* base_type = type;
// Update base_type in skip_addresses
return base_type->value;
}
int find_element_name(const type_ordinal t, const string& name, const string& recipe_name) {

View File

@ -4,21 +4,39 @@
//: atomic types
:(before "End is_mu_container(type) Special-cases")
if (!type->atom)
return is_mu_container(root_type(type));
return is_mu_container(get_base_type(type));
:(before "End is_mu_exclusive_container(type) Special-cases")
if (!type->atom)
return is_mu_exclusive_container(root_type(type));
// a few calls to root_type() without the assertion (for better error handling)
return is_mu_exclusive_container(get_base_type(type));
:(after "Update GET base_type in Check")
if (!base_type->atom) base_type = base_type->left;
base_type = get_base_type(base_type);
:(after "Update GET base_type in Run")
if (!base_type->atom) base_type = base_type->left;
base_type = get_base_type(base_type);
:(after "Update PUT base_type in Check")
if (!base_type->atom) base_type = base_type->left;
base_type = get_base_type(base_type);
:(after "Update PUT base_type in Run")
if (!base_type->atom) base_type = base_type->left;
base_type = get_base_type(base_type);
:(after "Update MAYBE_CONVERT base_type in Check")
if (!base_type->atom) base_type = base_type->left;
base_type = get_base_type(base_type);
:(after "Update base_type in size_of(type)")
base_type = get_base_type(base_type);
:(after "Update base_type in element_type")
base_type = get_base_type(base_type);
:(after "Update base_type in compute_container_address_offsets")
base_type = get_base_type(base_type);
:(after "Update base_type in append_container_address_offsets")
base_type = get_base_type(base_type);
:(after "Update element_base_type For Exclusive Container in append_addresses")
element_base_type = get_base_type(element_base_type);
:(after "Update base_type in skip_addresses")
base_type = get_base_type(base_type);
:(replace{} "const type_tree* get_base_type(const type_tree* t)")
const type_tree* get_base_type(const type_tree* t) {
const type_tree* result = t->atom ? t : t->left;
if (!result->atom)
raise << "invalid type " << to_string(t) << '\n' << end();
return result;
}
:(scenario ill_formed_container)
% Hide_errors = true;
@ -498,7 +516,7 @@ def main [
//: that we need to teach about type ingredients.
:(before "End compute_container_sizes Non-atom Special-cases")
const type_tree* root = root_type(type);
const type_tree* root = get_base_type(type);
type_info& info = get(Type, root->value);
if (info.kind == CONTAINER) {
compute_container_sizes(info, type, pending_metadata, location_for_error_messages);
@ -558,7 +576,7 @@ void test_container_sizes_recursive_shape_shifting_container() {
}
:(before "End compute_container_address_offsets Non-atom Special-cases")
const type_tree* root = root_type(type);
const type_tree* root = get_base_type(type);
type_info& info = get(Type, root->value);
if (info.kind == CONTAINER) {
compute_container_address_offsets(info, type, location_for_error_messages);

View File

@ -89,7 +89,7 @@ size_t hash_mu_array(size_t h, const reagent& r) {
}
size_t hash_mu_container(size_t h, const reagent& r) {
type_info& info = get(Type, root_type(r.type)->value);
type_info& info = get(Type, get_base_type(r.type)->value);
int address = r.value;
int offset = 0;
for (int i = 0; i < SIZE(info.elements); ++i) {
@ -104,7 +104,7 @@ size_t hash_mu_container(size_t h, const reagent& r) {
}
size_t hash_mu_exclusive_container(size_t h, const reagent& r) {
const type_tree* type = root_type(r.type);
const type_tree* type = get_base_type(r.type);
assert(type->value);
int tag = get(Memory, r.value);
reagent/*copy*/ variant = variant_type(r, tag);

View File

@ -205,7 +205,9 @@ recipe from_reagent(const reagent& r) {
assert(r.type->name == "recipe");
return result_header;
}
assert(root_type(r.type)->name == "recipe");
const type_tree* root_type = r.type->atom ? r.type : r.type->left;
assert(root_type->atom);
assert(root_type->name == "recipe");
const type_tree* curr = r.type->right;
for (/*nada*/; curr && !curr->atom; curr = curr->right) {
if (curr->left->atom && curr->left->name == "->") {

View File

@ -205,9 +205,9 @@ case GET_LOCATION: {
raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
break;
}
const type_tree* base_root_type = root_type(base.type);
const type_tree* base_type = get_base_type(base.type);
int offset = ingredients.at(1).at(0);
if (offset < 0 || offset >= SIZE(get(Type, base_root_type->value).elements)) break; // copied from Check above
if (offset < 0 || offset >= SIZE(get(Type, base_type->value).elements)) break; // copied from Check above
int result = base_address;
for (int i = 0; i < offset; ++i)
result += size_of(element_type(base.type, i));