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