From 9e751bb8c0cdf771d34c839cb6591d892b8e62de Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 7 Mar 2017 01:41:48 -0800 Subject: 3761 --- html/057immutable.cc.html | 183 +++++++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 91 deletions(-) (limited to 'html/057immutable.cc.html') diff --git a/html/057immutable.cc.html b/html/057immutable.cc.html index 99147f16..ae7eee7b 100644 --- a/html/057immutable.cc.html +++ b/html/057immutable.cc.html @@ -15,17 +15,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color a { text-decoration: none; } a:hover { text-decoration: underline; } * { font-size: 12pt; font-size: 1em; } -.Constant { color: #00a0a0; } .Special { color: #c00000; } .muRecipe { color: #ff8700; } -.traceContains { color: #008000; } +.Conceal { color: #4e4e4e; } +.cSpecial { color: #008000; } +.muData { color: #ffff00; } .Comment { color: #9090ff; } .Delimiter { color: #800080; } .LineNr { color: #444444; } .Identifier { color: #c0a020; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } -.muData { color: #ffff00; } -.cSpecial { color: #008000; } +.Constant { color: #00a0a0; } +.traceContains { color: #008000; } --> @@ -409,48 +410,48 @@ if ('onhashchange' in window) { 347 trace(9991, "transform") << "--- check mutability of ingredients in recipe " << caller.name << end(); 348 if (!caller.has_header) return; // skip check for old-style recipes calling next-ingredient directly 349 for (int i = 0; i < SIZE(caller.ingredients); ++i) { -350 const reagent& current_ingredient = caller.ingredients.at(i); -351 if (is_present_in_products(caller, current_ingredient.name)) continue; // not expected to be immutable -352 // End Immutable Ingredients Special-cases -353 set<reagent> immutable_vars; -354 immutable_vars.insert(current_ingredient); -355 for (int i = 0; i < SIZE(caller.steps); ++i) { -356 const instruction& inst = caller.steps.at(i); -357 check_immutable_ingredient_in_instruction(inst, immutable_vars, current_ingredient.name, caller); -358 if (inst.operation == INDEX && SIZE(inst.ingredients) > 1 && inst.ingredients.at(1).name == current_ingredient.name) continue; -359 update_aliases(inst, immutable_vars); -360 } +350 ¦ const reagent& current_ingredient = caller.ingredients.at(i); +351 ¦ if (is_present_in_products(caller, current_ingredient.name)) continue; // not expected to be immutable +352 ¦ // End Immutable Ingredients Special-cases +353 ¦ set<reagent> immutable_vars; +354 ¦ immutable_vars.insert(current_ingredient); +355 ¦ for (int i = 0; i < SIZE(caller.steps); ++i) { +356 ¦ ¦ const instruction& inst = caller.steps.at(i); +357 ¦ ¦ check_immutable_ingredient_in_instruction(inst, immutable_vars, current_ingredient.name, caller); +358 ¦ ¦ if (inst.operation == INDEX && SIZE(inst.ingredients) > 1 && inst.ingredients.at(1).name == current_ingredient.name) continue; +359 ¦ ¦ update_aliases(inst, immutable_vars); +360 ¦ } 361 } 362 } 363 364 void update_aliases(const instruction& inst, set<reagent>& current_ingredient_and_aliases) { 365 set<int> current_ingredient_indices = ingredient_indices(inst, current_ingredient_and_aliases); 366 if (!contains_key(Recipe, inst.operation)) { -367 // primitive recipe -368 switch (inst.operation) { -369 case COPY: -370 for (set<int>::iterator p = current_ingredient_indices.begin(); p != current_ingredient_indices.end(); ++p) -371 current_ingredient_and_aliases.insert(inst.products.at(*p).name); -372 break; -373 case GET: -374 case INDEX: -375 case MAYBE_CONVERT: -376 // current_ingredient_indices can only have 0 or one value -377 if (!current_ingredient_indices.empty() && !inst.products.empty()) { -378 if (is_mu_address(inst.products.at(0)) || is_mu_container(inst.products.at(0)) || is_mu_exclusive_container(inst.products.at(0))) -379 current_ingredient_and_aliases.insert(inst.products.at(0)); -380 } -381 break; -382 default: break; -383 } +367 ¦ // primitive recipe +368 ¦ switch (inst.operation) { +369 ¦ ¦ case COPY: +370 ¦ ¦ ¦ for (set<int>::iterator p = current_ingredient_indices.begin(); p != current_ingredient_indices.end(); ++p) +371 ¦ ¦ ¦ ¦ current_ingredient_and_aliases.insert(inst.products.at(*p).name); +372 ¦ ¦ ¦ break; +373 ¦ ¦ case GET: +374 ¦ ¦ case INDEX: +375 ¦ ¦ case MAYBE_CONVERT: +376 ¦ ¦ ¦ // current_ingredient_indices can only have 0 or one value +377 ¦ ¦ ¦ if (!current_ingredient_indices.empty() && !inst.products.empty()) { +378 ¦ ¦ ¦ ¦ if (is_mu_address(inst.products.at(0)) || is_mu_container(inst.products.at(0)) || is_mu_exclusive_container(inst.products.at(0))) +379 ¦ ¦ ¦ ¦ ¦ current_ingredient_and_aliases.insert(inst.products.at(0)); +380 ¦ ¦ ¦ } +381 ¦ ¦ ¦ break; +382 ¦ ¦ default: break; +383 ¦ } 384 } 385 else { -386 // defined recipe -387 set<int> contained_in_product_indices = scan_contained_in_product_indices(inst, current_ingredient_indices); -388 for (set<int>::iterator p = contained_in_product_indices.begin(); p != contained_in_product_indices.end(); ++p) { -389 if (*p < SIZE(inst.products)) -390 current_ingredient_and_aliases.insert(inst.products.at(*p)); -391 } +386 ¦ // defined recipe +387 ¦ set<int> contained_in_product_indices = scan_contained_in_product_indices(inst, current_ingredient_indices); +388 ¦ for (set<int>::iterator p = contained_in_product_indices.begin(); p != contained_in_product_indices.end(); ++p) { +389 ¦ ¦ if (*p < SIZE(inst.products)) +390 ¦ ¦ ¦ current_ingredient_and_aliases.insert(inst.products.at(*p)); +391 ¦ } 392 } 393 } 394 @@ -458,15 +459,15 @@ if ('onhashchange' in window) { 396 set<reagent> selected_ingredients; 397 const recipe& callee = get(Recipe, inst.operation); 398 for (set<int>::iterator p = ingredient_indices.begin(); p != ingredient_indices.end(); ++p) { -399 if (*p >= SIZE(callee.ingredients)) continue; // optional immutable ingredient -400 selected_ingredients.insert(callee.ingredients.at(*p)); +399 ¦ if (*p >= SIZE(callee.ingredients)) continue; // optional immutable ingredient +400 ¦ selected_ingredients.insert(callee.ingredients.at(*p)); 401 } 402 set<int> result; 403 for (int i = 0; i < SIZE(callee.products); ++i) { -404 const reagent& current_product = callee.products.at(i); -405 const string_tree* contained_in_name = property(current_product, "contained-in"); -406 if (contained_in_name && selected_ingredients.find(contained_in_name->value) != selected_ingredients.end()) -407 result.insert(i); +404 ¦ const reagent& current_product = callee.products.at(i); +405 ¦ const string_tree* contained_in_name = property(current_product, "contained-in"); +406 ¦ if (contained_in_name && selected_ingredients.find(contained_in_name->value) != selected_ingredients.end()) +407 ¦ ¦ result.insert(i); 408 } 409 return result; 410 } @@ -500,56 +501,56 @@ if ('onhashchange' in window) { 438 void check_immutable_ingredient_in_instruction(const instruction& inst, const set<reagent>& current_ingredient_and_aliases, const string& original_ingredient_name, const recipe& caller) { 439 // first check if the instruction is directly modifying something it shouldn't 440 for (int i = 0; i < SIZE(inst.products); ++i) { -441 if (has_property(inst.products.at(i), "lookup") -442 && current_ingredient_and_aliases.find(inst.products.at(i)) != current_ingredient_and_aliases.end()) { -443 string current_product_name = inst.products.at(i).name; -444 if (current_product_name == original_ingredient_name) -445 raise << maybe(caller.name) << "cannot modify '" << current_product_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -446 else -447 raise << maybe(caller.name) << "cannot modify '" << current_product_name << "' in instruction '" << inst.original_string << "' because that would modify " << original_ingredient_name << " which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -448 return; -449 } +441 ¦ if (has_property(inst.products.at(i), "lookup") +442 ¦ ¦ ¦ && current_ingredient_and_aliases.find(inst.products.at(i)) != current_ingredient_and_aliases.end()) { +443 ¦ ¦ string current_product_name = inst.products.at(i).name; +444 ¦ ¦ if (current_product_name == original_ingredient_name) +445 ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_product_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +446 ¦ ¦ else +447 ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_product_name << "' in instruction '" << inst.original_string << "' because that would modify " << original_ingredient_name << " which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +448 ¦ ¦ return; +449 ¦ } 450 } 451 // check if there's any indirect modification going on 452 set<int> current_ingredient_indices = ingredient_indices(inst, current_ingredient_and_aliases); 453 if (current_ingredient_indices.empty()) return; // ingredient not found in call 454 for (set<int>::iterator p = current_ingredient_indices.begin(); p != current_ingredient_indices.end(); ++p) { -455 const int current_ingredient_index = *p; -456 reagent current_ingredient = inst.ingredients.at(current_ingredient_index); -457 canonize_type(current_ingredient); -458 const string& current_ingredient_name = current_ingredient.name; -459 if (!contains_key(Recipe, inst.operation)) { -460 // primitive recipe -461 // we got here only because we got an instruction with an implicit product, and the instruction didn't explicitly spell it out -462 // put x, y:offset, z -463 // instead of -464 // x <- put x, y:offset, z -465 if (inst.operation == PUT || inst.operation == PUT_INDEX) { -466 if (current_ingredient_index == 0) { -467 if (current_ingredient_name == original_ingredient_name) -468 raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -469 else -470 raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because that would modify '" << original_ingredient_name << "' which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -471 } -472 } -473 } -474 else { -475 // defined recipe -476 if (is_modified_in_recipe(inst.operation, current_ingredient_index, caller)) { -477 if (current_ingredient_name == original_ingredient_name) -478 raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -479 else -480 raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because that would modify '" << original_ingredient_name << "' which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); -481 } -482 } +455 ¦ const int current_ingredient_index = *p; +456 ¦ reagent current_ingredient = inst.ingredients.at(current_ingredient_index); +457 ¦ canonize_type(current_ingredient); +458 ¦ const string& current_ingredient_name = current_ingredient.name; +459 ¦ if (!contains_key(Recipe, inst.operation)) { +460 ¦ ¦ // primitive recipe +461 ¦ ¦ // we got here only because we got an instruction with an implicit product, and the instruction didn't explicitly spell it out +462 ¦ ¦ // put x, y:offset, z +463 ¦ ¦ // instead of +464 ¦ ¦ // x <- put x, y:offset, z +465 ¦ ¦ if (inst.operation == PUT || inst.operation == PUT_INDEX) { +466 ¦ ¦ ¦ if (current_ingredient_index == 0) { +467 ¦ ¦ ¦ ¦ if (current_ingredient_name == original_ingredient_name) +468 ¦ ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +469 ¦ ¦ ¦ ¦ else +470 ¦ ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because that would modify '" << original_ingredient_name << "' which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +471 ¦ ¦ ¦ } +472 ¦ ¦ } +473 ¦ } +474 ¦ else { +475 ¦ ¦ // defined recipe +476 ¦ ¦ if (is_modified_in_recipe(inst.operation, current_ingredient_index, caller)) { +477 ¦ ¦ ¦ if (current_ingredient_name == original_ingredient_name) +478 ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because it's an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +479 ¦ ¦ ¦ else +480 ¦ ¦ ¦ ¦ raise << maybe(caller.name) << "cannot modify '" << current_ingredient_name << "' in instruction '" << inst.original_string << "' because that would modify '" << original_ingredient_name << "' which is an ingredient of recipe " << caller.name << " but not also a product\n" << end(); +481 ¦ ¦ } +482 ¦ } 483 } 484 } 485 486 bool is_modified_in_recipe(const recipe_ordinal r, const int ingredient_index, const recipe& caller) { 487 const recipe& callee = get(Recipe, r); 488 if (!callee.has_header) { -489 raise << maybe(caller.name) << "can't check mutability of ingredients in recipe " << callee.name << " because it uses 'next-ingredient' directly, rather than a recipe header.\n" << end(); -490 return true; +489 ¦ raise << maybe(caller.name) << "can't check mutability of ingredients in recipe " << callee.name << " because it uses 'next-ingredient' directly, rather than a recipe header.\n" << end(); +490 ¦ return true; 491 } 492 if (ingredient_index >= SIZE(callee.ingredients)) return false; // optional immutable ingredient 493 return is_present_in_products(callee, callee.ingredients.at(ingredient_index).name); @@ -557,8 +558,8 @@ if ('onhashchange' in window) { 495 496 bool is_present_in_products(const recipe& callee, const string& ingredient_name) { 497 for (int i = 0; i < SIZE(callee.products); ++i) { -498 if (callee.products.at(i).name == ingredient_name) -499 return true; +498 ¦ if (callee.products.at(i).name == ingredient_name) +499 ¦ ¦ return true; 500 } 501 return false; 502 } @@ -566,9 +567,9 @@ if ('onhashchange' in window) { 504 set<int> ingredient_indices(const instruction& inst, const set<reagent>& ingredient_names) { 505 set<int> result; 506 for (int i = 0; i < SIZE(inst.ingredients); ++i) { -507 if (is_literal(inst.ingredients.at(i))) continue; -508 if (ingredient_names.find(inst.ingredients.at(i)) != ingredient_names.end()) -509 result.insert(i); +507 ¦ if (is_literal(inst.ingredients.at(i))) continue; +508 ¦ if (ingredient_names.find(inst.ingredients.at(i)) != ingredient_names.end()) +509 ¦ ¦ result.insert(i); 510 } 511 return result; 512 } @@ -617,9 +618,9 @@ if ('onhashchange' in window) { 555 if (has_property(current_ingredient, "contained-in")) { 556 const string_tree* tmp = property(current_ingredient, "contained-in"); 557 if (!tmp->atom -558 || (!is_present_in_ingredients(caller, tmp->value) -559 && !is_present_in_products(caller, tmp->value))) { -560 raise << maybe(caller.name) << "/contained-in can only point to another ingredient or product, but got '" << to_string(property(current_ingredient, "contained-in")) << "'\n" << end(); +558 ¦ ¦ || (!is_present_in_ingredients(caller, tmp->value) +559 ¦ ¦ ¦ ¦ && !is_present_in_products(caller, tmp->value))) { +560 ¦ raise << maybe(caller.name) << "/contained-in can only point to another ingredient or product, but got '" << to_string(property(current_ingredient, "contained-in")) << "'\n" << end(); 561 } 562 continue; 563 } -- cgit 1.4.1-2-gfad0