diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-08-02 15:26:58 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-08-02 16:18:16 -0700 |
commit | 7f402c85eb34a739055dc3e5bb4be337169ec68c (patch) | |
tree | cbb0365029213b87f8da70b00268bf8981b9a892 | |
parent | d082b17675f40037b0e6c26384d99362acd0749e (diff) | |
download | mu-7f402c85eb34a739055dc3e5bb4be337169ec68c.tar.gz |
1921 - show trace by clicking on code
Region to click on to edit is now reduced to just the menu bar for the sandbox (excluding the 'x' for deleting the sandbox). The symmetry there might be useful, but we'll see if the relative click area is in line with how commonly the actions are performed.
-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 [ |