about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--cpp/.traces/reply_same_as_ingredient32
-rw-r--r--cpp/037call_reply.cc26
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 "[]";