about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-16 14:18:12 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-16 14:18:12 -0700
commit5138d7ef9c13a5793f4fb4c1f26363f6212f2eb0 (patch)
tree320d7f153a533a1573c5336a43c4c1dac1273968
parent7cae95a9ba04f234628bfa77b628f471ec1d3213 (diff)
downloadmu-5138d7ef9c13a5793f4fb4c1f26363f6212f2eb0.tar.gz
1795 - still debugging screen-in-screen rendering
I'm writing to location 'screen' somehow that's not the raw location.
-rw-r--r--036call_reply.cc1
-rw-r--r--050scenario.cc2
-rw-r--r--071print.mu43
-rw-r--r--081run_interactive.cc70
-rw-r--r--edit.mu152
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
     {
@@ -138,6 +179,8 @@ recipe print-character [
     }
 #?     $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
     cursor-color:address:number <- get-address cursor:address:screen-cell/deref, color: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<vector<double>
 }
 :(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<double> 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<double> warnings;
     warnings.push_back(warnings_from_trace());
     write_memory(current_instruction().products.at(1), warnings);
   }
+  if (SIZE(current_instruction().products) >= 3) {
+    vector<double> 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 [