https://github.com/akkartik/mu/blob/main/linux/tile/value.mu

      1 fn render-value-at screen: (addr screen), row: int, col: int, _val: (addr value), top-level?: boolean {
      2   move-cursor screen, row, col
      3   var val/esi: (addr value) <- copy _val
      4   var val-type/ecx: (addr int) <- get val, type
      5   # per-type rendering logic goes here
      6   compare *val-type, 1/string
      7   {
      8     break-if-!=
      9     var val-ah/eax: (addr handle array byte) <- get val, text-data
     10     var val-string/eax: (addr array byte) <- lookup *val-ah
     11     compare val-string, 0
     12     break-if-=
     13     var orig-len/ecx: int <- length val-string
     14     var truncated: (handle array byte)
     15     var truncated-ah/esi: (addr handle array byte) <- address truncated
     16     substring val-string, 0, 0xc, truncated-ah
     17     var truncated-string/eax: (addr array byte) <- lookup *truncated-ah
     18     var len/edx: int <- length truncated-string
     19     start-color screen, 0xf2, 7
     20     print-code-point screen, 0x275d/open-quote
     21     print-string screen, truncated-string
     22     compare len, orig-len
     23     {
     24       break-if-=
     25       print-code-point screen, 0x2026/ellipses
     26     }
     27     print-code-point screen, 0x275e/close-quote
     28     reset-formatting screen
     29     return
     30   }
     31   compare *val-type, 2/array
     32   {
     33     break-if-!=
     34     var val-ah/eax: (addr handle array value) <- get val, array-data
     35     var val-array/eax: (addr array value) <- lookup *val-ah
     36     render-array-at screen, row, col, val-array
     37     return
     38   }
     39   compare *val-type, 3/file
     40   {
     41     break-if-!=
     42     var val-ah/eax: (addr handle buffered-file) <- get val, file-data
     43     var val-file/eax: (addr buffered-file) <- lookup *val-ah
     44     start-color screen, 0, 7
     45     # TODO
     46     print-string screen, " FILE "
     47     return
     48   }
     49   compare *val-type, 4/screen
     50   {
     51     break-if-!=
     52 #?     print-string 0, "render-screen"
     53     var val-ah/eax: (addr handle screen) <- get val, screen-data
     54     var val-screen/eax: (addr screen) <- lookup *val-ah
     55     render-screen screen, row, col, val-screen
     56 #?     print-string 0, "}\n"
     57     return
     58   }
     59   # render ints by default for now
     60   var val-num/eax: (addr float) <- get val, number-data
     61   render-number screen, *val-num, top-level?
     62 }
     63
     64 # synaesthesia
     65 # TODO: right-justify
     66 fn render-number screen: (addr screen), val: float, top-level?: boolean {
     67   # if we're inside an array, don't color
     68   compare top-level?, 0
     69   {
     70     break-if-!=
     71     print-float-decimal-approximate screen, val, 3
     72     return
     73   }
     74   var val-int/eax: int <- convert val
     75   var bg/eax: int <- hash-color val-int
     76   var fg/ecx: int <- copy 7
     77   {
     78     compare bg, 2
     79     break-if-!=
     80     fg <- copy 0
     81   }
     82   {
     83     compare bg, 3
     84     break-if-!=
     85     fg <- copy 0
     86   }
     87   {
     88     compare bg, 6
     89     break-if-!=
     90     fg <- copy 0
     91   }
     92   start-color screen, fg, bg
     93   print-grapheme screen, 0x20/space
     94   print-float-decimal-approximate screen, val, 3
     95   print-grapheme screen, 0x20/space
     96 }
     97
     98 fn render-array-at screen: (addr screen), row: int, col: int, _a: (addr array value) {
     99   start-color screen, 0xf2, 7
    100   # don't surround in spaces
    101   print-grapheme screen, 0x5b/[
    102   increment col
    103   var a/esi: (addr array value) <- copy _a
    104   var max/ecx: int <- length a
    105   var i/eax: int <- copy 0
    106   {
    107     compare i, max
    108     break-if->=
    109     {
    110       compare i, 0
    111       break-if-=
    112       print-string screen, " "
    113     }
    114     var off/ecx: (offset value) <- compute-offset a, i
    115     var x/ecx: (addr value) <- index a, off
    116     render-value-at screen, row, col, x, 0
    117     {
    118       var w/eax: int <- value-width x, 0
    119       add-to col, w
    120       increment col
    121     }
    122     i <- increment
    123     loop
    124   }
    125   print-grapheme screen, 0x5d/]
    126 }
    127
    128 fn render-screen screen: (addr screen), row: int, col: int, _target-screen: (addr screen) {
    129   reset-formatting screen
    130   move-cursor screen, row, col
    131   var target-screen/esi: (addr screen) <- copy _target-screen
    132   var ncols-a/ecx: (addr int) <- get target-screen, num-cols
    133   print-upper-border screen, *ncols-a
    134   var r/edx: int <- copy 1
    135   var nrows-a/ebx: (addr int) <- get target-screen, num-rows
    136   {
    137     compare r, *nrows-a
    138     break-if->
    139     increment row  # mutate arg
    140     move-cursor screen, row, col
    141     print-string screen, " "
    142     var c/edi: int <- copy 1
    143     {
    144       compare c, *ncols-a
    145       break-if->
    146       print-screen-cell-of-fake-screen screen, target-screen, r, c
    147       c <- increment
    148       loop
    149     }
    150     print-string screen, " "
    151     r <- increment
    152     loop
    153   }
    154   increment row  # mutate arg
    155   move-cursor screen, row, col
    156   print-lower-border screen, *ncols-a
    157 }
    158
    159 fn hash-color val: int -> _/eax: int {
    160   var quotient/eax: int <- copy 0
    161   var remainder/edx: int <- copy 0
    162   quotient, remainder <- integer-divide val, 7  # assumes that 7 is always the background color
    163   return remainder
    164 }
    165
    166 fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), _row: int, _col: int {
    167   start-color screen, 0, 0xf6
    168   var target/esi: (addr screen) <- copy _target
    169   var row/ecx: int <- copy _row
    170   var col/edx: int <- copy _col
    171   # if cursor is at screen-cell, add some fancy
    172   {
    173     var cursor-row/eax: (addr int) <- get target, cursor-row
    174     compare *cursor-row, row
    175     break-if-!=
    176     var cursor-col/eax: (addr int) <- get target, cursor-col
    177     compare *cursor-col, col
    178     break-if-!=
    179     start-blinking screen
    180     start-color screen, 0, 1
    181   }
    182   var g/eax: grapheme <- screen-grapheme-at target, row, col
    183   {
    184     compare g, 0
    185     break-if-!=
    186     g <- copy 0x20/space
    187   }
    188   print-grapheme screen, g
    189   reset-formatting screen
    190 }
    191
    192 fn print-upper-border screen: (addr screen), width: int {
    193   print-code-point screen, 0x250c/top-left-corner
    194   var i/eax: int <- copy 0
    195   {
    196     compare i, width
    197     break-if->=
    198     print-code-point screen, 0x2500/horizontal-line
    199     i <- increment
    200     loop
    201   }
    202   print-code-point screen, 0x2510/top-right-corner
    203 }
    204
    205 fn print-lower-border screen: (addr screen), width: int {
    206   print-code-point screen, 0x2514/bottom-left-corner
    207   var i/eax: int <- copy 0
    208   {
    209     compare i, width
    210     break-if->=
    211     print-code-point screen, 0x2500/horizontal-line
    212     i <- increment
    213     loop
    214   }
    215   print-code-point screen, 0x2518/bottom-right-corner
    216 }
    217
    218 fn value-width _v: (addr value), top-level: boolean -> _/eax: int {
    219   var v/esi: (addr value) <- copy _v
    220   var type/eax: (addr int) <- get v, type
    221   {
    222     compare *type, 0/int
    223     break-if-!=
    224     var v-num/edx: (addr float) <- get v, number-data
    225     var result/eax: int <- float-size *v-num, 3
    226     return result
    227   }
    228   {
    229     compare *type, 1/string
    230     break-if-!=
    231     var s-ah/eax: (addr handle array byte) <- get v, text-data
    232     var s/eax: (addr array byte) <- lookup *s-ah
    233     compare s, 0
    234     break-if-=
    235     var result/eax: int <- length s
    236     compare result, 0xd/max-string-size
    237     {
    238       break-if-<=
    239       result <- copy 0xd
    240     }
    241     # if it's a nested string, include space for quotes
    242     # we don't do this for the top-level, where the quotes will overflow
    243     # into surrounding padding.
    244     compare top-level, 0/false
    245     {
    246       break-if-!=
    247       result <- add 2
    248     }
    249     return result
    250   }
    251   {
    252     compare *type, 2/array
    253     break-if-!=
    254     var a-ah/eax: (addr handle array value) <- get v, array-data
    255     var a/eax: (addr array value) <- lookup *a-ah
    256     compare a, 0
    257     break-if-=
    258     var result/eax: int <- array-width a
    259     return result
    260   }
    261   {
    262     compare *type, 3/file
    263     break-if-!=
    264     var f-ah/eax: (addr handle buffered-file) <- get v, file-data
    265     var f/eax: (addr buffered-file) <- lookup *f-ah
    266     compare f, 0
    267     break-if-=
    268     # TODO: visualizing file handles
    269     return 4
    270   }
    271   {
    272     compare *type, 4/screen
    273     break-if-!=
    274     var screen-ah/eax: (addr handle screen) <- get v, screen-data
    275     var screen/eax: (addr screen) <- lookup *screen-ah
    276     compare screen, 0
    277     break-if-=
    278     var ncols/ecx: (addr int) <- get screen, num-cols
    279     var result/eax: int <- copy *ncols
    280     result <- add 2  # left/right margins
    281     return *ncols
    282   }
    283   return 0
    284 }
    285
    286 # keep sync'd with render-array-at
    287 fn array-width _a: (addr array value) -> _/eax: int {
    288   var a/esi: (addr array value) <- copy _a
    289   var max/ecx: int <- length a
    290   var i/eax: int <- copy 0
    291   var result/edi: int <- copy 0
    292   {
    293     compare i, max
    294     break-if->=
    295     {
    296       compare i, 0
    297       break-if-=
    298       result <- increment  # for space
    299     }
    300     var off/ecx: (offset value) <- compute-offset a, i
    301     var x/ecx: (addr value) <- index a, off
    302     {
    303       var w/eax: int <- value-width x, 0
    304       result <- add w
    305     }
    306     i <- increment
    307     loop
    308   }
    309   # we won't add 2 for surrounding brackets since we don't surround arrays in
    310   # spaces like other value types
    311   return result
    312 }
    313
    314 fn value-height _v: (addr value) -> _/eax: int {
    315   var v/esi: (addr value) <- copy _v
    316   var type/eax: (addr int) <- get v, type
    317   {
    318     compare *type, 3/file
    319     break-if-!=
    320     # TODO: visualizing file handles
    321     return 1
    322   }
    323   {
    324     compare *type, 4/screen
    325     break-if-!=
    326     var screen-ah/eax: (addr handle screen) <- get v, screen-data
    327     var screen/eax: (addr screen) <- lookup *screen-ah
    328     compare screen, 0
    329     break-if-=
    330     var nrows/ecx: (addr int) <- get screen, num-rows
    331     var result/eax: int <- copy *nrows
    332     result <- add 2  # top and bottom border
    333     return result
    334   }
    335   return 1
    336 }
    337
    338 fn deep-copy-value _src: (addr value), _dest: (addr value) {
    339 #?   print-string 0, "deep-copy-value\n"
    340   var src/esi: (addr value) <- copy _src
    341   var dest/edi: (addr value) <- copy _dest
    342   var type/ebx: (addr int) <- get src, type
    343   var y/ecx: (addr int) <- get dest, type
    344   copy-object type, y
    345   compare *type, 0   # int
    346   {
    347     break-if-!=
    348 #?     print-string 0, "int value\n"
    349     var src-n/eax: (addr float) <- get src, number-data
    350     var dest-n/ecx: (addr float) <- get dest, number-data
    351     copy-object src-n, dest-n
    352     return
    353   }
    354   compare *type, 1/string
    355   {
    356     break-if-!=
    357 #?     print-string 0, "string value\n"
    358     var src-ah/eax: (addr handle array byte) <- get src, text-data
    359     var src/eax: (addr array byte) <- lookup *src-ah
    360     var dest-ah/edx: (addr handle array byte) <- get dest, text-data
    361     copy-array-object src, dest-ah
    362     return
    363   }
    364   compare *type, 2/array
    365   {
    366     break-if-!=
    367 #?     print-string 0, "array value\n"
    368     var src-ah/eax: (addr handle array value) <- get src, array-data
    369     var _src/eax: (addr array value) <- lookup *src-ah
    370     var src/esi: (addr array value) <- copy _src
    371     var n/ecx: int <- length src
    372     var dest-ah/edx: (addr handle array value) <- get dest, array-data
    373     populate dest-ah, n
    374     var _dest/eax: (addr array value) <- lookup *dest-ah
    375     var dest/edi: (addr array value) <- copy _dest
    376     var i/eax: int <- copy 0
    377     {
    378       compare i, n
    379       break-if->=
    380       {
    381         var offset/edx: (offset value) <- compute-offset src, i
    382         var src-element/eax: (addr value) <- index src, offset
    383         var dest-element/ecx: (addr value) <- index dest, offset
    384         deep-copy-value src-element, dest-element
    385       }
    386       i <- increment
    387       loop
    388     }
    389     copy-array-object src, dest-ah
    390     return
    391   }
    392   compare *type, 3/file
    393   {
    394     break-if-!=
    395 #?     print-string 0, "file value\n"
    396     var src-filename-ah/eax: (addr handle array byte) <- get src, filename
    397     var _src-filename/eax: (addr array byte) <- lookup *src-filename-ah
    398     var src-filename/ecx: (addr array byte) <- copy _src-filename
    399     var dest-filename-ah/ebx: (addr handle array byte) <- get dest, filename
    400     copy-array-object src-filename, dest-filename-ah
    401     var src-file-ah/eax: (addr handle buffered-file) <- get src, file-data
    402     var src-file/eax: (addr buffered-file) <- lookup *src-file-ah
    403     var dest-file-ah/edx: (addr handle buffered-file) <- get dest, file-data
    404     copy-file src-file, dest-file-ah, src-filename
    405     return
    406   }
    407   compare *type, 4/screen
    408   {
    409     break-if-!=
    410 #?     print-string 0, "screen value\n"
    411     var src-screen-ah/eax: (addr handle screen) <- get src, screen-data
    412     var _src-screen/eax: (addr screen) <- lookup *src-screen-ah
    413     var src-screen/ecx: (addr screen) <- copy _src-screen
    414     var dest-screen-ah/eax: (addr handle screen) <- get dest, screen-data
    415     allocate dest-screen-ah
    416     var dest-screen/eax: (addr screen) <- lookup *dest-screen-ah
    417     copy-object src-screen, dest-screen
    418     var dest-screen-data-ah/ebx: (addr handle array screen-cell) <- get dest-screen, data
    419     var src-screen-data-ah/eax: (addr handle array screen-cell) <- get src-screen, data
    420     var src-screen-data/eax: (addr array screen-cell) <- lookup *src-screen-data-ah
    421     copy-array-object src-screen-data, dest-screen-data-ah
    422     return
    423   }
    424 }