https://github.com/akkartik/mu/blob/main/shell/trace.mu
   1 # A trace records the evolution of a computation.
   2 # An integral part of the Mu Shell is facilities for browsing traces.
   3 
   4 type trace {
   5   curr-depth: int  # depth that will be assigned to next line appended
   6   data: (handle array trace-line)
   7   first-free: int
   8   first-full: int  # used only by check-trace-scan
   9 
  10   # steady-state life cycle of a trace:
  11   #   reload loop:
  12   #     there are already some visible lines
  13   #     append a bunch of new trace lines to the trace
  14   #     render loop:
  15   #       rendering displays trace lines that match visible lines
  16   #       rendering computes cursor-line based on the cursor-y coordinate
  17   #       edit-trace updates cursor-y coordinate
  18   #       edit-trace might add/remove lines to visible
  19   visible: (handle array trace-line)
  20   recompute-visible?: boolean
  21   top-line-index: int  # index into data
  22   cursor-y: int  # row index on screen
  23   cursor-line-index: int  # index into data
  24 }
  25 
  26 type trace-line {
  27   depth: int
  28   label: (handle array byte)
  29   data: (handle array byte)
  30   visible?: boolean
  31 }
  32 
  33 ## generating traces
  34 
  35 fn initialize-trace _self: (addr trace), capacity: int, visible-capacity: int {
  36   var self/esi: (addr trace) <- copy _self
  37   compare self, 0
  38   break-if-=
  39   var trace-ah/eax: (addr handle array trace-line) <- get self, data
  40   populate trace-ah, capacity
  41   var visible-ah/eax: (addr handle array trace-line) <- get self, visible
  42   populate visible-ah, visible-capacity
  43 }
  44 
  45 fn clear-trace _self: (addr trace) {
  46   var self/eax: (addr trace) <- copy _self
  47   compare self, 0
  48   break-if-=
  49   var len/edx: (addr int) <- get self, first-free
  50   copy-to *len, 0
  51   # might leak memory; existing elements won't be used anymore
  52 }
  53 
  54 fn has-errors? _self: (addr trace) -> _/eax: boolean {
  55   var self/eax: (addr trace) <- copy _self
  56   {
  57     compare self, 0
  58     break-if-!=
  59     return 0/false
  60   }
  61   var max/edx: (addr int) <- get self, first-free
  62   var trace-ah/eax: (addr handle array trace-line) <- get self, data
  63   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
  64   var trace/esi: (addr array trace-line) <- copy _trace
  65   var i/ecx: int <- copy 0
  66   {
  67     compare i, *max
  68     break-if->=
  69     var offset/eax: (offset trace-line) <- compute-offset trace, i
  70     var curr/eax: (addr trace-line) <- index trace, offset
  71     var curr-label-ah/eax: (addr handle array byte) <- get curr, label
  72     var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
  73     var error?/eax: boolean <- string-equal? curr-label, "error"
  74     compare error?, 0/false
  75     {
  76       break-if-=
  77       return 1/true
  78     }
  79     i <- increment
  80     loop
  81   }
  82   return 0/false
  83 }
  84 
  85 fn trace _self: (addr trace), label: (addr array byte), message: (addr stream byte) {
  86   var self/esi: (addr trace) <- copy _self
  87   compare self, 0
  88   break-if-=
  89   var data-ah/eax: (addr handle array trace-line) <- get self, data
  90   var data/eax: (addr array trace-line) <- lookup *data-ah
  91   var index-addr/edi: (addr int) <- get self, first-free
  92   {
  93     compare *index-addr, 0x8000/lines
  94     break-if-<
  95     return
  96   }
  97   var index/ecx: int <- copy *index-addr
  98   var offset/ecx: (offset trace-line) <- compute-offset data, index
  99   var dest/eax: (addr trace-line) <- index data, offset
 100   var depth/ecx: (addr int) <- get self, curr-depth
 101   rewind-stream message
 102   {
 103     compare *index-addr, 0x7fff/lines
 104     break-if-<
 105     clear-stream message
 106     write message, "No space left in trace\n"
 107     write message, "Please either:\n"
 108     write message, "  - find a smaller sub-computation to test,\n"
 109     write message, "  - allocate more space to the trace in initialize-sandbox\n"
 110     write message, "    (shell/sandbox.mu), or\n"
 111     write message, "  - move the computation to 'main' and run it using ctrl-s"
 112     initialize-trace-line 0/depth, "error", message, dest
 113     increment *index-addr
 114     return
 115   }
 116   initialize-trace-line *depth, label, message, dest
 117   increment *index-addr
 118 }
 119 
 120 fn trace-text self: (addr trace), label: (addr array byte), s: (addr array byte) {
 121   compare self, 0
 122   break-if-=
 123   var data-storage: (stream byte 0x100)
 124   var data/eax: (addr stream byte) <- address data-storage
 125   write data, s
 126   trace self, label, data
 127 }
 128 
 129 fn error self: (addr trace), message: (addr array byte) {
 130   trace-text self, "error", message
 131 }
 132 
 133 fn initialize-trace-line depth: int, label: (addr array byte), data: (addr stream byte), _out: (addr trace-line) {
 134   var out/edi: (addr trace-line) <- copy _out
 135   # depth
 136   var src/eax: int <- copy depth
 137   var dest/ecx: (addr int) <- get out, depth
 138   copy-to *dest, src
 139   # label
 140   var dest/eax: (addr handle array byte) <- get out, label
 141   copy-array-object label, dest
 142   # data
 143   var dest/eax: (addr handle array byte) <- get out, data
 144   stream-to-array data, dest
 145 }
 146 
 147 fn trace-lower _self: (addr trace) {
 148   var self/esi: (addr trace) <- copy _self
 149   compare self, 0
 150   break-if-=
 151   var depth/eax: (addr int) <- get self, curr-depth
 152   increment *depth
 153 }
 154 
 155 fn trace-higher _self: (addr trace) {
 156   var self/esi: (addr trace) <- copy _self
 157   compare self, 0
 158   break-if-=
 159   var depth/eax: (addr int) <- get self, curr-depth
 160   decrement *depth
 161 }
 162 
 163 ## checking traces
 164 
 165 fn check-trace-scans-to self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
 166   var tmp/eax: boolean <- trace-scans-to? self, label, data
 167   check tmp, message
 168 }
 169 
 170 fn trace-scans-to? _self: (addr trace), label: (addr array byte), data: (addr array byte) -> _/eax: boolean {
 171   var self/esi: (addr trace) <- copy _self
 172   var start/eax: (addr int) <- get self, first-full
 173   var result/eax: boolean <- trace-contains? self, label, data, *start
 174   return result
 175 }
 176 
 177 fn test-trace-scans-to {
 178   var t-storage: trace
 179   var t/esi: (addr trace) <- address t-storage
 180   initialize-trace t, 0x10, 0/visible  # we don't use trace UI
 181   #
 182   trace-text t, "label", "line 1"
 183   trace-text t, "label", "line 2"
 184   check-trace-scans-to t, "label", "line 1", "F - test-trace-scans-to/0"
 185   check-trace-scans-to t, "label", "line 2", "F - test-trace-scans-to/1"
 186   var tmp/eax: boolean <- trace-scans-to? t, "label", "line 1"
 187   check-not tmp, "F - test-trace-scans-to: fail on previously encountered lines"
 188   var tmp/eax: boolean <- trace-scans-to? t, "label", "line 3"
 189   check-not tmp, "F - test-trace-scans-to: fail on missing"
 190 }
 191 
 192 # scan trace from start
 193 # resets previous scans
 194 fn check-trace-contains self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
 195   var tmp/eax: boolean <- trace-contains? self, label, data, 0
 196   check tmp, message
 197 }
 198 
 199 fn test-trace-contains {
 200   var t-storage: trace
 201   var t/esi: (addr trace) <- address t-storage
 202   initialize-trace t, 0x10, 0/visible  # we don't use trace UI
 203   #
 204   trace-text t, "label", "line 1"
 205   trace-text t, "label", "line 2"
 206   check-trace-contains t, "label", "line 1", "F - test-trace-contains/0"
 207   check-trace-contains t, "label", "line 2", "F - test-trace-contains/1"
 208   check-trace-contains t, "label", "line 1", "F - test-trace-contains: find previously encountered lines"
 209   var tmp/eax: boolean <- trace-contains? t, "label", "line 3", 0/start
 210   check-not tmp, "F - test-trace-contains: fail on missing"
 211 }
 212 
 213 # this is super-inefficient, string comparing every trace line
 214 # against every visible line on every render
 215 fn trace-contains? _self: (addr trace), label: (addr array byte), data: (addr array byte), start: int -> _/eax: boolean {
 216   var self/esi: (addr trace) <- copy _self
 217   var candidates-ah/eax: (addr handle array trace-line) <- get self, data
 218   var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
 219   var i/ecx: int <- copy start
 220   var max/edx: (addr int) <- get self, first-free
 221   {
 222     compare i, *max
 223     break-if->=
 224     {
 225       var read-until-index/eax: (addr int) <- get self, first-full
 226       copy-to *read-until-index, i
 227     }
 228     {
 229       var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
 230       var curr/ecx: (addr trace-line) <- index candidates, curr-offset
 231       # if curr->label does not match, return false
 232       var curr-label-ah/eax: (addr handle array byte) <- get curr, label
 233       var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
 234       var match?/eax: boolean <- string-equal? curr-label, label
 235       compare match?, 0/false
 236       break-if-=
 237       # if curr->data does not match, return false
 238       var curr-data-ah/eax: (addr handle array byte) <- get curr, data
 239       var curr-data/eax: (addr array byte) <- lookup *curr-data-ah
 240       var match?/eax: boolean <- string-equal? curr-data, data
 241       compare match?, 0/false
 242       break-if-=
 243       return 1/true
 244     }
 245     i <- increment
 246     loop
 247   }
 248   return 0/false
 249 }
 250 
 251 fn trace-lines-equal? _a: (addr trace-line), _b: (addr trace-line) -> _/eax: boolean {
 252   var a/esi: (addr trace-line) <- copy _a
 253   var b/edi: (addr trace-line) <- copy _b
 254   var a-depth/ecx: (addr int) <- get a, depth
 255   var b-depth/edx: (addr int) <- get b, depth
 256   var benchmark/eax: int <- copy *b-depth
 257   compare *a-depth, benchmark
 258   {
 259     break-if-=
 260     return 0/false
 261   }
 262   var a-label-ah/eax: (addr handle array byte) <- get a, label
 263   var _a-label/eax: (addr array byte) <- lookup *a-label-ah
 264   var a-label/ecx: (addr array byte) <- copy _a-label
 265   var b-label-ah/ebx: (addr handle array byte) <- get b, label
 266   var b-label/eax: (addr array byte) <- lookup *b-label-ah
 267   var label-match?/eax: boolean <- string-equal? a-label, b-label
 268   {
 269     compare label-match?, 0/false
 270     break-if-!=
 271     return 0/false
 272   }
 273   var a-data-ah/eax: (addr handle array byte) <- get a, data
 274   var _a-data/eax: (addr array byte) <- lookup *a-data-ah
 275   var a-data/ecx: (addr array byte) <- copy _a-data
 276   var b-data-ah/ebx: (addr handle array byte) <- get b, data
 277   var b-data/eax: (addr array byte) <- lookup *b-data-ah
 278   var data-match?/eax: boolean <- string-equal? a-data, b-data
 279   return data-match?
 280 }
 281 
 282 fn dump-trace _self: (addr trace) {
 283   var already-hiding-lines?: boolean
 284   var y/ecx: int <- copy 0
 285   var self/esi: (addr trace) <- copy _self
 286   compare self, 0
 287   {
 288     break-if-!=
 289     return
 290   }
 291   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 292   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
 293   var trace/edi: (addr array trace-line) <- copy _trace
 294   var i/edx: int <- copy 0
 295   var max-addr/ebx: (addr int) <- get self, first-free
 296   var max/ebx: int <- copy *max-addr
 297   $dump-trace:loop: {
 298     compare i, max
 299     break-if->=
 300     $dump-trace:iter: {
 301       var offset/ebx: (offset trace-line) <- compute-offset trace, i
 302       var curr/ebx: (addr trace-line) <- index trace, offset
 303       y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg
 304     }
 305     i <- increment
 306     loop
 307   }
 308 }
 309 
 310 fn dump-trace-with-label _self: (addr trace), label: (addr array byte) {
 311   var already-hiding-lines?: boolean
 312   var y/ecx: int <- copy 0
 313   var self/esi: (addr trace) <- copy _self
 314   compare self, 0
 315   {
 316     break-if-!=
 317     return
 318   }
 319   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 320   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
 321   var trace/edi: (addr array trace-line) <- copy _trace
 322   var i/edx: int <- copy 0
 323   var max-addr/ebx: (addr int) <- get self, first-free
 324   var max/ebx: int <- copy *max-addr
 325   $dump-trace:loop: {
 326     compare i, max
 327     break-if->=
 328     $dump-trace:iter: {
 329       var offset/ebx: (offset trace-line) <- compute-offset trace, i
 330       var curr/ebx: (addr trace-line) <- index trace, offset
 331       var curr-label-ah/eax: (addr handle array byte) <- get curr, label
 332       var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
 333       var show?/eax: boolean <- string-equal? curr-label, label
 334       compare show?, 0/false
 335       break-if-=
 336       y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg
 337     }
 338     i <- increment
 339     loop
 340   }
 341 }
 342 
 343 ## UI stuff
 344 
 345 fn mark-lines-dirty _self: (addr trace) {
 346   var self/eax: (addr trace) <- copy _self
 347   var dest/edx: (addr boolean) <- get self, recompute-visible?
 348   copy-to *dest, 1/true
 349 }
 350 
 351 fn mark-lines-clean _self: (addr trace) {
 352   var self/eax: (addr trace) <- copy _self
 353   var dest/edx: (addr boolean) <- get self, recompute-visible?
 354   copy-to *dest, 0/false
 355 }
 356 
 357 fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean -> _/ecx: int {
 358   var already-hiding-lines?: boolean
 359   var y/ecx: int <- copy ymin
 360   var self/esi: (addr trace) <- copy _self
 361   compare self, 0
 362   {
 363     break-if-!=
 364     return ymin
 365   }
 366   clamp-cursor-to-top self, y
 367   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 368   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
 369   var trace/edi: (addr array trace-line) <- copy _trace
 370   var i/edx: int <- copy 0
 371   var max-addr/ebx: (addr int) <- get self, first-free
 372   var max/ebx: int <- copy *max-addr
 373   $render-trace:loop: {
 374     compare i, max
 375     break-if->=
 376     $render-trace:iter: {
 377       var offset/ebx: (offset trace-line) <- compute-offset trace, i
 378       var curr/ebx: (addr trace-line) <- index trace, offset
 379       var curr-label-ah/eax: (addr handle array byte) <- get curr, label
 380       var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
 381       var bg/edi: int <- copy 0xc5/bg=blue-bg
 382       compare show-cursor?, 0/false
 383       {
 384         break-if-=
 385         var cursor-y/eax: (addr int) <- get self, cursor-y
 386         compare *cursor-y, y
 387         break-if-!=
 388         bg <- copy 7/cursor-line-bg
 389         var cursor-line-index/eax: (addr int) <- get self, cursor-line-index
 390         copy-to *cursor-line-index, i
 391       }
 392       # always display errors
 393       var error?/eax: boolean <- string-equal? curr-label, "error"
 394       {
 395         compare error?, 0/false
 396         break-if-=
 397         y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0xc/fg=trace-error, bg
 398         copy-to already-hiding-lines?, 0/false
 399         break $render-trace:iter
 400       }
 401       # display expanded lines
 402       var display?/eax: boolean <- should-render? self, curr
 403       {
 404         compare display?, 0/false
 405         break-if-=
 406         y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0x38/fg=trace, bg
 407         copy-to already-hiding-lines?, 0/false
 408         break $render-trace:iter
 409       }
 410       # ignore the rest
 411       compare already-hiding-lines?, 0/false
 412       {
 413         break-if-!=
 414         var x/eax: int <- copy xmin
 415         x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, 9/fg=trace, bg
 416         y <- increment
 417         copy-to already-hiding-lines?, 1/true
 418       }
 419     }
 420     i <- increment
 421     loop
 422   }
 423   # prevent cursor from going too far down
 424   clamp-cursor-to-bottom self, y, screen, xmin, ymin, xmax, ymax
 425   mark-lines-clean self
 426   return y
 427 }
 428 
 429 fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int, ymin: int, xmax: int, ymax: int, fg: int, bg: int -> _/ecx: int {
 430   var self/esi: (addr trace-line) <- copy _self
 431   var xsave/edx: int <- copy xmin
 432   var y/ecx: int <- copy ymin
 433   var label-ah/eax: (addr handle array byte) <- get self, label
 434   var _label/eax: (addr array byte) <- lookup *label-ah
 435   var label/ebx: (addr array byte) <- copy _label
 436   var error?/eax: boolean <- string-equal? label, "error"
 437   compare error?, 0/false
 438   {
 439     break-if-!=
 440     var x/eax: int <- copy xsave
 441     {
 442       var depth/edx: (addr int) <- get self, depth
 443       x, y <- draw-int32-decimal-wrapping-right-then-down screen, *depth, xmin, ymin, xmax, ymax, x, y, fg, bg
 444       x, y <- draw-text-wrapping-right-then-down screen, " ", xmin, ymin, xmax, ymax, x, y, fg, bg
 445       # don't show label in UI; it's just for tests
 446     }
 447     xsave <- copy x
 448   }
 449   var data-ah/eax: (addr handle array byte) <- get self, data
 450   var _data/eax: (addr array byte) <- lookup *data-ah
 451   var data/ebx: (addr array byte) <- copy _data
 452   var x/eax: int <- copy xsave
 453   x, y <- draw-text-wrapping-right-then-down screen, data, xmin, ymin, xmax, ymax, x, y, fg, bg
 454   y <- increment
 455   return y
 456 }
 457 
 458 # this is super-inefficient, string comparing every trace line
 459 # against every visible line on every render
 460 fn should-render? _self: (addr trace), _line: (addr trace-line) -> _/eax: boolean {
 461   var self/esi: (addr trace) <- copy _self
 462   # if visible? is already cached, just return it
 463   var dest/edx: (addr boolean) <- get self, recompute-visible?
 464   compare *dest, 0/false
 465   {
 466     break-if-!=
 467     var line/eax: (addr trace-line) <- copy _line
 468     var result/eax: (addr boolean) <- get line, visible?
 469     return *result
 470   }
 471   # recompute
 472   var candidates-ah/eax: (addr handle array trace-line) <- get self, visible
 473   var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
 474   var i/ecx: int <- copy 0
 475   var len/edx: int <- length candidates
 476   {
 477     compare i, len
 478     break-if->=
 479     {
 480       var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
 481       var curr/ecx: (addr trace-line) <- index candidates, curr-offset
 482       var match?/eax: boolean <- trace-lines-equal? curr, _line
 483       compare match?, 0/false
 484       break-if-=
 485       var line/eax: (addr trace-line) <- copy _line
 486       var dest/eax: (addr boolean) <- get line, visible?
 487       copy-to *dest, 1/true
 488       return 1/true
 489     }
 490     i <- increment
 491     loop
 492   }
 493   var line/eax: (addr trace-line) <- copy _line
 494   var dest/eax: (addr boolean) <- get line, visible?
 495   copy-to *dest, 0/false
 496   return 0/false
 497 }
 498 
 499 fn clamp-cursor-to-top _self: (addr trace), _y: int {
 500   var y/ecx: int <- copy _y
 501   var self/esi: (addr trace) <- copy _self
 502   var cursor-y/eax: (addr int) <- get self, cursor-y
 503   compare *cursor-y, y
 504   break-if->=
 505   copy-to *cursor-y, y
 506 }
 507 
 508 # extremely hacky; consider deleting test-render-trace-empty-3 when you clean this up
 509 fn clamp-cursor-to-bottom _self: (addr trace), _y: int, screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int {
 510   var y/ebx: int <- copy _y
 511   compare y, ymin
 512   {
 513     break-if->
 514     return
 515   }
 516   y <- decrement
 517   var self/esi: (addr trace) <- copy _self
 518   var cursor-y/eax: (addr int) <- get self, cursor-y
 519   compare *cursor-y, y
 520   break-if-<=
 521   copy-to *cursor-y, y
 522   # redraw cursor-line
 523   # TODO: ugly duplication
 524   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 525   var trace/eax: (addr array trace-line) <- lookup *trace-ah
 526   var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
 527   var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
 528   var first-free/edx: (addr int) <- get self, first-free
 529   compare cursor-line-index, *first-free
 530   {
 531     break-if-<
 532     return
 533   }
 534   var cursor-offset/ecx: (offset trace-line) <- compute-offset trace, cursor-line-index
 535   var cursor-line/ecx: (addr trace-line) <- index trace, cursor-offset
 536   var display?/eax: boolean <- should-render? self, cursor-line
 537   {
 538     compare display?, 0/false
 539     break-if-=
 540     var dummy/ecx: int <- render-trace-line screen, cursor-line, xmin, y, xmax, ymax, 0x38/fg=trace, 7/cursor-line-bg
 541     return
 542   }
 543   var dummy1/eax: int <- copy 0
 544   var dummy2/ecx: int <- copy 0
 545   dummy1, dummy2 <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xmin, y, 9/fg=trace, 7/cursor-line-bg
 546 }
 547 
 548 fn test-render-trace-empty {
 549   var t-storage: trace
 550   var t/esi: (addr trace) <- address t-storage
 551   initialize-trace t, 0x10, 0x10
 552   # setup: screen
 553   var screen-on-stack: screen
 554   var screen/edi: (addr screen) <- address screen-on-stack
 555   initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
 556   #
 557   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor
 558   #
 559   check-ints-equal y, 0, "F - test-render-trace-empty/cursor"
 560   check-screen-row screen,                                  0/y, "    ", "F - test-render-trace-empty"
 561   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "    ", "F - test-render-trace-empty/bg"
 562 }
 563 
 564 fn test-render-trace-empty-2 {
 565   var t-storage: trace
 566   var t/esi: (addr trace) <- address t-storage
 567   initialize-trace t, 0x10, 0x10
 568   # setup: screen
 569   var screen-on-stack: screen
 570   var screen/edi: (addr screen) <- address screen-on-stack
 571   initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
 572   #
 573   var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 0/no-cursor  # cursor below top row
 574   #
 575   check-ints-equal y, 2, "F - test-render-trace-empty-2/cursor"
 576   check-screen-row screen,                                  2/y, "    ", "F - test-render-trace-empty-2"
 577   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "    ", "F - test-render-trace-empty-2/bg"
 578 }
 579 
 580 fn test-render-trace-empty-3 {
 581   var t-storage: trace
 582   var t/esi: (addr trace) <- address t-storage
 583   initialize-trace t, 0x10, 0x10
 584   # setup: screen
 585   var screen-on-stack: screen
 586   var screen/edi: (addr screen) <- address screen-on-stack
 587   initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
 588   #
 589   var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 1/show-cursor  # try show cursor
 590   # still no cursor to show
 591   check-ints-equal y, 2, "F - test-render-trace-empty-3/cursor"
 592   check-screen-row screen,                                  1/y, "    ", "F - test-render-trace-empty-3/line-above-cursor"
 593   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "    ", "F - test-render-trace-empty-3/bg-for-line-above-cursor"
 594   check-screen-row screen,                                  2/y, "    ", "F - test-render-trace-empty-3"
 595   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "    ", "F - test-render-trace-empty-3/bg"
 596 }
 597 
 598 fn test-render-trace-collapsed-by-default {
 599   var t-storage: trace
 600   var t/esi: (addr trace) <- address t-storage
 601   initialize-trace t, 0x10, 0x10
 602   trace-text t, "l", "data"
 603   # setup: screen
 604   var screen-on-stack: screen
 605   var screen/edi: (addr screen) <- address screen-on-stack
 606   initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
 607   #
 608   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor
 609   #
 610   check-ints-equal y, 1, "F - test-render-trace-collapsed-by-default/cursor"
 611   check-screen-row screen, 0/y, "... ", "F - test-render-trace-collapsed-by-default"
 612 }
 613 
 614 fn test-render-trace-error {
 615   var t-storage: trace
 616   var t/esi: (addr trace) <- address t-storage
 617   initialize-trace t, 0x10, 0x10
 618   error t, "error"
 619   # setup: screen
 620   var screen-on-stack: screen
 621   var screen/edi: (addr screen) <- address screen-on-stack
 622   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 623   #
 624   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
 625   #
 626   check-ints-equal y, 1, "F - test-render-trace-error/cursor"
 627   check-screen-row screen, 0/y, "error", "F - test-render-trace-error"
 628 }
 629 
 630 fn test-render-trace-error-at-start {
 631   var t-storage: trace
 632   var t/esi: (addr trace) <- address t-storage
 633   initialize-trace t, 0x10, 0x10
 634   #
 635   error t, "error"
 636   trace-text t, "l", "data"
 637   # setup: screen
 638   var screen-on-stack: screen
 639   var screen/edi: (addr screen) <- address screen-on-stack
 640   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 641   #
 642   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
 643   #
 644   check-ints-equal y, 2, "F - test-render-trace-error-at-start/cursor"
 645   check-screen-row screen, 0/y, "error", "F - test-render-trace-error-at-start/0"
 646   check-screen-row screen, 1/y, "...  ", "F - test-render-trace-error-at-start/1"
 647 }
 648 
 649 fn test-render-trace-error-at-end {
 650   var t-storage: trace
 651   var t/esi: (addr trace) <- address t-storage
 652   initialize-trace t, 0x10, 0x10
 653   #
 654   trace-text t, "l", "data"
 655   error t, "error"
 656   # setup: screen
 657   var screen-on-stack: screen
 658   var screen/edi: (addr screen) <- address screen-on-stack
 659   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 660   #
 661   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
 662   #
 663   check-ints-equal y, 2, "F - test-render-trace-error-at-end/cursor"
 664   check-screen-row screen, 0/y, "...  ", "F - test-render-trace-error-at-end/0"
 665   check-screen-row screen, 1/y, "error", "F - test-render-trace-error-at-end/1"
 666 }
 667 
 668 fn test-render-trace-error-in-the-middle {
 669   var t-storage: trace
 670   var t/esi: (addr trace) <- address t-storage
 671   initialize-trace t, 0x10, 0x10
 672   #
 673   trace-text t, "l", "line 1"
 674   error t, "error"
 675   trace-text t, "l", "line 3"
 676   # setup: screen
 677   var screen-on-stack: screen
 678   var screen/edi: (addr screen) <- address screen-on-stack
 679   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 680   #
 681   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
 682   #
 683   check-ints-equal y, 3, "F - test-render-trace-error-in-the-middle/cursor"
 684   check-screen-row screen, 0/y, "...  ", "F - test-render-trace-error-in-the-middle/0"
 685   check-screen-row screen, 1/y, "error", "F - test-render-trace-error-in-the-middle/1"
 686   check-screen-row screen, 2/y, "...  ", "F - test-render-trace-error-in-the-middle/2"
 687 }
 688 
 689 fn test-render-trace-cursor-in-single-line {
 690   var t-storage: trace
 691   var t/esi: (addr trace) <- address t-storage
 692   initialize-trace t, 0x10, 0x10
 693   #
 694   trace-text t, "l", "line 1"
 695   error t, "error"
 696   trace-text t, "l", "line 3"
 697   # setup: screen
 698   var screen-on-stack: screen
 699   var screen/edi: (addr screen) <- address screen-on-stack
 700   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 701   #
 702   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
 703   #
 704   check-screen-row screen,                                  0/y, "...   ", "F - test-render-trace-cursor-in-single-line/0"
 705   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||   ", "F - test-render-trace-cursor-in-single-line/0/cursor"
 706   check-screen-row screen,                                  1/y, "error ", "F - test-render-trace-cursor-in-single-line/1"
 707   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-render-trace-cursor-in-single-line/1/cursor"
 708   check-screen-row screen,                                  2/y, "...   ", "F - test-render-trace-cursor-in-single-line/2"
 709   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-render-trace-cursor-in-single-line/2/cursor"
 710 }
 711 
 712 fn render-trace-menu screen: (addr screen) {
 713   var width/eax: int <- copy 0
 714   var height/ecx: int <- copy 0
 715   width, height <- screen-size screen
 716   var y/ecx: int <- copy height
 717   y <- decrement
 718   set-cursor-position screen, 0/x, y
 719   draw-text-rightward-from-cursor screen, " ctrl-r ", width, 0/fg, 0x5c/bg=black
 720   draw-text-rightward-from-cursor screen, " run main  ", width, 7/fg, 0xc5/bg=blue-bg
 721   draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 0x5c/bg=black
 722   draw-text-rightward-from-cursor screen, " run sandbox  ", width, 7/fg, 0xc5/bg=blue-bg
 723   draw-text-rightward-from-cursor screen, " ctrl-m ", width, 0/fg, 3/bg=keyboard
 724   draw-text-rightward-from-cursor screen, " to keyboard  ", width, 7/fg, 0xc5/bg=blue-bg
 725   draw-text-rightward-from-cursor screen, " j ", width, 0/fg, 0x5c/bg=black
 726   draw-text-rightward-from-cursor screen, " down  ", width, 7/fg, 0xc5/bg=blue-bg
 727   draw-text-rightward-from-cursor screen, " k ", width, 0/fg, 0x5c/bg=black
 728   draw-text-rightward-from-cursor screen, " up  ", width, 7/fg, 0xc5/bg=blue-bg
 729   draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 0x5c/bg=black
 730   draw-text-rightward-from-cursor screen, " expand  ", width, 7/fg, 0xc5/bg=blue-bg
 731   draw-text-rightward-from-cursor screen, " backspace ", width, 0/fg, 0x5c/bg=black
 732   draw-text-rightward-from-cursor screen, " collapse  ", width, 7/fg, 0xc5/bg=blue-bg
 733 }
 734 
 735 fn edit-trace _self: (addr trace), key: grapheme {
 736   var self/esi: (addr trace) <- copy _self
 737   # cursor down
 738   {
 739     compare key, 0x6a/j
 740     break-if-!=
 741     var cursor-y/eax: (addr int) <- get self, cursor-y
 742     increment *cursor-y
 743     return
 744   }
 745   {
 746     compare key, 0x81/down-arrow
 747     break-if-!=
 748     var cursor-y/eax: (addr int) <- get self, cursor-y
 749     increment *cursor-y
 750     return
 751   }
 752   # cursor up
 753   {
 754     compare key, 0x6b/k
 755     break-if-!=
 756     var cursor-y/eax: (addr int) <- get self, cursor-y
 757     decrement *cursor-y
 758     return
 759   }
 760   {
 761     compare key, 0x82/up-arrow
 762     break-if-!=
 763     var cursor-y/eax: (addr int) <- get self, cursor-y
 764     decrement *cursor-y
 765     return
 766   }
 767   # enter = expand
 768   {
 769     compare key, 0xa/newline
 770     break-if-!=
 771     expand self
 772     return
 773   }
 774   # backspace = collapse
 775   {
 776     compare key, 8/backspace
 777     break-if-!=
 778     collapse self
 779     return
 780   }
 781 }
 782 
 783 fn expand _self: (addr trace) {
 784   var self/esi: (addr trace) <- copy _self
 785   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 786   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
 787   var trace/edi: (addr array trace-line) <- copy _trace
 788   var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
 789   var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
 790   var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
 791   var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
 792   var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
 793   var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
 794   var target-depth/ebx: int <- copy *cursor-line-depth
 795   # if cursor-line is already visible, increment target-depth
 796   compare *cursor-line-visible?, 0/false
 797   {
 798     break-if-=
 799     target-depth <- increment
 800   }
 801   # reveal the run of lines starting at cursor-line-index with depth target-depth
 802   var i/ecx: int <- copy cursor-line-index
 803   var max/edx: (addr int) <- get self, first-free
 804   {
 805     compare i, *max
 806     break-if->=
 807     var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
 808     var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
 809     var curr-line-depth/eax: (addr int) <- get curr-line, depth
 810     compare *curr-line-depth, target-depth
 811     break-if-<
 812     {
 813       break-if-!=
 814       var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
 815       copy-to *curr-line-visible?, 1/true
 816       reveal-trace-line self, curr-line
 817     }
 818     i <- increment
 819     loop
 820   }
 821 }
 822 
 823 fn collapse _self: (addr trace) {
 824   var self/esi: (addr trace) <- copy _self
 825   var trace-ah/eax: (addr handle array trace-line) <- get self, data
 826   var _trace/eax: (addr array trace-line) <- lookup *trace-ah
 827   var trace/edi: (addr array trace-line) <- copy _trace
 828   var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
 829   var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
 830   var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
 831   var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
 832   var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
 833   # if cursor-line is not visible, do nothing
 834   compare *cursor-line-visible?, 0/false
 835   {
 836     break-if-!=
 837     return
 838   }
 839   # hide all lines between previous and next line with a lower depth
 840   var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
 841   var cursor-y/edx: (addr int) <- get self, cursor-y
 842   var target-depth/ebx: int <- copy *cursor-line-depth
 843   var i/ecx: int <- copy cursor-line-index
 844   $collapse:loop1: {
 845     compare i, 0
 846     break-if-<
 847     var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
 848     var curr-line/eax: (addr trace-line) <- index trace, curr-line-offset
 849     {
 850       var curr-line-depth/eax: (addr int) <- get curr-line, depth
 851       compare *curr-line-depth, target-depth
 852       break-if-< $collapse:loop1
 853     }
 854     # if cursor-line is visible, decrement cursor-y
 855     {
 856       var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
 857       compare *curr-line-visible?, 0/false
 858       break-if-=
 859       decrement *cursor-y
 860     }
 861     i <- decrement
 862     loop
 863   }
 864   i <- increment
 865   var max/edx: (addr int) <- get self, first-free
 866   $collapse:loop2: {
 867     compare i, *max
 868     break-if->=
 869     var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
 870     var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
 871     var curr-line-depth/eax: (addr int) <- get curr-line, depth
 872     compare *curr-line-depth, target-depth
 873     break-if-<
 874     {
 875       hide-trace-line self, curr-line
 876       var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
 877       copy-to *curr-line-visible?, 0/false
 878     }
 879     i <- increment
 880     loop
 881   }
 882 }
 883 
 884 # the 'visible' array is not required to be in order
 885 # elements can also be deleted out of order
 886 # so it can have holes
 887 # however, lines in it always have visible? set
 888 # we'll use visible? being unset as a sign of emptiness
 889 fn reveal-trace-line _self: (addr trace), line: (addr trace-line) {
 890   var self/esi: (addr trace) <- copy _self
 891   var visible-ah/eax: (addr handle array trace-line) <- get self, visible
 892   var visible/eax: (addr array trace-line) <- lookup *visible-ah
 893   var i/ecx: int <- copy 0
 894   var len/edx: int <- length visible
 895   {
 896     compare i, len
 897     break-if->=
 898     var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
 899     var curr/edx: (addr trace-line) <- index visible, curr-offset
 900     var curr-visible?/eax: (addr boolean) <- get curr, visible?
 901     compare *curr-visible?, 0/false
 902     {
 903       break-if-!=
 904       # empty slot found
 905       copy-object line, curr
 906       return
 907     }
 908     i <- increment
 909     loop
 910   }
 911   abort "too many visible lines; increase size of array trace.visible"
 912 }
 913 
 914 fn hide-trace-line _self: (addr trace), line: (addr trace-line) {
 915   var self/esi: (addr trace) <- copy _self
 916   var visible-ah/eax: (addr handle array trace-line) <- get self, visible
 917   var visible/eax: (addr array trace-line) <- lookup *visible-ah
 918   var i/ecx: int <- copy 0
 919   var len/edx: int <- length visible
 920   {
 921     compare i, len
 922     break-if->=
 923     var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
 924     var curr/edx: (addr trace-line) <- index visible, curr-offset
 925     var found?/eax: boolean <- trace-lines-equal? curr, line
 926     compare found?, 0/false
 927     {
 928       break-if-=
 929       clear-object curr
 930     }
 931     i <- increment
 932     loop
 933   }
 934 }
 935 
 936 fn test-cursor-down-and-up-within-trace {
 937   var t-storage: trace
 938   var t/esi: (addr trace) <- address t-storage
 939   initialize-trace t, 0x10, 0x10
 940   #
 941   trace-text t, "l", "line 1"
 942   error t, "error"
 943   trace-text t, "l", "line 3"
 944   # setup: screen
 945   var screen-on-stack: screen
 946   var screen/edi: (addr screen) <- address screen-on-stack
 947   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 948   #
 949   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
 950   #
 951   check-screen-row screen,                                  0/y, "...   ", "F - test-cursor-down-and-up-within-trace/pre-0"
 952   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||   ", "F - test-cursor-down-and-up-within-trace/pre-0/cursor"
 953   check-screen-row screen,                                  1/y, "error ", "F - test-cursor-down-and-up-within-trace/pre-1"
 954   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-cursor-down-and-up-within-trace/pre-1/cursor"
 955   check-screen-row screen,                                  2/y, "...   ", "F - test-cursor-down-and-up-within-trace/pre-2"
 956   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-cursor-down-and-up-within-trace/pre-2/cursor"
 957   # cursor down
 958   edit-trace t, 0x6a/j
 959   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
 960   #
 961   check-screen-row screen,                                  0/y, "...   ", "F - test-cursor-down-and-up-within-trace/down-0"
 962   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "      ", "F - test-cursor-down-and-up-within-trace/down-0/cursor"
 963   check-screen-row screen,                                  1/y, "error ", "F - test-cursor-down-and-up-within-trace/down-1"
 964   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||||| ", "F - test-cursor-down-and-up-within-trace/down-1/cursor"
 965   check-screen-row screen,                                  2/y, "...   ", "F - test-cursor-down-and-up-within-trace/down-2"
 966   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-cursor-down-and-up-within-trace/down-2/cursor"
 967   # cursor up
 968   edit-trace t, 0x6b/k
 969   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
 970   #
 971   check-screen-row screen,                                  0/y, "...   ", "F - test-cursor-down-and-up-within-trace/up-0"
 972   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||   ", "F - test-cursor-down-and-up-within-trace/up-0/cursor"
 973   check-screen-row screen,                                  1/y, "error ", "F - test-cursor-down-and-up-within-trace/up-1"
 974   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-cursor-down-and-up-within-trace/up-1/cursor"
 975   check-screen-row screen,                                  2/y, "...   ", "F - test-cursor-down-and-up-within-trace/up-2"
 976   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-cursor-down-and-up-within-trace/up-2/cursor"
 977 }
 978 
 979 fn test-cursor-down-past-bottom-of-trace {
 980   var t-storage: trace
 981   var t/esi: (addr trace) <- address t-storage
 982   initialize-trace t, 0x10, 0x10
 983   #
 984   trace-text t, "l", "line 1"
 985   error t, "error"
 986   trace-text t, "l", "line 3"
 987   # setup: screen
 988   var screen-on-stack: screen
 989   var screen/edi: (addr screen) <- address screen-on-stack
 990   initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
 991   #
 992   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
 993   #
 994   check-screen-row screen,                                  0/y, "...   ", "F - test-cursor-down-past-bottom-of-trace/pre-0"
 995   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||   ", "F - test-cursor-down-past-bottom-of-trace/pre-0/cursor"
 996   check-screen-row screen,                                  1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/pre-1"
 997   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-cursor-down-past-bottom-of-trace/pre-1/cursor"
 998   check-screen-row screen,                                  2/y, "...   ", "F - test-cursor-down-past-bottom-of-trace/pre-2"
 999   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-cursor-down-past-bottom-of-trace/pre-2/cursor"
1000   # cursor down several times
1001   edit-trace t, 0x6a/j
1002   edit-trace t, 0x6a/j
1003   edit-trace t, 0x6a/j
1004   edit-trace t, 0x6a/j
1005   edit-trace t, 0x6a/j
1006   # hack: we do need to render to make this test pass; we're mixing state management with rendering
1007   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
1008   # cursor clamps at bottom
1009   check-screen-row screen,                                  0/y, "...   ", "F - test-cursor-down-past-bottom-of-trace/down-0"
1010   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "      ", "F - test-cursor-down-past-bottom-of-trace/down-0/cursor"
1011   check-screen-row screen,                                  1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/down-1"
1012   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-cursor-down-past-bottom-of-trace/down-1/cursor"
1013   check-screen-row screen,                                  2/y, "...   ", "F - test-cursor-down-past-bottom-of-trace/down-2"
1014   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||   ", "F - test-cursor-down-past-bottom-of-trace/down-2/cursor"
1015 }
1016 
1017 fn test-expand-within-trace {
1018   var t-storage: trace
1019   var t/esi: (addr trace) <- address t-storage
1020   initialize-trace t, 0x10, 0x10
1021   #
1022   trace-text t, "l", "line 1"
1023   trace-text t, "l", "line 2"
1024   # setup: screen
1025   var screen-on-stack: screen
1026   var screen/edi: (addr screen) <- address screen-on-stack
1027   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1028   #
1029   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1030   #
1031   check-screen-row screen,                                  0/y, "...      ", "F - test-expand-within-trace/pre-0"
1032   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||      ", "F - test-expand-within-trace/pre-0/cursor"
1033   check-screen-row screen,                                  1/y, "         ", "F - test-expand-within-trace/pre-1"
1034   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-expand-within-trace/pre-1/cursor"
1035   # expand
1036   edit-trace t, 0xa/enter
1037   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1038   #
1039   check-screen-row screen,                                  0/y, "0 line 1 ", "F - test-expand-within-trace/expand-0"
1040   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-expand-within-trace/expand-0/cursor"
1041   check-screen-row screen,                                  1/y, "0 line 2 ", "F - test-expand-within-trace/expand-1"
1042   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-expand-within-trace/expand-1/cursor"
1043   check-screen-row screen,                                  2/y, "         ", "F - test-expand-within-trace/expand-2"
1044   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "         ", "F - test-expand-within-trace/expand-2/cursor"
1045 }
1046 
1047 fn test-trace-expand-skips-lower-depth {
1048   var t-storage: trace
1049   var t/esi: (addr trace) <- address t-storage
1050   initialize-trace t, 0x10, 0x10
1051   #
1052   trace-text t, "l", "line 1"
1053   trace-lower t
1054   trace-text t, "l", "line 2"
1055   # setup: screen
1056   var screen-on-stack: screen
1057   var screen/edi: (addr screen) <- address screen-on-stack
1058   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1059   #
1060   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1061   #
1062   check-screen-row screen,                                  0/y, "...      ", "F - test-trace-expand-skips-lower-depth/pre-0"
1063   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||      ", "F - test-trace-expand-skips-lower-depth/pre-0/cursor"
1064   check-screen-row screen,                                  1/y, "         ", "F - test-trace-expand-skips-lower-depth/pre-1"
1065   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-trace-expand-skips-lower-depth/pre-1/cursor"
1066   # expand
1067   edit-trace t, 0xa/enter
1068   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1069   #
1070   check-screen-row screen,                                  0/y, "0 line 1 ", "F - test-trace-expand-skips-lower-depth/expand-0"
1071   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-skips-lower-depth/expand-0/cursor"
1072   check-screen-row screen,                                  1/y, "...      ", "F - test-trace-expand-skips-lower-depth/expand-1"
1073   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-trace-expand-skips-lower-depth/expand-1/cursor"
1074   check-screen-row screen,                                  2/y, "         ", "F - test-trace-expand-skips-lower-depth/expand-2"
1075   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "         ", "F - test-trace-expand-skips-lower-depth/expand-2/cursor"
1076 }
1077 
1078 fn test-trace-expand-continues-past-lower-depth {
1079   var t-storage: trace
1080   var t/esi: (addr trace) <- address t-storage
1081   initialize-trace t, 0x10, 0x10
1082   #
1083   trace-text t, "l", "line 1"
1084   trace-lower t
1085   trace-text t, "l", "line 1.1"
1086   trace-higher t
1087   trace-text t, "l", "line 2"
1088   # setup: screen
1089   var screen-on-stack: screen
1090   var screen/edi: (addr screen) <- address screen-on-stack
1091   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1092   #
1093   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1094   #
1095   check-screen-row screen,                                  0/y, "...      ", "F - test-trace-expand-continues-past-lower-depth/pre-0"
1096   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||      ", "F - test-trace-expand-continues-past-lower-depth/pre-0/cursor"
1097   check-screen-row screen,                                  1/y, "         ", "F - test-trace-expand-continues-past-lower-depth/pre-1"
1098   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-trace-expand-continues-past-lower-depth/pre-1/cursor"
1099   # expand
1100   edit-trace t, 0xa/enter
1101   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1102   #
1103   check-screen-row screen,                                  0/y, "0 line 1 ", "F - test-trace-expand-continues-past-lower-depth/expand-0"
1104   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-continues-past-lower-depth/expand-0/cursor"
1105   # TODO: might be too wasteful to show every place where lines are hidden
1106   check-screen-row screen,                                  1/y, "...      ", "F - test-trace-expand-continues-past-lower-depth/expand-1"
1107   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "         ", "F - test-trace-expand-continues-past-lower-depth/expand-1/cursor"
1108   check-screen-row screen,                                  2/y, "0 line 2 ", "F - test-trace-expand-continues-past-lower-depth/expand-2"
1109   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "         ", "F - test-trace-expand-continues-past-lower-depth/expand-2/cursor"
1110 }
1111 
1112 fn test-trace-expand-stops-at-higher-depth {
1113   var t-storage: trace
1114   var t/esi: (addr trace) <- address t-storage
1115   initialize-trace t, 0x10, 0x10
1116   #
1117   trace-text t, "l", "line 1.1"
1118   trace-lower t
1119   trace-text t, "l", "line 1.1.1"
1120   trace-higher t
1121   trace-text t, "l", "line 1.2"
1122   trace-higher t
1123   trace-text t, "l", "line 2"
1124   trace-lower t
1125   trace-text t, "l", "line 2.1"
1126   # setup: screen
1127   var screen-on-stack: screen
1128   var screen/edi: (addr screen) <- address screen-on-stack
1129   initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics
1130   #
1131   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1132   #
1133   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-expand-stops-at-higher-depth/pre-0"
1134   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-expand-stops-at-higher-depth/pre-0/cursor"
1135   check-screen-row screen,                                  1/y, "           ", "F - test-trace-expand-stops-at-higher-depth/pre-1"
1136   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-expand-stops-at-higher-depth/pre-1/cursor"
1137   # expand
1138   edit-trace t, 0xa/enter
1139   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1140   #
1141   check-screen-row screen,                                  0/y, "0 line 1.1 ", "F - test-trace-expand-stops-at-higher-depth/expand-0"
1142   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||||| ", "F - test-trace-expand-stops-at-higher-depth/expand-0/cursor"
1143   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-expand-stops-at-higher-depth/expand-1"
1144   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-expand-stops-at-higher-depth/expand-1/cursor"
1145   check-screen-row screen,                                  2/y, "0 line 1.2 ", "F - test-trace-expand-stops-at-higher-depth/expand-2"
1146   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-expand-stops-at-higher-depth/expand-2/cursor"
1147   check-screen-row screen,                                  3/y, "...        ", "F - test-trace-expand-stops-at-higher-depth/expand-3"
1148   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "           ", "F - test-trace-expand-stops-at-higher-depth/expand-3/cursor"
1149   check-screen-row screen,                                  4/y, "           ", "F - test-trace-expand-stops-at-higher-depth/expand-4"
1150   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "           ", "F - test-trace-expand-stops-at-higher-depth/expand-4/cursor"
1151 }
1152 
1153 fn test-trace-expand-twice {
1154   var t-storage: trace
1155   var t/esi: (addr trace) <- address t-storage
1156   initialize-trace t, 0x10, 0x10
1157   #
1158   trace-text t, "l", "line 1"
1159   trace-lower t
1160   trace-text t, "l", "line 1.1"
1161   trace-higher t
1162   trace-text t, "l", "line 2"
1163   # setup: screen
1164   var screen-on-stack: screen
1165   var screen/edi: (addr screen) <- address screen-on-stack
1166   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1167   #
1168   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1169   #
1170   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-expand-twice/pre-0"
1171   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-expand-twice/pre-0/cursor"
1172   check-screen-row screen,                                  1/y, "           ", "F - test-trace-expand-twice/pre-1"
1173   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-expand-twice/pre-1/cursor"
1174   # expand
1175   edit-trace t, 0xa/enter
1176   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1177   #
1178   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-expand-twice/expand-0"
1179   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-expand-twice/expand-0/cursor"
1180   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-expand-twice/expand-1"
1181   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-expand-twice/expand-1/cursor"
1182   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-expand-twice/expand-2"
1183   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-expand-twice/expand-2/cursor"
1184   # cursor down
1185   edit-trace t, 0x6a/j
1186   # hack: we need to render here to make this test pass; we're mixing state management with rendering
1187   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1188   #
1189   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-expand-twice/down-0"
1190   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-expand-twice/down-0/cursor"
1191   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-expand-twice/down-1"
1192   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||        ", "F - test-trace-expand-twice/down-1/cursor"
1193   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-expand-twice/down-2"
1194   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-expand-twice/down-2/cursor"
1195   # expand again
1196   edit-trace t, 0xa/enter
1197   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1198   #
1199   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-expand-twice/expand2-0"
1200   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-expand-twice/expand2-0/cursor"
1201   check-screen-row screen,                                  1/y, "1 line 1.1 ", "F - test-trace-expand-twice/expand2-1"
1202   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-expand-twice/expand2-1/cursor"
1203   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-expand-twice/expand2-2"
1204   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-expand-twice/expand2-2/cursor"
1205 }
1206 
1207 fn test-trace-refresh-cursor {
1208   var t-storage: trace
1209   var t/esi: (addr trace) <- address t-storage
1210   initialize-trace t, 0x10, 0x10
1211   #
1212   trace-text t, "l", "line 1"
1213   trace-text t, "l", "line 2"
1214   trace-text t, "l", "line 3"
1215   # setup: screen
1216   var screen-on-stack: screen
1217   var screen/edi: (addr screen) <- address screen-on-stack
1218   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1219   #
1220   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1221   #
1222   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-refresh-cursor/pre-0"
1223   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-refresh-cursor/pre-0/cursor"
1224   check-screen-row screen,                                  1/y, "           ", "F - test-trace-refresh-cursor/pre-1"
1225   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-refresh-cursor/pre-1/cursor"
1226   # expand
1227   edit-trace t, 0xa/enter
1228   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1229   #
1230   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-refresh-cursor/expand-0"
1231   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-refresh-cursor/expand-0/cursor"
1232   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-refresh-cursor/expand-1"
1233   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-refresh-cursor/expand-1/cursor"
1234   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-refresh-cursor/expand-2"
1235   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-refresh-cursor/expand-2/cursor"
1236   # cursor down
1237   edit-trace t, 0x6a/j
1238   edit-trace t, 0x6a/j
1239   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1240   #
1241   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-refresh-cursor/down-0"
1242   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-refresh-cursor/down-0/cursor"
1243   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-refresh-cursor/down-1"
1244   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-refresh-cursor/down-1/cursor"
1245   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-refresh-cursor/down-2"
1246   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-refresh-cursor/down-2/cursor"
1247   # recreate trace
1248   clear-trace t
1249   trace-text t, "l", "line 1"
1250   trace-text t, "l", "line 2"
1251   trace-text t, "l", "line 3"
1252   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1253   # cursor remains unchanged
1254   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-refresh-cursor/refresh-0"
1255   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-refresh-cursor/refresh-0/cursor"
1256   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-refresh-cursor/refresh-1"
1257   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-refresh-cursor/refresh-1/cursor"
1258   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-refresh-cursor/refresh-2"
1259   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-refresh-cursor/refresh-2/cursor"
1260 }
1261 
1262 fn test-trace-preserve-cursor-on-refresh {
1263   var t-storage: trace
1264   var t/esi: (addr trace) <- address t-storage
1265   initialize-trace t, 0x10, 0x10
1266   #
1267   trace-text t, "l", "line 1"
1268   trace-text t, "l", "line 2"
1269   trace-text t, "l", "line 3"
1270   # setup: screen
1271   var screen-on-stack: screen
1272   var screen/edi: (addr screen) <- address screen-on-stack
1273   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1274   #
1275   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1276   #
1277   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-preserve-cursor-on-refresh/pre-0"
1278   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-preserve-cursor-on-refresh/pre-0/cursor"
1279   check-screen-row screen,                                  1/y, "           ", "F - test-trace-preserve-cursor-on-refresh/pre-1"
1280   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-preserve-cursor-on-refresh/pre-1/cursor"
1281   # expand
1282   edit-trace t, 0xa/enter
1283   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1284   #
1285   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-preserve-cursor-on-refresh/expand-0"
1286   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-preserve-cursor-on-refresh/expand-0/cursor"
1287   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-preserve-cursor-on-refresh/expand-1"
1288   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-preserve-cursor-on-refresh/expand-1/cursor"
1289   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-preserve-cursor-on-refresh/expand-2"
1290   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "              ", "F - test-trace-preserve-cursor-on-refresh/expand-2/cursor"
1291   # cursor down
1292   edit-trace t, 0x6a/j
1293   edit-trace t, 0x6a/j
1294   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1295   #
1296   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-preserve-cursor-on-refresh/down-0"
1297   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-preserve-cursor-on-refresh/down-0/cursor"
1298   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-preserve-cursor-on-refresh/down-1"
1299   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-preserve-cursor-on-refresh/down-1/cursor"
1300   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-preserve-cursor-on-refresh/down-2"
1301   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-preserve-cursor-on-refresh/down-2/cursor"
1302   # recreate trace with slightly different lines
1303   clear-trace t
1304   trace-text t, "l", "line 4"
1305   trace-text t, "l", "line 5"
1306   trace-text t, "l", "line 3"  # cursor line is unchanged
1307   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1308   # cursor remains unchanged
1309   check-screen-row screen,                                  0/y, "0 line 4   ", "F - test-trace-preserve-cursor-on-refresh/refresh-0"
1310   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-preserve-cursor-on-refresh/refresh-0/cursor"
1311   check-screen-row screen,                                  1/y, "0 line 5   ", "F - test-trace-preserve-cursor-on-refresh/refresh-1"
1312   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-preserve-cursor-on-refresh/refresh-1/cursor"
1313   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-preserve-cursor-on-refresh/refresh-2"
1314   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-preserve-cursor-on-refresh/refresh-2/cursor"
1315 }
1316 
1317 fn test-trace-keep-cursor-visible-on-refresh {
1318   var t-storage: trace
1319   var t/esi: (addr trace) <- address t-storage
1320   initialize-trace t, 0x10, 0x10
1321   #
1322   trace-text t, "l", "line 1"
1323   trace-text t, "l", "line 2"
1324   trace-text t, "l", "line 3"
1325   # setup: screen
1326   var screen-on-stack: screen
1327   var screen/edi: (addr screen) <- address screen-on-stack
1328   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1329   #
1330   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1331   #
1332   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0"
1333   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0/cursor"
1334   check-screen-row screen,                                  1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1"
1335   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1/cursor"
1336   # expand
1337   edit-trace t, 0xa/enter
1338   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1339   #
1340   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0"
1341   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0/cursor"
1342   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1"
1343   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1/cursor"
1344   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2"
1345   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "              ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2/cursor"
1346   # cursor down
1347   edit-trace t, 0x6a/j
1348   edit-trace t, 0x6a/j
1349   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1350   #
1351   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-keep-cursor-visible-on-refresh/down-0"
1352   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/down-0/cursor"
1353   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-keep-cursor-visible-on-refresh/down-1"
1354   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/down-1/cursor"
1355   check-screen-row screen,                                  2/y, "0 line 3   ", "F - test-trace-keep-cursor-visible-on-refresh/down-2"
1356   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-keep-cursor-visible-on-refresh/down-2/cursor"
1357   # recreate trace with entirely different lines
1358   clear-trace t
1359   trace-text t, "l", "line 4"
1360   trace-text t, "l", "line 5"
1361   trace-text t, "l", "line 6"
1362   mark-lines-dirty t
1363   clear-screen screen
1364   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1365   # trace collapses, and cursor bumps up
1366   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0"
1367   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0/cursor"
1368   check-screen-row screen,                                  1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1"
1369   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1/cursor"
1370   check-screen-row screen,                                  2/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2"
1371   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2/cursor"
1372 }
1373 
1374 fn test-trace-collapse-at-top {
1375   var t-storage: trace
1376   var t/esi: (addr trace) <- address t-storage
1377   initialize-trace t, 0x10, 0x10
1378   #
1379   trace-text t, "l", "line 1"
1380   trace-lower t
1381   trace-text t, "l", "line 1.1"
1382   trace-higher t
1383   trace-text t, "l", "line 2"
1384   # setup: screen
1385   var screen-on-stack: screen
1386   var screen/edi: (addr screen) <- address screen-on-stack
1387   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1388   #
1389   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1390   #
1391   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-at-top/pre-0"
1392   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-at-top/pre-0/cursor"
1393   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-at-top/pre-1"
1394   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-at-top/pre-1/cursor"
1395   # expand
1396   edit-trace t, 0xa/enter
1397   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1398   #
1399   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-at-top/expand-0"
1400   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-collapse-at-top/expand-0/cursor"
1401   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-at-top/expand-1"
1402   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-at-top/expand-1/cursor"
1403   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-at-top/expand-2"
1404   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-at-top/expand-2/cursor"
1405   # collapse
1406   edit-trace t, 8/backspace
1407   # hack: we need to render here to make this test pass; we're mixing state management with rendering
1408   clear-screen screen
1409   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1410   #
1411   check-ints-equal y, 1, "F - test-trace-collapse-at-top/post-0/y"
1412   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-at-top/post-0"
1413   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-at-top/post-0/cursor"
1414   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-at-top/post-1"
1415   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-at-top/post-1/cursor"
1416 }
1417 
1418 fn test-trace-collapse {
1419   var t-storage: trace
1420   var t/esi: (addr trace) <- address t-storage
1421   initialize-trace t, 0x10, 0x10
1422   #
1423   trace-text t, "l", "line 1"
1424   trace-text t, "l", "line 2"
1425   # setup: screen
1426   var screen-on-stack: screen
1427   var screen/edi: (addr screen) <- address screen-on-stack
1428   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1429   #
1430   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1431   #
1432   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse/pre-0"
1433   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse/pre-0/cursor"
1434   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse/pre-1"
1435   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse/pre-1/cursor"
1436   # expand
1437   edit-trace t, 0xa/enter
1438   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1439   #
1440   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse/expand-0"
1441   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-collapse/expand-0/cursor"
1442   check-screen-row screen,                                  1/y, "0 line 2   ", "F - test-trace-collapse/expand-1"
1443   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse/expand-1/cursor"
1444   # cursor down
1445   edit-trace t, 0x6a/j
1446   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1447   # collapse
1448   edit-trace t, 8/backspace
1449   clear-screen screen
1450   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1451   #
1452   check-ints-equal y, 1, "F - test-trace-collapse/post-0/y"
1453   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse/post-0"
1454   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse/post-0/cursor"
1455   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse/post-1"
1456   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse/post-1/cursor"
1457 }
1458 
1459 fn test-trace-collapse-skips-invisible-lines {
1460   var t-storage: trace
1461   var t/esi: (addr trace) <- address t-storage
1462   initialize-trace t, 0x10, 0x10
1463   #
1464   trace-text t, "l", "line 1"
1465   trace-lower t
1466   trace-text t, "l", "line 1.1"
1467   trace-higher t
1468   trace-text t, "l", "line 2"
1469   # setup: screen
1470   var screen-on-stack: screen
1471   var screen/edi: (addr screen) <- address screen-on-stack
1472   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1473   #
1474   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1475   #
1476   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-skips-invisible-lines/pre-0"
1477   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-skips-invisible-lines/pre-0/cursor"
1478   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-skips-invisible-lines/pre-1"
1479   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-skips-invisible-lines/pre-1/cursor"
1480   # expand
1481   edit-trace t, 0xa/enter
1482   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1483   # two visible lines with an invisible line in between
1484   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-skips-invisible-lines/expand-0"
1485   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-collapse-skips-invisible-lines/expand-0/cursor"
1486   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-skips-invisible-lines/expand-1"
1487   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-skips-invisible-lines/expand-1/cursor"
1488   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-skips-invisible-lines/expand-2"
1489   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-skips-invisible-lines/expand-2/cursor"
1490   # cursor down to second visible line
1491   edit-trace t, 0x6a/j
1492   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1493   edit-trace t, 0x6a/j
1494   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1495   # collapse
1496   edit-trace t, 8/backspace
1497   clear-screen screen
1498   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1499   #
1500   check-ints-equal y, 1, "F - test-trace-collapse-skips-invisible-lines/post-0/y"
1501   var cursor-y/eax: (addr int) <- get t, cursor-y
1502   check-ints-equal *cursor-y, 0, "F - test-trace-collapse-skips-invisible-lines/post-0/cursor-y"
1503   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-skips-invisible-lines/post-0"
1504   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-skips-invisible-lines/post-0/cursor"
1505   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-skips-invisible-lines/post-1"
1506   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-skips-invisible-lines/post-1/cursor"
1507 }
1508 
1509 fn test-trace-collapse-two-levels {
1510   var t-storage: trace
1511   var t/esi: (addr trace) <- address t-storage
1512   initialize-trace t, 0x10, 0x10
1513   #
1514   trace-text t, "l", "line 1"
1515   trace-lower t
1516   trace-text t, "l", "line 1.1"
1517   trace-higher t
1518   trace-text t, "l", "line 2"
1519   # setup: screen
1520   var screen-on-stack: screen
1521   var screen/edi: (addr screen) <- address screen-on-stack
1522   initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
1523   #
1524   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1525   #
1526   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-two-levels/pre-0"
1527   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-two-levels/pre-0/cursor"
1528   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-two-levels/pre-1"
1529   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-two-levels/pre-1/cursor"
1530   # expand
1531   edit-trace t, 0xa/enter
1532   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1533   # two visible lines with an invisible line in between
1534   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-two-levels/expand-0"
1535   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-collapse-two-levels/expand-0/cursor"
1536   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-two-levels/expand-1"
1537   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-two-levels/expand-1/cursor"
1538   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-two-levels/expand-2"
1539   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-two-levels/expand-2/cursor"
1540   # cursor down to ellipses
1541   edit-trace t, 0x6a/j
1542   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1543   # expand
1544   edit-trace t, 0xa/enter
1545   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1546   # two visible lines with an invisible line in between
1547   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-two-levels/expand2-0"
1548   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-collapse-two-levels/expand2-0/cursor"
1549   check-screen-row screen,                                  1/y, "1 line 1.1 ", "F - test-trace-collapse-two-levels/expand2-1"
1550   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-collapse-two-levels/expand2-1/cursor"
1551   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-two-levels/expand2-2"
1552   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-two-levels/expand2-2/cursor"
1553   # cursor down to second visible line
1554   edit-trace t, 0x6a/j
1555   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1556   # collapse
1557   edit-trace t, 8/backspace
1558   clear-screen screen
1559   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
1560   #
1561   check-ints-equal y, 1, "F - test-trace-collapse-two-levels/post-0/y"
1562   var cursor-y/eax: (addr int) <- get t, cursor-y
1563   check-ints-equal *cursor-y, 0, "F - test-trace-collapse-two-levels/post-0/cursor-y"
1564   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-two-levels/post-0"
1565   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-two-levels/post-0/cursor"
1566   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-two-levels/post-1"
1567   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-two-levels/post-1/cursor"
1568 }
1569 
1570 fn test-trace-collapse-nested-level {
1571   var t-storage: trace
1572   var t/esi: (addr trace) <- address t-storage
1573   initialize-trace t, 0x10, 0x10
1574   #
1575   trace-text t, "l", "line 1"
1576   trace-lower t
1577   trace-text t, "l", "line 1.1"
1578   trace-higher t
1579   trace-text t, "l", "line 2"
1580   trace-lower t
1581   trace-text t, "l", "line 2.1"
1582   trace-text t, "l", "line 2.2"
1583   trace-higher t
1584   # setup: screen
1585   var screen-on-stack: screen
1586   var screen/edi: (addr screen) <- address screen-on-stack
1587   initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics
1588   #
1589   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1590   #
1591   check-screen-row screen,                                  0/y, "...        ", "F - test-trace-collapse-nested-level/pre-0"
1592   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||        ", "F - test-trace-collapse-nested-level/pre-0/cursor"
1593   check-screen-row screen,                                  1/y, "           ", "F - test-trace-collapse-nested-level/pre-1"
1594   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-nested-level/pre-1/cursor"
1595   # expand
1596   edit-trace t, 0xa/enter
1597   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1598   # two visible lines with an invisible line in between
1599   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-nested-level/expand-0"
1600   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||||||||   ", "F - test-trace-collapse-nested-level/expand-0/cursor"
1601   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-nested-level/expand-1"
1602   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-nested-level/expand-1/cursor"
1603   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-nested-level/expand-2"
1604   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-nested-level/expand-2/cursor"
1605   check-screen-row screen,                                  3/y, "...        ", "F - test-trace-collapse-nested-level/expand-3"
1606   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "           ", "F - test-trace-collapse-nested-level/expand-3/cursor"
1607   # cursor down to bottom
1608   edit-trace t, 0x6a/j
1609   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1610   edit-trace t, 0x6a/j
1611   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1612   edit-trace t, 0x6a/j
1613   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1614   # expand
1615   edit-trace t, 0xa/enter
1616   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1617   # two visible lines with an invisible line in between
1618   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-nested-level/expand2-0"
1619   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-collapse-nested-level/expand2-0/cursor"
1620   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-nested-level/expand2-1"
1621   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-nested-level/expand2-1/cursor"
1622   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-nested-level/expand2-2"
1623   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "           ", "F - test-trace-collapse-nested-level/expand2-2/cursor"
1624   check-screen-row screen,                                  3/y, "1 line 2.1 ", "F - test-trace-collapse-nested-level/expand2-3"
1625   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "|||||||||| ", "F - test-trace-collapse-nested-level/expand2-3/cursor"
1626   check-screen-row screen,                                  4/y, "1 line 2.2 ", "F - test-trace-collapse-nested-level/expand2-4"
1627   check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, "           ", "F - test-trace-collapse-nested-level/expand2-4/cursor"
1628   # collapse
1629   edit-trace t, 8/backspace
1630   clear-screen screen
1631   var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
1632   #
1633   check-ints-equal y, 4, "F - test-trace-collapse-nested-level/post-0/y"
1634   var cursor-y/eax: (addr int) <- get t, cursor-y
1635   check-ints-equal *cursor-y, 2, "F - test-trace-collapse-nested-level/post-0/cursor-y"
1636   check-screen-row screen,                                  0/y, "0 line 1   ", "F - test-trace-collapse-nested-level/post-0"
1637   check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "           ", "F - test-trace-collapse-nested-level/post-0/cursor"
1638   check-screen-row screen,                                  1/y, "...        ", "F - test-trace-collapse-nested-level/post-1"
1639   check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "           ", "F - test-trace-collapse-nested-level/post-1/cursor"
1640   check-screen-row screen,                                  2/y, "0 line 2   ", "F - test-trace-collapse-nested-level/post-2"
1641   check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||||||||   ", "F - test-trace-collapse-nested-level/post-2/cursor"
1642   check-screen-row screen,                                  3/y, "...        ", "F - test-trace-collapse-nested-level/post-3"
1643   check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "           ", "F - test-trace-collapse-nested-level/post-3/cursor"
1644 }