From 82ac0b7ecbc145ed8c8ecd8309166f654af1ee75 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 14 Apr 2015 19:06:57 -0700 Subject: 1063 - variable names for surrounding spaces now work This was a pain to debug. --- cpp/.traces/closure | 120 +++++++++++++++++ cpp/.traces/convert_names_warns | 1 + cpp/.traces/new | 2 + cpp/.traces/new_array | 2 + .../string-equal-common-lengths-but-distinct | 2 + cpp/.traces/string-equal-distinct-lengths | 2 + cpp/.traces/string-equal-identical | 2 + cpp/.traces/string-equal-reflexive | 2 + cpp/.traces/string-equal-with-empty | 2 + cpp/.traces/surrounding_space | 3 +- cpp/010vm | 4 +- cpp/013run | 1 + cpp/023call_reply | 1 + cpp/025name | 18 ++- cpp/026new | 1 + cpp/027space | 9 +- cpp/028space_surround | 20 ++- cpp/036closure_name | 142 +++++++++++++++++++++ cpp/090debug | 2 + mu.arc | 12 +- 20 files changed, 326 insertions(+), 22 deletions(-) create mode 100644 cpp/.traces/closure create mode 100644 cpp/036closure_name diff --git a/cpp/.traces/closure b/cpp/.traces/closure new file mode 100644 index 00000000..152df47e --- /dev/null +++ b/cpp/.traces/closure @@ -0,0 +1,120 @@ +parse/0: instruction: 30 +parse/0: ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]} +parse/0: ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]} +parse/0: product: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]} +parse/0: instruction: 1001 +parse/0: product: {name: "1", value: 0, type: 2-0, properties: ["1": "address":"space", "names": "init-counter"]} +parse/0: instruction: 1002 +parse/0: ingredient: {name: "1", value: 0, type: 2-0, properties: ["1": "address":"space", "names": "init-counter"]} +parse/0: product: {name: "2", value: 0, type: 1, properties: ["2": "integer", "raw": ]} +parse/0: instruction: 1002 +parse/0: ingredient: {name: "1", value: 0, type: 2-0, properties: ["1": "address":"space", "names": "init-counter"]} +parse/0: product: {name: "3", value: 0, type: 1, properties: ["3": "integer", "raw": ]} +parse/0: instruction: 30 +parse/0: ingredient: {name: "location", value: 0, type: 0, properties: ["location": "type"]} +parse/0: ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]} +parse/0: product: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]} +parse/0: product: {name: "x", value: 0, type: 1, properties: ["x": "integer"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "3", value: 0, type: 0, properties: ["3": "literal"]} +parse/0: product: {name: "y", value: 0, type: 1, properties: ["y": "integer"]} +parse/0: instruction: 23 +parse/0: ingredient: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]} +parse/0: instruction: 30 +parse/0: ingredient: {name: "space", value: 0, type: 0, properties: ["space": "literal"]} +parse/0: ingredient: {name: "30", value: 0, type: 0, properties: ["30": "literal"]} +parse/0: product: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]} +parse/0: instruction: 22 +parse/0: product: {name: "0", value: 0, type: 2-0, properties: ["0": "address":"space", "names": "init-counter"]} +parse/0: instruction: 2 +parse/0: ingredient: {name: "y", value: 0, type: 1, properties: ["y": "integer", "space": "1"]} +parse/0: ingredient: {name: "1", value: 0, type: 0, properties: ["1": "literal"]} +parse/0: product: {name: "y", value: 0, type: 1, properties: ["y": "integer", "space": "1"]} +parse/0: instruction: 1 +parse/0: ingredient: {name: "234", value: 0, type: 0, properties: ["234": "literal"]} +parse/0: product: {name: "y", value: 0, type: 1, properties: ["y": "integer"]} +parse/0: instruction: 23 +parse/0: ingredient: {name: "y", value: 0, type: 1, properties: ["y": "integer", "space": "1"]} +name/0: recipe increment-counter is surrounded by init-counter +new/0: location -> 1 +name/0: assign x 1 +name/0: assign y 2 +new/0: space -> 0 +name/0: assign y 1 +new/0: location -> 1 +after-brace/0: recipe init-counter +after-brace/0: new ... +after-brace/0: copy ... +after-brace/0: copy ... +after-brace/0: reply ... +after-brace/0: recipe increment-counter +after-brace/0: new ... +after-brace/0: next-ingredient ... +after-brace/0: add ... +after-brace/0: copy ... +after-brace/0: reply ... +after-brace/0: recipe main +after-brace/0: new ... +after-brace/0: init-counter ... +after-brace/0: increment-counter ... +after-brace/0: increment-counter ... +run/0: instruction main/0 +mem/0: new alloc: 1000 +mem/0: array size is 30 +run/0: instruction main/1 +run/0: instruction init-counter/0 +mem/0: new alloc: 1030 +mem/0: array size is 30 +run/0: instruction init-counter/1 +run/0: ingredient 0 is 23 +mem/0: storing 23 in location 1032 +run/0: instruction init-counter/2 +run/0: ingredient 0 is 3 +mem/0: storing 3 in location 1033 +run/0: instruction init-counter/3 +run/0: result 0 is 1030 +mem/0: storing 1030 in location 1002 +run/0: instruction main/2 +mem/0: location 1002 is 1030 +run/0: instruction increment-counter/0 +mem/0: new alloc: 1060 +mem/0: array size is 30 +run/0: instruction increment-counter/1 +run/0: product 0 is 1030 +mem/0: storing 1030 in location 1061 +run/0: instruction increment-counter/2 +run/0: ingredient 0 is y +mem/0: location 1033 is 3 +run/0: ingredient 1 is 1 +run/0: product 0 is 4 +mem/0: storing 4 in location 1033 +run/0: instruction increment-counter/3 +run/0: ingredient 0 is 234 +mem/0: storing 234 in location 1062 +run/0: instruction increment-counter/4 +mem/0: location 1033 is 4 +run/0: result 0 is 4 +mem/0: storing 4 in location 2 +run/0: instruction main/3 +mem/0: location 1002 is 1030 +run/0: instruction increment-counter/0 +mem/0: new alloc: 1090 +mem/0: array size is 30 +run/0: instruction increment-counter/1 +run/0: product 0 is 1030 +mem/0: storing 1030 in location 1091 +run/0: instruction increment-counter/2 +run/0: ingredient 0 is y +mem/0: location 1033 is 4 +run/0: ingredient 1 is 1 +run/0: product 0 is 5 +mem/0: storing 5 in location 1033 +run/0: instruction increment-counter/3 +run/0: ingredient 0 is 234 +mem/0: storing 234 in location 1092 +run/0: instruction increment-counter/4 +mem/0: location 1033 is 5 +run/0: result 0 is 5 +mem/0: storing 5 in location 3 diff --git a/cpp/.traces/convert_names_warns b/cpp/.traces/convert_names_warns index 837f83df..11614845 100644 --- a/cpp/.traces/convert_names_warns +++ b/cpp/.traces/convert_names_warns @@ -2,6 +2,7 @@ parse/0: instruction: 1 parse/0: ingredient: {name: "y", value: 0, type: 1, properties: ["y": "integer"]} parse/0: product: {name: "x", value: 0, type: 1, properties: ["x": "integer"]} warn/0: use before set: y in main +warn/0: name not found: y name/0: assign x 1 after-brace/0: recipe main after-brace/0: copy ... diff --git a/cpp/.traces/new b/cpp/.traces/new index e9be5862..4c3d8001 100644 --- a/cpp/.traces/new +++ b/cpp/.traces/new @@ -15,8 +15,10 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: equal ... run/0: instruction main/0 +mem/0: new alloc: 1000 mem/0: storing 1000 in location 1 run/0: instruction main/1 +mem/0: new alloc: 1001 mem/0: storing 1001 in location 2 run/0: instruction main/2 run/0: ingredient 0 is 1 diff --git a/cpp/.traces/new_array b/cpp/.traces/new_array index 8a44bcf8..d2e846bb 100644 --- a/cpp/.traces/new_array +++ b/cpp/.traces/new_array @@ -16,9 +16,11 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: subtract ... run/0: instruction main/0 +mem/0: new alloc: 1000 mem/0: storing 1000 in location 1 mem/0: array size is 5 run/0: instruction main/1 +mem/0: new alloc: 1005 mem/0: storing 1005 in location 2 run/0: instruction main/2 run/0: ingredient 0 is 2 diff --git a/cpp/.traces/string-equal-common-lengths-but-distinct b/cpp/.traces/string-equal-common-lengths-but-distinct index 58112874..e5e99282 100644 --- a/cpp/.traces/string-equal-common-lengths-but-distinct +++ b/cpp/.traces/string-equal-common-lengths-but-distinct @@ -23,6 +23,7 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: string-equal ... run/0: instruction test-string-equal-common-lengths-but-distinct/0 +mem/0: new alloc: 1000 mem/0: array size is 30 run/0: instruction test-string-equal-common-lengths-but-distinct/1 mem/0: storing 1030 in location 1002 @@ -32,6 +33,7 @@ run/0: instruction test-string-equal-common-lengths-but-distinct/3 mem/0: location 1002 is 1030 mem/0: location 1003 is 1034 run/0: instruction string-equal/0 +mem/0: new alloc: 1038 mem/0: array size is 30 run/0: instruction string-equal/1 run/0: product 0 is 1030 diff --git a/cpp/.traces/string-equal-distinct-lengths b/cpp/.traces/string-equal-distinct-lengths index 6008eaf4..4af8113c 100644 --- a/cpp/.traces/string-equal-distinct-lengths +++ b/cpp/.traces/string-equal-distinct-lengths @@ -23,6 +23,7 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: string-equal ... run/0: instruction test-string-equal-distinct-lengths/0 +mem/0: new alloc: 1000 mem/0: array size is 30 run/0: instruction test-string-equal-distinct-lengths/1 mem/0: storing 1030 in location 1002 @@ -32,6 +33,7 @@ run/0: instruction test-string-equal-distinct-lengths/3 mem/0: location 1002 is 1030 mem/0: location 1003 is 1034 run/0: instruction string-equal/0 +mem/0: new alloc: 1039 mem/0: array size is 30 run/0: instruction string-equal/1 run/0: product 0 is 1030 diff --git a/cpp/.traces/string-equal-identical b/cpp/.traces/string-equal-identical index ad2db713..7d25443e 100644 --- a/cpp/.traces/string-equal-identical +++ b/cpp/.traces/string-equal-identical @@ -23,6 +23,7 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: string-equal ... run/0: instruction test-string-equal-identical/0 +mem/0: new alloc: 1000 mem/0: array size is 30 run/0: instruction test-string-equal-identical/1 mem/0: storing 1030 in location 1002 @@ -32,6 +33,7 @@ run/0: instruction test-string-equal-identical/3 mem/0: location 1002 is 1030 mem/0: location 1003 is 1034 run/0: instruction string-equal/0 +mem/0: new alloc: 1038 mem/0: array size is 30 run/0: instruction string-equal/1 run/0: product 0 is 1030 diff --git a/cpp/.traces/string-equal-reflexive b/cpp/.traces/string-equal-reflexive index be1548bb..ab94aa39 100644 --- a/cpp/.traces/string-equal-reflexive +++ b/cpp/.traces/string-equal-reflexive @@ -17,6 +17,7 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: string-equal ... run/0: instruction test-string-equal-reflexive/0 +mem/0: new alloc: 1000 mem/0: array size is 30 run/0: instruction test-string-equal-reflexive/1 mem/0: storing 1030 in location 1002 @@ -24,6 +25,7 @@ run/0: instruction test-string-equal-reflexive/2 mem/0: location 1002 is 1030 mem/0: location 1002 is 1030 run/0: instruction string-equal/0 +mem/0: new alloc: 1034 mem/0: array size is 30 run/0: instruction string-equal/1 run/0: product 0 is 1030 diff --git a/cpp/.traces/string-equal-with-empty b/cpp/.traces/string-equal-with-empty index 13f64aac..22a9d4a9 100644 --- a/cpp/.traces/string-equal-with-empty +++ b/cpp/.traces/string-equal-with-empty @@ -23,6 +23,7 @@ after-brace/0: new ... after-brace/0: new ... after-brace/0: string-equal ... run/0: instruction test-string-equal-with-empty/0 +mem/0: new alloc: 1000 mem/0: array size is 30 run/0: instruction test-string-equal-with-empty/1 mem/0: storing 1030 in location 1002 @@ -32,6 +33,7 @@ run/0: instruction test-string-equal-with-empty/3 mem/0: location 1002 is 1030 mem/0: location 1003 is 1031 run/0: instruction string-equal/0 +mem/0: new alloc: 1036 mem/0: array size is 30 run/0: instruction string-equal/1 run/0: product 0 is 1030 diff --git a/cpp/.traces/surrounding_space b/cpp/.traces/surrounding_space index 0f1371d5..f4bc55fe 100644 --- a/cpp/.traces/surrounding_space +++ b/cpp/.traces/surrounding_space @@ -9,13 +9,14 @@ parse/0: ingredient: {name: "10", value: 0, type: 0, properties: ["10": "liter parse/0: product: {name: "default-space", value: 0, type: 2-0, properties: ["default-space": "address":"space"]} parse/0: instruction: 1 parse/0: ingredient: {name: "20", value: 0, type: 0, properties: ["20": "literal"]} -parse/0: product: {name: "0", value: 0, type: 2-0, properties: ["0": "address":"space"]} +parse/0: product: {name: "0", value: 0, type: 2-0, properties: ["0": "address":"space", "names": "dummy"]} parse/0: instruction: 1 parse/0: ingredient: {name: "32", value: 0, type: 0, properties: ["32": "literal"]} parse/0: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]} parse/0: instruction: 1 parse/0: ingredient: {name: "33", value: 0, type: 0, properties: ["33": "literal"]} parse/0: product: {name: "1", value: 0, type: 1, properties: ["1": "integer", "space": "1"]} +name/0: recipe main is surrounded by dummy after-brace/0: recipe main after-brace/0: copy ... after-brace/0: copy ... diff --git a/cpp/010vm b/cpp/010vm index 54fc8906..2c230c10 100644 --- a/cpp/010vm +++ b/cpp/010vm @@ -46,7 +46,7 @@ struct reagent { reagent(string s); reagent(); void set_value(int v) { value = v; initialized = true; } - string to_string(); + string to_string() const; }; :(before "struct reagent") @@ -192,7 +192,7 @@ Next_recipe_number = 1000; // consistent new numbers for each test // assigned to. properties.push_back(pair >("", vector())); } - string reagent::to_string() { + string reagent::to_string() const { ostringstream out; out << "{name: \"" << name << "\", value: " << value << ", type: "; for (size_t i = 0; i < types.size(); ++i) { diff --git a/cpp/013run b/cpp/013run index 1606a82d..91e242a7 100644 --- a/cpp/013run +++ b/cpp/013run @@ -44,6 +44,7 @@ void run(routine rr) { //? cout << "AAA " << Trace_stream << " ^" << Trace_stream->dump_layer << "$\n"; //? 1 trace("run") << "instruction " << recipe_name(rr) << '/' << pc; //? cout << "operation " << instructions[pc].operation << '\n'; //? 3 +//? if (!instructions[pc].products.empty()) trace("foo") << "AAA product 0 is " << instructions[pc].products[0].to_string(); //? 1 switch (instructions[pc].operation) { // Primitive Recipe Implementations case COPY: { diff --git a/cpp/023call_reply b/cpp/023call_reply index 476875ab..4c9fe34c 100644 --- a/cpp/023call_reply +++ b/cpp/023call_reply @@ -27,6 +27,7 @@ case REPLY: { callee_results.push_back(read_memory(instructions[pc].ingredients[i])); } rr.calls.pop(); + assert(!rr.calls.empty()); size_t& caller_pc = rr.calls.top().pc; instruction& caller_instruction = Recipe[rr.calls.top().running_recipe].steps[caller_pc]; assert(caller_instruction.products.size() <= callee_results.size()); diff --git a/cpp/025name b/cpp/025name index 81ab0cc9..45fdece2 100644 --- a/cpp/025name +++ b/cpp/025name @@ -40,6 +40,7 @@ void transform_names(const recipe_number r) { // Per-recipe Transforms // map names to addresses for (size_t in = 0; in < inst.ingredients.size(); ++in) { +//? cout << "ingredients\n"; //? 1 if (is_raw(inst.ingredients[in])) continue; //? cout << "ingredient " << inst.ingredients[in].name << '\n'; //? 1 if (inst.ingredients[in].name == "default-space") @@ -47,13 +48,15 @@ void transform_names(const recipe_number r) { if (inst.ingredients[in].types[0] // not a literal && !inst.ingredients[in].initialized && inst.ingredients[in].name.find_first_not_of("0123456789-.") != string::npos) { - if (names.find(inst.ingredients[in].name) == names.end()) { + if (!already_transformed(inst.ingredients[in], names)) { raise << "use before set: " << inst.ingredients[in].name << " in " << Recipe[r].name << '\n'; } - inst.ingredients[in].set_value(names[inst.ingredients[in].name]); + inst.ingredients[in].set_value(lookup_name(inst.ingredients[in], r)); +//? cout << "lookup ingredient " << Recipe[r].name << "/" << i << ": " << inst.ingredients[in].to_string() << '\n'; //? 1 } } for (size_t out = 0; out < inst.products.size(); ++out) { +//? cout << "products\n"; //? 1 if (is_raw(inst.products[out])) continue; //? cout << "product " << out << '/' << inst.products.size() << " " << inst.products[out].name << '\n'; //? 4 //? cout << inst.products[out].types[0] << '\n'; //? 1 @@ -67,12 +70,21 @@ void transform_names(const recipe_number r) { names[inst.products[out].name] = curr_idx; curr_idx += size_of(inst.products[out]); } - inst.products[out].set_value(names[inst.products[out].name]); + inst.products[out].set_value(lookup_name(inst.products[out], r)); +//? cout << "lookup product " << Recipe[r].name << "/" << i << ": " << inst.products[out].to_string() << '\n'; //? 1 } } } } +bool already_transformed(const reagent& r, const unordered_map& names) { + return names.find(r.name) != names.end(); +} + +size_t lookup_name(const reagent& r, const recipe_number default_recipe) { + return Name[default_recipe][r.name]; +} + type_number skip_addresses(const vector& types) { for (size_t i = 0; i < types.size(); ++i) { if (types[i] != Type_number["address"]) return types[i]; diff --git a/cpp/026new b/cpp/026new index 02196c49..e75d4148 100644 --- a/cpp/026new +++ b/cpp/026new @@ -45,6 +45,7 @@ Next_recipe_number++; :(before "End Primitive Recipe Implementations") case NEW: { vector result; + trace("mem") << "new alloc: " << Current_routine->alloc; result.push_back(Current_routine->alloc); write_memory(instructions[pc].products[0], result); vector types; diff --git a/cpp/027space b/cpp/027space index 2a845015..1bb91b8e 100644 --- a/cpp/027space +++ b/cpp/027space @@ -35,13 +35,15 @@ call(recipe_number r) :running_recipe(r), pc(0), next_ingredient_to_process(0), reagent r = absolutize(x); :(code) reagent absolutize(reagent x) { -//? cout << "absolutize " << x.to_string() << '\n'; //? 2 +//? if (Recipe_number.find("increment-counter") != Recipe_number.end()) //? 1 +//? cout << "AAA " << "increment-counter/2: " << Recipe[Recipe_number["increment-counter"]].steps[2].products[0].to_string() << '\n'; //? 1 +//? cout << "absolutize " << x.to_string() << '\n'; //? 3 //? cout << is_raw(x) << '\n'; //? 1 if (is_raw(x) || is_dummy(x)) return x; //? cout << "not raw: " << x.to_string() << '\n'; //? 1 assert(x.initialized); reagent r = x; - r.set_value(address(r.value, space(r))); + r.set_value(address(r.value, space_base(r))); //? cout << "after absolutize: " << r.value << '\n'; //? 1 r.properties.push_back(pair >("raw", vector())); assert(is_raw(r)); @@ -51,12 +53,13 @@ reagent absolutize(reagent x) { result.properties.push_back(pair >("raw", vector())); :(code) -int space(const reagent& x) { +int space_base(const reagent& x) { return Current_routine->calls.top().default_space; } int address(int offset, int base) { if (base == 0) return offset; // raw +//? cout << base << '\n'; //? 1 if (offset >= Memory[base]) { // todo: test raise << "location " << offset << " is out of bounds " << Memory[base] << '\n'; diff --git a/cpp/028space_surround b/cpp/028space_surround index dd4fb44f..76cd5807 100644 --- a/cpp/028space_surround +++ b/cpp/028space_surround @@ -10,7 +10,7 @@ recipe main [ 10:integer <- copy 5:literal # pretend array 20:integer <- copy 5:literal # pretend array default-space:address:space <- copy 10:literal - 0:address:space <- copy 20:literal + 0:address:space/names:dummy <- copy 20:literal # later layers will explain the /names: property 1:integer <- copy 32:literal 1:integer/space:1 <- copy 33:literal ] @@ -25,14 +25,20 @@ recipe main [ //: lifetime, surrounding allows managing shorter lifetimes inside a longer //: one. -:(replace{} "int space(const reagent& x)") -int space(const reagent& x) { - return space(x, space_index(x), Current_routine->calls.top().default_space); +:(replace{} "int space_base(const reagent& x)") +int space_base(const reagent& x) { + return space_base(x, space_index(x), Current_routine->calls.top().default_space); } -int space(const reagent& x, int space_index, int base) { - if (space_index == 0) return base; - return space(x, space_index-1, Memory[base+1]); +int space_base(const reagent& x, int space_index, int base) { +//? trace("foo") << "base of space " << space_index << '\n'; //? 1 + if (space_index == 0) { +//? trace("foo") << "base of space " << space_index << " is " << base << '\n'; //? 1 + return base; + } +//? trace("foo") << "base of space " << space_index << " is " << Memory[base+1] << '\n'; //? 1 + int result = space_base(x, space_index-1, Memory[base+1]); + return result; } int space_index(const reagent& x) { diff --git a/cpp/036closure_name b/cpp/036closure_name new file mode 100644 index 00000000..76a1bdd7 --- /dev/null +++ b/cpp/036closure_name @@ -0,0 +1,142 @@ +//: Writing to a literal (not computed) address of 0 in a recipe chains two +//: spaces together. When a variable has a property of /space:1, it looks up +//: the variable in the chained/surrounding space. /space:2 looks up the +//: surrounding space of the surrounding space, etc. +:(scenario "closure") +recipe main [ + default-space:address:space <- new location:type, 30:literal + 1:address:space/names:init-counter <- init-counter +#? $print [AAAAAAAAAAAAAAAA] +#? $print 1:address:space + 2:integer/raw <- increment-counter 1:address:space/names:init-counter + 3:integer/raw <- increment-counter 1:address:space/names:init-counter +] + +recipe init-counter [ + default-space:address:space <- new location:type, 30:literal + x:integer <- copy 23:literal + y:integer <- copy 3:literal # variable that will be incremented + reply default-space:address:space +] + +recipe increment-counter [ + default-space:address:space <- new space:literal, 30:literal + 0:address:space/names:init-counter <- next-ingredient # outer space must be created by 'init-counter' above + y:integer/space:1 <- add y:integer/space:1, 1:literal # increment + y:integer <- copy 234:literal # dummy + reply y:integer/space:1 +] + ++name: recipe increment-counter is surrounded by init-counter ++mem: storing 5 in location 3 + +//: To make this work, compute the recipe that provides names for the +//: surrounding space of each recipe. This must happen before transform_names. +:(before "End Globals") +unordered_map Surrounding_space; + +:(after "int main") + Transform.push_back(collect_surrounding_spaces); + +:(code) +void collect_surrounding_spaces(const recipe_number r) { + for (size_t i = 0; i < Recipe[r].steps.size(); ++i) { + const instruction& inst = Recipe[r].steps[i]; + if (inst.is_label) continue; + for (size_t j = 0; j < inst.products.size(); ++j) { + if (isa_literal(inst.products[j])) continue; + if (inst.products[j].name != "0") continue; + if (inst.products[j].types.size() != 2 + || inst.products[j].types[0] != Type_number["address"] + || inst.products[j].types[1] != Type_number["space"]) { + raise << "slot 0 should always have type address:space, but is " << inst.products[j].to_string() << '\n'; + continue; + } + vector s = property(inst.products[j], "names"); + if (s.empty()) + raise << "slot 0 requires a /names property in recipe " << Recipe[r].name << die(); + if (s.size() > 1) raise << "slot 0 should have a single value in /names, got " << inst.products[j].to_string() << '\n'; + string surrounding_recipe_name = s[0]; + if (Surrounding_space.find(r) != Surrounding_space.end() + && Surrounding_space[r] != Recipe_number[surrounding_recipe_name]) { + raise << "recipe " << Recipe[r].name << " can have only one 'surrounding' recipe but has " << Recipe[Surrounding_space[r]].name << " and " << surrounding_recipe_name << '\n'; + continue; + } + trace("name") << "recipe " << Recipe[r].name << " is surrounded by " << surrounding_recipe_name; + Surrounding_space[r] = Recipe_number[surrounding_recipe_name]; + } + } +} + +vector property(const reagent& r, const string& name) { + for (size_t p = 0; p != r.properties.size(); ++p) { + if (r.properties[p].first == name) + return r.properties[p].second; + } + return vector(); +} + +//: Once surrounding spaces are available, transform_names uses them to handle +//: /space properties. + +:(replace{} "size_t lookup_name(const reagent& r, const recipe_number default_recipe)") +size_t lookup_name(const reagent& x, const recipe_number default_recipe) { +//? cout << "AAA " << default_recipe << " " << Recipe[default_recipe].name << '\n'; //? 2 +//? cout << "AAA " << x.to_string() << '\n'; //? 1 + if (!has_property(x, "space")) { + if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << die(); + return Name[default_recipe][x.name]; + } + vector p = property(x, "space"); + if (p.size() != 1) raise << "/space property should have exactly one (non-negative integer) value\n"; + int n = to_int(p[0]); + assert(n >= 0); + recipe_number surrounding_recipe = lookup_surrounding_recipe(default_recipe, n); + set done; + vector path; + return lookup_name(x, surrounding_recipe, done, path); +} + +// If the recipe we need to lookup this name in doesn't have names done yet, +// recursively call transform_names on it. +size_t lookup_name(const reagent& x, const recipe_number r, set& done, vector& path) { + if (!Name[r].empty()) return Name[r][x.name]; + if (done.find(r) != done.end()) { + raise << "can't compute address of " << x.to_string() << " because "; + for (size_t i = 1; i < path.size(); ++i) { + raise << path[i-1] << " requires computing names of " << path[i] << '\n'; + } + raise << path[path.size()-1] << " requires computing names of " << r << "..ad infinitum\n" << die(); + return 0; + } + done.insert(r); + path.push_back(r); + transform_names(r); // Not passing 'done' through. Might this somehow cause an infinite loop? + assert(!Name[r].empty()); + return Name[r][x.name]; +} + +recipe_number lookup_surrounding_recipe(const recipe_number r, size_t n) { + if (n == 0) return r; + if (Surrounding_space.find(r) == Surrounding_space.end()) { + raise << "don't know surrounding recipe of " << Recipe[r].name << '\n'; + return 0; + } + assert(Surrounding_space[r]); + return lookup_surrounding_recipe(Surrounding_space[r], n-1); +} + +//: weaken use-before-set warnings just a tad +:(replace{} "bool already_transformed(const reagent& r, const unordered_map& names)") +bool already_transformed(const reagent& r, const unordered_map& names) { + if (has_property(r, "space")) { + vector p = property(r, "space"); + assert(p.size() == 1); + if (p[0] != "0") return true; + } + return names.find(r.name) != names.end(); +} + +:(before "End Includes") +#include +using std::set; diff --git a/cpp/090debug b/cpp/090debug index 08373a49..b6acae9d 100644 --- a/cpp/090debug +++ b/cpp/090debug @@ -7,11 +7,13 @@ assert(Next_recipe_number < _PRINT); :(before "End Primitive Recipe Implementations") case _PRINT: { if (isa_literal(instructions[pc].ingredients[0])) { + trace("run") << "$print: " << instructions[pc].ingredients[0].name; cout << instructions[pc].ingredients[0].name << '\n'; break; } vector result(read_memory(instructions[pc].ingredients[0])); for (size_t i = 0; i < result.size(); ++i) { + trace("run") << "$print: " << result[i]; cout << result[i] << " "; } cout << '\n'; diff --git a/mu.arc b/mu.arc index 283f056f..292126b3 100644 --- a/mu.arc +++ b/mu.arc @@ -1134,12 +1134,12 @@ (die "routine has no globals: @operand")) :else (iflet base rep.routine*!call-stack.0!default-space - (lookup-space (rem [caris _ 'space] operand) - base - space.operand) + (space-base (rem [caris _ 'space] operand) + base + space.operand) operand))) -(def lookup-space (operand base space) +(def space-base (operand base space) ;? (prn operand " " base) ;? 1 (if (is 0 space) ; base case @@ -1149,8 +1149,8 @@ (raw)) (die "no room for var @operand in routine of size @memory*.base")) ; recursive case - (lookup-space operand (memory* (+ base 1)) ; location 0 points to next space - (- space 1)))) + (space-base operand (memory* (+ base 1)) ; location 0 points to next space + (- space 1)))) (def space (operand) (or (alref metadata.operand 'space) -- cgit 1.4.1-2-gfad0