From 5138d7ef9c13a5793f4fb4c1f26363f6212f2eb0 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 16 Jul 2015 14:18:12 -0700 Subject: 1795 - still debugging screen-in-screen rendering I'm writing to location 'screen' somehow that's not the raw location. --- 036call_reply.cc | 1 + 050scenario.cc | 2 +- 071print.mu | 43 ++++++++++++++ 081run_interactive.cc | 70 ++++++++++++++++------- edit.mu | 152 +++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 244 insertions(+), 24 deletions(-) diff --git a/036call_reply.cc b/036call_reply.cc index 22eeea79..618ad651 100644 --- a/036call_reply.cc +++ b/036call_reply.cc @@ -51,6 +51,7 @@ case REPLY: { raise << current_recipe_name() << ": 'same-as-ingredient' result " << caller_instruction.products.at(i).value << " from call to " << callee << " must be location " << caller_instruction.ingredients.at(ingredient_index).value << '\n'; } } + // End Reply break; // continue to process rest of *caller* instruction } diff --git a/050scenario.cc b/050scenario.cc index 8f3ec77e..dc43abba 100644 --- a/050scenario.cc +++ b/050scenario.cc @@ -131,7 +131,7 @@ const scenario* Current_scenario = NULL; void run_mu_scenario(const scenario& s) { Current_scenario = &s; bool not_already_inside_test = !Trace_stream; -//? cerr << s.name << '\n'; //? 12 +//? cerr << s.name << '\n'; //? 13 if (not_already_inside_test) { Trace_file = s.name; Trace_stream = new trace_stream; diff --git a/071print.mu b/071print.mu index f0be8cfa..987a9537 100644 --- a/071print.mu +++ b/071print.mu @@ -69,6 +69,33 @@ recipe clear-screen [ reply x:address:screen/same-as-ingredient:0 ] +recipe fake-screen-is-clear? [ + local-scope + screen:address:screen <- next-ingredient +#? $print [screen: ], screen:address:screen, [ +#? ] #? 1 + reply-unless screen:address:screen, 1:literal/true + buf:address:array:screen-cell <- get screen:address:screen/deref, data:offset + i:number <- copy 0:literal + len:number <- length buf:address:array:screen-cell/deref +#? $print len:number, [ +#? ] #? 1 +#? $exit #? 1 + { + done?:boolean <- greater-or-equal i:number, len:number + break-if done?:boolean + curr:screen-cell <- index buf:address:array:screen-cell/deref, i:number + curr-contents:character <- get curr:screen-cell, contents:offset + i:number <- add i:number, 1:literal +#? $print [char: ], curr-contents:character, [ +#? ] #? 1 + loop-unless curr-contents:character + # not 0 + reply 0:literal/false + } + reply 1:literal/true +] + recipe print-character [ local-scope x:address:screen <- next-ingredient @@ -90,6 +117,8 @@ recipe print-character [ # if x exists # (handle special cases exactly like in the real screen) break-unless x:address:screen +#? $print [screen ], x:address:screen, [ +#? ] #? 1 row:address:number <- get-address x:address:screen/deref, cursor-row:offset column:address:number <- get-address x:address:screen/deref, cursor-column:offset width:number <- get x:address:screen/deref, num-columns:offset @@ -114,8 +143,20 @@ recipe print-character [ # save character in fake screen #? $print row:address:number/deref, [, ], column:address:number/deref, [ #? ] #? 1 +#? $print [0: ], x:address:screen, [ row ], row:address:number, [ ], row:address:number/deref, [ col ], column:address:number, [ ], column:address:number/deref, [ +#? ] #? 2 +#? { +#? foo:boolean <- greater-than row:address:number/deref, 1000 +#? #? break-unless foo:boolean +#? $print [0: ], x:address:screen, [ row ], row:address:number, [ ], row:address:number/deref, [ col ], column:address:number, [ ], column:address:number/deref, [ +#? ] #? 1 +#? } index:number <- multiply row:address:number/deref, width:number +#? $print [1: ], index:number, [ +#? ] #? 1 index:number <- add index:number, column:address:number/deref +#? $print [2: ], index:number, [ +#? ] #? 1 buf:address:array:screen-cell <- get x:address:screen/deref, data:offset # special-case: backspace { @@ -137,6 +178,8 @@ recipe print-character [ reply x:address:screen/same-as-ingredient:0 } #? $print [saving character ], c:character, [ to fake screen ], cursor:address/screen, [ +#? ] #? 1 +#? $print index:number, [ #? ] #? 1 cursor:address:screen-cell <- index-address buf:address:array:screen-cell/deref, index:number cursor-contents:address:character <- get-address cursor:address:screen-cell/deref, contents:offset diff --git a/081run_interactive.cc b/081run_interactive.cc index 1d317d4b..a4a36482 100644 --- a/081run_interactive.cc +++ b/081run_interactive.cc @@ -15,8 +15,10 @@ recipe main [ # result is null +mem: storing 0 in location 1 -//: run code in 'interactive mode', i.e. with warnings off, and recording -//: output in case we want to print it to screen +//: run code in 'interactive mode', i.e. with warnings off and return: +//: stringified output in case we want to print it to screen +//: any warnings encountered +//: simulated screen any prints went to :(before "End Primitive Recipe Declarations") RUN_INTERACTIVE, :(before "End Primitive Recipe Numbers") @@ -25,11 +27,12 @@ Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE; :(before "End Primitive Recipe Implementations") case RUN_INTERACTIVE: { assert(scalar(ingredients.at(0))); - products.resize(2); + products.resize(3); bool new_code_pushed_to_stack = run_interactive(ingredients.at(0).at(0)); if (!new_code_pushed_to_stack) { products.at(0).push_back(0); products.at(1).push_back(warnings_from_trace()); + products.at(2).push_back(0); clean_up_interactive(); break; // done with this instruction } @@ -40,8 +43,10 @@ case RUN_INTERACTIVE: { :(before "End Globals") bool Running_interactive = false; +long long int Old_screen = 0; // we can support one iteration of screen inside screen :(before "End Setup") Running_interactive = false; +Old_screen = 0; :(code) // reads a string, tries to call it as code (treating it as a test), saving // all warnings. @@ -49,6 +54,8 @@ Running_interactive = false; bool run_interactive(long long int address) { if (Recipe_ordinal.find("interactive") == Recipe_ordinal.end()) Recipe_ordinal["interactive"] = Next_recipe_ordinal++; + Old_screen = Memory[SCREEN]; + cerr << "save screen: " << Old_screen << '\n'; //? 1 // try to sandbox the run as best you can // todo: test this if (!Current_scenario) { @@ -57,6 +64,7 @@ bool run_interactive(long long int address) { Memory.erase(i); Name[Recipe_ordinal["interactive"]].clear(); } + Name[Recipe_ordinal["interactive"]]["screen"] = SCREEN; string command = trim(strip_comments(to_string(address))); if (command.empty()) return false; Recipe.erase(Recipe_ordinal["interactive"]); @@ -67,7 +75,10 @@ bool run_interactive(long long int address) { Trace_stream->collect_layer = "warn"; } // call run(string) but without the scheduling - load("recipe interactive [\n"+command+"\n]\n"); + load(string("recipe interactive [\n") + + "screen:address <- new-fake-screen 5, 5\n" + + command + "\n" + + "]\n"); transform_all(); if (trace_count("warn") > 0) return false; Running_interactive = true; @@ -75,21 +86,6 @@ bool run_interactive(long long int address) { return true; } -:(after "Starting Reply") -if (current_recipe_name() == "interactive") clean_up_interactive(); -:(after "Falling Through End Of Recipe") -if (current_recipe_name() == "interactive") clean_up_interactive(); -:(code) -void clean_up_interactive() { - Hide_warnings = false; - Running_interactive = false; - // hack: assume collect_layer isn't set anywhere else - if (Trace_stream->collect_layer == "warn") { - delete Trace_stream; - Trace_stream = NULL; - } -} - :(scenario "run_interactive_returns_stringified_result") recipe main [ # try to interactively add 2 and 2 @@ -157,17 +153,49 @@ void record_products(const instruction& instruction, const vector } :(before "Complete Call Fallthrough") if (current_instruction().operation == RUN_INTERACTIVE && !current_instruction().products.empty()) { - assert(SIZE(current_instruction().products) <= 2); + assert(SIZE(current_instruction().products) <= 3); // Send the results of the most recently executed instruction, regardless of // call depth, to be converted to string and potentially printed to string. vector result; result.push_back(new_string(Most_recent_results)); write_memory(current_instruction().products.at(0), result); - if (SIZE(current_instruction().products) == 2) { + if (SIZE(current_instruction().products) >= 2) { vector warnings; warnings.push_back(warnings_from_trace()); write_memory(current_instruction().products.at(1), warnings); } + if (SIZE(current_instruction().products) >= 3) { + vector screen; + cerr << "returning screen " << Memory[SCREEN] << '\n'; //? 1 + screen.push_back(Memory[SCREEN]); + write_memory(current_instruction().products.at(2), screen); + } +} + +//: clean up reply after we've popped it off the call-stack +//: however, we need what was on the stack to decide whether to clean up +:(after "Starting Reply") +bool must_clean_up_interactive = (current_recipe_name() == "interactive"); +cerr << "reply: " << Memory[SCREEN] << '\n'; +:(after "Falling Through End Of Recipe") +bool must_clean_up_interactive = (current_recipe_name() == "interactive"); +cerr << "pop: " << Memory[SCREEN] << '\n'; +:(before "End Reply") +if (must_clean_up_interactive) clean_up_interactive(); +:(before "Complete Call Fallthrough") +if (must_clean_up_interactive) clean_up_interactive(); +:(code) +void clean_up_interactive() { + Hide_warnings = false; + Running_interactive = false; + // hack: assume collect_layer isn't set anywhere else + if (Trace_stream->collect_layer == "warn") { + delete Trace_stream; + Trace_stream = NULL; + } + cerr << "restore screen: " << Old_screen << '\n'; //? 1 + Memory[SCREEN] = Old_screen; + Old_screen = 0; } :(code) diff --git a/edit.mu b/edit.mu index d9e5e882..0fe56345 100644 --- a/edit.mu +++ b/edit.mu @@ -302,6 +302,7 @@ recipe render [ ] # row:number, screen:address <- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number +# move cursor at start of next line # print a string 's' to 'editor' in 'color' starting at 'row' # leave cursor at start of next line recipe render-string [ @@ -370,6 +371,74 @@ recipe render-string [ reply row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0 ] +# row:number, screen:address <- render-screen screen:address, sandbox-screen:address:screen, left:number, right:number, row:number +# print the fake sandbox screen to 'screen' with appropriate delimiters +# leave cursor at start of next line +recipe render-screen [ + local-scope + screen:address <- next-ingredient + s:address:screen <- next-ingredient + left:number <- next-ingredient + right:number <- next-ingredient + row:number <- next-ingredient + row:number <- add row:number, 1:literal + reply-unless s:address:screen, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 +#? $start-tracing #? 1 + # print 'screen:' + column:number <- copy left:number + move-cursor screen:address, row:number, column:number + screen-height:number <- screen-height screen:address + header:address:array:character <- new [screen:] + row:number <- subtract row:number, 1:literal # compensate for render-string below + row:number <- render-string screen:address, header:address:array:character, left:number, right:number, 245:literal/grey, row:number + # start printing s + column:number <- copy left:number + move-cursor screen:address, row:number, column:number + s-width:number <- screen-width s:address:screen + s-height:number <- screen-height s:address:screen + buf:address:array:screen-cell <- get s:address:screen/deref, data:offset + stop-printing:number <- add s-width:number, 3:literal + max-column:number <- min stop-printing:number, right:number + i:number <- copy 0:literal + { + done?:boolean <- greater-or-equal i:number, s-height:number + break-if done?:boolean + done?:boolean <- greater-or-equal row:number, screen-height:number + break-if done?:boolean + column:number <- copy left:number + move-cursor screen:address, row:number, column:number + # initial leader for each row: two spaces and a '.' + print-character screen:address, 32:literal/space, 245:literal/grey + print-character screen:address, 32:literal/space, 245:literal/grey + print-character screen:address, 46:literal/full-stop, 245:literal/grey + column:number <- add left:number, 3:literal + { + # print row + row-done?:boolean <- greater-than column:number, max-column:number + break-if row-done?:boolean + curr:screen-cell <- index buf:address:array:screen-cell/deref, i:number + print-character screen:address, 32:literal/space + column:number <- add column:number, 1:literal + i:number <- add i:number, 1:literal + loop + } + # print final '.' + print-character screen:address, 46:literal/full-stop, 245:literal/grey + column:number <- add column:number, 1:literal + { + # clear rest of current line + line-done?:boolean <- greater-than column:number, right:number + break-if line-done?:boolean + print-character screen:address, 32:literal/space + column:number <- add column:number, 1:literal + loop + } + row:number <- add row:number, 1:literal + loop + } + reply row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 +] + recipe clear-line-delimited [ local-scope screen:address <- next-ingredient @@ -1061,7 +1130,11 @@ recipe render-sandbox-side [ row:number <- add row:number, 1:literal draw-horizontal screen:address, row:number, left:number, right:number, 9473:literal/horizontal-double sandbox:address:sandbox-data <- get env:address:programming-environment-data/deref, sandbox:offset + $print [ddd ], screen:address, [ +] row:number, screen:address <- render-sandboxes screen:address, sandbox:address:sandbox-data, left:number, right:number, row:number + $print [kkk ], screen:address, [ +] # clear next line, in case we just processed a backspace row:number <- add row:number, 1:literal move-cursor screen:address, row:number, left:number @@ -1086,6 +1159,7 @@ recipe render-sandboxes [ # render sandbox warnings or response, in that order sandbox-response:address:array:character <- get sandbox:address:sandbox-data/deref, response:offset sandbox-warnings:address:array:character <- get sandbox:address:sandbox-data/deref, warnings:offset + sandbox-screen:address:screen <- get sandbox:address:sandbox-data/deref, screen:offset { break-unless sandbox-warnings:address:array:character row:number, screen:address <- render-string screen:address, sandbox-warnings:address:array:character, left:number, right:number, 1:literal/red, row:number @@ -1094,11 +1168,31 @@ recipe render-sandboxes [ break-if sandbox-warnings:address:array:character row:number, screen:address <- render-string screen:address, sandbox-response:address:array:character, left:number, right:number, 245:literal/grey, row:number } + # render sandbox screen if necessary + { + empty-screen?:boolean <- fake-screen-is-clear? sandbox-screen:address:screen +#? $print empty-screen?:boolean, [ +#? ] #? 1 + break-if empty-screen?:boolean + $print [eee ], screen:address, [ +] + row:number, screen:address <- render-screen screen:address, sandbox-screen:address:screen, left:number, right:number, row:number + $print [fff ], screen:address, [ +] + } + $print [fffa ], screen:address, [ +] # draw solid line after sandbox draw-horizontal screen:address, row:number, left:number, right:number, 9473:literal/horizontal-double + $print [ggg ], screen:address, [ +] # draw next sandbox next-sandbox:address:sandbox-data <- get sandbox:address:sandbox-data/deref, next-sandbox:offset + $print [hhh ], screen:address, [ +] row:number, screen:address <- render-sandboxes screen:address, next-sandbox:address:sandbox-data, left:number, right:number, row:number + $print [jjj ], screen:address, [ +] reply row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 ] @@ -2510,6 +2604,7 @@ container sandbox-data [ data:address:array:character response:address:array:character warnings:address:array:character + screen:address:screen next-sandbox:address:sandbox-data ] @@ -2610,14 +2705,19 @@ recipe run-sandboxes [ init:address:address:duplex-list <- get-address current-sandbox:address:editor-data/deref, data:offset init:address:address:duplex-list/deref <- push-duplex 167:literal/§, 0:literal/tail } - # rerun other sandboxes + # run all sandboxes curr:address:sandbox-data <- get env:address:programming-environment-data/deref, sandbox:offset { break-unless curr:address:sandbox-data data:address:address:array:character <- get-address curr:address:sandbox-data/deref, data:offset response:address:address:array:character <- get-address curr:address:sandbox-data/deref, response:offset warnings:address:address:array:character <- get-address curr:address:sandbox-data/deref, warnings:offset - response:address:address:array:character/deref, warnings:address:address:array:character/deref <- run-interactive data:address:address:array:character/deref + fake-screen:address:address:screen <- get-address curr:address:sandbox-data/deref, screen:offset + $print [bbb +] + response:address:address:array:character/deref, warnings:address:address:array:character/deref, fake-screen:address:address:screen/deref <- run-interactive data:address:address:array:character/deref + $print [ccc +] #? $print warnings:address:address:array:character/deref, [ ], warnings:address:address:array:character/deref/deref, [ #? ] #? 1 curr:address:sandbox-data <- get curr:address:sandbox-data/deref, next-sandbox:offset @@ -2757,6 +2857,48 @@ scenario run-instruction-and-print-warnings-only-once [ ] ] +scenario run-instruction-can-print-and-render-screen [ +#? $close-trace # trace too long for github #? 1 + assume-screen 100:literal/width, 20:literal/height + # left editor is empty + 1:address:array:character <- new [] + # right editor contains an illegal instruction + 2:address:array:character <- new [print-integer screen:address, 4] + 3:address:programming-environment-data <- new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + # run the code in the editor + assume-console [ + press 65526 # F10 + ] + run [ + $print [aaa +] + event-loop screen:address, console:address, 3:address:programming-environment-data + $print [lll +] + ] + # check that it prints a little 5x5 toy screen + # hack: screen address is brittle + $print [mmm +] + screen-should-contain [ + . run (F10) . + . ┊ . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. + . ┊print-integer screen:address, 4 . + . ┊5557 . + . ┊screen: . + . ┊ .4 . . + . ┊ . . . + . ┊ . . . + . ┊ . . . + . ┊ . . . + . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. + . ┊ . + ] + $print [zzz +] +] + recipe editor-contents [ local-scope editor:address:editor-data <- next-ingredient @@ -2851,10 +2993,16 @@ recipe draw-horizontal [ { continue?:boolean <- lesser-or-equal x:number, right:number # right is inclusive, to match editor-data semantics break-unless continue?:boolean +#? $print [aaaa ], screen:address, [ +#? ] #? 1 print-character screen:address, style:character, color:number, bg-color:number +#? $print [bbbb ], screen:address, [ +#? ] #? 1 x:number <- add x:number, 1:literal loop } + $print [fffz ], screen:address, [ +] ] recipe draw-vertical [ -- cgit 1.4.1-2-gfad0