https://github.com/akkartik/mu/blob/main/shell/cell.mu

      1 type cell {
      2   type: int
      3   # type 0: pair; the unit of lists, trees, DAGS or graphs
      4   left: (handle cell)
      5   right: (handle cell)
      6   # type 1: number
      7   number-data: float
      8   # type 2: symbol
      9   # type 3: stream
     10   text-data: (handle stream byte)
     11   # type 4: primitive function
     12   index-data: int
     13   # type 5: screen
     14   screen-data: (handle screen)
     15   # type 6: keyboard
     16   keyboard-data: (handle gap-buffer)
     17   # TODO: array, (associative) table
     18   # if you add types here, don't forget to update cell-isomorphic?
     19 }
     20
     21 fn allocate-symbol _out: (addr handle cell) {
     22   var out/eax: (addr handle cell) <- copy _out
     23   allocate out
     24   var out-addr/eax: (addr cell) <- lookup *out
     25   var type/ecx: (addr int) <- get out-addr, type
     26   copy-to *type, 2/symbol
     27   var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data
     28   populate-stream dest-ah, 0x40/max-symbol-size
     29 }
     30
     31 fn initialize-symbol _out: (addr handle cell), val: (addr array byte) {
     32   var out/eax: (addr handle cell) <- copy _out
     33   var out-addr/eax: (addr cell) <- lookup *out
     34   var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data
     35   var dest/eax: (addr stream byte) <- lookup *dest-ah
     36   write dest, val
     37 }
     38
     39 fn new-symbol out: (addr handle cell), val: (addr array byte) {
     40   allocate-symbol out
     41   initialize-symbol out, val
     42 }
     43
     44 fn symbol-equal? _in: (addr cell), name: (addr array byte) -> _/eax: boolean {
     45   var in/esi: (addr cell) <- copy _in
     46   var in-type/eax: (addr int) <- get in, type
     47   compare *in-type, 2/symbol
     48   {
     49     break-if-=
     50     return 0/false
     51   }
     52   var in-data-ah/eax: (addr handle stream byte) <- get in, text-data
     53   var in-data/eax: (addr stream byte) <- lookup *in-data-ah
     54   var result/eax: boolean <- stream-data-equal? in-data, name
     55   return result
     56 }
     57
     58 fn allocate-stream _out: (addr handle cell) {
     59   var out/eax: (addr handle cell) <- copy _out
     60   allocate out
     61   var out-addr/eax: (addr cell) <- lookup *out
     62   var type/ecx: (addr int) <- get out-addr, type
     63   copy-to *type, 3/stream
     64   var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data
     65   populate-stream dest-ah, 0x40/max-stream-size
     66 }
     67
     68 fn allocate-number _out: (addr handle cell) {
     69   var out/eax: (addr handle cell) <- copy _out
     70   allocate out
     71   var out-addr/eax: (addr cell) <- lookup *out
     72   var type/ecx: (addr int) <- get out-addr, type
     73   copy-to *type, 1/number
     74 }
     75
     76 fn initialize-integer _out: (addr handle cell), n: int {
     77   var out/eax: (addr handle cell) <- copy _out
     78   var out-addr/eax: (addr cell) <- lookup *out
     79   var dest-addr/eax: (addr float) <- get out-addr, number-data
     80   var src/xmm0: float <- convert n
     81   copy-to *dest-addr, src
     82 }
     83
     84 fn new-integer out: (addr handle cell), n: int {
     85   allocate-number out
     86   initialize-integer out, n
     87 }
     88
     89 fn initialize-float _out: (addr handle cell), n: float {
     90   var out/eax: (addr handle cell) <- copy _out
     91   var out-addr/eax: (addr cell) <- lookup *out
     92   var dest-ah/eax: (addr float) <- get out-addr, number-data
     93   var src/xmm0: float <- copy n
     94   copy-to *dest-ah, src
     95 }
     96
     97 fn new-float out: (addr handle cell), n: float {
     98   allocate-number out
     99   initialize-float out, n
    100 }
    101
    102 fn allocate-pair out: (addr handle cell) {
    103   allocate out
    104   # new cells have type pair by default
    105 }
    106
    107 fn initialize-pair _out: (addr handle cell), left: (handle cell), right: (handle cell) {
    108   var out/eax: (addr handle cell) <- copy _out
    109   var out-addr/eax: (addr cell) <- lookup *out
    110   var dest-ah/ecx: (addr handle cell) <- get out-addr, left
    111   copy-handle left, dest-ah
    112   dest-ah <- get out-addr, right
    113   copy-handle right, dest-ah
    114 }
    115
    116 fn new-pair out: (addr handle cell), left: (handle cell), right: (handle cell) {
    117   allocate-pair out
    118   initialize-pair out, left, right
    119 }
    120
    121 fn nil out: (addr handle cell) {
    122   allocate-pair out
    123 }
    124
    125 fn allocate-primitive-function _out: (addr handle cell) {
    126   var out/eax: (addr handle cell) <- copy _out
    127   allocate out
    128   var out-addr/eax: (addr cell) <- lookup *out
    129   var type/ecx: (addr int) <- get out-addr, type
    130   copy-to *type, 4/primitive-function
    131 }
    132
    133 fn initialize-primitive-function _out: (addr handle cell), n: int {
    134   var out/eax: (addr handle cell) <- copy _out
    135   var out-addr/eax: (addr cell) <- lookup *out
    136   var dest-addr/eax: (addr int) <- get out-addr, index-data
    137   var src/ecx: int <- copy n
    138   copy-to *dest-addr, src
    139 }
    140
    141 fn new-primitive-function out: (addr handle cell), n: int {
    142   allocate-primitive-function out
    143   initialize-primitive-function out, n
    144 }
    145
    146 fn allocate-screen _out: (addr handle cell) {
    147   var out/eax: (addr handle cell) <- copy _out
    148   allocate out
    149   var out-addr/eax: (addr cell) <- lookup *out
    150   var type/ecx: (addr int) <- get out-addr, type
    151   copy-to *type, 5/screen
    152 }
    153
    154 fn new-fake-screen _out: (addr handle cell), width: int, height: int, pixel-graphics?: boolean {
    155   var out/eax: (addr handle cell) <- copy _out
    156   allocate-screen out
    157   var out-addr/eax: (addr cell) <- lookup *out
    158   var dest-ah/eax: (addr handle screen) <- get out-addr, screen-data
    159   allocate dest-ah
    160   var dest-addr/eax: (addr screen) <- lookup *dest-ah
    161   initialize-screen dest-addr, width, height, pixel-graphics?
    162 }
    163
    164 fn clear-screen-var _self-ah: (addr handle cell) {
    165   var self-ah/eax: (addr handle cell) <- copy _self-ah
    166   var self/eax: (addr cell) <- lookup *self-ah
    167   compare self, 0
    168   {
    169     break-if-!=
    170     return
    171   }
    172   var screen-ah/eax: (addr handle screen) <- get self, screen-data
    173   var screen/eax: (addr screen) <- lookup *screen-ah
    174   clear-screen screen
    175 }
    176
    177 fn allocate-keyboard _out: (addr handle cell) {
    178   var out/eax: (addr handle cell) <- copy _out
    179   allocate out
    180   var out-addr/eax: (addr cell) <- lookup *out
    181   var type/ecx: (addr int) <- get out-addr, type
    182   copy-to *type, 6/keyboard
    183 }
    184
    185 fn new-fake-keyboard _out: (addr handle cell), capacity: int {
    186   var out/eax: (addr handle cell) <- copy _out
    187   allocate-keyboard out
    188   var out-addr/eax: (addr cell) <- lookup *out
    189   var dest-ah/eax: (addr handle gap-buffer) <- get out-addr, keyboard-data
    190   allocate dest-ah
    191   var dest-addr/eax: (addr gap-buffer) <- lookup *dest-ah
    192   initialize-gap-buffer dest-addr, capacity
    193 }
    194
    195 fn rewind-keyboard-var _self-ah: (addr handle cell) {
    196   var self-ah/eax: (addr handle cell) <- copy _self-ah
    197   var self/eax: (addr cell) <- lookup *self-ah
    198   compare self, 0
    199   {
    200     break-if-!=
    201     return
    202   }
    203   var keyboard-ah/eax: (addr handle gap-buffer) <- get self, keyboard-data
    204   var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah
    205   rewind-gap-buffer keyboard
    206 }