From 317c0a34e82c9a64050f106761ee837310c3fd0c Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 20 Mar 2017 16:53:36 -0700 Subject: 3803 --- 026call.cc | 2 +- 072scheduler.cc | 2 +- 101run_sandboxed.cc | 1 - html/026call.cc.html | 2 +- html/072scheduler.cc.html | 2 +- html/101run_sandboxed.cc.html | 441 +++++++++++++++++++++--------------------- 6 files changed, 224 insertions(+), 226 deletions(-) diff --git a/026call.cc b/026call.cc index 113e71bb..7ad4dd33 100644 --- a/026call.cc +++ b/026call.cc @@ -155,7 +155,7 @@ const vector& routine::steps() const { return get(Recipe, calls.front().running_recipe).steps; } -:(before "Running One Instruction") +:(after "Running One Instruction") // when we reach the end of one call, we may reach the end of the one below // it, and the one below that, and so on while (current_step_index() >= SIZE(Current_routine->steps())) { diff --git a/072scheduler.cc b/072scheduler.cc index 68f2e463..ad79bace 100644 --- a/072scheduler.cc +++ b/072scheduler.cc @@ -22,7 +22,7 @@ int Scheduling_interval = 500; int instructions_run_this_scheduling_slice; :(before "End routine Constructor") instructions_run_this_scheduling_slice = 0; -:(before "Running One Instruction") +:(after "Running One Instruction") ++Current_routine->instructions_run_this_scheduling_slice; :(replace{} "bool should_continue_running(const routine* current_routine)") bool should_continue_running(const routine* current_routine) { diff --git a/101run_sandboxed.cc b/101run_sandboxed.cc index d47cdb86..b048b321 100644 --- a/101run_sandboxed.cc +++ b/101run_sandboxed.cc @@ -337,7 +337,6 @@ def main [ :(scenario "run_interactive_ignores_products_in_nested_functions") def main [ 1:text <- new [foo] - stash [aaa] 2:text <- run-sandboxed 1:text 10:@:char <- copy *2:text ] diff --git a/html/026call.cc.html b/html/026call.cc.html index bb0dcfcd..40a396b5 100644 --- a/html/026call.cc.html +++ b/html/026call.cc.html @@ -219,7 +219,7 @@ if ('onhashchange' in window) { 155 return get(Recipe, calls.front().running_recipe).steps; 156 } 157 -158 :(before "Running One Instruction") +158 :(after "Running One Instruction") 159 // when we reach the end of one call, we may reach the end of the one below 160 // it, and the one below that, and so on 161 while (current_step_index() >= SIZE(Current_routine->steps())) { diff --git a/html/072scheduler.cc.html b/html/072scheduler.cc.html index f63cfae0..bdb3cd76 100644 --- a/html/072scheduler.cc.html +++ b/html/072scheduler.cc.html @@ -87,7 +87,7 @@ if ('onhashchange' in window) { 22 int instructions_run_this_scheduling_slice; 23 :(before "End routine Constructor") 24 instructions_run_this_scheduling_slice = 0; - 25 :(before "Running One Instruction") + 25 :(after "Running One Instruction") 26 ++Current_routine->instructions_run_this_scheduling_slice; 27 :(replace{} "bool should_continue_running(const routine* current_routine)") 28 bool should_continue_running(const routine* current_routine) { diff --git a/html/101run_sandboxed.cc.html b/html/101run_sandboxed.cc.html index 0eaeea27..8c3b1f54 100644 --- a/html/101run_sandboxed.cc.html +++ b/html/101run_sandboxed.cc.html @@ -120,9 +120,9 @@ if ('onhashchange' in window) { 56 if (!new_code_pushed_to_stack) { 57 ¦ products.resize(5); 58 ¦ products.at(0).push_back(0); - 59 ¦ products.at(1).push_back(trace_error_contents()); + 59 ¦ products.at(1).push_back(trace_error_contents()); 60 ¦ products.at(2).push_back(0); - 61 ¦ products.at(3).push_back(trace_app_contents()); + 61 ¦ products.at(3).push_back(trace_app_contents()); 62 ¦ products.at(4).push_back(1); // completed 63 ¦ run_code_end(); 64 ¦ break; // done with this instruction @@ -161,7 +161,7 @@ if ('onhashchange' in window) { 97 ¦ for (int i = 1; i < Reserved_for_tests; ++i) 98 ¦ ¦ Memory.erase(i); 99 } -100 string command = trim(strip_comments(read_mu_text(address))); +100 string command = trim(strip_comments(read_mu_text(address))); 101 Name[get(Recipe_ordinal, "interactive")].clear(); 102 run_code_begin(/*should_stash_snapshots*/true); 103 if (command.empty()) return false; @@ -355,7 +355,7 @@ if ('onhashchange' in window) { 291 :(before "End Primitive Recipe Implementations") 292 case SAVE_ERRORS: { 293 products.resize(1); -294 products.at(0).push_back(trace_error_contents()); +294 products.at(0).push_back(trace_error_contents()); 295 break; 296 } 297 @@ -370,7 +370,7 @@ if ('onhashchange' in window) { 306 :(before "End Primitive Recipe Implementations") 307 case SAVE_APP_TRACE: { 308 products.resize(1); -309 products.at(0).push_back(trace_app_contents()); +309 products.at(0).push_back(trace_app_contents()); 310 break; 311 } 312 @@ -401,222 +401,221 @@ if ('onhashchange' in window) { 337 :(scenario "run_interactive_ignores_products_in_nested_functions") 338 def main [ 339 1:text <- new [foo] -340 stash [aaa] -341 2:text <- run-sandboxed 1:text -342 10:@:char <- copy *2:text -343 ] -344 def foo [ -345 20:num <- copy 1234 -346 { -347 ¦ break -348 ¦ reply 5678 -349 } -350 ] -351 # no product should have been tracked -352 +mem: storing 0 in location 10 -353 -354 :(scenario "run_interactive_returns_text") -355 def main [ -356 # try to interactively add 2 and 2 -357 1:text <- new [ -358 ¦ x:text <- new [a] -359 ¦ y:text <- new [b] -360 ¦ z:text <- append x:text, y:text -361 ] -362 2:text <- run-sandboxed 1:text -363 10:@:char <- copy *2:text -364 ] -365 # output contains "ab" -366 +mem: storing 97 in location 11 -367 +mem: storing 98 in location 12 -368 -369 :(scenario "run_interactive_returns_errors") -370 def main [ -371 # run a command that generates an error -372 1:text <- new [x:num <- copy 34 -373 get x:num, foo:offset] -374 2:text, 3:text <- run-sandboxed 1:text -375 10:@:char <- copy *3:text -376 ] -377 # error should be "unknown element foo in container number" -378 +mem: storing 117 in location 11 -379 +mem: storing 110 in location 12 -380 +mem: storing 107 in location 13 -381 +mem: storing 110 in location 14 -382 # ... -383 -384 :(scenario run_interactive_with_comment) -385 def main [ -386 # 2 instructions, with a comment after the first -387 1:&:@:num <- new [a:num <- copy 0 # abc -388 b:num <- copy 0 -389 ] -390 2:text, 3:text <- run-sandboxed 1:text -391 ] -392 # no errors -393 +mem: storing 0 in location 3 -394 -395 :(before "End Running One Instruction") -396 if (Track_most_recent_products && SIZE(Current_routine->calls) == Call_depth_to_track_most_recent_products_at) { -397 track_most_recent_products(current_instruction(), products); -398 } -399 :(code) -400 void track_most_recent_products(const instruction& instruction, const vector<vector<double> >& products) { -401 ostringstream out; -402 for (int i = 0; i < SIZE(products); ++i) { -403 ¦ // A sandbox can print a string result, but only if it is actually saved -404 ¦ // to a variable in the sandbox, because otherwise the results are -405 ¦ // reclaimed before the sandbox sees them. So you get these interactions -406 ¦ // in the sandbox: -407 ¦ // -408 ¦ // new [abc] -409 ¦ // => <address> -410 ¦ // -411 ¦ // x:text <- new [abc] -412 ¦ // => abc -413 ¦ if (i < SIZE(instruction.products)) { -414 ¦ ¦ if (is_mu_text(instruction.products.at(i))) { -415 ¦ ¦ ¦ if (!scalar(products.at(i))) continue; // error handled elsewhere -416 ¦ ¦ ¦ out << read_mu_text(products.at(i).at(0)) << '\n'; -417 ¦ ¦ ¦ continue; -418 ¦ ¦ } -419 ¦ } -420 ¦ for (int j = 0; j < SIZE(products.at(i)); ++j) -421 ¦ ¦ out << no_scientific(products.at(i).at(j)) << ' '; -422 ¦ out << '\n'; -423 } -424 Most_recent_products = out.str(); -425 } -426 -427 :(code) -428 string strip_comments(string in) { -429 ostringstream result; -430 for (int i = 0; i < SIZE(in); ++i) { -431 ¦ if (in.at(i) != '#') { -432 ¦ ¦ result << in.at(i); -433 ¦ } -434 ¦ else { -435 ¦ ¦ while (i+1 < SIZE(in) && in.at(i+1) != '\n') -436 ¦ ¦ ¦ ++i; -437 ¦ } -438 } -439 return result.str(); -440 } -441 -442 int stringified_value_of_location(int address) { -443 // convert to string -444 ostringstream out; -445 out << no_scientific(get_or_insert(Memory, address)); -446 return new_mu_text(out.str()); -447 } -448 -449 int trace_error_contents() { -450 if (!Trace_stream) return 0; -451 ostringstream out; -452 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -453 ¦ if (p->label != "error") continue; -454 ¦ out << p->contents; -455 ¦ if (*--p->contents.end() != '\n') out << '\n'; -456 } -457 string result = out.str(); -458 truncate(result); -459 if (result.empty()) return 0; -460 return new_mu_text(result); -461 } -462 -463 int trace_app_contents() { -464 if (!Trace_stream) return 0; -465 ostringstream out; -466 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -467 ¦ if (p->depth != App_depth) continue; -468 ¦ out << p->contents; -469 ¦ if (*--p->contents.end() != '\n') out << '\n'; -470 } -471 string result = out.str(); -472 if (result.empty()) return 0; -473 truncate(result); -474 return new_mu_text(result); -475 } -476 -477 void truncate(string& x) { -478 if (SIZE(x) > 1024) { -479 ¦ x.erase(1024); -480 ¦ *x.rbegin() = '\n'; -481 ¦ *++x.rbegin() = '.'; -482 ¦ *++++x.rbegin() = '.'; -483 } -484 } -485 -486 //: simpler version of run-sandboxed: doesn't do any running, just loads -487 //: recipes and reports errors. -488 -489 :(before "End Primitive Recipe Declarations") -490 RELOAD, -491 :(before "End Primitive Recipe Numbers") -492 put(Recipe_ordinal, "reload", RELOAD); -493 :(before "End Primitive Recipe Checks") -494 case RELOAD: { -495 if (SIZE(inst.ingredients) != 1) { -496 ¦ raise << maybe(get(Recipe, r).name) << "'reload' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); -497 ¦ break; -498 } -499 if (!is_mu_text(inst.ingredients.at(0))) { -500 ¦ raise << maybe(get(Recipe, r).name) << "first ingredient of 'reload' should be a string, but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); -501 ¦ break; -502 } -503 break; -504 } -505 :(before "End Primitive Recipe Implementations") -506 case RELOAD: { -507 restore_non_recipe_snapshots(); -508 string code = read_mu_text(ingredients.at(0).at(0)); -509 run_code_begin(/*should_stash_snapshots*/false); -510 routine* save_current_routine = Current_routine; -511 Current_routine = NULL; -512 Sandbox_mode = true; -513 vector<recipe_ordinal> recipes_reloaded = load(code); -514 transform_all(); -515 Trace_stream->newline(); // flush trace -516 Sandbox_mode = false; -517 Current_routine = save_current_routine; -518 products.resize(1); -519 products.at(0).push_back(trace_error_contents()); -520 run_code_end(); // wait until we're done with the trace contents -521 break; -522 } -523 -524 :(scenario reload_continues_past_error) -525 def main [ -526 local-scope -527 x:text <- new [recipe foo [ -528 get 1234:num, foo:offset -529 ]] -530 reload x -531 1:num/raw <- copy 34 -532 ] -533 +mem: storing 34 in location 1 -534 -535 :(scenario reload_can_repeatedly_load_container_definitions) -536 # define a container and try to create it (merge requires knowing container size) -537 def main [ -538 local-scope -539 x:text <- new [ -540 ¦ container foo [ -541 ¦ ¦ x:num -542 ¦ ¦ y:num -543 ¦ ] -544 ¦ recipe bar [ -545 ¦ ¦ local-scope -546 ¦ ¦ x:foo <- merge 34, 35 -547 ¦ ] -548 ] -549 # save warning addresses in locations of type 'number' to avoid spurious changes to them due to 'abandon' -550 1:num/raw <- reload x -551 2:num/raw <- reload x -552 ] -553 # no errors on either load -554 +mem: storing 0 in location 1 -555 +mem: storing 0 in location 2 +340 2:text <- run-sandboxed 1:text +341 10:@:char <- copy *2:text +342 ] +343 def foo [ +344 20:num <- copy 1234 +345 { +346 ¦ break +347 ¦ reply 5678 +348 } +349 ] +350 # no product should have been tracked +351 +mem: storing 0 in location 10 +352 +353 :(scenario "run_interactive_returns_text") +354 def main [ +355 # try to interactively add 2 and 2 +356 1:text <- new [ +357 ¦ x:text <- new [a] +358 ¦ y:text <- new [b] +359 ¦ z:text <- append x:text, y:text +360 ] +361 2:text <- run-sandboxed 1:text +362 10:@:char <- copy *2:text +363 ] +364 # output contains "ab" +365 +mem: storing 97 in location 11 +366 +mem: storing 98 in location 12 +367 +368 :(scenario "run_interactive_returns_errors") +369 def main [ +370 # run a command that generates an error +371 1:text <- new [x:num <- copy 34 +372 get x:num, foo:offset] +373 2:text, 3:text <- run-sandboxed 1:text +374 10:@:char <- copy *3:text +375 ] +376 # error should be "unknown element foo in container number" +377 +mem: storing 117 in location 11 +378 +mem: storing 110 in location 12 +379 +mem: storing 107 in location 13 +380 +mem: storing 110 in location 14 +381 # ... +382 +383 :(scenario run_interactive_with_comment) +384 def main [ +385 # 2 instructions, with a comment after the first +386 1:&:@:num <- new [a:num <- copy 0 # abc +387 b:num <- copy 0 +388 ] +389 2:text, 3:text <- run-sandboxed 1:text +390 ] +391 # no errors +392 +mem: storing 0 in location 3 +393 +394 :(before "End Running One Instruction") +395 if (Track_most_recent_products && SIZE(Current_routine->calls) == Call_depth_to_track_most_recent_products_at) { +396 track_most_recent_products(current_instruction(), products); +397 } +398 :(code) +399 void track_most_recent_products(const instruction& instruction, const vector<vector<double> >& products) { +400 ostringstream out; +401 for (int i = 0; i < SIZE(products); ++i) { +402 ¦ // A sandbox can print a string result, but only if it is actually saved +403 ¦ // to a variable in the sandbox, because otherwise the results are +404 ¦ // reclaimed before the sandbox sees them. So you get these interactions +405 ¦ // in the sandbox: +406 ¦ // +407 ¦ // new [abc] +408 ¦ // => <address> +409 ¦ // +410 ¦ // x:text <- new [abc] +411 ¦ // => abc +412 ¦ if (i < SIZE(instruction.products)) { +413 ¦ ¦ if (is_mu_text(instruction.products.at(i))) { +414 ¦ ¦ ¦ if (!scalar(products.at(i))) continue; // error handled elsewhere +415 ¦ ¦ ¦ out << read_mu_text(products.at(i).at(0)) << '\n'; +416 ¦ ¦ ¦ continue; +417 ¦ ¦ } +418 ¦ } +419 ¦ for (int j = 0; j < SIZE(products.at(i)); ++j) +420 ¦ ¦ out << no_scientific(products.at(i).at(j)) << ' '; +421 ¦ out << '\n'; +422 } +423 Most_recent_products = out.str(); +424 } +425 +426 :(code) +427 string strip_comments(string in) { +428 ostringstream result; +429 for (int i = 0; i < SIZE(in); ++i) { +430 ¦ if (in.at(i) != '#') { +431 ¦ ¦ result << in.at(i); +432 ¦ } +433 ¦ else { +434 ¦ ¦ while (i+1 < SIZE(in) && in.at(i+1) != '\n') +435 ¦ ¦ ¦ ++i; +436 ¦ } +437 } +438 return result.str(); +439 } +440 +441 int stringified_value_of_location(int address) { +442 // convert to string +443 ostringstream out; +444 out << no_scientific(get_or_insert(Memory, address)); +445 return new_mu_text(out.str()); +446 } +447 +448 int trace_error_contents() { +449 if (!Trace_stream) return 0; +450 ostringstream out; +451 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +452 ¦ if (p->label != "error") continue; +453 ¦ out << p->contents; +454 ¦ if (*--p->contents.end() != '\n') out << '\n'; +455 } +456 string result = out.str(); +457 truncate(result); +458 if (result.empty()) return 0; +459 return new_mu_text(result); +460 } +461 +462 int trace_app_contents() { +463 if (!Trace_stream) return 0; +464 ostringstream out; +465 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +466 ¦ if (p->depth != App_depth) continue; +467 ¦ out << p->contents; +468 ¦ if (*--p->contents.end() != '\n') out << '\n'; +469 } +470 string result = out.str(); +471 if (result.empty()) return 0; +472 truncate(result); +473 return new_mu_text(result); +474 } +475 +476 void truncate(string& x) { +477 if (SIZE(x) > 1024) { +478 ¦ x.erase(1024); +479 ¦ *x.rbegin() = '\n'; +480 ¦ *++x.rbegin() = '.'; +481 ¦ *++++x.rbegin() = '.'; +482 } +483 } +484 +485 //: simpler version of run-sandboxed: doesn't do any running, just loads +486 //: recipes and reports errors. +487 +488 :(before "End Primitive Recipe Declarations") +489 RELOAD, +490 :(before "End Primitive Recipe Numbers") +491 put(Recipe_ordinal, "reload", RELOAD); +492 :(before "End Primitive Recipe Checks") +493 case RELOAD: { +494 if (SIZE(inst.ingredients) != 1) { +495 ¦ raise << maybe(get(Recipe, r).name) << "'reload' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); +496 ¦ break; +497 } +498 if (!is_mu_text(inst.ingredients.at(0))) { +499 ¦ raise << maybe(get(Recipe, r).name) << "first ingredient of 'reload' should be a string, but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); +500 ¦ break; +501 } +502 break; +503 } +504 :(before "End Primitive Recipe Implementations") +505 case RELOAD: { +506 restore_non_recipe_snapshots(); +507 string code = read_mu_text(ingredients.at(0).at(0)); +508 run_code_begin(/*should_stash_snapshots*/false); +509 routine* save_current_routine = Current_routine; +510 Current_routine = NULL; +511 Sandbox_mode = true; +512 vector<recipe_ordinal> recipes_reloaded = load(code); +513 transform_all(); +514 Trace_stream->newline(); // flush trace +515 Sandbox_mode = false; +516 Current_routine = save_current_routine; +517 products.resize(1); +518 products.at(0).push_back(trace_error_contents()); +519 run_code_end(); // wait until we're done with the trace contents +520 break; +521 } +522 +523 :(scenario reload_continues_past_error) +524 def main [ +525 local-scope +526 x:text <- new [recipe foo [ +527 get 1234:num, foo:offset +528 ]] +529 reload x +530 1:num/raw <- copy 34 +531 ] +532 +mem: storing 34 in location 1 +533 +534 :(scenario reload_can_repeatedly_load_container_definitions) +535 # define a container and try to create it (merge requires knowing container size) +536 def main [ +537 local-scope +538 x:text <- new [ +539 ¦ container foo [ +540 ¦ ¦ x:num +541 ¦ ¦ y:num +542 ¦ ] +543 ¦ recipe bar [ +544 ¦ ¦ local-scope +545 ¦ ¦ x:foo <- merge 34, 35 +546 ¦ ] +547 ] +548 # save warning addresses in locations of type 'number' to avoid spurious changes to them due to 'abandon' +549 1:num/raw <- reload x +550 2:num/raw <- reload x +551 ] +552 # no errors on either load +553 +mem: storing 0 in location 1 +554 +mem: storing 0 in location 2 -- cgit 1.4.1-2-gfad0