# Mu - shell/sandbox.mu

https://github.com/akkartik/mu/blob/main/shell/sandbox.mu

       1 type sandbox {
       2   data: (handle gap-buffer)
       3   value: (handle stream byte)
       4   trace: (handle trace)
       5   screen-var: (handle cell)
       6   keyboard-var: (handle cell)
       7   cursor-in-data?: boolean
       8   cursor-in-trace?: boolean
       9   cursor-in-keyboard?: boolean
      10 }
      11
      12 fn initialize-sandbox _self: (addr sandbox), fake-screen-and-keyboard?: boolean {
      13   var self/esi: (addr sandbox) <- copy _self
      14   var data-ah/eax: (addr handle gap-buffer) <- get self, data
      15   allocate data-ah
      16   var data/eax: (addr gap-buffer) <- lookup *data-ah
      17   initialize-gap-buffer data, 0x1000/4KB
      18   #
      19   var value-ah/eax: (addr handle stream byte) <- get self, value
      20   populate-stream value-ah, 0x1000/4KB
      21   #
      22   {
      23     compare fake-screen-and-keyboard?, 0/false
      24     break-if-=
      25     var screen-ah/eax: (addr handle cell) <- get self, screen-var
      26     new-fake-screen screen-ah, 8/width, 3/height, 1/enable-pixel-graphics
      27     var keyboard-ah/eax: (addr handle cell) <- get self, keyboard-var
      28     new-fake-keyboard keyboard-ah, 0x10/keyboard-capacity
      29   }
      30   #
      31   var trace-ah/eax: (addr handle trace) <- get self, trace
      32   allocate trace-ah
      33   var trace/eax: (addr trace) <- lookup *trace-ah
      34   initialize-trace trace, 4/max-depth, 0x8000/lines, 0x80/visible
      35   var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
      36   copy-to *cursor-in-data?, 1/true
      37 }
      38
      39 ## some helpers for tests
      40
      41 fn initialize-sandbox-with _self: (addr sandbox), s: (addr array byte) {
      42   var self/esi: (addr sandbox) <- copy _self
      43   var data-ah/eax: (addr handle gap-buffer) <- get self, data
      44   allocate data-ah
      45   var data/eax: (addr gap-buffer) <- lookup *data-ah
      46   initialize-gap-buffer-with data, s
      47   var value-ah/eax: (addr handle stream byte) <- get self, value
      48   populate-stream value-ah, 0x1000/4KB
      49   var trace-ah/eax: (addr handle trace) <- get self, trace
      50   allocate trace-ah
      51   var trace/eax: (addr trace) <- lookup *trace-ah
      52   initialize-trace trace, 3/max-depth, 0x8000/lines, 0x80/visible
      53   var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
      54   copy-to *cursor-in-data?, 1/true
      55 }
      56
      57 fn allocate-sandbox-with _out: (addr handle sandbox), s: (addr array byte) {
      58   var out/eax: (addr handle sandbox) <- copy _out
      59   allocate out
      60   var out-addr/eax: (addr sandbox) <- lookup *out
      61   initialize-sandbox-with out-addr, s
      62 }
      63
      64 fn write-sandbox out: (addr stream byte), _self: (addr sandbox) {
      65   var self/eax: (addr sandbox) <- copy _self
      66   var data-ah/eax: (addr handle gap-buffer) <- get self, data
      67   var data/eax: (addr gap-buffer) <- lookup *data-ah
      68   {
      69     var len/eax: int <- gap-buffer-length data
      70     compare len, 0
      71     break-if-!=
      72     return
      73   }
      74   write out, "  (sandbox . "
      75   append-gap-buffer data, out
      76   write out, ")\n"
      77 }
      78
      79 ##
      80
      81 fn render-sandbox screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean {
      82   clear-rect screen, xmin, ymin, xmax, ymax, 0xc5/bg=blue-bg
      83   add-to xmin, 1/padding-left
      84   add-to ymin, 1/padding-top
      85   subtract-from xmax, 1/padding-right
      86   var self/esi: (addr sandbox) <- copy _self
      87   # data
      88   var data-ah/eax: (addr handle gap-buffer) <- get self, data
      89   var _data/eax: (addr gap-buffer) <- lookup *data-ah
      90   var data/edx: (addr gap-buffer) <- copy _data
      91   var x/eax: int <- copy xmin
      92   var y/ecx: int <- copy ymin
      93   y <- maybe-render-empty-screen screen, self, xmin, y
      94   y <- maybe-render-keyboard screen, self, xmin, y
      95   var cursor-in-editor?/ebx: boolean <- copy show-cursor?
      96   {
      97     compare cursor-in-editor?, 0/false
      98     break-if-=
      99     var cursor-in-data-a/eax: (addr boolean) <- get self, cursor-in-data?
     100     cursor-in-editor? <- copy *cursor-in-data-a
     101   }
     102   x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, xmax, ymax, cursor-in-editor?, 7/fg, 0xc5/bg=blue-bg
     103   y <- increment
     104   # trace
     105   var trace-ah/eax: (addr handle trace) <- get self, trace
     106   var _trace/eax: (addr trace) <- lookup *trace-ah
     107   var trace/edx: (addr trace) <- copy _trace
     108   var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     109   y <- render-trace screen, trace, xmin, y, xmax, ymax, *cursor-in-trace?
     110   # value
     111   $render-sandbox:value: {
     112     compare y, ymax
     113     break-if->=
     114     var value-ah/eax: (addr handle stream byte) <- get self, value
     115     var _value/eax: (addr stream byte) <- lookup *value-ah
     116     var value/esi: (addr stream byte) <- copy _value
     117     rewind-stream value
     118     var done?/eax: boolean <- stream-empty? value
     119     compare done?, 0/false
     120     break-if-!=
     121     var x/eax: int <- copy 0
     122     x, y <- draw-text-wrapping-right-then-down screen, "=> ", xmin, y, xmax, ymax, xmin, y, 7/fg, 0xc5/bg=blue-bg
     123     var x2/edx: int <- copy x
     124     var dummy/eax: int <- draw-stream-rightward screen, value, x2, xmax, y, 7/fg=grey, 0xc5/bg=blue-bg
     125   }
     126   y <- add 2  # padding
     127   y <- maybe-render-screen screen, self, xmin, y
     128 }
     129
     130 fn render-sandbox-menu screen: (addr screen), _self: (addr sandbox) {
     131   var self/esi: (addr sandbox) <- copy _self
     132   var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     133   compare *cursor-in-data?, 0/false
     134   {
     135     break-if-=
     136     render-sandbox-edit-menu screen, self
     137     return
     138   }
     139   var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     140   compare *cursor-in-trace?, 0/false
     141   {
     142     break-if-=
     143     render-trace-menu screen
     144     return
     145   }
     146   var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
     147   compare *cursor-in-keyboard?, 0/false
     148   {
     149     break-if-=
     150     render-keyboard-menu screen
     151     return
     152   }
     153 }
     154
     155 fn clear-sandbox-output screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int, xmax: int, ymax: int {
     156   # render just enough of the sandbox to figure out what to erase
     157   var self/esi: (addr sandbox) <- copy _self
     158   var data-ah/eax: (addr handle gap-buffer) <- get self, data
     159   var _data/eax: (addr gap-buffer) <- lookup *data-ah
     160   var data/edx: (addr gap-buffer) <- copy _data
     161   var x/eax: int <- copy xmin
     162   var y/ecx: int <- copy ymin
     163   y <- maybe-render-empty-screen screen, self, xmin, y
     164   y <- maybe-render-keyboard screen, self, xmin, y
     165   var cursor-in-sandbox?/ebx: (addr boolean) <- get self, cursor-in-data?
     166   x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, xmax, ymax, *cursor-in-sandbox?, 3/fg, 0xc5/bg=blue-bg
     167   y <- increment
     168   clear-rect screen, xmin, y, xmax, ymax, 0xc5/bg=blue-bg
     169 }
     170
     171 fn maybe-render-empty-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
     172   var self/esi: (addr sandbox) <- copy _self
     173   var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var
     174   var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah
     175   compare screen-obj-cell, 0
     176   {
     177     break-if-!=
     178     return ymin
     179   }
     180   var screen-obj-cell-type/ecx: (addr int) <- get screen-obj-cell, type
     181   compare *screen-obj-cell-type, 5/screen
     182   {
     183     break-if-=
     184     return ymin  # silently give up on rendering the screen
     185   }
     186   var y/ecx: int <- copy ymin
     187   var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data
     188   var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
     189   var screen-obj/edx: (addr screen) <- copy _screen-obj
     190   var x/eax: int <- draw-text-rightward screen, "screen:   ", xmin, 0x99/xmax, y, 0x17/fg, 0xc5/bg=blue-bg
     191   y <- render-empty-screen screen, screen-obj, x, y
     192   return y
     193 }
     194
     195 fn maybe-render-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
     196   var self/esi: (addr sandbox) <- copy _self
     197   var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var
     198   var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah
     199   compare screen-obj-cell, 0
     200   {
     201     break-if-!=
     202     return ymin
     203   }
     204   var screen-obj-cell-type/ecx: (addr int) <- get screen-obj-cell, type
     205   compare *screen-obj-cell-type, 5/screen
     206   {
     207     break-if-=
     208     return ymin  # silently give up on rendering the screen
     209   }
     210   var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data
     211   var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
     212   var screen-obj/edx: (addr screen) <- copy _screen-obj
     213   {
     214     var screen-empty?/eax: boolean <- fake-screen-empty? screen-obj
     215     compare screen-empty?, 0/false
     216     break-if-=
     217     return ymin
     218   }
     219   var x/eax: int <- draw-text-rightward screen, "screen:   ", xmin, 0x99/xmax, ymin, 0x17/fg, 0xc5/bg=blue-bg
     220   var y/ecx: int <- copy ymin
     221   y <- render-screen screen, screen-obj, x, y
     222   return y
     223 }
     224
     225 fn render-empty-screen screen: (addr screen), _target-screen: (addr screen), xmin: int, ymin: int -> _/ecx: int {
     226   var target-screen/esi: (addr screen) <- copy _target-screen
     227   var screen-y/edi: int <- copy ymin
     228   # screen
     229   var height/edx: (addr int) <- get target-screen, height
     230   var y/ecx: int <- copy 0
     231   {
     232     compare y, *height
     233     break-if->=
     234     set-cursor-position screen, xmin, screen-y
     235     var width/edx: (addr int) <- get target-screen, width
     236     var x/ebx: int <- copy 0
     237     {
     238       compare x, *width
     239       break-if->=
     240       draw-code-point-at-cursor screen, 0x20/space, 0x18/fg, 0/bg
     241       move-cursor-right screen
     242       x <- increment
     243       loop
     244     }
     245     y <- increment
     246     screen-y <- increment
     247     loop
     248   }
     249   return screen-y
     250 }
     251
     252 fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int, ymin: int -> _/ecx: int {
     253   var target-screen/esi: (addr screen) <- copy _target-screen
     254   var screen-y/edi: int <- copy ymin
     255   # text data
     256   {
     257     var height/edx: (addr int) <- get target-screen, height
     258     var y/ecx: int <- copy 0
     259     {
     260       compare y, *height
     261       break-if->=
     262       set-cursor-position screen, xmin, screen-y
     263       var width/edx: (addr int) <- get target-screen, width
     264       var x/ebx: int <- copy 0
     265       {
     266         compare x, *width
     267         break-if->=
     268         print-screen-cell-of-fake-screen screen, target-screen, x, y
     269         move-cursor-right screen
     270         x <- increment
     271         loop
     272       }
     273       y <- increment
     274       screen-y <- increment
     275       loop
     276     }
     277   }
     278   # pixel data
     279   {
     280     # screen top left pixels x y width height
     281     var tmp/eax: int <- copy xmin
     282     tmp <- shift-left 3/log2-font-width
     283     var left: int
     284     copy-to left, tmp
     285     tmp <- copy ymin
     286     tmp <- shift-left 4/log2-font-height
     287     var top: int
     288     copy-to top, tmp
     289     var pixels-ah/eax: (addr handle array byte) <- get target-screen, pixels
     290     var _pixels/eax: (addr array byte) <- lookup *pixels-ah
     291     var pixels/edi: (addr array byte) <- copy _pixels
     292     compare pixels, 0
     293     break-if-=
     294     var y/ebx: int <- copy 0
     295     var height-addr/edx: (addr int) <- get target-screen, height
     296     var height/edx: int <- copy *height-addr
     297     height <- shift-left 4/log2-font-height
     298     {
     299       compare y, height
     300       break-if->=
     301       var width-addr/edx: (addr int) <- get target-screen, width
     302       var width/edx: int <- copy *width-addr
     303       width <- shift-left 3/log2-font-width
     304       var x/eax: int <- copy 0
     305       {
     306         compare x, width
     307         break-if->=
     308         {
     309           var idx/ecx: int <- pixel-index target-screen, x, y
     310           var color-addr/ecx: (addr byte) <- index pixels, idx
     311           var color/ecx: byte <- copy-byte *color-addr
     312           var color2/ecx: int <- copy color
     313           compare color2, 0
     314           break-if-=
     315           var x2/eax: int <- copy x
     316           x2 <- add left
     317           var y2/ebx: int <- copy y
     318           y2 <- add top
     319           pixel screen, x2, y2, color2
     320         }
     321         x <- increment
     322         loop
     323       }
     324       y <- increment
     325       loop
     326     }
     327   }
     328   return screen-y
     329 }
     330
     331 fn has-keyboard? _self: (addr sandbox) -> _/eax: boolean {
     332   var self/esi: (addr sandbox) <- copy _self
     333   var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
     334   var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah
     335   compare keyboard-obj-cell, 0
     336   {
     337     break-if-!=
     338     return 0/false
     339   }
     340   var keyboard-obj-cell-type/ecx: (addr int) <- get keyboard-obj-cell, type
     341   compare *keyboard-obj-cell-type, 6/keyboard
     342   {
     343     break-if-=
     344     return 0/false
     345   }
     346   var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data
     347   var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah
     348   var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj
     349   compare keyboard-obj, 0
     350   {
     351     break-if-!=
     352     return 0/false
     353   }
     354   return 1/true
     355 }
     356
     357 fn maybe-render-keyboard screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int {
     358   var self/esi: (addr sandbox) <- copy _self
     359   var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
     360   var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah
     361   compare keyboard-obj-cell, 0
     362   {
     363     break-if-!=
     364     return ymin
     365   }
     366   var keyboard-obj-cell-type/ecx: (addr int) <- get keyboard-obj-cell, type
     367   compare *keyboard-obj-cell-type, 6/keyboard
     368   {
     369     break-if-=
     370     return ymin  # silently give up on rendering the keyboard
     371   }
     372   var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data
     373   var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah
     374   var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj
     375   var y/ecx: int <- copy ymin
     376   y <- increment  # padding
     377   var x/eax: int <- draw-text-rightward screen, "keyboard: ", xmin, 0x99/xmax, y, 0x17/fg, 0xc5/bg=blue-bg
     378   var cursor-in-keyboard?/esi: (addr boolean) <- get self, cursor-in-keyboard?
     379   y <- render-keyboard screen, keyboard-obj, x, y, *cursor-in-keyboard?
     380   y <- increment  # padding
     381   return y
     382 }
     383
     384 fn render-keyboard screen: (addr screen), _keyboard: (addr gap-buffer), xmin: int, ymin: int, render-cursor?: boolean -> _/ecx: int {
     385   var keyboard/esi: (addr gap-buffer) <- copy _keyboard
     386   var width/edx: int <- copy 0x10/keyboard-capacity
     387   var y/edi: int <- copy ymin
     388   # keyboard
     389   var x/eax: int <- copy xmin
     390   var xmax/ecx: int <- copy x
     391   xmax <- add 0x10
     392   var ymax/edx: int <- copy ymin
     393   ymax <- add 1
     394   clear-rect screen, x, y, xmax, ymax, 0/bg
     395   x <- render-gap-buffer screen, keyboard, x, y, render-cursor?, 3/fg, 0/bg
     396   y <- increment
     397   return y
     398 }
     399
     400 fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), x: int, y: int {
     401   var target/ecx: (addr screen) <- copy _target
     402   var data-ah/eax: (addr handle array screen-cell) <- get target, data
     403   var data/eax: (addr array screen-cell) <- lookup *data-ah
     404   var index/ecx: int <- screen-cell-index target, x, y
     405   var offset/ecx: (offset screen-cell) <- compute-offset data, index
     406   var src-cell/esi: (addr screen-cell) <- index data, offset
     407   var src-grapheme/eax: (addr grapheme) <- get src-cell, data
     408   var src-color/ecx: (addr int) <- get src-cell, color
     409   var src-background-color/edx: (addr int) <- get src-cell, background-color
     410   draw-grapheme-at-cursor screen, *src-grapheme, *src-color, *src-background-color
     411 }
     412
     413 fn render-sandbox-edit-menu screen: (addr screen), _self: (addr sandbox) {
     414   var _width/eax: int <- copy 0
     415   var height/ecx: int <- copy 0
     416   _width, height <- screen-size screen
     417   var width/edx: int <- copy _width
     418   var y/ecx: int <- copy height
     419   y <- decrement
     420   var height/ebx: int <- copy y
     421   height <- increment
     422   clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg
     423   set-cursor-position screen, 0/x, y
     424   draw-text-rightward-from-cursor screen, " ^r ", width, 0/fg, 0x5c/bg=menu-highlight
     425   draw-text-rightward-from-cursor screen, " run main  ", width, 7/fg, 0xc5/bg=blue-bg
     426   draw-text-rightward-from-cursor screen, " ^s ", width, 0/fg, 0x5c/bg=menu-highlight
     427   draw-text-rightward-from-cursor screen, " run sandbox  ", width, 7/fg, 0xc5/bg=blue-bg
     428   draw-text-rightward-from-cursor screen, " ^g ", width, 0/fg, 0x5c/bg=menu-highlight
     429   draw-text-rightward-from-cursor screen, " go to  ", width, 7/fg, 0xc5/bg=blue-bg
     430   $render-sandbox-edit-menu:render-ctrl-m: {
     431     var self/eax: (addr sandbox) <- copy _self
     432     var has-trace?/eax: boolean <- has-trace? self
     433     compare has-trace?, 0/false
     434     {
     435       break-if-=
     436       draw-text-rightward-from-cursor screen, " ^m ", width, 0/fg, 0x38/bg=trace
     437       draw-text-rightward-from-cursor screen, " to trace  ", width, 7/fg, 0xc5/bg=blue-bg
     438       break $render-sandbox-edit-menu:render-ctrl-m
     439     }
     440     draw-text-rightward-from-cursor screen, " ^m ", width, 0/fg, 3/bg=keyboard
     441     draw-text-rightward-from-cursor screen, " to keyboard  ", width, 7/fg, 0xc5/bg=blue-bg
     442   }
     443   draw-text-rightward-from-cursor screen, " ^a ", width, 0/fg, 0x5c/bg=menu-highlight
     444   draw-text-rightward-from-cursor screen, " <<  ", width, 7/fg, 0xc5/bg=blue-bg
     445   draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg, 0x5c/bg=menu-highlight
     446   draw-text-rightward-from-cursor screen, " <word  ", width, 7/fg, 0xc5/bg=blue-bg
     447   draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg, 0x5c/bg=menu-highlight
     448   draw-text-rightward-from-cursor screen, " word>  ", width, 7/fg, 0xc5/bg=blue-bg
     449   draw-text-rightward-from-cursor screen, " ^e ", width, 0/fg, 0x5c/bg=menu-highlight
     450   draw-text-rightward-from-cursor screen, " >>  ", width, 7/fg, 0xc5/bg=blue-bg
     451 }
     452
     453 fn render-keyboard-menu screen: (addr screen) {
     454   var width/eax: int <- copy 0
     455   var height/ecx: int <- copy 0
     456   width, height <- screen-size screen
     457   var y/ecx: int <- copy height
     458   y <- decrement
     459   var height/edx: int <- copy y
     460   height <- increment
     461   clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg
     462   set-cursor-position screen, 0/x, y
     463   draw-text-rightward-from-cursor screen, " ^r ", width, 0/fg, 0x5c/bg=menu-highlight
     464   draw-text-rightward-from-cursor screen, " run main  ", width, 7/fg, 0xc5/bg=blue-bg
     465   draw-text-rightward-from-cursor screen, " ^s ", width, 0/fg, 0x5c/bg=menu-highlight
     466   draw-text-rightward-from-cursor screen, " run sandbox  ", width, 7/fg, 0xc5/bg=blue-bg
     467   draw-text-rightward-from-cursor screen, " ^g ", width, 0/fg, 0x5c/bg=menu-highlight
     468   draw-text-rightward-from-cursor screen, " go to  ", width, 7/fg, 0xc5/bg=blue-bg
     469   draw-text-rightward-from-cursor screen, " ^m ", width, 0/fg, 7/bg
     470   draw-text-rightward-from-cursor screen, " to sandbox  ", width, 7/fg, 0xc5/bg=blue-bg
     471 }
     472
     473 fn edit-sandbox _self: (addr sandbox), key: grapheme, globals: (addr global-table), data-disk: (addr disk), tweak-real-screen?: boolean {
     474   var self/esi: (addr sandbox) <- copy _self
     475   # ctrl-s
     476   {
     477     compare key, 0x13/ctrl-s
     478     break-if-!=
     479     # if cursor is in trace, skip
     480     var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     481     compare *cursor-in-trace?, 0/false
     482     break-if-!=
     483     # minor gotcha here: any bindings created later in this iteration won't be
     484     # persisted until the next call to ctrl-s.
     485     store-state data-disk, self, globals
     486     #
     487     run-sandbox self, globals, tweak-real-screen?
     488     return
     489   }
     490   # ctrl-m
     491   {
     492     compare key, 0xd/ctrl-m
     493     break-if-!=
     494     # if cursor in data, switch to trace or fall through to keyboard
     495     {
     496       var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     497       compare *cursor-in-data?, 0/false
     498       break-if-=
     499       var has-trace?/eax: boolean <- has-trace? self
     500       compare has-trace?, 0/false
     501       {
     502         break-if-=
     503         var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     504         copy-to *cursor-in-data?, 0/false
     505         var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     506         copy-to *cursor-in-trace?, 1/false
     507         return
     508       }
     509       var has-keyboard?/eax: boolean <- has-keyboard? self
     510       compare has-keyboard?, 0/false
     511       {
     512         break-if-=
     513         var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     514         copy-to *cursor-in-data?, 0/false
     515         var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
     516         copy-to *cursor-in-keyboard?, 1/false
     517         return
     518       }
     519       return
     520     }
     521     # if cursor in trace, switch to keyboard or fall through to data
     522     {
     523       var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     524       compare *cursor-in-trace?, 0/false
     525       break-if-=
     526       copy-to *cursor-in-trace?, 0/false
     527       var cursor-target/ecx: (addr boolean) <- get self, cursor-in-keyboard?
     528       var has-keyboard?/eax: boolean <- has-keyboard? self
     529       compare has-keyboard?, 0/false
     530       {
     531         break-if-!=
     532         cursor-target <- get self, cursor-in-data?
     533       }
     534       copy-to *cursor-target, 1/true
     535       return
     536     }
     537     # otherwise if cursor in keyboard, switch to data
     538     {
     539       var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
     540       compare *cursor-in-keyboard?, 0/false
     541       break-if-=
     542       copy-to *cursor-in-keyboard?, 0/false
     543       var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     544       copy-to *cursor-in-data?, 1/true
     545       return
     546     }
     547     return
     548   }
     549   # if cursor in data, send key to data
     550   {
     551     var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data?
     552     compare *cursor-in-data?, 0/false
     553     break-if-=
     554     var data-ah/eax: (addr handle gap-buffer) <- get self, data
     555     var data/eax: (addr gap-buffer) <- lookup *data-ah
     556     edit-gap-buffer data, key
     557     return
     558   }
     559   # if cursor in keyboard, send key to keyboard
     560   {
     561     var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard?
     562     compare *cursor-in-keyboard?, 0/false
     563     break-if-=
     564     var keyboard-cell-ah/eax: (addr handle cell) <- get self, keyboard-var
     565     var keyboard-cell/eax: (addr cell) <- lookup *keyboard-cell-ah
     566     compare keyboard-cell, 0
     567     {
     568       break-if-!=
     569       return
     570     }
     571     var keyboard-cell-type/ecx: (addr int) <- get keyboard-cell, type
     572     compare *keyboard-cell-type, 6/keyboard
     573     {
     574       break-if-=
     575       return
     576     }
     577     var keyboard-ah/eax: (addr handle gap-buffer) <- get keyboard-cell, keyboard-data
     578     var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah
     579     edit-gap-buffer keyboard, key
     580     return
     581   }
     582   # if cursor in trace, send key to trace
     583   {
     584     var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
     585     compare *cursor-in-trace?, 0/false
     586     break-if-=
     587     var trace-ah/eax: (addr handle trace) <- get self, trace
     588     var trace/eax: (addr trace) <- lookup *trace-ah
     589     # if expanding the trace, first check if we need to run the sandbox again with a deeper trace
     590     {
     591       compare key, 0xa/newline
     592       break-if-!=
     593       {
     594         var need-rerun?/eax: boolean <- cursor-too-deep? trace
     595         compare need-rerun?, 0/false
     596       }
     597       break-if-=
     598 #?       draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "rerun", 7/fg 0/bg
     599       # save trace lines at various cached indices
     600       var save: trace-index-stash
     601       var save-addr/ecx: (addr trace-index-stash) <- address save
     602       save-indices trace, save-addr
     603       # rerun at higher depth
     604       var max-depth-addr/ecx: (addr int) <- get trace, max-depth
     605       increment *max-depth-addr
     606       run-sandbox self, globals, tweak-real-screen?
     607       # recompute cached indices
     608       recompute-all-visible-lines trace
     609       var save-addr/ecx: (addr trace-index-stash) <- address save
     610       restore-indices trace, save-addr
     611     }
     612     edit-trace trace, key
     613     return
     614   }
     615 }
     616
     617 # hack: tweak-real-screen guards things there are no tests for
     618 fn run-sandbox _self: (addr sandbox), globals: (addr global-table), tweak-real-screen?: boolean {
     619   var self/esi: (addr sandbox) <- copy _self
     620   var data-ah/ecx: (addr handle gap-buffer) <- get self, data
     621   var value-ah/eax: (addr handle stream byte) <- get self, value
     622   var _value/eax: (addr stream byte) <- lookup *value-ah
     623   var value/edx: (addr stream byte) <- copy _value
     624   var trace-ah/eax: (addr handle trace) <- get self, trace
     625   var _trace/eax: (addr trace) <- lookup *trace-ah
     626   var trace/ebx: (addr trace) <- copy _trace
     627   clear-trace trace
     628   {
     629     compare tweak-real-screen?, 0/false
     630     break-if-=
     631     clear-sandbox-output 0/screen, self, 0x56/sandbox-left-margin, 1/y, 0x80/screen-width, 0x2f/screen-height-without-menu
     632   }
     633   var screen-cell/eax: (addr handle cell) <- get self, screen-var
     634   clear-screen-cell screen-cell
     635   var keyboard-cell/esi: (addr handle cell) <- get self, keyboard-var
     636   rewind-keyboard-cell keyboard-cell  # don't clear keys from before
     637   {
     638     compare tweak-real-screen?, 0/false
     639     break-if-=
     640     set-cursor-position 0/screen, 0/x, 0/y  # for any debug prints during evaluation
     641   }
     642   run data-ah, value, globals, trace, screen-cell, keyboard-cell
     643 }
     644
     645 fn run _in-ah: (addr handle gap-buffer), out: (addr stream byte), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
     646   var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah
     647   var in/eax: (addr gap-buffer) <- lookup *in-ah
     648   var read-result-h: (handle cell)
     649   var read-result-ah/esi: (addr handle cell) <- address read-result-h
     650   read-cell in, read-result-ah, trace
     651   var error?/eax: boolean <- has-errors? trace
     652   {
     653     compare error?, 0/false
     654     break-if-=
     655     return
     656   }
     657   macroexpand read-result-ah, globals, trace
     658   var error?/eax: boolean <- has-errors? trace
     659   {
     660     compare error?, 0/false
     661     break-if-=
     662     return
     663   }
     664   var nil-h: (handle cell)
     665   var nil-ah/eax: (addr handle cell) <- address nil-h
     666   allocate-pair nil-ah
     667   var eval-result-h: (handle cell)
     668   var eval-result-ah/edi: (addr handle cell) <- address eval-result-h
     669 #?   set-cursor-position 0/screen, 0 0
     670 #?   turn-on-debug-print
     671   debug-print "^", 4/fg, 0/bg
     672   evaluate read-result-ah, eval-result-ah, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number
     673   debug-print "$", 4/fg, 0/bg
     674   var error?/eax: boolean <- has-errors? trace
     675   {
     676     compare error?, 0/false
     677     break-if-=
     678     return
     679   }
     680   # if there was no error and the read-result starts with "set" or "def", save
     681   # the gap buffer in the modified global, then create a new one for the next
     682   # command.
     683   maybe-stash-gap-buffer-to-global globals, read-result-ah, _in-ah
     684   clear-stream out
     685   print-cell eval-result-ah, out, trace
     686   mark-lines-dirty trace
     687 }
     688
     689 fn read-evaluate-and-move-to-globals _in-ah: (addr handle gap-buffer), globals: (addr global-table), definition-name: (addr stream byte) {
     690   var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah
     691   var in/eax: (addr gap-buffer) <- lookup *in-ah
     692   var read-result-h: (handle cell)
     693   var read-result-ah/esi: (addr handle cell) <- address read-result-h
     694   var trace-storage: trace
     695   var trace/edx: (addr trace) <- address trace-storage
     696   initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible
     697   read-cell in, read-result-ah, trace
     698   macroexpand read-result-ah, globals, trace
     699   var nil-storage: (handle cell)
     700   var nil-ah/eax: (addr handle cell) <- address nil-storage
     701   allocate-pair nil-ah
     702   var eval-result-storage: (handle cell)
     703   var eval-result/edi: (addr handle cell) <- address eval-result-storage
     704   debug-print "^", 4/fg, 0/bg
     705   evaluate read-result-ah, eval-result, *nil-ah, globals, trace, 0/no-screen-cell, 0/no-keyboard-cell, 1/call-number
     706   {
     707     var error?/eax: boolean <- has-errors? trace
     708     compare error?, 0/false
     709     break-if-=
     710     set-cursor-position 0/screen, 0x40/x, 0x18/y
     711     draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "error when loading definition for ", 4/fg 0/bg
     712     rewind-stream definition-name
     713     draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, definition-name, 3/fg 0/bg
     714     set-cursor-position 0/screen, 0x40/x, 0x19/y
     715     draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "see trace in grey at top-left", 7/fg 0/bg
     716     dump-trace trace  # will print from 0, 0
     717     {
     718       loop
     719     }
     720   }
     721   debug-print "$", 4/fg, 0/bg
     722   move-gap-buffer-to-global globals, read-result-ah, _in-ah
     723 }
     724
     725 fn test-run-integer {
     726   var sandbox-storage: sandbox
     727   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     728   initialize-sandbox-with sandbox, "1"
     729   # eval
     730   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     731   # setup: screen
     732   var screen-on-stack: screen
     733   var screen/edi: (addr screen) <- address screen-on-stack
     734   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     735   #
     736   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     737   # skip one line of padding
     738   check-screen-row screen, 1/y, " 1    ", "F - test-run-integer/0"
     739   check-screen-row screen, 2/y, " ...  ", "F - test-run-integer/1"
     740   check-screen-row screen, 3/y, " => 1 ", "F - test-run-integer/2"
     741 }
     742
     743 fn test-run-error-invalid-integer {
     744   var sandbox-storage: sandbox
     745   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     746   initialize-sandbox-with sandbox, "1a"
     747   # eval
     748   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     749   # setup: screen
     750   var screen-on-stack: screen
     751   var screen/edi: (addr screen) <- address screen-on-stack
     752   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     753   #
     754   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     755   # skip one line of padding
     756   check-screen-row            screen,               1/y, " 1a             ", "F - test-run-error-invalid-integer/0"
     757   check-screen-row            screen,               2/y, " ...            ", "F - test-run-error-invalid-integer/1"
     758   check-screen-row-in-color   screen, 0xc/fg=error, 3/y, " invalid number ", "F - test-run-error-invalid-integer/2"
     759 }
     760
     761 fn test-run-error-unknown-symbol {
     762   var sandbox-storage: sandbox
     763   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     764   initialize-sandbox-with sandbox, "a"
     765   # eval
     766   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     767   # setup: screen
     768   var screen-on-stack: screen
     769   var screen/edi: (addr screen) <- address screen-on-stack
     770   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     771   #
     772   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     773   # skip one line of padding
     774   check-screen-row            screen,               1/y, " a                  ", "F - test-run-error-unknown-symbol/0"
     775   check-screen-row            screen,               2/y, " ...                ", "F - test-run-error-unknown-symbol/1"
     776   check-screen-row-in-color   screen, 0xc/fg=error, 3/y, " unbound symbol: a  ", "F - test-run-error-unknown-symbol/2"
     777 }
     778
     779 fn test-run-with-spaces {
     780   var sandbox-storage: sandbox
     781   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     782   initialize-sandbox-with sandbox, " 1 \n"
     783   # eval
     784   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     785   # setup: screen
     786   var screen-on-stack: screen
     787   var screen/edi: (addr screen) <- address screen-on-stack
     788   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     789   #
     790   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     791   # skip one line of padding
     792   check-screen-row screen, 1/y, "  1   ", "F - test-run-with-spaces/0"
     793   check-screen-row screen, 2/y, "      ", "F - test-run-with-spaces/1"
     794   check-screen-row screen, 3/y, " ...  ", "F - test-run-with-spaces/2"
     795   check-screen-row screen, 4/y, " => 1 ", "F - test-run-with-spaces/3"
     796 }
     797
     798 fn test-run-quote {
     799   var sandbox-storage: sandbox
     800   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     801   initialize-sandbox-with sandbox, "'a"
     802   # eval
     803   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     804   # setup: screen
     805   var screen-on-stack: screen
     806   var screen/edi: (addr screen) <- address screen-on-stack
     807   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     808   #
     809   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     810   # skip one line of padding
     811   check-screen-row screen, 1/y, " 'a   ", "F - test-run-quote/0"
     812   check-screen-row screen, 2/y, " ...  ", "F - test-run-quote/1"
     813   check-screen-row screen, 3/y, " => a ", "F - test-run-quote/2"
     814 }
     815
     816 fn test-run-dotted-list {
     817   var sandbox-storage: sandbox
     818   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     819   initialize-sandbox-with sandbox, "'(a . b)"
     820   # eval
     821   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     822   # setup: screen
     823   var screen-on-stack: screen
     824   var screen/edi: (addr screen) <- address screen-on-stack
     825   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     826   #
     827   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     828   # skip one line of padding
     829   check-screen-row screen, 1/y, " '(a . b)   ", "F - test-run-dotted-list/0"
     830   check-screen-row screen, 2/y, " ...        ", "F - test-run-dotted-list/1"
     831   check-screen-row screen, 3/y, " => (a . b) ", "F - test-run-dotted-list/2"
     832 }
     833
     834 fn test-run-dot-and-list {
     835   var sandbox-storage: sandbox
     836   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     837   initialize-sandbox-with sandbox, "'(a . (b))"
     838   # eval
     839   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     840   # setup: screen
     841   var screen-on-stack: screen
     842   var screen/edi: (addr screen) <- address screen-on-stack
     843   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     844   #
     845   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     846   # skip one line of padding
     847   check-screen-row screen, 1/y, " '(a . (b)) ", "F - test-run-dot-and-list/0"
     848   check-screen-row screen, 2/y, " ...        ", "F - test-run-dot-and-list/1"
     849   check-screen-row screen, 3/y, " => (a b)   ", "F - test-run-dot-and-list/2"
     850 }
     851
     852 fn test-run-final-dot {
     853   var sandbox-storage: sandbox
     854   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     855   initialize-sandbox-with sandbox, "'(a .)"
     856   # eval
     857   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     858   # setup: screen
     859   var screen-on-stack: screen
     860   var screen/edi: (addr screen) <- address screen-on-stack
     861   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     862   #
     863   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     864   # skip one line of padding
     865   check-screen-row screen, 1/y, " '(a .)               ", "F - test-run-final-dot/0"
     866   check-screen-row screen, 2/y, " ...                  ", "F - test-run-final-dot/1"
     867   check-screen-row screen, 3/y, " '. )' makes no sense ", "F - test-run-final-dot/2"
     868   # further errors may occur
     869 }
     870
     871 fn test-run-double-dot {
     872   var sandbox-storage: sandbox
     873   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     874   initialize-sandbox-with sandbox, "'(a . .)"
     875   # eval
     876   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     877   # setup: screen
     878   var screen-on-stack: screen
     879   var screen/edi: (addr screen) <- address screen-on-stack
     880   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     881   #
     882   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     883   # skip one line of padding
     884   check-screen-row screen, 1/y, " '(a . .)             ", "F - test-run-double-dot/0"
     885   check-screen-row screen, 2/y, " ...                  ", "F - test-run-double-dot/1"
     886   check-screen-row screen, 3/y, " '. .' makes no sense ", "F - test-run-double-dot/2"
     887   # further errors may occur
     888 }
     889
     890 fn test-run-multiple-expressions-after-dot {
     891   var sandbox-storage: sandbox
     892   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     893   initialize-sandbox-with sandbox, "'(a . b c)"
     894   # eval
     895   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     896   # setup: screen
     897   var screen-on-stack: screen
     898   var screen/edi: (addr screen) <- address screen-on-stack
     899   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     900   #
     901   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     902   # skip one line of padding
     903   check-screen-row screen, 1/y, " '(a . b c)                                           ", "F - test-run-multiple-expressions-after-dot/0"
     904   check-screen-row screen, 2/y, " ...                                                  ", "F - test-run-multiple-expressions-after-dot/1"
     905   check-screen-row screen, 3/y, " cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2"
     906   # further errors may occur
     907 }
     908
     909 fn test-run-stream {
     910   var sandbox-storage: sandbox
     911   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     912   initialize-sandbox-with sandbox, "[a b]"
     913   # eval
     914   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     915   # setup: screen
     916   var screen-on-stack: screen
     917   var screen/edi: (addr screen) <- address screen-on-stack
     918   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     919   #
     920   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     921   # skip one line of padding
     922   check-screen-row screen, 1/y, " [a b]    ", "F - test-run-stream/0"
     923   check-screen-row screen, 2/y, " ...      ", "F - test-run-stream/1"
     924   check-screen-row screen, 3/y, " => [a b] ", "F - test-run-stream/2"
     925 }
     926
     927 fn test-run-move-cursor-into-trace {
     928   var sandbox-storage: sandbox
     929   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     930   initialize-sandbox-with sandbox, "12"
     931   # eval
     932   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     933   # setup: screen
     934   var screen-on-stack: screen
     935   var screen/edi: (addr screen) <- address screen-on-stack
     936   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     937   #
     938   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     939   # skip one line of padding
     940   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-move-cursor-into-trace/pre-0"
     941   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "   |   ", "F - test-run-move-cursor-into-trace/pre-0/cursor"
     942   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-move-cursor-into-trace/pre-1"
     943   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "       ", "F - test-run-move-cursor-into-trace/pre-1/cursor"
     944   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-move-cursor-into-trace/pre-2"
     945   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-move-cursor-into-trace/pre-2/cursor"
     946   # move cursor into trace
     947   edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     948   #
     949   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     950   # skip one line of padding
     951   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-move-cursor-into-trace/trace-0"
     952   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-move-cursor-into-trace/trace-0/cursor"
     953   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-move-cursor-into-trace/trace-1"
     954   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " |||   ", "F - test-run-move-cursor-into-trace/trace-1/cursor"
     955   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-move-cursor-into-trace/trace-2"
     956   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-move-cursor-into-trace/trace-2/cursor"
     957   # move cursor into input
     958   edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     959   #
     960   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
     961   # skip one line of padding
     962   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-move-cursor-into-trace/input-0"
     963   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "   |   ", "F - test-run-move-cursor-into-trace/input-0/cursor"
     964   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-move-cursor-into-trace/input-1"
     965   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "       ", "F - test-run-move-cursor-into-trace/input-1/cursor"
     966   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-move-cursor-into-trace/input-2"
     967   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-move-cursor-into-trace/input-2/cursor"
     968 }
     969
     970 fn has-trace? _self: (addr sandbox) -> _/eax: boolean {
     971   var self/esi: (addr sandbox) <- copy _self
     972   var trace-ah/eax: (addr handle trace) <- get self, trace
     973   var _trace/eax: (addr trace) <- lookup *trace-ah
     974   var trace/edx: (addr trace) <- copy _trace
     975   compare trace, 0
     976   {
     977     break-if-!=
     978     abort "null trace"
     979   }
     980   var first-free/ebx: (addr int) <- get trace, first-free
     981   compare *first-free, 0
     982   {
     983     break-if->
     984     return 0/false
     985   }
     986   return 1/true
     987 }
     988
     989 fn test-run-expand-trace {
     990   var sandbox-storage: sandbox
     991   var sandbox/esi: (addr sandbox) <- address sandbox-storage
     992   initialize-sandbox-with sandbox, "12"
     993   # eval
     994   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
     995   # setup: screen
     996   var screen-on-stack: screen
     997   var screen/edi: (addr screen) <- address screen-on-stack
     998   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
     999   #
    1000   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1001   # skip one line of padding
    1002   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-expand-trace/pre0-0"
    1003   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "   |   ", "F - test-run-expand-trace/pre0-0/cursor"
    1004   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-expand-trace/pre0-1"
    1005   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "       ", "F - test-run-expand-trace/pre0-1/cursor"
    1006   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-expand-trace/pre0-2"
    1007   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-expand-trace/pre0-2/cursor"
    1008   # move cursor into trace
    1009   edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1010   #
    1011   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1012   # skip one line of padding
    1013   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-expand-trace/pre1-0"
    1014   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-expand-trace/pre1-0/cursor"
    1015   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-expand-trace/pre1-1"
    1016   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " |||   ", "F - test-run-expand-trace/pre1-1/cursor"
    1017   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-expand-trace/pre1-2"
    1018   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-expand-trace/pre1-2/cursor"
    1019   # expand
    1020   edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1021   #
    1022   clear-screen screen
    1023   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1024   # skip one line of padding
    1025   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-expand-trace/expand-0"
    1026   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-expand-trace/expand-0/cursor"
    1027   check-screen-row screen,                                  2/y, " 1 toke", "F - test-run-expand-trace/expand-1"
    1028   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ||||||", "F - test-run-expand-trace/expand-1/cursor"
    1029   check-screen-row screen,                                  3/y, " ...   ", "F - test-run-expand-trace/expand-2"
    1030   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-expand-trace/expand-2/cursor"
    1031   check-screen-row screen,                                  4/y, " 1 pars", "F - test-run-expand-trace/expand-2"
    1032   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "       ", "F - test-run-expand-trace/expand-2/cursor"
    1033 }
    1034
    1035 fn test-run-can-rerun-when-expanding-trace {
    1036   var sandbox-storage: sandbox
    1037   var sandbox/esi: (addr sandbox) <- address sandbox-storage
    1038   # initialize sandbox with a max-depth of 3
    1039   initialize-sandbox-with sandbox, "12"
    1040   # eval
    1041   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1042   # setup: screen
    1043   var screen-on-stack: screen
    1044   var screen/edi: (addr screen) <- address screen-on-stack
    1045   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
    1046   #
    1047   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1048   # skip one line of padding
    1049   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-can-rerun-when-expanding-trace/pre0-0"
    1050   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "   |   ", "F - test-run-can-rerun-when-expanding-trace/pre0-0/cursor"
    1051   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-can-rerun-when-expanding-trace/pre0-1"
    1052   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre0-1/cursor"
    1053   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-can-rerun-when-expanding-trace/pre0-2"
    1054   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre0-2/cursor"
    1055   # move cursor into trace
    1056   edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1057   #
    1058   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1059   # skip one line of padding
    1060   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-can-rerun-when-expanding-trace/pre1-0"
    1061   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre1-0/cursor"
    1062   check-screen-row screen,                                  2/y, " ...   ", "F - test-run-can-rerun-when-expanding-trace/pre1-1"
    1063   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " |||   ", "F - test-run-can-rerun-when-expanding-trace/pre1-1/cursor"
    1064   check-screen-row screen,                                  3/y, " => 12 ", "F - test-run-can-rerun-when-expanding-trace/pre1-2"
    1065   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre1-2/cursor"
    1066   # expand
    1067   edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1068   #
    1069   clear-screen screen
    1070   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1071   # skip one line of padding
    1072   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-can-rerun-when-expanding-trace/pre2-0"
    1073   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre2-0/cursor"
    1074   check-screen-row screen,                                  2/y, " 1 toke", "F - test-run-can-rerun-when-expanding-trace/pre2-1"
    1075   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ||||||", "F - test-run-can-rerun-when-expanding-trace/pre2-1/cursor"
    1076   check-screen-row screen,                                  3/y, " ...   ", "F - test-run-can-rerun-when-expanding-trace/pre2-2"
    1077   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre2-2/cursor"
    1078   check-screen-row screen,                                  4/y, " 1 pars", "F - test-run-can-rerun-when-expanding-trace/pre2-2"
    1079   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "       ", "F - test-run-can-rerun-when-expanding-trace/pre2-2/cursor"
    1080   # move cursor down and expand
    1081   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1082   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1083   edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1084   #
    1085   clear-screen screen
    1086   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1087   # screen looks same as if trace max-depth was really high
    1088   check-screen-row screen,                                  1/y, " 12    ", "F - test-run-can-rerun-when-expanding-trace/expand-0"
    1089   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "       ", "F - test-run-can-rerun-when-expanding-trace/expand-0/cursor"
    1090   check-screen-row screen,                                  2/y, " 1 toke", "F - test-run-can-rerun-when-expanding-trace/expand-1"
    1091   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "       ", "F - test-run-can-rerun-when-expanding-trace/expand-1/cursor"
    1092   check-screen-row screen,                                  3/y, " 2 next", "F - test-run-can-rerun-when-expanding-trace/expand-2"
    1093   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ||||||", "F - test-run-can-rerun-when-expanding-trace/expand-2/cursor"
    1094   check-screen-row screen,                                  4/y, " ...   ", "F - test-run-can-rerun-when-expanding-trace/expand-3"
    1095   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "       ", "F - test-run-can-rerun-when-expanding-trace/expand-3/cursor"
    1096   check-screen-row screen,                                  5/y, " 2 => 1", "F - test-run-can-rerun-when-expanding-trace/expand-4"
    1097   check-background-color-in-screen-row screen, 7/bg=cursor, 5/y, "       ", "F - test-run-can-rerun-when-expanding-trace/expand-4/cursor"
    1098 }
    1099
    1100 fn test-run-preserves-trace-view-on-rerun {
    1101   var sandbox-storage: sandbox
    1102   var sandbox/esi: (addr sandbox) <- address sandbox-storage
    1103   # initialize sandbox with a max-depth of 3
    1104   initialize-sandbox-with sandbox, "7"
    1105   # eval
    1106   edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1107   # setup: screen
    1108   var screen-on-stack: screen
    1109   var screen/edi: (addr screen) <- address screen-on-stack
    1110   initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics
    1111   #
    1112   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1113   # skip one line of padding
    1114   check-screen-row screen,                                  1/y, " 7                     ", "F - test-run-preserves-trace-view-on-rerun/pre0-0"
    1115   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "  |                    ", "F - test-run-preserves-trace-view-on-rerun/pre0-0/cursor"
    1116   check-screen-row screen,                                  2/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre0-1"
    1117   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre0-1/cursor"
    1118   check-screen-row screen,                                  3/y, " => 7                  ", "F - test-run-preserves-trace-view-on-rerun/pre0-2"
    1119   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre0-2/cursor"
    1120   # move cursor into trace
    1121   edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1122   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1123   #
    1124   check-screen-row screen,                                  1/y, " 7                     ", "F - test-run-preserves-trace-view-on-rerun/pre1-0"
    1125   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre1-0/cursor"
    1126   check-screen-row screen,                                  2/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre1-1"
    1127   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " |||                   ", "F - test-run-preserves-trace-view-on-rerun/pre1-1/cursor"
    1128   check-screen-row screen,                                  3/y, " => 7                  ", "F - test-run-preserves-trace-view-on-rerun/pre1-2"
    1129   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre1-2/cursor"
    1130   # expand
    1131   edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1132   clear-screen screen
    1133   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1134   #
    1135   check-screen-row screen,                                  1/y, " 7                     ", "F - test-run-preserves-trace-view-on-rerun/pre2-0"
    1136   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-0/cursor"
    1137   check-screen-row screen,                                  2/y, " 1 tokenize            ", "F - test-run-preserves-trace-view-on-rerun/pre2-1"
    1138   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ||||||||||            ", "F - test-run-preserves-trace-view-on-rerun/pre2-1/cursor"
    1139   check-screen-row screen,                                  3/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre2-2"
    1140   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-2/cursor"
    1141   check-screen-row screen,                                  4/y, " 1 parse               ", "F - test-run-preserves-trace-view-on-rerun/pre2-3"
    1142   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-3/cursor"
    1143   check-screen-row screen,                                  5/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre2-4"
    1144   check-background-color-in-screen-row screen, 7/bg=cursor, 5/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-4/cursor"
    1145   check-screen-row screen,                                  6/y, " 1 macroexpand 7       ", "F - test-run-preserves-trace-view-on-rerun/pre2-5"
    1146   check-background-color-in-screen-row screen, 7/bg=cursor, 6/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-5/cursor"
    1147   check-screen-row screen,                                  7/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre2-6"
    1148   check-background-color-in-screen-row screen, 7/bg=cursor, 7/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-6/cursor"
    1149   check-screen-row screen,                                  8/y, " 1 => 7                ", "F - test-run-preserves-trace-view-on-rerun/pre2-7"
    1150   check-background-color-in-screen-row screen, 7/bg=cursor, 8/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre2-7/cursor"
    1151   # move cursor down below the macroexpand line and expand
    1152   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1153   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1154   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1155   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1156   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1157   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1158   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1159   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1160   edit-sandbox sandbox, 0x6a/j, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1161   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1162   #
    1163   check-screen-row screen,                                  1/y, " 7                     ", "F - test-run-preserves-trace-view-on-rerun/pre3-0"
    1164   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-0/cursor"
    1165   check-screen-row screen,                                  2/y, " 1 tokenize            ", "F - test-run-preserves-trace-view-on-rerun/pre3-1"
    1166   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-1/cursor"
    1167   check-screen-row screen,                                  3/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre3-2"
    1168   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-2/cursor"
    1169   check-screen-row screen,                                  4/y, " 1 parse               ", "F - test-run-preserves-trace-view-on-rerun/pre3-3"
    1170   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-3/cursor"
    1171   check-screen-row screen,                                  5/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre3-4"
    1172   check-background-color-in-screen-row screen, 7/bg=cursor, 5/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-4/cursor"
    1173   check-screen-row screen,                                  6/y, " 1 macroexpand 7       ", "F - test-run-preserves-trace-view-on-rerun/pre3-5"
    1174   check-background-color-in-screen-row screen, 7/bg=cursor, 6/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-5/cursor"
    1175   check-screen-row screen,                                  7/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/pre3-6"
    1176   check-background-color-in-screen-row screen, 7/bg=cursor, 7/y, " |||                   ", "F - test-run-preserves-trace-view-on-rerun/pre3-6/cursor"
    1177   check-screen-row screen,                                  8/y, " 1 => 7                ", "F - test-run-preserves-trace-view-on-rerun/pre3-7"
    1178   check-background-color-in-screen-row screen, 7/bg=cursor, 8/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/pre3-7/cursor"
    1179   # expand
    1180   edit-sandbox sandbox, 0xa/newline, 0/no-globals, 0/no-disk, 0/no-tweak-screen
    1181   clear-screen screen
    1182   render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
    1183   # cursor line is expanded
    1184   check-screen-row screen,                                  1/y, " 7                     ", "F - test-run-preserves-trace-view-on-rerun/expand-0"
    1185   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-0/cursor"
    1186   check-screen-row screen,                                  2/y, " 1 tokenize            ", "F - test-run-preserves-trace-view-on-rerun/expand-1"
    1187   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-1/cursor"
    1188   check-screen-row screen,                                  3/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/expand-2"
    1189   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-2/cursor"
    1190   check-screen-row screen,                                  4/y, " 1 parse               ", "F - test-run-preserves-trace-view-on-rerun/expand-3"
    1191   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-3/cursor"
    1192   check-screen-row screen,                                  5/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/expand-4"
    1193   check-background-color-in-screen-row screen, 7/bg=cursor, 5/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-4/cursor"
    1194   check-screen-row screen,                                  6/y, " 1 macroexpand 7       ", "F - test-run-preserves-trace-view-on-rerun/expand-5"
    1195   check-background-color-in-screen-row screen, 7/bg=cursor, 6/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-5/cursor"
    1196   check-screen-row screen,                                  7/y, " 2 macroexpand-iter 7  ", "F - test-run-preserves-trace-view-on-rerun/expand-6"
    1197   check-background-color-in-screen-row screen, 7/bg=cursor, 7/y, " ||||||||||||||||||||  ", "F - test-run-preserves-trace-view-on-rerun/expand-6/cursor"
    1198   check-screen-row screen,                                  8/y, " ...                   ", "F - test-run-preserves-trace-view-on-rerun/expand-7"
    1199   check-background-color-in-screen-row screen, 7/bg=cursor, 8/y, "                       ", "F - test-run-preserves-trace-view-on-rerun/expand-7/cursor"
    1200 }