about summary refs log blame commit diff stats
path: root/apps/tile/value.mu
blob: cd3e1594f4fdc0c91cffbfb0d83bdc88dbee8776 (plain) (tree)
1
2
                                                                                                  
                              














                                                                       










                                                  
          





                                                                    
                                               
          








                                                                     
          
   
                                

               
                                      

                                                                
                                              
                            
          
   



                                                  


































                                                                   
                                                                                      


                                    
               












                                                      
                                          




                                        





                                    


                                                                                           
                              

                                                             
                                     

                                                            

                       
              


                                
                            

                         

                                                                  








                              
                             


                                     




                                                                                           

























                                                                                                         

























                                                         




















































                                                                        






                                                                 



                                                     
   


          
                                  

























                                                                             























                                                                 























































































                                                                                         
fn render-value-at screen: (addr screen), row: int, col: int, _val: (addr value), max-width: int {
  move-cursor screen, row, col
  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 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
    return
  }
  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-at screen, row, col, val-array
    return
  }
  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 "
    return
  }
  compare *val-type, 4  # screen
  {
    break-if-!=
#?     print-string 0, "render-screen"
    var val-ah/eax: (addr handle screen) <- get val, screen-data
    var val-screen/eax: (addr screen) <- lookup *val-ah
    render-screen screen, row, col, val-screen
#?     print-string 0, "}\n"
    return
  }
  # 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-at screen: (addr screen), row: int, col: int, _a: (addr array value) {
  start-color screen, 0xf2, 7
  # don't surround in spaces
  print-grapheme screen, 0x5b  # '['
  increment col
  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-at screen, row, col, x, 0
    {
      var w/eax: int <- value-width x, 0
      add-to col, w
      increment col
    }
    i <- increment
    loop
  }
  print-grapheme screen, 0x5d  # ']'
}

fn render-screen screen: (addr screen), row: int, col: int, _target-screen: (addr screen) {
  reset-formatting screen
  start-color screen, 0xf2, 7
  move-cursor screen, row, col
  var target-screen/esi: (addr screen) <- copy _target-screen
  var ncols-a/ecx: (addr int) <- get target-screen, num-cols
  print-upper-border screen, *ncols-a
  var r/edx: int <- copy 1
  var nrows-a/ebx: (addr int) <- get target-screen, num-rows
  {
    compare r, *nrows-a
    break-if->
    increment row  # mutate arg
    move-cursor screen, row, col
    print-string screen, " "
    var c/edi: int <- copy 1
    {
      compare c, *ncols-a
      break-if->
      print-screen-cell-of-fake-screen screen, target-screen, r, c
      c <- increment
      loop
    }
    print-string screen, " "
    r <- increment
    loop
  }
  increment row  # mutate arg
  move-cursor screen, row, col
  start-color screen, 0xf2, 7
  print-lower-border screen, *ncols-a
}

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 print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), _row: int, _col: int {
  start-color screen, 0, 0xf6
  var target/esi: (addr screen) <- copy _target
  var row/ecx: int <- copy _row
  var col/edx: int <- copy _col
  # if cursor is at screen-cell, add some fancy
  {
    var cursor-row/eax: (addr int) <- get target, cursor-row
    compare *cursor-row, row
    break-if-!=
    var cursor-col/eax: (addr int) <- get target, cursor-col
    compare *cursor-col, col
    break-if-!=
    start-blinking screen
    start-color screen, 0, 1
  }
  var g/eax: grapheme <- screen-grapheme-at target, row, col
  {
    compare g, 0
    break-if-!=
    g <- copy 0x20  # space
  }
  print-grapheme screen, g
  reset-formatting screen
}

fn print-upper-border screen: (addr screen), width: int {
  print-code-point screen, 0x250c  # top-left corner
  var i/eax: int <- copy 0
  {
    compare i, width
    break-if->=
    print-code-point screen, 0x2500  # horizontal line
    i <- increment
    loop
  }
  print-code-point screen, 0x2510  # top-right corner
}

fn print-lower-border screen: (addr screen), width: int {
  print-code-point screen, 0x2514  # bottom-left corner
  var i/eax: int <- copy 0
  {
    compare i, width
    break-if->=
    print-code-point screen, 0x2500  # horizontal line
    i <- increment
    loop
  }
  print-code-point screen, 0x2518  # bottom-right corner
}

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-=
    var ncols/ecx: (addr int) <- get screen, num-cols
    var result/eax: int <- copy *ncols
    result <- add 2  # left/right margins
    return *ncols
  }
  return 0
}

