mu/shell/trace.mu
Kartik K. Agaram d85529f3fa cache visibility for all lines in trace
So far we were only doing so for the first few lines, just enough to render
one page's worth of lines. We'd have probably noticed if we collapsed some
lines after re-evaluating.
2021-05-29 17:13:06 -07:00

1792 lines
85 KiB
Forth

# A trace records the evolution of a computation.
# Traces are useful for:
# error-handling
# testing
# auditing
# debugging
# learning
#
# An integral part of the Mu computer is facilities for browsing traces.
type trace {
max-depth: int
curr-depth: int # depth that will be assigned to next line appended
data: (handle array trace-line)
first-free: int
first-full: int # used only by check-trace-scan
# steady-state life cycle of a trace:
# reload loop:
# there are already some visible lines
# append a bunch of new trace lines to the trace
# recreate trace caches
# render loop:
# rendering displays trace lines that match visible lines
# (caching in each line)
# rendering computes cursor-line based on the cursor-y coordinate
# edit-trace updates cursor-y coordinate
# edit-trace might add/remove lines to visible
visible: (handle array trace-line)
recreate-caches?: boolean
cursor-line-index: int # index into data
cursor-y: int # row index on screen
unclip-cursor-line?: boolean # extremely short-lived; reset any time cursor moves
top-line-index: int # index into data
}
type trace-line {
depth: int
label: (handle array byte)
data: (handle array byte)
visible?: boolean
}
## generating traces
fn initialize-trace _self: (addr trace), max-depth: int, capacity: int, visible-capacity: int {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var src/ecx: int <- copy max-depth
var dest/eax: (addr int) <- get self, max-depth
copy-to *dest, src
dest <- get self, curr-depth
copy-to *dest, 1 # 0 is the error depth
var trace-ah/eax: (addr handle array trace-line) <- get self, data
populate trace-ah, capacity
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
populate visible-ah, visible-capacity
}
fn clear-trace _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var len/edx: (addr int) <- get self, first-free
copy-to *len, 0
# might leak memory; existing elements won't be used anymore
}
fn has-errors? _self: (addr trace) -> _/eax: boolean {
var self/eax: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var max/edx: (addr int) <- get self, first-free
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/esi: (addr array trace-line) <- copy _trace
var i/ecx: int <- copy 0
{
compare i, *max
break-if->=
var offset/eax: (offset trace-line) <- compute-offset trace, i
var curr/eax: (addr trace-line) <- index trace, offset
var curr-depth-a/eax: (addr int) <- get curr, depth
compare *curr-depth-a, 0/error
{
break-if-!=
return 1/true
}
i <- increment
loop
}
return 0/false
}
fn should-trace? _self: (addr trace) -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var depth-a/ecx: (addr int) <- get self, curr-depth
var depth/ecx: int <- copy *depth-a
var max-depth-a/eax: (addr int) <- get self, max-depth
compare depth, *max-depth-a
{
break-if->=
return 1/true
}
return 0/false
}
fn trace _self: (addr trace), label: (addr array byte), message: (addr stream byte) {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var should-trace?/eax: boolean <- should-trace? self
compare should-trace?, 0/false
{
break-if-!=
return
}
var data-ah/eax: (addr handle array trace-line) <- get self, data
var data/eax: (addr array trace-line) <- lookup *data-ah
var index-addr/edi: (addr int) <- get self, first-free
{
compare *index-addr, 0x8000/lines
break-if-<
return
}
var index/ecx: int <- copy *index-addr
var offset/ecx: (offset trace-line) <- compute-offset data, index
var dest/eax: (addr trace-line) <- index data, offset
var depth/ecx: (addr int) <- get self, curr-depth
rewind-stream message
{
compare *index-addr, 0x7fff/lines
break-if-<
clear-stream message
write message, "No space left in trace\n"
write message, "Please either:\n"
write message, " - find a smaller sub-computation to test,\n"
write message, " - allocate more space to the trace in initialize-sandbox\n"
write message, " (shell/sandbox.mu), or\n"
write message, " - move the computation to 'main' and run it using ctrl-r"
initialize-trace-line 0/depth, "error", message, dest
increment *index-addr
return
}
initialize-trace-line *depth, label, message, dest
increment *index-addr
}
fn trace-text self: (addr trace), label: (addr array byte), s: (addr array byte) {
compare self, 0
{
break-if-!=
abort "null trace"
}
var data-storage: (stream byte 0x100)
var data/eax: (addr stream byte) <- address data-storage
write data, s
trace self, label, data
}
fn error _self: (addr trace), message: (addr array byte) {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var curr-depth-a/eax: (addr int) <- get self, curr-depth
var save-depth/ecx: int <- copy *curr-depth-a
copy-to *curr-depth-a, 0/error
trace-text self, "error", message
copy-to *curr-depth-a, save-depth
}
fn initialize-trace-line depth: int, label: (addr array byte), data: (addr stream byte), _out: (addr trace-line) {
var out/edi: (addr trace-line) <- copy _out
# depth
var src/eax: int <- copy depth
var dest/ecx: (addr int) <- get out, depth
copy-to *dest, src
# label
var dest/eax: (addr handle array byte) <- get out, label
copy-array-object label, dest
# data
var dest/eax: (addr handle array byte) <- get out, data
stream-to-array data, dest
}
fn trace-lower _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var depth/eax: (addr int) <- get self, curr-depth
increment *depth
}
fn trace-higher _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var depth/eax: (addr int) <- get self, curr-depth
decrement *depth
}
## checking traces
fn check-trace-scans-to self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
var tmp/eax: boolean <- trace-scans-to? self, label, data
check tmp, message
}
fn trace-scans-to? _self: (addr trace), label: (addr array byte), data: (addr array byte) -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
var start/eax: (addr int) <- get self, first-full
var result/eax: boolean <- trace-contains? self, label, data, *start
return result
}
fn test-trace-scans-to {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10/capacity, 0/visible # we don't use trace UI
#
trace-text t, "label", "line 1"
trace-text t, "label", "line 2"
check-trace-scans-to t, "label", "line 1", "F - test-trace-scans-to/0"
check-trace-scans-to t, "label", "line 2", "F - test-trace-scans-to/1"
var tmp/eax: boolean <- trace-scans-to? t, "label", "line 1"
check-not tmp, "F - test-trace-scans-to: fail on previously encountered lines"
var tmp/eax: boolean <- trace-scans-to? t, "label", "line 3"
check-not tmp, "F - test-trace-scans-to: fail on missing"
}
# scan trace from start
# resets previous scans
fn check-trace-contains self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
var tmp/eax: boolean <- trace-contains? self, label, data, 0
check tmp, message
}
fn test-trace-contains {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10/capacity, 0/visible # we don't use trace UI
#
trace-text t, "label", "line 1"
trace-text t, "label", "line 2"
check-trace-contains t, "label", "line 1", "F - test-trace-contains/0"
check-trace-contains t, "label", "line 2", "F - test-trace-contains/1"
check-trace-contains t, "label", "line 1", "F - test-trace-contains: find previously encountered lines"
var tmp/eax: boolean <- trace-contains? t, "label", "line 3", 0/start
check-not tmp, "F - test-trace-contains: fail on missing"
}
# this is super-inefficient, string comparing every trace line
# against every visible line on every render
fn trace-contains? _self: (addr trace), label: (addr array byte), data: (addr array byte), start: int -> _/eax: boolean {
var self/esi: (addr trace) <- copy _self
var candidates-ah/eax: (addr handle array trace-line) <- get self, data
var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
var i/ecx: int <- copy start
var max/edx: (addr int) <- get self, first-free
{
compare i, *max
break-if->=
{
var read-until-index/eax: (addr int) <- get self, first-full
copy-to *read-until-index, i
}
{
var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
var curr/ecx: (addr trace-line) <- index candidates, curr-offset
# if curr->label does not match, return false
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var match?/eax: boolean <- string-equal? curr-label, label
compare match?, 0/false
break-if-=
# if curr->data does not match, return false
var curr-data-ah/eax: (addr handle array byte) <- get curr, data
var curr-data/eax: (addr array byte) <- lookup *curr-data-ah
var match?/eax: boolean <- string-equal? curr-data, data
compare match?, 0/false
break-if-=
return 1/true
}
i <- increment
loop
}
return 0/false
}
fn trace-lines-equal? _a: (addr trace-line), _b: (addr trace-line) -> _/eax: boolean {
var a/esi: (addr trace-line) <- copy _a
var b/edi: (addr trace-line) <- copy _b
var a-depth/ecx: (addr int) <- get a, depth
var b-depth/edx: (addr int) <- get b, depth
var benchmark/eax: int <- copy *b-depth
compare *a-depth, benchmark
{
break-if-=
return 0/false
}
var a-label-ah/eax: (addr handle array byte) <- get a, label
var _a-label/eax: (addr array byte) <- lookup *a-label-ah
var a-label/ecx: (addr array byte) <- copy _a-label
var b-label-ah/ebx: (addr handle array byte) <- get b, label
var b-label/eax: (addr array byte) <- lookup *b-label-ah
var label-match?/eax: boolean <- string-equal? a-label, b-label
{
compare label-match?, 0/false
break-if-!=
return 0/false
}
var a-data-ah/eax: (addr handle array byte) <- get a, data
var _a-data/eax: (addr array byte) <- lookup *a-data-ah
var a-data/ecx: (addr array byte) <- copy _a-data
var b-data-ah/ebx: (addr handle array byte) <- get b, data
var b-data/eax: (addr array byte) <- lookup *b-data-ah
var data-match?/eax: boolean <- string-equal? a-data, b-data
return data-match?
}
fn dump-trace _self: (addr trace) {
var already-hiding-lines?: boolean
var y/ecx: int <- copy 0
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
$dump-trace:loop: {
compare i, max
break-if->=
$dump-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg, 0/clip
}
i <- increment
loop
}
}
fn dump-trace-with-label _self: (addr trace), label: (addr array byte) {
var already-hiding-lines?: boolean
var y/ecx: int <- copy 0
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
$dump-trace:loop: {
compare i, max
break-if->=
$dump-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var show?/eax: boolean <- string-equal? curr-label, label
compare show?, 0/false
break-if-=
y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg, 0/clip
}
i <- increment
loop
}
}
## UI stuff
fn mark-lines-dirty _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
var dest/edx: (addr boolean) <- get self, recreate-caches?
copy-to *dest, 1/true
}
fn mark-lines-clean _self: (addr trace) {
var self/eax: (addr trace) <- copy _self
var dest/edx: (addr boolean) <- get self, recreate-caches?
copy-to *dest, 0/false
}
fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean -> _/ecx: int {
var already-hiding-lines?: boolean
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
abort "null trace"
}
var y/ecx: int <- copy ymin
# recreate caches if necessary
var recreate-caches?/eax: (addr boolean) <- get self, recreate-caches?
compare *recreate-caches?, 0/false
{
break-if-=
recompute-all-visible-lines self
mark-lines-clean self
}
clamp-cursor-to-top self, y
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
# display trace depth (not in tests)
$render-trace:render-depth: {
compare max, 0
break-if-<=
var max-depth/edx: (addr int) <- get self, max-depth
{
var width/eax: int <- copy 0
var height/ecx: int <- copy 0
width, height <- screen-size screen
compare width, 0x80
break-if-< $render-trace:render-depth
}
set-cursor-position screen, 0x70/x, y
draw-text-rightward-from-cursor-over-full-screen screen, "trace depth: ", 0x17/fg, 0xc5/bg=blue-bg
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, *max-depth, 0x7/fg, 0xc5/bg=blue-bg
}
$render-trace:loop: {
compare i, max
break-if->=
$render-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
var bg: int
copy-to bg, 0xc5/bg=blue-bg
var fg: int
copy-to fg, 0x38/fg=trace
compare show-cursor?, 0/false
{
break-if-=
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if-!=
copy-to bg, 7/trace-cursor-line-bg
copy-to fg, 0x68/cursor-line-fg=sober-blue
var cursor-line-index/eax: (addr int) <- get self, cursor-line-index
copy-to *cursor-line-index, i
}
# always display errors
{
var curr-depth/eax: (addr int) <- get curr, depth
compare *curr-depth, 0/error
break-if-!=
y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0xc/fg=trace-error, bg, 0/clip
copy-to already-hiding-lines?, 0/false
break $render-trace:iter
}
# display expanded lines
var display?/eax: boolean <- should-render? curr
{
compare display?, 0/false
break-if-=
var unclip-cursor-line?/eax: boolean <- unclip-cursor-line? self, i
y <- render-trace-line screen, curr, xmin, y, xmax, ymax, fg, bg, unclip-cursor-line?
copy-to already-hiding-lines?, 0/false
break $render-trace:iter
}
# ignore the rest
compare already-hiding-lines?, 0/false
{
break-if-!=
var x/eax: int <- copy xmin
x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, fg, bg
y <- increment
copy-to already-hiding-lines?, 1/true
}
}
i <- increment
loop
}
# prevent cursor from going too far down
clamp-cursor-to-bottom self, y, screen, xmin, ymin, xmax, ymax
return y
}
fn unclip-cursor-line? _self: (addr trace), _i: int -> _/eax: boolean {
# if unclip? and i == *cursor-line-index, render unclipped
var self/esi: (addr trace) <- copy _self
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
compare *unclip-cursor-line?, 0/false
{
break-if-!=
return 0/false
}
var cursor-line-index/eax: (addr int) <- get self, cursor-line-index
var i/ecx: int <- copy _i
compare i, *cursor-line-index
{
break-if-=
return 0/false
}
return 1/true
}
fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int, ymin: int, xmax: int, ymax: int, fg: int, bg: int, unclip?: boolean -> _/ecx: int {
var self/esi: (addr trace-line) <- copy _self
var xsave/edx: int <- copy xmin
var y/ecx: int <- copy ymin
# show depth for non-errors
var depth-a/ebx: (addr int) <- get self, depth
compare *depth-a, 0/error
{
break-if-=
var x/eax: int <- copy xsave
{
x, y <- draw-int32-decimal-wrapping-right-then-down screen, *depth-a, xmin, ymin, xmax, ymax, x, y, fg, bg
x, y <- draw-text-wrapping-right-then-down screen, " ", xmin, ymin, xmax, ymax, x, y, fg, bg
# don't show label in UI; it's just for tests
}
xsave <- copy x
}
var data-ah/eax: (addr handle array byte) <- get self, data
var _data/eax: (addr array byte) <- lookup *data-ah
var data/ebx: (addr array byte) <- copy _data
var x/eax: int <- copy xsave
compare unclip?, 0/false
{
break-if-=
x, y <- draw-text-wrapping-right-then-down screen, data, xmin, ymin, xmax, ymax, x, y, fg, bg
}
compare unclip?, 0/false
{
break-if-!=
x <- draw-text-rightward screen, data, x, xmax, y, fg, bg
}
y <- increment
return y
}
fn should-render? _line: (addr trace-line) -> _/eax: boolean {
var line/eax: (addr trace-line) <- copy _line
var result/eax: (addr boolean) <- get line, visible?
return *result
}
# This is super-inefficient, string-comparing every trace line
# against every visible line.
fn recompute-all-visible-lines _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
var max-addr/edx: (addr int) <- get self, first-free
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/esi: (addr array trace-line) <- copy _trace
var i/ecx: int <- copy 0
{
compare i, *max-addr
break-if->=
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
recompute-visibility _self, curr
i <- increment
loop
}
}
fn recompute-visibility _self: (addr trace), _line: (addr trace-line) {
var self/esi: (addr trace) <- copy _self
# recompute
var candidates-ah/eax: (addr handle array trace-line) <- get self, visible
var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
var i/ecx: int <- copy 0
var len/edx: int <- length candidates
{
compare i, len
break-if->=
{
var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
var curr/ecx: (addr trace-line) <- index candidates, curr-offset
var match?/eax: boolean <- trace-lines-equal? curr, _line
compare match?, 0/false
break-if-=
var line/eax: (addr trace-line) <- copy _line
var dest/eax: (addr boolean) <- get line, visible?
copy-to *dest, 1/true
}
i <- increment
loop
}
var line/eax: (addr trace-line) <- copy _line
var dest/eax: (addr boolean) <- get line, visible?
copy-to *dest, 0/false
}
fn clamp-cursor-to-top _self: (addr trace), _y: int {
var y/ecx: int <- copy _y
var self/esi: (addr trace) <- copy _self
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if->=
copy-to *cursor-y, y
}
# extremely hacky; consider deleting test-render-trace-empty-3 when you clean this up
fn clamp-cursor-to-bottom _self: (addr trace), _y: int, screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int {
var y/ebx: int <- copy _y
compare y, ymin
{
break-if->
return
}
y <- decrement
var self/esi: (addr trace) <- copy _self
var cursor-y/eax: (addr int) <- get self, cursor-y
compare *cursor-y, y
break-if-<=
copy-to *cursor-y, y
# redraw cursor-line
# TODO: ugly duplication
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var trace/eax: (addr array trace-line) <- lookup *trace-ah
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var first-free/edx: (addr int) <- get self, first-free
compare cursor-line-index, *first-free
{
break-if-<
return
}
var cursor-offset/ecx: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/ecx: (addr trace-line) <- index trace, cursor-offset
var display?/eax: boolean <- should-render? cursor-line
{
compare display?, 0/false
break-if-=
var dummy/ecx: int <- render-trace-line screen, cursor-line, xmin, y, xmax, ymax, 0x38/fg=trace, 7/cursor-line-bg, 0/clip
return
}
var dummy1/eax: int <- copy 0
var dummy2/ecx: int <- copy 0
dummy1, dummy2 <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xmin, y, 9/fg=trace, 7/cursor-line-bg
}
fn test-render-trace-empty {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 0, "F - test-render-trace-empty/cursor"
check-screen-row screen, 0/y, " ", "F - test-render-trace-empty"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-trace-empty/bg"
}
fn test-render-trace-empty-2 {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 0/no-cursor # cursor below top row
#
check-ints-equal y, 2, "F - test-render-trace-empty-2/cursor"
check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-2/bg"
}
fn test-render-trace-empty-3 {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 1/show-cursor # try show cursor
# still no cursor to show
check-ints-equal y, 2, "F - test-render-trace-empty-3/cursor"
check-screen-row screen, 1/y, " ", "F - test-render-trace-empty-3/line-above-cursor"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-empty-3/bg-for-line-above-cursor"
check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-3/bg"
}
fn test-render-trace-collapsed-by-default {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
trace-text t, "l", "data"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 1, "F - test-render-trace-collapsed-by-default/cursor"
check-screen-row screen, 0/y, "... ", "F - test-render-trace-collapsed-by-default"
}
fn test-render-trace-error {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
error t, "error"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 1, "F - test-render-trace-error/cursor"
check-screen-row screen, 0/y, "error", "F - test-render-trace-error"
}
fn test-render-trace-error-at-start {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
error t, "error"
trace-text t, "l", "data"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 2, "F - test-render-trace-error-at-start/cursor"
check-screen-row screen, 0/y, "error", "F - test-render-trace-error-at-start/0"
check-screen-row screen, 1/y, "... ", "F - test-render-trace-error-at-start/1"
}
fn test-render-trace-error-at-end {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "data"
error t, "error"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 2, "F - test-render-trace-error-at-end/cursor"
check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-at-end/0"
check-screen-row screen, 1/y, "error", "F - test-render-trace-error-at-end/1"
}
fn test-render-trace-error-in-the-middle {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor
#
check-ints-equal y, 3, "F - test-render-trace-error-in-the-middle/cursor"
check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-in-the-middle/0"
check-screen-row screen, 1/y, "error", "F - test-render-trace-error-in-the-middle/1"
check-screen-row screen, 2/y, "... ", "F - test-render-trace-error-in-the-middle/2"
}
fn test-render-trace-cursor-in-single-line {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-render-trace-cursor-in-single-line/0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-render-trace-cursor-in-single-line/0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-render-trace-cursor-in-single-line/1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-cursor-in-single-line/1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-render-trace-cursor-in-single-line/2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-cursor-in-single-line/2/cursor"
}
fn render-trace-menu screen: (addr screen) {
var width/eax: int <- copy 0
var height/ecx: int <- copy 0
width, height <- screen-size screen
var y/ecx: int <- copy height
y <- decrement
var height/edx: int <- copy y
height <- increment
clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg
set-cursor-position screen, 0/x, y
draw-text-rightward-from-cursor screen, " enter/bksp ", width, 0/fg, 0x5c/bg=black
draw-text-rightward-from-cursor screen, " expand/collapse ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ctrl+... ", width, 0xf/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " r ", width, 0/fg, 0x5c/bg=black
draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " m ", width, 0/fg, 3/bg=keyboard
draw-text-rightward-from-cursor screen, " to keyboard ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " s ", width, 0/fg, 3/bg=keyboard
draw-text-rightward-from-cursor screen, " show whole line ", width, 7/fg, 0xc5/bg=blue-bg
}
fn edit-trace _self: (addr trace), key: grapheme {
var self/esi: (addr trace) <- copy _self
# cursor down
{
compare key, 0x6a/j
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
increment *cursor-y
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
copy-to *unclip-cursor-line?, 0/false
return
}
{
compare key, 0x81/down-arrow
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
increment *cursor-y
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
copy-to *unclip-cursor-line?, 0/false
return
}
# cursor up
{
compare key, 0x6b/k
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
decrement *cursor-y
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
copy-to *unclip-cursor-line?, 0/false
return
}
{
compare key, 0x82/up-arrow
break-if-!=
var cursor-y/eax: (addr int) <- get self, cursor-y
decrement *cursor-y
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
copy-to *unclip-cursor-line?, 0/false
return
}
# enter = expand
{
compare key, 0xa/newline
break-if-!=
expand self
return
}
# backspace = collapse
{
compare key, 8/backspace
break-if-!=
collapse self
return
}
# ctrl-s: temporarily unclip current line
{
compare key, 0x13/ctrl-s
break-if-!=
var unclip-cursor-line?/eax: (addr boolean) <- get self, unclip-cursor-line?
copy-to *unclip-cursor-line?, 1/true
return
}
}
fn expand _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
var target-depth/ebx: int <- copy *cursor-line-depth
# if cursor-line is already visible, increment target-depth
compare *cursor-line-visible?, 0/false
{
break-if-=
target-depth <- increment
}
# reveal the run of lines starting at cursor-line-index with depth target-depth
var i/ecx: int <- copy cursor-line-index
var max/edx: (addr int) <- get self, first-free
{
compare i, *max
break-if->=
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-<
{
break-if-!=
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
copy-to *curr-line-visible?, 1/true
reveal-trace-line self, curr-line
}
i <- increment
loop
}
}
fn collapse _self: (addr trace) {
var self/esi: (addr trace) <- copy _self
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index
var cursor-line-index/ecx: int <- copy *cursor-line-index-addr
var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index
var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset
var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible?
# if cursor-line is not visible, do nothing
compare *cursor-line-visible?, 0/false
{
break-if-!=
return
}
# hide all lines between previous and next line with a lower depth
var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth
var cursor-y/edx: (addr int) <- get self, cursor-y
var target-depth/ebx: int <- copy *cursor-line-depth
var i/ecx: int <- copy cursor-line-index
$collapse:loop1: {
compare i, 0
break-if-<
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/eax: (addr trace-line) <- index trace, curr-line-offset
{
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-< $collapse:loop1
}
# if cursor-line is visible, decrement cursor-y
{
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
compare *curr-line-visible?, 0/false
break-if-=
decrement *cursor-y
}
i <- decrement
loop
}
i <- increment
var max/edx: (addr int) <- get self, first-free
$collapse:loop2: {
compare i, *max
break-if->=
var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i
var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset
var curr-line-depth/eax: (addr int) <- get curr-line, depth
compare *curr-line-depth, target-depth
break-if-<
{
hide-trace-line self, curr-line
var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible?
copy-to *curr-line-visible?, 0/false
}
i <- increment
loop
}
}
# the 'visible' array is not required to be in order
# elements can also be deleted out of order
# so it can have holes
# however, lines in it always have visible? set
# we'll use visible? being unset as a sign of emptiness
fn reveal-trace-line _self: (addr trace), line: (addr trace-line) {
var self/esi: (addr trace) <- copy _self
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
var visible/eax: (addr array trace-line) <- lookup *visible-ah
var i/ecx: int <- copy 0
var len/edx: int <- length visible
{
compare i, len
break-if->=
var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
var curr/edx: (addr trace-line) <- index visible, curr-offset
var curr-visible?/eax: (addr boolean) <- get curr, visible?
compare *curr-visible?, 0/false
{
break-if-!=
# empty slot found
copy-object line, curr
return
}
i <- increment
loop
}
abort "too many visible lines; increase size of array trace.visible"
}
fn hide-trace-line _self: (addr trace), line: (addr trace-line) {
var self/esi: (addr trace) <- copy _self
var visible-ah/eax: (addr handle array trace-line) <- get self, visible
var visible/eax: (addr array trace-line) <- lookup *visible-ah
var i/ecx: int <- copy 0
var len/edx: int <- length visible
{
compare i, len
break-if->=
var curr-offset/edx: (offset trace-line) <- compute-offset visible, i
var curr/edx: (addr trace-line) <- index visible, curr-offset
var found?/eax: boolean <- trace-lines-equal? curr, line
compare found?, 0/false
{
break-if-=
clear-object curr
}
i <- increment
loop
}
}
fn test-cursor-down-and-up-within-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/pre-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/pre-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/pre-2/cursor"
# cursor down
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-and-up-within-trace/down-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||||| ", "F - test-cursor-down-and-up-within-trace/down-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/down-2/cursor"
# cursor up
edit-trace t, 0x6b/k
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/up-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/up-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/up-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/up-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/up-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/up-2/cursor"
}
fn test-cursor-down-past-bottom-of-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
error t, "error"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/pre-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-2/cursor"
# cursor down several times
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
# hack: we do need to render to make this test pass; we're mixing state management with rendering
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor
# cursor clamps at bottom
check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-0/cursor"
check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-1/cursor"
check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/down-2/cursor"
}
fn test-expand-within-trace {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-expand-within-trace/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-expand-within-trace/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-expand-within-trace/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-expand-within-trace/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-expand-within-trace/expand-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-expand-within-trace/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/expand-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-expand-within-trace/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-expand-within-trace/expand-2/cursor"
}
fn test-trace-expand-skips-lower-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-skips-lower-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-skips-lower-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-expand-skips-lower-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-skips-lower-depth/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-skips-lower-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/expand-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2/cursor"
}
fn test-trace-expand-continues-past-lower-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-continues-past-lower-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-continues-past-lower-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-expand-continues-past-lower-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-continues-past-lower-depth/expand-0/cursor"
# TODO: might be too wasteful to show every place where lines are hidden
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-continues-past-lower-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-expand-continues-past-lower-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-2/cursor"
}
fn test-trace-expand-stops-at-higher-depth {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-lower t
trace-text t, "l", "line 1.1"
trace-lower t
trace-text t, "l", "line 1.1.1"
trace-higher t
trace-text t, "l", "line 1.2"
trace-higher t
trace-text t, "l", "line 2"
trace-lower t
trace-text t, "l", "line 2.1"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-stops-at-higher-depth/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-stops-at-higher-depth/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "2 line 1.1 ", "F - test-trace-expand-stops-at-higher-depth/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||||| ", "F - test-trace-expand-stops-at-higher-depth/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-1/cursor"
check-screen-row screen, 2/y, "2 line 1.2 ", "F - test-trace-expand-stops-at-higher-depth/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-3/cursor"
check-screen-row screen, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4"
check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4/cursor"
}
fn test-trace-expand-twice {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-expand-twice/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-twice/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-expand-twice/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-expand-twice/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-twice/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-expand-twice/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
# hack: we need to render here to make this test pass; we're mixing state management with rendering
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-expand-twice/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/down-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||| ", "F - test-trace-expand-twice/down-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-expand-twice/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/down-2/cursor"
# expand again
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-expand-twice/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/expand2-0/cursor"
check-screen-row screen, 1/y, "2 line 1.1 ", "F - test-trace-expand-twice/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-expand-twice/expand2-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-expand-twice/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand2-2/cursor"
}
fn test-trace-refresh-cursor {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-refresh-cursor/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-refresh-cursor/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-refresh-cursor/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-refresh-cursor/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-refresh-cursor/expand-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-refresh-cursor/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-refresh-cursor/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-refresh-cursor/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-refresh-cursor/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/down-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-refresh-cursor/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/down-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-refresh-cursor/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/down-2/cursor"
# recreate trace
clear-trace t
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# cursor remains unchanged
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-refresh-cursor/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/refresh-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-refresh-cursor/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/refresh-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-refresh-cursor/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/refresh-2/cursor"
}
fn test-trace-preserve-cursor-on-refresh {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-preserve-cursor-on-refresh/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-preserve-cursor-on-refresh/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-preserve-cursor-on-refresh/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/expand-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-preserve-cursor-on-refresh/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-preserve-cursor-on-refresh/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-preserve-cursor-on-refresh/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-preserve-cursor-on-refresh/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-preserve-cursor-on-refresh/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/down-2/cursor"
# recreate trace with slightly different lines
clear-trace t
trace-text t, "l", "line 4"
trace-text t, "l", "line 5"
trace-text t, "l", "line 3" # cursor line is unchanged
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# cursor remains unchanged
check-screen-row screen, 0/y, "1 line 4 ", "F - test-trace-preserve-cursor-on-refresh/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-0/cursor"
check-screen-row screen, 1/y, "1 line 5 ", "F - test-trace-preserve-cursor-on-refresh/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-preserve-cursor-on-refresh/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/refresh-2/cursor"
}
fn test-trace-keep-cursor-visible-on-refresh {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
trace-text t, "l", "line 3"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2/cursor"
# cursor down
edit-trace t, 0x6a/j
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/down-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/down-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-1/cursor"
check-screen-row screen, 2/y, "1 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/down-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/down-2/cursor"
# recreate trace with entirely different lines
clear-trace t
trace-text t, "l", "line 4"
trace-text t, "l", "line 5"
trace-text t, "l", "line 6"
mark-lines-dirty t
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# trace collapses, and cursor bumps up
check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1/cursor"
check-screen-row screen, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2/cursor"
}
fn test-trace-collapse-at-top {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-at-top/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-at-top/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-at-top/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-at-top/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-at-top/expand-2/cursor"
# collapse
edit-trace t, 8/backspace
# hack: we need to render here to make this test pass; we're mixing state management with rendering
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-at-top/post-0/y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/post-1/cursor"
}
fn test-trace-collapse {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse/expand-0/cursor"
check-screen-row screen, 1/y, "1 line 2 ", "F - test-trace-collapse/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/expand-1/cursor"
# cursor down
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse/post-0/y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/post-1/cursor"
}
fn test-trace-collapse-skips-invisible-lines {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-skips-invisible-lines/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-skips-invisible-lines/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-skips-invisible-lines/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-skips-invisible-lines/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-2/cursor"
# cursor down to second visible line
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-skips-invisible-lines/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 0, "F - test-trace-collapse-skips-invisible-lines/post-0/cursor-y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1/cursor"
}
fn test-trace-collapse-two-levels {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-two-levels/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-two-levels/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-two-levels/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-two-levels/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand-2/cursor"
# cursor down to ellipses
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-two-levels/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-two-levels/expand2-0/cursor"
check-screen-row screen, 1/y, "2 line 1.1 ", "F - test-trace-collapse-two-levels/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-collapse-two-levels/expand2-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-two-levels/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand2-2/cursor"
# cursor down to second visible line
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor
#
check-ints-equal y, 1, "F - test-trace-collapse-two-levels/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 0, "F - test-trace-collapse-two-levels/post-0/cursor-y"
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/post-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/post-1/cursor"
}
fn test-trace-collapse-nested-level {
var t-storage: trace
var t/esi: (addr trace) <- address t-storage
initialize-trace t, 0x100/max-depth, 0x10, 0x10
#
trace-text t, "l", "line 1"
trace-lower t
trace-text t, "l", "line 1.1"
trace-higher t
trace-text t, "l", "line 2"
trace-lower t
trace-text t, "l", "line 2.1"
trace-text t, "l", "line 2.2"
trace-higher t
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics
#
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-nested-level/pre-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-nested-level/pre-0/cursor"
check-screen-row screen, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1/cursor"
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-nested-level/expand-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-nested-level/expand-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-nested-level/expand-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/expand-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/expand-3/cursor"
# cursor down to bottom
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
edit-trace t, 0x6a/j
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# expand
edit-trace t, 0xa/enter
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
# two visible lines with an invisible line in between
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-nested-level/expand2-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/expand2-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand2-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand2-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-nested-level/expand2-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand2-2/cursor"
check-screen-row screen, 3/y, "2 line 2.1 ", "F - test-trace-collapse-nested-level/expand2-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "|||||||||| ", "F - test-trace-collapse-nested-level/expand2-3/cursor"
check-screen-row screen, 4/y, "2 line 2.2 ", "F - test-trace-collapse-nested-level/expand2-4"
check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-collapse-nested-level/expand2-4/cursor"
# collapse
edit-trace t, 8/backspace
clear-screen screen
var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor
#
check-ints-equal y, 4, "F - test-trace-collapse-nested-level/post-0/y"
var cursor-y/eax: (addr int) <- get t, cursor-y
check-ints-equal *cursor-y, 2, "F - test-trace-collapse-nested-level/post-0/cursor-y"
check-screen-row screen, 0/y, "1 line 1 ", "F - test-trace-collapse-nested-level/post-0"
check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/post-0/cursor"
check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/post-1"
check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/post-1/cursor"
check-screen-row screen, 2/y, "1 line 2 ", "F - test-trace-collapse-nested-level/post-2"
check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-collapse-nested-level/post-2/cursor"
check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/post-3"
check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/post-3/cursor"
}