about summary refs log tree commit diff stats
path: root/cpp/037call_reply.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-28 12:42:54 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-28 12:42:54 -0700
commit87cc473c955d726460ddb900ff0135c0a186ec1c (patch)
tree0545a004cbba33af41cceee48e9303d5247f09c8 /cpp/037call_reply.cc
parent04e61832321756646250a2c0d0d6ade9ee7e194f (diff)
downloadmu-87cc473c955d726460ddb900ff0135c0a186ec1c.tar.gz
1211 - /same-as-ingredient property is now checked
Diffstat (limited to 'cpp/037call_reply.cc')
-rw-r--r--cpp/037call_reply.cc26
1 files changed, 26 insertions, 0 deletions
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 "[]";