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