From 3adc9e08715fb695b8a7f53d5cfb3db1bd434b05 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 17 Feb 2016 10:09:48 -0800 Subject: 2667 - redo container data structure I've been gradually Greenspunning reagents. Just go all the way. --- 010vm.cc | 10 ++---- 030container.cc | 74 ++++++++++++++++-------------------------- 032array.cc | 19 ++++++----- 033exclusive_container.cc | 20 ++++-------- 042name.cc | 5 ++- 058shape_shifting_container.cc | 12 +++---- 077hash.cc | 2 +- 7 files changed, 57 insertions(+), 85 deletions(-) diff --git a/010vm.cc b/010vm.cc index 758d8d26..970b88c5 100644 --- a/010vm.cc +++ b/010vm.cc @@ -148,10 +148,8 @@ void setup_types() { } void teardown_types() { for (map::iterator p = Type.begin(); p != Type.end(); ++p) { - for (long long int i = 0; i < SIZE(p->second.elements); ++i) { - delete p->second.elements.at(i); - delete p->second.element_type_names.at(i); - } + for (long long int i = 0; i < SIZE(p->second.elements); ++i) + p->second.elements.clear(); } Type_ordinal.clear(); } @@ -180,9 +178,7 @@ struct type_info { string name; kind_of_type kind; long long int size; // only if type is not primitive; primitives and addresses have size 1 (except arrays are dynamic) - vector elements; - vector element_type_names; - vector element_names; + vector elements; // End type_info Fields type_info() :kind(PRIMITIVE), size(0) {} }; diff --git a/030container.cc b/030container.cc index ca5b1080..d4ccf32c 100644 --- a/030container.cc +++ b/030container.cc @@ -6,12 +6,8 @@ type_ordinal point = put(Type_ordinal, "point", Next_type_ordinal++); get_or_insert(Type, point).size = 2; get(Type, point).kind = CONTAINER; get(Type, point).name = "point"; -get(Type, point).element_type_names.push_back(new string_tree("number")); -get(Type, point).elements.push_back(new type_tree(number)); -get(Type, point).element_names.push_back("x"); -get(Type, point).element_type_names.push_back(new string_tree("number")); -get(Type, point).elements.push_back(new type_tree(number)); -get(Type, point).element_names.push_back("y"); +get(Type, point).elements.push_back(reagent("x:number")); +get(Type, point).elements.push_back(reagent("y:number")); //: Containers can be copied around with a single instruction just like //: numbers, no matter how large they are. @@ -43,12 +39,8 @@ type_ordinal point_number = put(Type_ordinal, "point-number", Next_type_ordinal+ get_or_insert(Type, point_number).size = 2; get(Type, point_number).kind = CONTAINER; get(Type, point_number).name = "point-number"; -get(Type, point_number).elements.push_back(new type_tree(point)); -get(Type, point_number).element_type_names.push_back(new string_tree("point")); -get(Type, point_number).element_names.push_back("xy"); -get(Type, point_number).elements.push_back(new type_tree(number)); -get(Type, point_number).element_type_names.push_back(new string_tree("number")); -get(Type, point_number).element_names.push_back("z"); +get(Type, point_number).elements.push_back(reagent("xy:point")); +get(Type, point_number).elements.push_back(reagent("z:number")); :(scenario copy_handles_nested_container_elements) recipe main [ @@ -101,12 +93,12 @@ if (t.kind == CONTAINER) { long long int result = 0; for (long long int i = 0; i < SIZE(t.elements); ++i) { // todo: strengthen assertion to disallow mutual type recursion - if (t.elements.at(i)->value == type->value) { + if (t.elements.at(i).type->value == type->value) { raise_error << "container " << t.name << " can't include itself as a member\n" << end(); return 0; } // End size_of(type) Container Cases - result += size_of(t.elements.at(i)); + result += size_of(t.elements.at(i).type); } return result; } @@ -185,7 +177,7 @@ case GET: { long long int src = base_address; for (long long int i = 0; i < offset; ++i) { // End GET field Cases - src += size_of(get(Type, base_type).elements.at(i)); + src += size_of(get(Type, base_type).elements.at(i).type); } trace(9998, "run") << "address to copy is " << src << end(); reagent tmp = element_type(base, offset); @@ -202,11 +194,7 @@ const reagent element_type(const reagent& canonized_base, long long int offset_v assert(!get(Type, canonized_base.type->value).name.empty()); const type_info& info = get(Type, canonized_base.type->value); assert(info.kind == CONTAINER); - reagent element; - element.name = info.element_names.at(offset_value); - element.type = new type_tree(*info.elements.at(offset_value)); - element.properties.resize(1); - element.properties.at(0).second = new string_tree(*info.element_type_names.at(offset_value)); + reagent element = info.elements.at(offset_value); // End element_type Special-cases return element; } @@ -330,7 +318,7 @@ case GET_ADDRESS: { long long int result = base_address; for (long long int i = 0; i < offset; ++i) { // End GET_ADDRESS field Cases - result += size_of(get(Type, base_type).elements.at(i)); + result += size_of(get(Type, base_type).elements.at(i).type); } trace(9998, "run") << "address to copy is " << result << end(); products.resize(1); @@ -380,10 +368,8 @@ container foo [ y:number ] +parse: --- defining container foo -+parse: element name: x -+parse: type: 1 -+parse: element name: y -+parse: type: 1 ++parse: element: x: number -- {"x": "number"} ++parse: element: y: number -- {"y": "number"} :(scenario container_use_before_definition) container foo [ @@ -397,12 +383,15 @@ container bar [ ] +parse: --- defining container foo +parse: type number: 1000 -+parse: element name: x -+parse: type: 1 -+parse: element name: y -+parse: type: 1001 ++parse: element: x: number -- {"x": "number"} +# todo: brittle +# type bar is unknown at this point, but we assign it a number ++parse: element: y: ?1001 -- {"y": "bar"} +# later type bar gets a definition +parse: --- defining container bar +parse: type number: 1001 ++parse: element: x: number -- {"x": "number"} ++parse: element: y: number -- {"y": "number"} :(before "End Command Handlers") else if (command == "container") { @@ -429,16 +418,13 @@ void insert_container(const string& command, kind_of_type kind, istream& in) { skip_whitespace_and_comments(in); string element = next_word(in); if (element == "]") break; - istringstream inner(element); - info.element_names.push_back(slurp_until(inner, ':')); - trace(9993, "parse") << " element name: " << info.element_names.back() << end(); - info.element_type_names.push_back(parse_property_list(inner)); - info.elements.push_back(new_type_tree_with_new_types_for_unknown(info.element_type_names.back(), info)); - for (long long int i = 0; i < SIZE(info.elements); ++i) - trace(9993, "parse") << " type: " << info.elements.at(i)->value << end(); + info.elements.push_back(reagent(element)); + // handle undefined types + delete info.elements.back().type; + info.elements.back().type = new_type_tree_with_new_types_for_unknown(info.elements.back().properties.at(0).second, info); + trace(9993, "parse") << " element: " << debug_string(info.elements.back()) << end(); // End Load Container Element Definition } - assert(SIZE(info.elements) == SIZE(info.element_names)); info.size = SIZE(info.elements); } @@ -499,10 +485,8 @@ for (long long int i = 0; i < SIZE(Recently_added_types); ++i) { if (!contains_key(Type, Recently_added_types.at(i))) continue; Type_ordinal.erase(get(Type, Recently_added_types.at(i)).name); // todo: why do I explicitly need to provide this? - for (long long int j = 0; j < SIZE(Type.at(Recently_added_types.at(i)).elements); ++j) { - delete Type.at(Recently_added_types.at(i)).elements.at(j); - delete Type.at(Recently_added_types.at(i)).element_type_names.at(j); - } + for (long long int j = 0; j < SIZE(Type.at(Recently_added_types.at(i)).elements); ++j) + Type.at(Recently_added_types.at(i)).elements.at(j).clear(); Type.erase(Recently_added_types.at(i)); } Recently_added_types.clear(); @@ -603,10 +587,8 @@ container foo [ y:number ] +parse: --- defining container foo -+parse: element name: x -+parse: type: 1 -+parse: element name: y -+parse: type: 1 ++parse: element: x: number -- {"x": "number"} ++parse: element: y: number -- {"y": "number"} :(before "End Transform All") check_container_field_types(); @@ -617,7 +599,7 @@ void check_container_field_types() { const type_info& info = p->second; // Check Container Field Types(info) for (long long int i = 0; i < SIZE(info.elements); ++i) - check_invalid_types(info.elements.at(i), maybe(info.name), info.element_names.at(i)); + check_invalid_types(info.elements.at(i).type, maybe(info.name), info.elements.at(i).name); } } diff --git a/032array.cc b/032array.cc index aace0a5a..b558d98f 100644 --- a/032array.cc +++ b/032array.cc @@ -134,14 +134,17 @@ container foo [ +error: container 'foo' cannot determine size of element x :(before "End Load Container Element Definition") -if (info.element_type_names.back()->value == "array") { - if (!info.element_type_names.back()->right) { - raise_error << "container '" << name << "' doesn't specify type of array elements for " << info.element_names.back() << '\n' << end(); - continue; - } - if (!info.element_type_names.back()->right->right) { // array has no length - raise_error << "container '" << name << "' cannot determine size of element " << info.element_names.back() << '\n' << end(); - continue; +{ + const string_tree* type_name = info.elements.back().properties.at(0).second; + if (type_name->value == "array") { + if (!type_name->right) { + raise_error << "container '" << name << "' doesn't specify type of array elements for " << info.elements.back().name << '\n' << end(); + continue; + } + if (!type_name->right->right) { // array has no length + raise_error << "container '" << name << "' cannot determine size of element " << info.elements.back().name << '\n' << end(); + continue; + } } } diff --git a/033exclusive_container.cc b/033exclusive_container.cc index 3b1dc201..26169637 100644 --- a/033exclusive_container.cc +++ b/033exclusive_container.cc @@ -11,12 +11,8 @@ type_ordinal tmp = put(Type_ordinal, "number-or-point", Next_type_ordinal++); get_or_insert(Type, tmp).size = 2; get(Type, tmp).kind = EXCLUSIVE_CONTAINER; get(Type, tmp).name = "number-or-point"; -get(Type, tmp).element_type_names.push_back(new string_tree("number")); -get(Type, tmp).elements.push_back(new type_tree(number)); -get(Type, tmp).element_names.push_back("i"); -get(Type, tmp).element_type_names.push_back(new string_tree("point")); -get(Type, tmp).elements.push_back(new type_tree(point)); -get(Type, tmp).element_names.push_back("p"); +get(Type, tmp).elements.push_back(reagent("i:number")); +get(Type, tmp).elements.push_back(reagent("p:point")); } //: Tests in this layer often explicitly setup memory before reading it as an @@ -41,7 +37,7 @@ if (t.kind == EXCLUSIVE_CONTAINER) { long long int result = 0; for (long long int i = 0; i < t.size; ++i) { // End size_of(type) Exclusive Container Cases - long long int size = size_of(t.elements.at(i)); + long long int size = size_of(t.elements.at(i).type); if (size > result) result = size; } // ...+1 for its tag. @@ -143,9 +139,7 @@ const reagent variant_type(const reagent& canonized_base, long long int tag) { assert(!get(Type, canonized_base.type->value).name.empty()); const type_info& info = get(Type, canonized_base.type->value); assert(info.kind == EXCLUSIVE_CONTAINER); - reagent element; - element.type = new type_tree(*info.elements.at(tag)); - element.properties.at(0).second = new string_tree(*info.element_type_names.at(tag)); + reagent element = info.elements.at(tag); // End variant_type Special-cases return element; } @@ -169,10 +163,8 @@ exclusive-container foo [ y:number ] +parse: --- defining exclusive-container foo -+parse: element name: x -+parse: type: 1 -+parse: element name: y -+parse: type: 1 ++parse: element: x: number -- {"x": "number"} ++parse: element: y: number -- {"y": "number"} :(before "End Command Handlers") else if (command == "exclusive-container") { diff --git a/042name.cc b/042name.cc index a8268b4a..bdaf50e9 100644 --- a/042name.cc +++ b/042name.cc @@ -104,9 +104,8 @@ type_ordinal skip_addresses(type_tree* type, const string& recipe_name) { int find_element_name(const type_ordinal t, const string& name, const string& recipe_name) { const type_info& container = get(Type, t); - for (long long int i = 0; i < SIZE(container.element_names); ++i) { - if (container.element_names.at(i) == name) return i; - } + for (long long int i = 0; i < SIZE(container.elements); ++i) + if (container.elements.at(i).name == name) return i; raise_error << maybe(recipe_name) << "unknown element " << name << " in container " << get(Type, t).name << '\n' << end(); return -1; } diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc index e4822cc0..476468b7 100644 --- a/058shape_shifting_container.cc +++ b/058shape_shifting_container.cc @@ -71,9 +71,9 @@ if (type->value >= START_TYPE_INGREDIENTS return; :(before "End size_of(type) Container Cases") -if (t.elements.at(i)->value >= START_TYPE_INGREDIENTS) { +if (t.elements.at(i).type->value >= START_TYPE_INGREDIENTS) { trace(9999, "type") << "checking size of type ingredient\n" << end(); - long long int size = size_of_type_ingredient(t.elements.at(i), type->right); + long long int size = size_of_type_ingredient(t.elements.at(i).type, type->right); if (!size) raise_error << "illegal type '" << debug_string(type) << "' seems to be missing a type ingredient or three\n" << end(); result += size; @@ -100,9 +100,9 @@ recipe main [ $mem: 7 :(before "End size_of(type) Exclusive Container Cases") -if (t.elements.at(i)->value >= START_TYPE_INGREDIENTS) { +if (t.elements.at(i).type->value >= START_TYPE_INGREDIENTS) { trace(9999, "type") << "checking size of type ingredient\n" << end(); - long long int size = size_of_type_ingredient(t.elements.at(i), type->right); + long long int size = size_of_type_ingredient(t.elements.at(i).type, type->right); if (!size) raise_error << "illegal type '" << debug_string(type) << "' seems to be missing a type ingredient or three\n" << end(); if (size > result) result = size; @@ -147,7 +147,7 @@ recipe main [ +mem: storing 16 in location 2 :(before "End GET field Cases") -const type_tree* type = get(Type, base_type).elements.at(i); +const type_tree* type = get(Type, base_type).elements.at(i).type; if (type->value >= START_TYPE_INGREDIENTS) { long long int size = size_of_type_ingredient(type, base.type->right); if (!size) @@ -267,7 +267,7 @@ recipe main [ +mem: storing 12 in location 1 :(before "End GET_ADDRESS field Cases") -const type_tree* type = get(Type, base_type).elements.at(i); +const type_tree* type = get(Type, base_type).elements.at(i).type; if (type->value >= START_TYPE_INGREDIENTS) { long long int size = size_of_type_ingredient(type, base.type->right); if (!size) diff --git a/077hash.cc b/077hash.cc index ea185cfa..f2cc403d 100644 --- a/077hash.cc +++ b/077hash.cc @@ -104,7 +104,7 @@ size_t hash_mu_container(size_t h, const reagent& r) { element.set_value(address+offset); h = hash(h, element); //? cerr << i << ": " << h << '\n'; - offset += size_of(info.elements.at(i)); + offset += size_of(info.elements.at(i).type); } return h; } -- cgit 1.4.1-2-gfad0