diff options
-rw-r--r-- | 003trace.cc | 12 | ||||
-rw-r--r-- | 020run.cc | 2 | ||||
-rw-r--r-- | 029tools.cc | 23 | ||||
-rw-r--r-- | 031address.cc | 4 | ||||
-rw-r--r-- | 042name.cc | 2 | ||||
-rw-r--r-- | 081run_interactive.cc | 27 | ||||
-rwxr-xr-x | build_and_test_until | 4 | ||||
-rw-r--r-- | edit.mu | 153 |
8 files changed, 201 insertions, 26 deletions
diff --git a/003trace.cc b/003trace.cc index 3695703a..d2afb21c 100644 --- a/003trace.cc +++ b/003trace.cc @@ -103,7 +103,7 @@ struct trace_stream { string curr_layer; int curr_depth; string dump_layer; - string collect_layer; // if set, ignore all other layers + set<string> collect_layers; // if not empty, ignore all absent layers ofstream null_stream; // never opens a file, so writes silently fail trace_stream() :curr_stream(NULL), curr_depth(0) {} ~trace_stream() { if (curr_stream) delete curr_stream; } @@ -113,13 +113,21 @@ struct trace_stream { } ostream& stream(int depth, string layer) { - if (!collect_layer.empty() && layer != collect_layer) return null_stream; + if (!is_collecting(layer)) return null_stream; curr_stream = new ostringstream; curr_layer = layer; curr_depth = depth; return *curr_stream; } + bool is_collecting(const string& layer) { + return collect_layers.empty() || collect_layers.find(layer) != collect_layers.end(); + } + + bool is_narrowly_collecting(const string& layer) { + return collect_layers.find(layer) != collect_layers.end(); + } + // be sure to call this before messing with curr_stream or curr_layer void newline() { if (!curr_stream) return; diff --git a/020run.cc b/020run.cc index a4b75db6..72fc2b7c 100644 --- a/020run.cc +++ b/020run.cc @@ -133,7 +133,7 @@ if (!Run_tests) { setup(); //? Trace_file = "interactive"; //? 2 //? START_TRACING_UNTIL_END_OF_SCOPE; //? 2 -//? Trace_stream->collect_layer = "app"; //? 1 +//? Trace_stream->collect_layer.insert("app"); //? 1 transform_all(); recipe_ordinal r = Recipe_ordinal[string("main")]; if (r) run(r); diff --git a/029tools.cc b/029tools.cc index cd4123fa..587818ea 100644 --- a/029tools.cc +++ b/029tools.cc @@ -12,15 +12,22 @@ TRACE, Recipe_ordinal["trace"] = TRACE; :(before "End Primitive Recipe Implementations") case TRACE: { - if (SIZE(ingredients) != 2) { - raise << current_recipe_name() << ": 'trace' takes exactly two ingredients rather than '" << current_instruction().to_string() << "'\n" << end(); - break; + if (SIZE(ingredients) == 2) { + assert(is_literal(current_instruction().ingredients.at(0))); + string label = current_instruction().ingredients.at(0).name; + assert(is_literal(current_instruction().ingredients.at(1))); + string message = current_instruction().ingredients.at(1).name; + trace(1, label) << message << end(); + } + else if (SIZE(ingredients) == 1) { + assert(is_literal(current_instruction().ingredients.at(0))); + string message = current_instruction().ingredients.at(0).name; + cerr << "tracing " << message << '\n'; + trace(1, "app") << message << end(); + } + else { + raise << current_recipe_name() << ": 'trace' takes one or two ingredients rather than '" << current_instruction().to_string() << "'\n" << end(); } - assert(is_literal(current_instruction().ingredients.at(0))); - string label = current_instruction().ingredients.at(0).name; - assert(is_literal(current_instruction().ingredients.at(1))); - string message = current_instruction().ingredients.at(1).name; - trace(1, label) << message << end(); break; } diff --git a/031address.cc b/031address.cc index e79ff314..b7b395c6 100644 --- a/031address.cc +++ b/031address.cc @@ -25,7 +25,7 @@ recipe main [ :(before "long long int base = x.value" following "void write_memory(reagent x, vector<double> data)") x = canonize(x); if (x.value == 0) { - raise << "can't write to location 0\n" << end(); + raise << "can't write to location 0 in '" << current_instruction().to_string() << "'\n" << end(); return; } @@ -37,7 +37,7 @@ recipe main [ 1:address:number/lookup <- copy 34 ] -mem: storing 34 in location 0 -+warn: can't write to location 0 ++warn: can't write to location 0 in '1:address:number/lookup <- copy 34' :(code) reagent canonize(reagent x) { diff --git a/042name.cc b/042name.cc index 304d050d..45f5a3b2 100644 --- a/042name.cc +++ b/042name.cc @@ -148,7 +148,7 @@ recipe main [ x:number/raw <- copy 0 ] -name: assign x 1 -+warn: can't write to location 0 ++warn: can't write to location 0 in 'x:number/raw <- copy 0' :(scenarios transform) :(scenario transform_names_warns_when_mixing_names_and_numeric_locations) diff --git a/081run_interactive.cc b/081run_interactive.cc index e8032100..59c79432 100644 --- a/081run_interactive.cc +++ b/081run_interactive.cc @@ -19,6 +19,7 @@ recipe main [ //: stringified output in case we want to print it to screen //: any warnings encountered //: simulated screen any prints went to +//: any 'app' layer traces generated :(before "End Primitive Recipe Declarations") RUN_INTERACTIVE, :(before "End Primitive Recipe Numbers") @@ -26,7 +27,7 @@ Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE; //? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1 :(before "End Primitive Recipe Implementations") case RUN_INTERACTIVE: { - products.resize(3); + products.resize(4); if (SIZE(ingredients) != 1) { raise << current_recipe_name() << ": 'run-interactive' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end(); break; @@ -40,6 +41,7 @@ case RUN_INTERACTIVE: { products.at(0).push_back(0); 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(); break; // done with this instruction } @@ -81,7 +83,8 @@ bool run_interactive(long long int address) { if (!Trace_stream) { Trace_file = ""; // if there wasn't already a stream we don't want to save it Trace_stream = new trace_stream; - Trace_stream->collect_layer = "warn"; + Trace_stream->collect_layers.insert("warn"); + Trace_stream->collect_layers.insert("app"); } // call run(string) but without the scheduling // we won't create a local scope so that we can get to the new screen after @@ -164,7 +167,7 @@ void record_products(const instruction& instruction, const vector<vector<double> } :(before "Complete Call Fallthrough") if (current_instruction().operation == RUN_INTERACTIVE && !current_instruction().products.empty()) { - assert(SIZE(current_instruction().products) <= 3); + assert(SIZE(current_instruction().products) <= 4); // Send the results of the most recently executed instruction, regardless of // call depth, to be converted to string and potentially printed to string. vector<double> result; @@ -180,6 +183,12 @@ if (current_instruction().operation == RUN_INTERACTIVE && !current_instruction() screen.push_back(Memory[SCREEN]); write_memory(current_instruction().products.at(2), screen); } + if (SIZE(current_instruction().products) >= 4) { +//? cerr << "emitting trace\n"; //? 1 + vector<double> trace; + trace.push_back(trace_contents("app")); + write_memory(current_instruction().products.at(3), trace); + } } //: clean up reply after we've popped it off the call-stack @@ -197,8 +206,8 @@ void clean_up_interactive() { Trace_stream->newline(); // flush trace Hide_warnings = false; Running_interactive = false; - // hack: assume collect_layer isn't set anywhere else - if (Trace_stream->collect_layer == "warn") { + // hack: assume collect_layers isn't set anywhere else + if (Trace_stream->is_narrowly_collecting("warn")) { delete Trace_stream; Trace_stream = NULL; } @@ -250,7 +259,9 @@ bool is_mu_string(const reagent& x) { long long int trace_contents(const string& layer) { if (!Trace_stream) return 0; +//? cerr << "trace stream exists\n"; //? 1 if (trace_count(layer) <= 0) return 0; +//? cerr << layer << " has something\n"; //? 1 ostringstream out; for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { if (p->label != layer) continue; @@ -258,6 +269,7 @@ long long int trace_contents(const string& layer) { if (*--p->contents.end() != '\n') out << '\n'; } assert(!out.str().empty()); +//? cerr << layer << ":\n" << out.str() << "\n--\n"; //? 1 return new_mu_string(out.str()); } @@ -281,7 +293,7 @@ case RELOAD: { if (!Trace_stream) { Trace_file = ""; // if there wasn't already a stream we don't want to save it Trace_stream = new trace_stream; - Trace_stream->collect_layer = "warn"; + Trace_stream->collect_layers.insert("warn"); } Hide_warnings = true; Disable_redefine_warnings = true; @@ -291,7 +303,8 @@ case RELOAD: { Disable_redefine_warnings = false; Hide_warnings = false; products.at(0).push_back(trace_contents("warn")); - if (Trace_stream->collect_layer == "warn") { + // hack: assume collect_layers isn't set anywhere else + if (Trace_stream->is_narrowly_collecting("warn")) { delete Trace_stream; Trace_stream = NULL; } diff --git a/build_and_test_until b/build_and_test_until index b83db304..20845064 100755 --- a/build_and_test_until +++ b/build_and_test_until @@ -9,5 +9,5 @@ make enumerate/enumerate ./tangle/tangle $(./enumerate/enumerate --until $* |grep -v '.mu$') |grep -v "^\s*//:" > mu.cc cat /dev/null $(./enumerate/enumerate --until $* |grep '.mu$') > core.mu make autogenerated_lists -make valgrind -#? make test #? 2 +make valgrind #? 1 +#? make test #? 3 diff --git a/edit.mu b/edit.mu index a19fd07d..82f81c5d 100644 --- a/edit.mu +++ b/edit.mu @@ -2673,10 +2673,12 @@ container sandbox-data [ data:address:array:character response:address:array:character warnings:address:array:character + trace:address:array:character expected-response:address:array:character # coordinates to track clicks starting-row-on-screen:number response-starting-row-on-screen:number + display-trace?:boolean screen:address:screen # prints in the sandbox go here next-sandbox:address:sandbox-data ] @@ -2812,9 +2814,9 @@ recipe run-sandboxes [ data <- get-address *curr, data:offset response:address:address:array:character <- get-address *curr, response:offset warnings:address:address:array:character <- get-address *curr, warnings:offset + trace:address:address:array:character <- get-address *curr, trace:offset fake-screen:address:address:screen <- get-address *curr, screen:offset - *response, *warnings, *fake-screen <- run-interactive *data -#? $print *warnings, [ ], **warnings, 10/newline + *response, *warnings, *fake-screen, *trace <- run-interactive *data curr <- get *curr, next-sandbox:offset loop } @@ -2901,6 +2903,7 @@ recipe render-sandboxes [ sandbox-response:address:array:character <- get *sandbox, response:offset sandbox-warnings:address:array:character <- get *sandbox, warnings:offset sandbox-screen:address <- get *sandbox, screen:offset + +render-sandbox-results { break-unless sandbox-warnings *response-starting-row <- copy 0 # no response @@ -3237,7 +3240,7 @@ recipe foo [ ] # click somewhere on the sandbox assume-console [ - left-click 4, 30 + left-click 3, 30 ] run [ event-loop screen:address, console:address, 3:address:programming-environment-data @@ -3623,6 +3626,150 @@ after +render-sandbox-response [ } ] +## click on the code typed into a sandbox to toggle its trace + +scenario sandbox-click-on-code-toggles-app-trace [ + $close-trace + assume-screen 40/width, 10/height + # basic recipe + 1:address:array:character <- new [ +recipe foo [ + trace [abc] +]] + # run it + 2:address:array:character <- new [foo] + assume-console [ + press 65532 # F4 + ] + 3:address:programming-environment-data <- new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + event-loop screen:address, console:address, 3:address:programming-environment-data + screen-should-contain [ + . run (F4) . + . ┊ . + .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━. + . trace [abc] ┊ x. + .] ┊foo . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━. + . ┊ . + ] + # click on the 'foo' line in the sandbox + assume-console [ + left-click 4, 21 + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + # trace now printed + screen-should-contain [ + . run (F4) . + . ┊ . + .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━. + . trace [abc] ┊ x. + .] ┊foo . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc . + . ┊━━━━━━━━━━━━━━━━━━━. + . ┊ . + ] + screen-should-contain-in-color 245/grey, [ + . . + . ┊ . + . ┊━━━━━━━━━━━━━━━━━━━. + . ┊ x. + . ┊ . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc . + . ┊━━━━━━━━━━━━━━━━━━━. + . ┊ . + ] + # click again on the same region + assume-console [ + left-click 4, 25 + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + # trace hidden again + screen-should-contain [ + . run (F4) . + . ┊ . + .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━. + . trace [abc] ┊ x. + .] ┊foo . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━. + . ┊ . + ] +] + +# clicks on sandbox code toggle its display-trace? flag +after +global-touch [ + # right side of screen? check if it's inside the code of any sandbox + { + sandbox-left-margin:number <- get *current-sandbox, left:offset + click-column:number <- get *t, column:offset + on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin + break-unless on-sandbox-side? + first-sandbox:address:sandbox-data <- get *env, sandbox:offset + break-unless first-sandbox + first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset + click-row:number <- get *t, row:offset + below-sandbox-editor?:boolean <- greater-or-equal click-row, first-sandbox-begins + break-unless below-sandbox-editor? + # identify the sandbox whose code is being clicked on + sandbox:address:sandbox-data <- find-click-in-sandbox-code env, click-row + break-unless sandbox + # toggle its display-trace? property + x:address:boolean <- get-address *sandbox, display-trace?:offset + *x <- not *x + screen <- render-sandbox-side screen, env, 1/clear + # no change in cursor + show-screen screen + loop +next-event:label + } +] + +recipe find-click-in-sandbox-code [ + local-scope + env:address:programming-environment-data <- next-ingredient + click-row:number <- next-ingredient + # assert click-row >= sandbox.starting-row-on-screen + sandbox:address:sandbox-data <- get *env, sandbox:offset + start:number <- get *sandbox, starting-row-on-screen:offset + clicked-on-sandboxes?:boolean <- greater-or-equal click-row, start + assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor] + # while click-row < sandbox.next-sandbox.starting-row-on-screen + { + next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset + break-unless next-sandbox + next-start:number <- get *next-sandbox, starting-row-on-screen:offset + found?:boolean <- lesser-than click-row, next-start + break-if found? + sandbox <- copy next-sandbox + loop + } + # return sandbox if click is in its code region + response-starting-row:number <- get *sandbox, response-starting-row-on-screen:offset + click-above-response?:boolean <- lesser-than click-row, response-starting-row + start:number <- get *sandbox, starting-row-on-screen:offset + click-below-menu?:boolean <- greater-than click-row, start + click-on-sandbox-code?:boolean <- and click-above-response?, click-below-menu? + { + break-if click-on-sandbox-code? + reply 0/no-click-in-sandbox-output + } + reply sandbox +] + +# when rendering a sandbox, dump its trace if display-trace? property is set +after +render-sandbox-results [ + { + display-trace?:boolean <- get *sandbox, display-trace?:offset + break-unless display-trace? + sandbox-trace:address:array:character <- get *sandbox, trace:offset + break-unless sandbox-trace # nothing to print; move on + row, screen <- render-string, screen, sandbox-trace, left, right, 245/grey, row + jump +render-sandbox-end:label + } +] + ## handling malformed programs scenario run-shows-warnings-in-get [ |