# keep sync'd with render-array-at
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
}

fn value-height _v: (addr value) -> _/eax: int {
  var v/esi: (addr value) <- copy _v
  var type/eax: (addr int) <- get v, type
  {
    compare *type, 3  # file handle
    break-if-!=
    # TODO: visualizing file handles
    return 1
  }
  {
    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-=
    var nrows/ecx: (addr int) <- get screen, num-rows
    var result/eax: int <- copy *nrows
    result <- add 2  # top and bottom border
    return result
  }
  return 1
}

fn deep-copy-value _src: (addr value), _dest: (addr value) {
#?   print-string 0, "deep-copy-value\n"
  var src/esi: (addr value) <- copy _src
  var dest/edi: (addr value) <- copy _dest
  var type/ebx: (addr int) <- get src, type
  var y/ecx: (addr int) <- get dest, type
  copy-object type, y
  compare *type, 0   # int
  {
    break-if-!=
#?     print-string 0, "int value\n"
    var x/eax: (addr int) <- get src, int-data
    y <- get dest, int-data
    copy-object x, y
    return
  }
  compare *type, 1  # string
  {
    break-if-!=
#?     print-string 0, "string value\n"
    var src-ah/eax: (addr handle array byte) <- get src, text-data
    var src/eax: (addr array byte) <- lookup *src-ah
    var dest-ah/edx: (addr handle array byte) <- get dest, text-data
    copy-array-object src, dest-ah
    return
  }
  compare *type, 2  # array
  {
    break-if-!=
#?     print-string 0, "array value\n"
    var src-ah/eax: (addr handle array value) <- get src, array-data
    var _src/eax: (addr array value) <- lookup *src-ah
    var src/esi: (addr array value) <- copy _src
    var n/ecx: int <- length src
    var dest-ah/edx: (addr handle array value) <- get dest, array-data
    populate dest-ah, n
    var _dest/eax: (addr array value) <- lookup *dest-ah
    var dest/edi: (addr array value) <- copy _dest
    var i/eax: int <- copy 0
    {
      compare i, n
      break-if->=
      {
        var offset/edx: (offset value) <- compute-offset src, i
        var src-element/eax: (addr value) <- index src, offset
        var dest-element/ecx: (addr value) <- index dest, offset
        deep-copy-value src-element, dest-element
      }
      i <- increment
      loop
    }
    copy-array-object src, dest-ah
    return
  }
  compare *type, 3  # file
  {
    break-if-!=
#?     print-string 0, "file value\n"
    var src-filename-ah/eax: (addr handle array byte) <- get src, filename
    var _src-filename/eax: (addr array byte) <- lookup *src-filename-ah
    var src-filename/ecx: (addr array byte) <- copy _src-filename
    var dest-filename-ah/ebx: (addr handle array byte) <- get dest, filename
    copy-array-object src-filename, dest-filename-ah
    var src-file-ah/eax: (addr handle buffered-file) <- get src, file-data
    var src-file/eax: (addr buffered-file) <- lookup *src-file-ah
    var dest-file-ah/edx: (addr handle buffered-file) <- get dest, file-data
    copy-file src-file, dest-file-ah, src-filename
    return
  }
  compare *type, 4  # screen
  {
    break-if-!=
#?     print-string 0, "screen value\n"
    var src-screen-ah/eax: (addr handle screen) <- get src, screen-data
    var _src-screen/eax: (addr screen) <- lookup *src-screen-ah
    var src-screen/ecx: (addr screen) <- copy _src-screen
    var dest-screen-ah/eax: (addr handle screen) <- get dest, screen-data
    allocate dest-screen-ah
    var dest-screen/eax: (addr screen) <- lookup *dest-screen-ah
    copy-object src-screen, dest-screen
    var dest-screen-data-ah/ebx: (addr handle array screen-cell) <- get dest-screen, data
    var src-screen-data-ah/eax: (addr handle array screen-cell) <- get src-screen, data
    var src-screen-data/eax: (addr array screen-cell) <- lookup *src-screen-data-ah
    copy-array-object src-screen-data, dest-screen-data-ah
    return
  }
}