## Rendering values fn render-value screen: (addr screen), _val: (addr value), max-width: int { $render-value:body: { var val/esi: (addr value) <- copy _val var val-type/ecx: (addr int) <- get val, type # per-type rendering logic goes here compare *val-type, 1 # string { break-if-!= var val-ah/eax: (addr handle array byte) <- get val, text-data var val-string/eax: (addr array byte) <- lookup *val-ah compare val-string, 0 break-if-= var orig-len/ecx: int <- length val-string var truncated: (handle array byte) var truncated-ah/esi: (addr handle array byte) <- address truncated substring val-string, 0, 0xc, truncated-ah var truncated-string/eax: (addr array byte) <- lookup *truncated-ah #? { #? var foo/eax: int <- copy truncated-string #? print-int32-hex 0, foo #? print-string 0, "\n" #? } var len/edx: int <- length truncated-string start-color screen, 0xf2, 7 print-code-point screen, 0x275d # open-quote print-string screen, truncated-string compare len, orig-len { break-if-= print-code-point screen, 0x2026 # ellipses } print-code-point screen, 0x275e # close-quote reset-formatting screen break $render-value:body } compare *val-type, 2 # array { break-if-!= var val-ah/eax: (addr handle array value) <- get val, array-data var val-array/eax: (addr array value) <- lookup *val-ah render-array screen, val-array break $render-value:body } compare *val-type, 3 # file { break-if-!= var val-ah/eax: (addr handle buffered-file) <- get val, file-data var val-file/eax: (addr buffered-file) <- lookup *val-ah start-color screen, 0, 7 # TODO print-string screen, " FILE " break $render-value:body } compare *val-type, 4 # file { break-if-!= var val-ah/eax: (addr handle screen) <- get val, screen-data var val-screen/eax: (addr screen) <- lookup *val-ah start-color screen, 0, 7 # TODO print-string screen, " SCREEN " break $render-value:body } # render ints by default for now var val-int/eax: (addr int) <- get val, int-data render-integer screen, *val-int, max-width } } # synaesthesia fn render-integer screen: (addr screen), val: int, max-width: int { $render-integer:body: { # if max-width is 0, we're inside an array. No coloring. compare max-width, 0 { break-if-!= print-int32-decimal screen, val break $render-integer:body } var bg/eax: int <- hash-color val var fg/ecx: int <- copy 7 { compare bg, 2 break-if-!= fg <- copy 0 } { compare bg, 3 break-if-!= fg <- copy 0 } { compare bg, 6 break-if-!= fg <- copy 0 } start-color screen, fg, bg print-grapheme screen, 0x20 # space print-int32-decimal-right-justified screen, val, max-width print-grapheme screen, 0x20 # space } } fn render-array screen: (addr screen), _a: (addr array value) { start-color screen, 0xf2, 7 # don't surround in spaces print-grapheme screen, 0x5b # '[' var a/esi: (addr array value) <- copy _a var max/ecx: int <- length a var i/eax: int <- copy 0 { compare i, max break-if->= { compare i, 0 break-if-= print-string screen, " " } var off/ecx: (offset value) <- compute-offset a, i var x/ecx: (addr value) <- index a, off render-value screen, x, 0 i <- increment loop } print-grapheme screen, 0x5d # ']' } fn hash-color val: int -> _/eax: int { var result/eax: int <- try-modulo val, 7 # assumes that 7 is always the background color return result } fn value-width _v: (addr value), top-level: boolean -> _/eax: int { var v/esi: (addr value) <- copy _v var type/eax: (addr int) <- get v, type { compare *type, 0 # int break-if-!= var v-int/edx: (addr int) <- get v, int-data var result/eax: int <- decimal-size *v-int return result } { compare *type, 1 # string break-if-!= var s-ah/eax: (addr handle array byte) <- get v, text-data var s/eax: (addr array byte) <- lookup *s-ah compare s, 0 break-if-= var result/eax: int <- length s compare result, 0xd # max string size { break-if-<= result <- copy 0xd } # if it's a nested string, include space for quotes # we don't do this for the top-level, where the quotes will overflow # into surrounding padding. compare top-level, 0 # false { break-if-!= result <- add 2 } return result } { compare *type, 2 # array break-if-!= var a-ah/eax: (addr handle array value) <- get v, array-data var a/eax: (addr array value) <- lookup *a-ah compare a, 0 break-if-= var result/eax: int <- array-width a return result } { compare *type, 3 # file handle break-if-!= var f-ah/eax: (addr handle buffered-file) <- get v, file-data var f/eax: (addr buffered-file) <- lookup *f-ah compare f, 0 break-if-= # TODO: visualizing file handles return 4 } { compare *type, 4 # screen break-if-!= var screen-ah/eax: (addr handle screen) <- get v, screen-data var screen/eax: (addr screen) <- lookup *screen-ah compare screen, 0 break-if-= # TODO: visualizing screen return 6 } return 0 } # keep sync'd with render-array fn array-width _a: (addr array value) -> _/eax: int { var a/esi: (addr array value) <- copy _a var max/ecx: int <- length a var i/eax: int <- copy 0 var result/edi: int <- copy 0 { compare i, max break-if->= { compare i, 0 break-if-= result <- increment # for space } var off/ecx: (offset value) <- compute-offset a, i var x/ecx: (addr value) <- index a, off { var w/eax: int <- value-width x, 0 result <- add w } i <- increment loop } # we won't add 2 for surrounding brackets since we don't surround arrays in # spaces like other value types return result }