diff options
-rw-r--r-- | cpp/.traces/reply_same_as_ingredient | 32 | ||||
-rw-r--r-- | cpp/037call_reply.cc | 26 |
2 files changed, 58 insertions, 0 deletions
diff --git a/cpp/.traces/reply_same_as_ingredient b/cpp/.traces/reply_same_as_ingredient new file mode 100644 index 00000000..65f90f7d --- /dev/null +++ b/cpp/.traces/reply_same_as_ingredient @@ -0,0 +1,32 @@ +parse/0: instruction: 37 +parse/0: ingredient: {name: "integer", value: 0, type: 0, properties: ["integer": "type"]} +parse/0: product: {name: "1", value: 0, type: 2-1, properties: ["1": "address":"integer"]} +parse/0: instruction: 1001 +parse/0: ingredient: {name: "1", value: 0, type: 2-1, properties: ["1": "address":"integer"]} +parse/0: product: {name: "2", value: 0, type: 2-1, properties: ["2": "address":"integer"]} +parse/0: instruction: 25 +parse/0: product: {name: "10", value: 0, type: 2-1, properties: ["10": "address":"integer"]} +parse/0: instruction: 28 +parse/0: ingredient: {name: "10", value: 0, type: 2-1, properties: ["10": "address":"integer", "same-as-ingredient": "0"]} +new/0: integer -> 1 +after-brace/0: recipe main +after-brace/0: new ... +after-brace/0: test1 ... +after-brace/0: recipe test1 +after-brace/0: next-ingredient ... +after-brace/0: reply ... +new/0: routine allocated memory from 1000 to 101000 +schedule/0: main +run/0: instruction main/0 +mem/0: new alloc: 1000 +mem/0: storing 1000 in location 1 +run/0: instruction main/1 +mem/0: location 1 is 1000 +run/0: instruction test1/0 +run/0: product 0 is 1000 +mem/0: storing 1000 in location 10 +run/0: instruction test1/1 +mem/0: location 10 is 1000 +run/0: result 0 is 1000 +warn/0: 'same-as-ingredient' result 2 must be location 1 +mem/0: storing 1000 in location 2 diff --git a/cpp/037call_reply.cc b/cpp/037call_reply.cc index 9e62c1da..a0dfa2ea 100644 --- a/cpp/037call_reply.cc +++ b/cpp/037call_reply.cc @@ -25,12 +25,22 @@ case REPLY: { for (size_t i = 0; i < current_instruction().ingredients.size(); ++i) { callee_results.push_back(read_memory(current_instruction().ingredients[i])); } + const instruction& reply_inst = current_instruction(); // save pointer into recipe before pop Current_routine->calls.pop(); assert(!Current_routine->calls.empty()); const instruction& caller_instruction = current_instruction(); assert(caller_instruction.products.size() <= callee_results.size()); for (size_t i = 0; i < caller_instruction.products.size(); ++i) { trace("run") << "result " << i << " is " << to_string(callee_results[i]); + // check that any reply ingredients with /same-as-ingredient connect up + // the corresponding ingredient and product in the caller. + if (has_property(reply_inst.ingredients[i], "same-as-ingredient")) { + vector<string> tmp = property(reply_inst.ingredients[i], "same-as-ingredient"); + assert(tmp.size() == 1); + int ingredient_index = to_int(tmp[0]); + if (caller_instruction.products[i].value != caller_instruction.ingredients[ingredient_index].value) + raise << "'same-as-ingredient' result " << caller_instruction.products[i].value << " must be location " << caller_instruction.ingredients[ingredient_index].value << '\n'; + } write_memory(caller_instruction.products[i], callee_results[i]); } break; // instruction loop will increment caller's step_index @@ -51,6 +61,22 @@ recipe f [ +mem: storing 2 in location 3 +mem: storing 35 in location 4 +//: In mu we'd like to assume that any instruction doesn't modify its +//: ingredients unless they're also products. The /same-as-ingredient inside +//: the recipe's 'reply' will help catch accidental misuse of such +//: 'ingredient-results' (sometimes called in-out parameters in other languages). +:(scenario reply_same_as_ingredient) +% Hide_warnings = true; +recipe main [ + 1:address:integer <- new integer:type + 2:address:integer <- test1 1:address:integer # call with different ingredient and product +] +recipe test1 [ + 10:address:integer <- next-ingredient + reply 10:address:integer/same-as-ingredient:0 +] ++warn: 'same-as-ingredient' result 2 must be location 1 + :(code) string to_string(const vector<int>& in) { if (in.empty()) return "[]"; |