From 5db2faebe215e588172bcfe1810416f4c7b909b1 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 16 Aug 2015 19:13:45 -0700 Subject: 2022 - run sandboxes in separate routines --- 011load.cc | 7 +-- 038scheduler.cc | 12 +++++ 081run_interactive.cc | 124 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 104 insertions(+), 39 deletions(-) diff --git a/011load.cc b/011load.cc index 5f172aae..301dfdf2 100644 --- a/011load.cc +++ b/011load.cc @@ -27,7 +27,7 @@ vector 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 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 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 diff --git a/038scheduler.cc b/038scheduler.cc index d32fb76a..613491b5 100644 --- a/038scheduler.cc +++ b/038scheduler.cc @@ -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 diff --git a/081run_interactive.cc b/081run_interactive.cc index 80b6b8bc..b3746321 100644 --- a/081run_interactive.cc +++ b/081run_interactive.cc @@ -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 vectorcalls.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; -- cgit 1.4.1-2-gfad0