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