about summary refs log blame commit diff stats
path: root/090scenario_filesystem_test.mu
blob: b487bfe08bfbdcad76a9b035c6bc488d60c1ad3f (plain) (tree)
s="p">) return ""; :(scenario run_interactive_comments) recipe main [ 1:address:array:character <- new [# ab add 2, 2] 2:address:array:character <- run-interactive 1:address:array:character 3:array:character <- copy *2:address:array:character ] +mem: storing 52 in location 4 :(before "End Primitive Recipe Declarations") _START_TRACKING_PRODUCTS, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "$start-tracking-products", _START_TRACKING_PRODUCTS); :(before "End Primitive Recipe Checks") case _START_TRACKING_PRODUCTS: { break; } :(before "End Primitive Recipe Implementations") case _START_TRACKING_PRODUCTS: { Track_most_recent_products = true; break; } :(before "End Primitive Recipe Declarations") _STOP_TRACKING_PRODUCTS, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "$stop-tracking-products", _STOP_TRACKING_PRODUCTS); :(before "End Primitive Recipe Checks") case _STOP_TRACKING_PRODUCTS: { break; } :(before "End Primitive Recipe Implementations") case _STOP_TRACKING_PRODUCTS: { Track_most_recent_products = false; break; } :(before "End Primitive Recipe Declarations") _MOST_RECENT_PRODUCTS, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "$most-recent-products", _MOST_RECENT_PRODUCTS); :(before "End Primitive Recipe Checks") case _MOST_RECENT_PRODUCTS: { break; } :(before "End Primitive Recipe Implementations") case _MOST_RECENT_PRODUCTS: { products.resize(1); products.at(0).push_back(new_mu_string(Most_recent_products)); break; } :(before "End Primitive Recipe Declarations") SAVE_ERRORS_WARNINGS, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "save-errors-warnings", SAVE_ERRORS_WARNINGS); :(before "End Primitive Recipe Checks") case SAVE_ERRORS_WARNINGS: { break; } :(before "End Primitive Recipe Implementations") case SAVE_ERRORS_WARNINGS: { products.resize(1); products.at(0).push_back(trace_error_warning_contents()); break; } :(before "End Primitive Recipe Declarations") SAVE_APP_TRACE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "save-app-trace", SAVE_APP_TRACE); :(before "End Primitive Recipe Checks") case SAVE_APP_TRACE: { break; } :(before "End Primitive Recipe Implementations") case SAVE_APP_TRACE: { products.resize(1); products.at(0).push_back(trace_app_contents()); break; } :(before "End Primitive Recipe Declarations") _CLEANUP_RUN_INTERACTIVE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "$cleanup-run-interactive", _CLEANUP_RUN_INTERACTIVE); :(before "End Primitive Recipe Checks") case _CLEANUP_RUN_INTERACTIVE: { break; } :(before "End Primitive Recipe Implementations") case _CLEANUP_RUN_INTERACTIVE: { run_code_end(); break; } :(scenario "run_interactive_converts_result_to_text") recipe main [ # try to interactively add 2 and 2 1:address:array:character <- new [add 2, 2] 2:address:array:character <- run-interactive 1:address:array:character 10:array:character <- copy 2:address:array:character/lookup ] # first letter in the output should be '4' in unicode +mem: storing 52 in location 11 :(scenario "run_interactive_returns_text") recipe main [ # try to interactively add 2 and 2 1:address:array:character <- new [ x:address:array:character <- new [a] y:address:array:character <- new [b] z:address:array:character <- append x:address:array:character, y:address:array:character ] 2:address:array:character <- run-interactive 1:address:array:character 10:array:character <- copy 2:address:array:character/lookup ] # output contains "ab" +mem: storing 97 in location 11 +mem: storing 98 in location 12 :(scenario "run_interactive_returns_errors") recipe main [ # run a command that generates an error 1:address:array:character <- new [x:number <- copy 34 get x:number, foo:offset] 2:address:array:character, 3:address:array:character <- run-interactive 1:address:array:character 10:array:character <- copy 3:address:array:character/lookup ] # error should be "unknown element foo in container number" +mem: storing 117 in location 11 +mem: storing 110 in location 12 +mem: storing 107 in location 13 +mem: storing 110 in location 14 # ... :(scenario run_interactive_with_comment) recipe main [ # 2 instructions, with a comment after the first 1:address:array:number <- new [a:number <- copy 0 # abc b:number <- copy 0 ] 2:address:array:character, 3:address:array:character <- run-interactive 1:address:array:character ] # no errors +mem: storing 0 in location 3 :(code) void test_run_interactive_cleans_up_any_created_specializations() { // define a generic recipe assert(!contains_key(Recipe_ordinal, "foo")); load("recipe foo x:_elem -> n:number [\n" " reply 34\n" "]\n"); assert(SIZE(Recently_added_recipes) == 1); // foo assert(variant_count("foo") == 1); // run-interactive a call that specializes this recipe run("recipe main [\n" " 1:number/raw <- copy 0\n" " 2:address:array:character <- new [foo 1:number/raw]\n" " run-interactive 2:address:array:character\n" "]\n"); assert(SIZE(Recently_added_recipes) == 2); // foo, main // check that number of variants doesn't change CHECK_EQ(variant_count("foo"), 1); } long long int variant_count(string recipe_name) { if (!contains_key(Recipe_variants, recipe_name)) return 0; return non_ghost_size(get(Recipe_variants, recipe_name)); } :(before "End Globals") string Most_recent_products; :(before "End Setup") Most_recent_products = ""; :(before "End of Instruction") if (Track_most_recent_products) { track_most_recent_products(current_instruction(), products); } :(code) void track_most_recent_products(const instruction& instruction, const vector<vector<double> >& products) { ostringstream out; for (long long int i = 0; i < SIZE(products); ++i) { // string if (i < SIZE(instruction.products)) { if (is_mu_string(instruction.products.at(i))) { if (!scalar(products.at(i))) { tb_shutdown(); cerr << read_mu_string(trace_error_warning_contents()) << '\n'; cerr << SIZE(products.at(i)) << ": "; for (long long int j = 0; j < SIZE(products.at(i)); ++j) cerr << no_scientific(products.at(i).at(j)) << ' '; cerr << '\n'; } assert(scalar(products.at(i))); out << read_mu_string(products.at(i).at(0)) << '\n'; continue; } // End Record Product Special-cases } for (long long int j = 0; j < SIZE(products.at(i)); ++j) out << no_scientific(products.at(i).at(j)) << ' '; out << '\n'; } Most_recent_products = out.str(); } :(code) string strip_comments(string in) { ostringstream result; for (long long int i = 0; i < SIZE(in); ++i) { if (in.at(i) != '#') { result << in.at(i); } else { while (i+1 < SIZE(in) && in.at(i+1) != '\n') ++i; } } return result.str(); } long long int stringified_value_of_location(long long int address) { // convert to string ostringstream out; out << no_scientific(get_or_insert(Memory, address)); return new_mu_string(out.str()); } long long int trace_error_warning_contents() { if (!Trace_stream) return 0; ostringstream out; for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { if (p->depth > Warning_depth) continue; out << p->contents; if (*--p->contents.end() != '\n') out << '\n'; } string result = out.str(); if (result.empty()) return 0; truncate(result); return new_mu_string(result); } long long int trace_app_contents() { if (!Trace_stream) return 0; ostringstream out; for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { if (p->depth != App_depth) continue; out << p->contents; if (*--p->contents.end() != '\n') out << '\n'; } string result = out.str(); if (result.empty()) return 0; truncate(result); return new_mu_string(result); } void truncate(string& x) { if (SIZE(x) > 512) { x.erase(512); *x.rbegin() = '\n'; *++x.rbegin() = '.'; *++++x.rbegin() = '.'; } } //: simpler version of run-interactive: doesn't do any running, just loads //: recipes and reports errors+warnings. :(before "End Primitive Recipe Declarations") RELOAD, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "reload", RELOAD); :(before "End Primitive Recipe Checks") case RELOAD: { if (SIZE(inst.ingredients) != 1) { raise_error << maybe(get(Recipe, r).name) << "'reload' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_string(inst.ingredients.at(0))) { raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'reload' should be a string, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; } :(before "End Primitive Recipe Implementations") case RELOAD: { //? cerr << "== reload\n"; // clear any containers in advance for (long long int i = 0; i < SIZE(Recently_added_types); ++i) { Type_ordinal.erase(get(Type, Recently_added_types.at(i)).name); Type.erase(Recently_added_types.at(i)); } for (map<string, vector<recipe_ordinal> >::iterator p = Recipe_variants.begin(); p != Recipe_variants.end(); ++p) { //? cerr << p->first << ":\n"; vector<recipe_ordinal>& variants = p->second; for (long long int i = 0; i < SIZE(p->second); ++i) { if (variants.at(i) == -1) continue; if (find(Recently_added_shape_shifting_recipes.begin(), Recently_added_shape_shifting_recipes.end(), variants.at(i)) != Recently_added_shape_shifting_recipes.end()) { //? cerr << " " << variants.at(i) << ' ' << get(Recipe, variants.at(i)).name << '\n'; variants.at(i) = -1; // ghost } } } for (long long int i = 0; i < SIZE(Recently_added_shape_shifting_recipes); ++i) { Recipe_ordinal.erase(get(Recipe, Recently_added_shape_shifting_recipes.at(i)).name); Recipe.erase(Recently_added_shape_shifting_recipes.at(i)); } Recently_added_shape_shifting_recipes.clear(); string code = read_mu_string(ingredients.at(0).at(0)); run_code_begin(/*snapshot_recently_added_recipes*/false); routine* save_current_routine = Current_routine; Current_routine = NULL; vector<recipe_ordinal> recipes_reloaded = load(code); // clear a few things from previous runs // ad hoc list; we've probably missed a few for (long long int i = 0; i < SIZE(recipes_reloaded); ++i) Name.erase(recipes_reloaded.at(i)); transform_all(); Trace_stream->newline(); // flush trace Current_routine = save_current_routine; products.resize(1); products.at(0).push_back(trace_error_warning_contents()); run_code_end(); // wait until we're done with the trace contents //? cerr << "reload done\n"; break; } :(scenario reload_continues_past_error) recipe main [ local-scope x:address:array:character <- new [recipe foo [ get 1234:number, foo:offset ]] reload x 1:number/raw <- copy 34 ] +mem: storing 34 in location 1 :(code) void test_reload_cleans_up_any_created_specializations() { // define a generic recipe and a call to it assert(!contains_key(Recipe_ordinal, "foo")); assert(variant_count("foo") == 0); // a call that specializes this recipe run("recipe main [\n" " local-scope\n" " x:address:array:character <- new [recipe foo x:_elem -> n:number [\n" "local-scope\n" "load-ingredients\n" "reply 34\n" "]\n" "recipe main2 [\n" "local-scope\n" "load-ingredients\n" "x:number <- copy 34\n" "foo x:number\n" "]]\n" " reload x\n" "]\n"); // check that number of variants includes specialization assert(SIZE(Recently_added_recipes) == 4); // foo, main, main2, foo specialization CHECK_EQ(variant_count("foo"), 2); }