2417 - support mutable ingredients in headers
If a name repeats between ingredients, we raise an error. If a name repeats across ingredients and products, every call should share the same name across the corresponding ingredients and products.
This commit is contained in:
parent
c4e7c10d15
commit
c1585c88fa
|
@ -67,7 +67,7 @@ case REPLY: {
|
|||
if (ingredient_index >= SIZE(caller_instruction.ingredients))
|
||||
raise_error << maybe(current_recipe_name()) << "'same-as-ingredient' metadata overflows ingredients in: " << caller_instruction.to_string() << '\n' << end();
|
||||
if (!is_dummy(caller_instruction.products.at(i)) && caller_instruction.products.at(i).value != caller_instruction.ingredients.at(ingredient_index).value)
|
||||
raise_error << maybe(current_recipe_name()) << "'same-as-ingredient' product from call to " << callee << " must be " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end();
|
||||
raise_error << maybe(current_recipe_name()) << "'" << caller_instruction.to_string() << "' should write to " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end();
|
||||
}
|
||||
}
|
||||
// End Reply
|
||||
|
@ -117,7 +117,7 @@ recipe test1 [
|
|||
10:number <- next-ingredient
|
||||
reply 10:number/same-as-ingredient:0
|
||||
]
|
||||
+error: main: 'same-as-ingredient' product from call to test1 must be 1:number rather than 2:number
|
||||
+error: main: '2:number <- test1 1:number' should write to 1:number rather than 2:number
|
||||
|
||||
:(scenario reply_same_as_ingredient_dummy)
|
||||
# % Hide_errors = true;
|
||||
|
|
|
@ -134,10 +134,10 @@ recipe add2 x:number, y:number -> z:number [
|
|||
+error: add2: replied with the wrong type at 'reply z'
|
||||
|
||||
:(after "Transform.push_back(check_types_by_name)")
|
||||
Transform.push_back(check_header_products); // idempotent
|
||||
Transform.push_back(check_reply_instructions_against_header); // idempotent
|
||||
|
||||
:(code)
|
||||
void check_header_products(const recipe_ordinal r) {
|
||||
void check_reply_instructions_against_header(const recipe_ordinal r) {
|
||||
const recipe& rr = get(Recipe, r);
|
||||
if (rr.products.empty()) return;
|
||||
trace(9991, "transform") << "--- checking reply instructions against header for " << rr.name << end();
|
||||
|
@ -154,6 +154,33 @@ void check_header_products(const recipe_ordinal r) {
|
|||
}
|
||||
}
|
||||
|
||||
:(scenario recipe_headers_check_for_duplicate_names)
|
||||
% Hide_errors = true;
|
||||
recipe add2 x:number, x:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply z
|
||||
]
|
||||
+error: add2: x can't repeat in the ingredients
|
||||
|
||||
:(before "End recipe Fields")
|
||||
map<string, int> ingredient_index;
|
||||
|
||||
:(after "Transform.push_back(insert_fragments)")
|
||||
Transform.push_back(check_and_update_header_reagents); // idempotent
|
||||
|
||||
:(code)
|
||||
void check_and_update_header_reagents(const recipe_ordinal r) {
|
||||
recipe& rr = get(Recipe, r);
|
||||
if (rr.products.empty()) return;
|
||||
trace(9991, "transform") << "--- checking reply instructions against header for " << rr.name << end();
|
||||
for (long long int i = 0; i < SIZE(rr.ingredients); ++i) {
|
||||
if (contains_key(rr.ingredient_index, rr.ingredients.at(i).name))
|
||||
raise_error << maybe(rr.name) << rr.ingredients.at(i).name << " can't repeat in the ingredients\n" << end();
|
||||
put(rr.ingredient_index, rr.ingredients.at(i).name, i);
|
||||
}
|
||||
}
|
||||
|
||||
//: Deduce types from the header if possible.
|
||||
|
||||
:(scenarios run)
|
||||
|
@ -169,7 +196,7 @@ recipe add2 x:number, y:number -> z:number [
|
|||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(before "Transform.push_back(check_header_products)")
|
||||
:(before "Transform.push_back(check_reply_instructions_against_header)")
|
||||
Transform.push_back(deduce_types_from_header); // idempotent
|
||||
|
||||
:(code)
|
||||
|
@ -236,18 +263,40 @@ recipe add2 x:number, y:number -> z:number [
|
|||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(after "Transform.push_back(insert_fragments)")
|
||||
Transform.push_back(fill_in_reply_ingredients);
|
||||
:(after "Transform.push_back(check_and_update_header_reagents)")
|
||||
Transform.push_back(fill_in_reply_ingredients); // idempotent
|
||||
|
||||
:(code)
|
||||
void fill_in_reply_ingredients(recipe_ordinal r) {
|
||||
if (!get(Recipe, r).has_header) return;
|
||||
trace(9991, "transform") << "--- fill in reply ingredients from header for recipe " << get(Recipe, r).name << end();
|
||||
for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
|
||||
instruction& inst = get(Recipe, r).steps.at(i);
|
||||
if (inst.name == "reply" && inst.ingredients.empty()) {
|
||||
for (long long int i = 0; i < SIZE(get(Recipe, r).products); ++i)
|
||||
inst.ingredients.push_back(get(Recipe, r).products.at(i));
|
||||
recipe& rr = get(Recipe, r);
|
||||
if (!rr.has_header) return;
|
||||
trace(9991, "transform") << "--- fill in reply ingredients from header for recipe " << rr.name << end();
|
||||
for (long long int i = 0; i < SIZE(rr.steps); ++i) {
|
||||
instruction& inst = rr.steps.at(i);
|
||||
if (inst.name == "reply" && inst.ingredients.empty())
|
||||
add_header_products(inst, rr);
|
||||
}
|
||||
// fall through reply
|
||||
if (rr.steps.at(SIZE(rr.steps)-1).name != "reply") {
|
||||
instruction inst;
|
||||
inst.name = "reply";
|
||||
add_header_products(inst, rr);
|
||||
rr.steps.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
void add_header_products(instruction& inst, const recipe& rr) {
|
||||
assert(inst.name == "reply");
|
||||
// collect any products with the same names as ingredients
|
||||
for (long long int i = 0; i < SIZE(rr.products); ++i) {
|
||||
// if the ingredient is missing, add it from the header
|
||||
if (SIZE(inst.ingredients) == i)
|
||||
inst.ingredients.push_back(rr.products.at(i));
|
||||
// if it's missing /same_as_ingredient, try to fill it in
|
||||
if (contains_key(rr.ingredient_index, rr.products.at(i).name) && !has_property(inst.ingredients.at(i), "same_as_ingredient")) {
|
||||
ostringstream same_as_ingredient;
|
||||
same_as_ingredient << get(rr.ingredient_index, rr.products.at(i).name);
|
||||
inst.ingredients.at(i).properties.push_back(pair<string, string_tree*>("same-as-ingredient", new string_tree(same_as_ingredient.str())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,25 +327,6 @@ recipe add2 x:number, y:number -> z:number [
|
|||
+transform: instruction: reply z:number
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(after "Transform.push_back(insert_fragments)")
|
||||
Transform.push_back(deduce_fallthrough_reply);
|
||||
|
||||
:(code)
|
||||
void deduce_fallthrough_reply(const recipe_ordinal r) {
|
||||
recipe& rr = get(Recipe, r);
|
||||
if (rr.products.empty()) return;
|
||||
if (rr.steps.empty()) return;
|
||||
if (rr.steps.at(SIZE(rr.steps)-1).name != "reply") {
|
||||
instruction inst;
|
||||
inst.operation = REPLY;
|
||||
inst.name = "reply";
|
||||
for (long long int i = 0; i < SIZE(rr.products); ++i) {
|
||||
inst.ingredients.push_back(rr.products.at(i));
|
||||
}
|
||||
rr.steps.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
:(scenario reply_on_fallthrough_already_exists)
|
||||
recipe main [
|
||||
1:number/raw <- add2 3, 5
|
||||
|
@ -310,3 +340,16 @@ recipe add2 x:number, y:number -> z:number [
|
|||
+transform: instruction: reply z
|
||||
-transform: instruction: reply z:number
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(scenario recipe_headers_perform_same_ingredient_check)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:number <- add2 1:number, 2:number
|
||||
]
|
||||
recipe add2 x:number, y:number -> x:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
]
|
||||
+error: main: '3:number <- add2 1:number, 2:number' should write to 1:number rather than 3:number
|
||||
|
|
|
@ -259,7 +259,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
]
|
||||
|
||||
# helper for tests
|
||||
recipe editor-render screen:address:screen, editor:address:editor-data [
|
||||
recipe editor-render screen:address:screen, editor:address:editor-data -> screen:address:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
left:number <- get *editor, left:offset
|
||||
|
|
|
@ -391,6 +391,7 @@ scenario run-updates-results [
|
|||
1:address:array:character <- new [
|
||||
recipe foo [
|
||||
z:number <- add 2, 2
|
||||
reply z
|
||||
]]
|
||||
# sandbox editor contains an instruction without storing outputs
|
||||
2:address:array:character <- new [foo]
|
||||
|
@ -405,9 +406,9 @@ z:number <- add 2, 2
|
|||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
.z:number <- add 2, 2 ┊ x.
|
||||
.] ┊foo .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
.reply z ┊foo .
|
||||
.] ┊4 .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. ┊ .
|
||||
]
|
||||
# make a change (incrementing one of the args to 'add'), then rerun
|
||||
|
@ -426,9 +427,9 @@ z:number <- add 2, 2
|
|||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
.z:number <- add 2, 3 ┊ x.
|
||||
.] ┊foo .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊5 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
.reply z ┊foo .
|
||||
.] ┊5 .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. ┊ .
|
||||
]
|
||||
]
|
||||
|
|
|
@ -6,7 +6,7 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
|
|||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
recipe foo [
|
||||
add 2, 2
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
|
@ -19,7 +19,7 @@ recipe foo [
|
|||
. run (F4) .
|
||||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. add 2, 2 ┊ x.
|
||||
. reply 4 ┊ x.
|
||||
.] ┊foo .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━.
|
||||
|
@ -37,7 +37,7 @@ recipe foo [
|
|||
. run (F4) .
|
||||
. ┊foo .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. add 2, 2 ┊ .
|
||||
. reply 4 ┊ .
|
||||
.] ┊ .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .
|
||||
. ┊ .
|
||||
|
@ -54,7 +54,7 @@ recipe foo [
|
|||
. run (F4) .
|
||||
. ┊0foo .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. add 2, 2 ┊ .
|
||||
. reply 4 ┊ .
|
||||
.] ┊ .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .
|
||||
. ┊ .
|
||||
|
|
|
@ -6,7 +6,7 @@ scenario sandbox-click-on-result-toggles-color-to-green [
|
|||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
recipe foo [
|
||||
add 2, 2
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
|
@ -19,7 +19,7 @@ recipe foo [
|
|||
. run (F4) .
|
||||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. add 2, 2 ┊ x.
|
||||
. reply 4 ┊ x.
|
||||
.] ┊foo .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━.
|
||||
|
@ -51,13 +51,13 @@ recipe foo [
|
|||
. run (F4) .
|
||||
.␣ ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. add 2, 2 ┊ x.
|
||||
. reply 4 ┊ x.
|
||||
.] ┊foo .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. ┊ .
|
||||
]
|
||||
# now change the second arg of the 'add'
|
||||
# now change the result
|
||||
# then rerun
|
||||
assume-console [
|
||||
left-click 3, 11 # cursor to end of line
|
||||
|
@ -75,7 +75,7 @@ recipe foo [
|
|||
. .
|
||||
. .
|
||||
. .
|
||||
. 5 .
|
||||
. 3 .
|
||||
. .
|
||||
. .
|
||||
]
|
||||
|
|
|
@ -80,7 +80,7 @@ scenario sandbox-shows-app-trace-and-result [
|
|||
1:address:array:character <- new [
|
||||
recipe foo [
|
||||
stash [abc]
|
||||
add 2, 2
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
|
@ -94,7 +94,7 @@ recipe foo [
|
|||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. stash [abc] ┊ x.
|
||||
. add 2, 2 ┊foo .
|
||||
. reply 4 ┊foo .
|
||||
.] ┊4 .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.
|
||||
. ┊ .
|
||||
|
@ -112,7 +112,7 @@ recipe foo [
|
|||
. ┊ .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.
|
||||
. stash [abc] ┊ x.
|
||||
. add 2, 2 ┊foo .
|
||||
. reply 4 ┊foo .
|
||||
.] ┊abc .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .
|
||||
. ┊━━━━━━━━━━━━━━━━━━━.
|
||||
|
|
Loading…
Reference in New Issue
Block a user