2022 - run sandboxes in separate routines
This commit is contained in:
parent
221caac615
commit
5db2faebe2
|
@ -27,7 +27,7 @@ vector<recipe_ordinal> load(istream& in) {
|
|||
// Command Handlers
|
||||
if (command == "recipe") {
|
||||
string recipe_name = next_word(in);
|
||||
//? cerr << "recipe: " << recipe_name << '\n'; //? 1
|
||||
//? cerr << "recipe: " << recipe_name << '\n'; //? 2
|
||||
if (recipe_name.empty())
|
||||
raise << "empty recipe name\n" << end();
|
||||
if (Recipe_ordinal.find(recipe_name) == Recipe_ordinal.end()) {
|
||||
|
@ -39,7 +39,7 @@ vector<recipe_ordinal> load(istream& in) {
|
|||
}
|
||||
// todo: save user-defined recipes to mu's memory
|
||||
Recipe[Recipe_ordinal[recipe_name]] = slurp_recipe(in);
|
||||
//? cerr << Recipe_ordinal[recipe_name] << ": " << recipe_name << '\n'; //? 1
|
||||
//? cerr << Recipe_ordinal[recipe_name] << ": " << recipe_name << '\n'; //? 2
|
||||
Recipe[Recipe_ordinal[recipe_name]].name = recipe_name;
|
||||
// track added recipes because we may need to undo them in tests; see below
|
||||
recently_added_recipes.push_back(Recipe_ordinal[recipe_name]);
|
||||
|
@ -234,7 +234,8 @@ vector<recipe_ordinal> recently_added_recipes;
|
|||
:(before "End Setup")
|
||||
for (long long int i = 0; i < SIZE(recently_added_recipes); ++i) {
|
||||
//? cout << "AAA clearing " << Recipe[recently_added_recipes.at(i)].name << '\n'; //? 2
|
||||
Recipe_ordinal.erase(Recipe[recently_added_recipes.at(i)].name);
|
||||
if (recently_added_recipes.at(i) >= Reserved_for_tests) // don't renumber existing recipes, like 'interactive'
|
||||
Recipe_ordinal.erase(Recipe[recently_added_recipes.at(i)].name);
|
||||
Recipe.erase(recently_added_recipes.at(i));
|
||||
}
|
||||
// Clear Other State For recently_added_recipes
|
||||
|
|
|
@ -130,6 +130,18 @@ START_RUNNING,
|
|||
Recipe_ordinal["start-running"] = START_RUNNING;
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case START_RUNNING: {
|
||||
if (ingredients.empty()) {
|
||||
raise << "'start-running' requires at least one ingredient: the recipe to start running\n" << end();
|
||||
break;
|
||||
}
|
||||
if (!scalar(ingredients.at(0))) {
|
||||
raise << "first ingredient of 'start-running' should be a recipe, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
|
||||
break;
|
||||
}
|
||||
if (!ingredients.at(0).at(0)) {
|
||||
raise << "'start-running' received non-existent recipe: '" << current_instruction().to_string() << "'\n" << end();
|
||||
break;
|
||||
}
|
||||
routine* new_routine = new routine(ingredients.at(0).at(0));
|
||||
new_routine->parent_index = Current_routine_index;
|
||||
// populate ingredients
|
||||
|
|
|
@ -42,7 +42,7 @@ case RUN_INTERACTIVE: {
|
|||
products.at(1).push_back(trace_contents("warn"));
|
||||
products.at(2).push_back(0);
|
||||
products.at(3).push_back(trace_contents("app"));
|
||||
clean_up_interactive();
|
||||
cleanup_run_interactive();
|
||||
break; // done with this instruction
|
||||
}
|
||||
else {
|
||||
|
@ -59,8 +59,7 @@ Track_most_recent_products = false;
|
|||
// all warnings.
|
||||
// returns true if successfully called (no errors found during load and transform)
|
||||
bool run_interactive(long long int address) {
|
||||
if (Recipe_ordinal.find("interactive") == Recipe_ordinal.end())
|
||||
Recipe_ordinal["interactive"] = Next_recipe_ordinal++;
|
||||
assert(Recipe_ordinal.find("interactive") != Recipe_ordinal.end() && Recipe_ordinal["interactive"] != 0);
|
||||
// try to sandbox the run as best you can
|
||||
// todo: test this
|
||||
if (!Current_scenario) {
|
||||
|
@ -71,6 +70,7 @@ bool run_interactive(long long int address) {
|
|||
if (command.empty()) return false;
|
||||
Recipe.erase(Recipe_ordinal["interactive"]);
|
||||
Name[Recipe_ordinal["interactive"]].clear();
|
||||
// stuff to undo later, in cleanup_run_interactive()
|
||||
Hide_warnings = true;
|
||||
if (!Trace_stream) {
|
||||
Trace_file = ""; // if there wasn't already a stream we don't want to save it
|
||||
|
@ -81,17 +81,99 @@ bool run_interactive(long long int address) {
|
|||
// call run(string) but without the scheduling
|
||||
load(string("recipe interactive [\n") +
|
||||
"local-scope\n" +
|
||||
"screen:address <- new-fake-screen 30, 5\n" +
|
||||
"screen:address <- next-ingredient\n" +
|
||||
"$start-tracking-products\n" +
|
||||
command + "\n" +
|
||||
"$stop-tracking-products\n" +
|
||||
"reply screen\n" +
|
||||
"]\n");
|
||||
transform_all();
|
||||
if (trace_count("warn") > 0) return false;
|
||||
Track_most_recent_products = true;
|
||||
Current_routine->calls.push_front(call(Recipe_ordinal["interactive"]));
|
||||
// now call 'sandbox' which will run 'interactive' in a separate routine,
|
||||
// and wait for it
|
||||
Current_routine->calls.push_front(call(Recipe_ordinal["sandbox"]));
|
||||
return true;
|
||||
}
|
||||
|
||||
:(before "End Load Recipes")
|
||||
load(string(
|
||||
"recipe interactive [\n") + // just a dummy version to initialize the Recipe_ordinal and so on
|
||||
"]\n" +
|
||||
"recipe sandbox [\n" +
|
||||
"local-scope\n" +
|
||||
"screen:address/shared <- new-fake-screen 30, 5\n" +
|
||||
"r:number/routine_id <- start-running interactive:recipe, screen:address\n" +
|
||||
"wait-for-routine r\n" +
|
||||
"output:address:array:character <- $most-recent-products\n" +
|
||||
"warnings:address:array:character <- save-trace [warn]\n" +
|
||||
"stashes:address:array:character <- save-trace [app]\n" +
|
||||
"$cleanup-run-interactive\n" +
|
||||
"reply output, warnings, screen, stashes\n" +
|
||||
"]\n");
|
||||
transform_all();
|
||||
recently_added_recipes.clear();
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
_START_TRACKING_PRODUCTS,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
Recipe_ordinal["$start-tracking-products"] = _START_TRACKING_PRODUCTS;
|
||||
:(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")
|
||||
Recipe_ordinal["$stop-tracking-products"] = _STOP_TRACKING_PRODUCTS;
|
||||
:(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")
|
||||
Recipe_ordinal["$most-recent-products"] = _MOST_RECENT_PRODUCTS;
|
||||
:(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_TRACE,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
Recipe_ordinal["save-trace"] = SAVE_TRACE;
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case SAVE_TRACE: {
|
||||
products.resize(1);
|
||||
products.at(0).push_back(trace_contents(current_instruction().ingredients.at(0).name));
|
||||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
_CLEANUP_RUN_INTERACTIVE,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
Recipe_ordinal["$cleanup-run-interactive"] = _CLEANUP_RUN_INTERACTIVE;
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case _CLEANUP_RUN_INTERACTIVE: {
|
||||
cleanup_run_interactive();
|
||||
break;
|
||||
}
|
||||
|
||||
:(code)
|
||||
void cleanup_run_interactive() {
|
||||
Hide_warnings = false;
|
||||
if (Trace_stream->is_narrowly_collecting("warn")) { // hack
|
||||
delete Trace_stream;
|
||||
Trace_stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
:(scenario "run_interactive_returns_stringified_result")
|
||||
recipe main [
|
||||
# try to interactively add 2 and 2
|
||||
|
@ -166,36 +248,6 @@ void track_most_recent_products(const instruction& instruction, const vector<vec
|
|||
Most_recent_products = out.str();
|
||||
}
|
||||
|
||||
//: Recipe 'interactive' doesn't return what 'run-interactive seems to return.
|
||||
//: Massage results from former to latter.
|
||||
|
||||
:(after "Starting Reply")
|
||||
if (Current_routine->calls.front().running_recipe == Recipe_ordinal["interactive"]) {
|
||||
products.resize(4);
|
||||
products.at(0).push_back(new_mu_string(Most_recent_products));
|
||||
products.at(1).push_back(trace_contents("warn"));
|
||||
assert(SIZE(ingredients) == 1);
|
||||
assert(scalar(ingredients.at(0)));
|
||||
products.at(2).push_back(ingredients.at(0).at(0)); // screen
|
||||
products.at(3).push_back(trace_contents("app"));
|
||||
--Callstack_depth;
|
||||
Current_routine->calls.pop_front();
|
||||
assert(!Current_routine->calls.empty());
|
||||
clean_up_interactive();
|
||||
break;
|
||||
}
|
||||
|
||||
//: clean up reply after we've popped it off the call-stack
|
||||
:(code)
|
||||
void clean_up_interactive() {
|
||||
Hide_warnings = false;
|
||||
Track_most_recent_products = false;
|
||||
if (Trace_stream->is_narrowly_collecting("warn")) { // hack
|
||||
delete Trace_stream;
|
||||
Trace_stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
:(code)
|
||||
string strip_comments(string in) {
|
||||
ostringstream result;
|
||||
|
|
Loading…
Reference in New Issue
Block a user