1211 - /same-as-ingredient property is now checked

This commit is contained in:
Kartik K. Agaram 2015-04-28 12:42:54 -07:00
parent 04e6183232
commit 87cc473c95
2 changed files with 58 additions and 0 deletions

View File

@ -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

View File

@ -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 "[]";