diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-03-20 21:12:51 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-03-20 21:16:12 -0700 |
commit | a3d9828c190c86d9984a8e788f16dc10dfb95afa (patch) | |
tree | 3632b7319a88da648a99d595b38078ffd8d529b4 | |
parent | ad68bbce689969c4b0483a148c2a5260e9256fa7 (diff) | |
download | mu-a3d9828c190c86d9984a8e788f16dc10dfb95afa.tar.gz |
961 - done converting names?
I'm making two changes to how I compute field offsets: a) I just replace offset names up front, before I even manage field names. I don't bother disallowing x:integer and x:offset in the same function. Let's see if that leads us astray. Certainly saves code. b) I don't bother canonizing the first arg of a get since we know it has to have a type that is some number of 'address' followed by a record. Just assume that we have the right number of 'deref's.
-rw-r--r-- | cpp/.traces/convert_names_transforms_record_elements | 31 | ||||
-rw-r--r-- | cpp/010vm | 5 | ||||
-rw-r--r-- | cpp/018record | 2 | ||||
-rw-r--r-- | cpp/020array | 1 | ||||
-rw-r--r-- | cpp/025name | 48 |
5 files changed, 85 insertions, 2 deletions
diff --git a/cpp/.traces/convert_names_transforms_record_elements b/cpp/.traces/convert_names_transforms_record_elements new file mode 100644 index 00000000..99c78e6a --- /dev/null +++ b/cpp/.traces/convert_names_transforms_record_elements @@ -0,0 +1,31 @@ +parse/0: instruction: 18 +parse/0: ingredient: {name: "0", value: 0, type: 4, properties: [0: point]} +parse/0: ingredient: {name: "y", value: 0, type: 0, properties: [y: offset]} +parse/0: product: {name: "a", value: 0, type: 1, properties: [a: integer]} +parse/0: instruction: 18 +parse/0: ingredient: {name: "0", value: 0, type: 4, properties: [0: point]} +parse/0: ingredient: {name: "x", value: 0, type: 0, properties: [x: offset]} +parse/0: product: {name: "b", value: 0, type: 1, properties: [b: integer]} +name/0: field y of type point is at offset 1 +name/0: assign a 1 +name/0: field x of type point is at offset 0 +name/0: assign b 2 +after-brace/0: recipe main +after-brace/0: get ... +after-brace/0: get ... +run/0: instruction main/0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is y +run/0: address to copy is 1 +run/0: its type is 1 +mem/0: location 1 is 0 +run/0: product 0 is 0 +mem/0: storing in location 1 +run/0: instruction main/1 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is x +run/0: address to copy is 0 +run/0: its type is 1 +mem/0: location 0 is 0 +run/0: product 0 is 0 +mem/0: storing in location 2 diff --git a/cpp/010vm b/cpp/010vm index 45b4c3e5..d37dd83a 100644 --- a/cpp/010vm +++ b/cpp/010vm @@ -82,10 +82,13 @@ void setup_types() { // Mu Types Initialization. int integer = Type_number["integer"] = Next_type_number++; Type[integer].size = 1; + Type[integer].name = "integer"; int address = Type_number["address"] = Next_type_number++; Type[address].size = 1; + Type[address].name = "address"; int boolean = Type_number["boolean"] = Next_type_number++; Type[boolean].size = 1; + Type[boolean].name = "boolean"; // End Mu Types Initialization. } :(before "End Setup") @@ -99,10 +102,12 @@ void setup_types() { // storing bank balance next to a person's name might require a record, and // high scores in a game might need an array of numbers. struct type_info { + string name; size_t size; bool is_record; bool is_array; vector<vector<type_number> > elements; // only if is_record + vector<string> element_names; // only if is_record vector<type_number> element; // only if is_array // End type_info Fields. type_info() :size(0), is_record(false), is_array(false) {} diff --git a/cpp/018record b/cpp/018record index 3a9b3c37..062f35cf 100644 --- a/cpp/018record +++ b/cpp/018record @@ -4,6 +4,7 @@ int point = Type_number["point"] = Next_type_number++; Type[point].size = 2; Type[point].is_record = true; +Type[point].name = "point"; vector<type_number> i; i.push_back(integer); Type[point].elements.push_back(i); @@ -77,6 +78,7 @@ recipe main [ int point_integer = Type_number["point-integer"] = Next_type_number++; Type[point_integer].size = 2; Type[point_integer].is_record = true; +Type[point_integer].name = "point-integer"; vector<type_number> p2; p2.push_back(point); Type[point_integer].elements.push_back(p2); diff --git a/cpp/020array b/cpp/020array index 709fd65a..457ed366 100644 --- a/cpp/020array +++ b/cpp/020array @@ -4,6 +4,7 @@ int integer_array = Type_number["integer-array"] = Next_type_number++; Type[integer_array].is_array = true; Type[integer_array].element.push_back(integer); +Type[integer_array].name = "integer-array"; //: Arrays can be copied around with a single instruction just like integers, //: no matter how large they are. diff --git a/cpp/025name b/cpp/025name index 606f4d2b..f226d8e6 100644 --- a/cpp/025name +++ b/cpp/025name @@ -28,7 +28,21 @@ void transform_names(const recipe_number r) { for (size_t i = 0; i < Recipe[r].steps.size(); ++i) { //? cout << "instruction " << i << '\n'; //? 2 instruction& inst = Recipe[r].steps[i]; - // map names to addresses + // 1: replace element names of records with offsets + if (inst.operation == Recipe_number["get"] + || inst.operation == Recipe_number["get-address"]) { + // at least 2 args, and second arg is offset + assert(inst.ingredients.size() >= 2); + assert(!inst.ingredients[1].types.empty()); + assert(inst.ingredients[1].types[0] == 0); + if (inst.ingredients[1].name.find_first_not_of("0123456789") == string::npos) continue; + // since first non-address in base type must be a record, we don't have to canonize + type_number record = skip_addresses(inst.ingredients[0].types); + inst.ingredients[1].value = find_element_name(record, inst.ingredients[1].name); + inst.ingredients[1].initialized = true; + trace("name") << "field " << inst.ingredients[1].name << " of type " << Type[record].name << " is at offset " << inst.ingredients[1].value; + } + // 2: map names to addresses for (size_t in = 0; in < inst.ingredients.size(); ++in) { //? cout << "ingredient " << inst.ingredients[in].name << '\n'; //? 1 if (inst.ingredients[in].name != "default_space" @@ -42,7 +56,7 @@ void transform_names(const recipe_number r) { inst.ingredients[in].initialized = true; } } - // replace names with addresses + // 3: replace names with addresses for (size_t out = 0; out < inst.products.size(); ++out) { //? cout << "product " << out << '/' << inst.products.size() << " " << inst.products[out].name << '\n'; //? 3 //? cout << inst.products[out].types[0] << '\n'; //? 1 @@ -62,6 +76,24 @@ void transform_names(const recipe_number r) { } } +type_number skip_addresses(const vector<type_number>& types) { + for (size_t i = 0; i < types.size(); ++i) { + if (types[i] != Type_number["address"]) return types[i]; + } + raise << "expected a record" << '\n' << die(); + return -1; +} + +int find_element_name(const type_number t, const string& name) { + const type_info& record = Type[t]; +//? cout << "looking for field " << name << " in type " << record.name << " with " << record.element_names.size() << " fields\n"; //? 1 + for (size_t i = 0; i < record.element_names.size(); ++i) { + if (record.element_names[i] == name) return i; + } + raise << "unknown element " << name << " in record " << t << '\n' << die(); + return -1; +} + :(scenario "convert_names_passes_dummy") # _ is just a dummy result that never gets consumed recipe main [ @@ -77,3 +109,15 @@ recipe main [ ] +name: assign x 1 -name: assign default_space 1 + +//: update our running example record for the next test +:(before "End Mu Types Initialization") +Type[point].element_names.push_back("x"); +Type[point].element_names.push_back("y"); +:(scenario "convert_names_transforms_record_elements") +recipe main [ + a:integer <- get 0:point, y:offset + b:integer <- get 0:point, x:offset +] ++name: field y of type point is at offset 1 ++name: field x of type point is at offset 0 |