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   var out/eax: (addr handle cell) <- copy _out
 89   allocate out
 90   # new cells have type pair by default
 91 }
 92 
 93 fn initialize-pair _out: (addr handle cell), left: (handle cell), right: (handle cell) {
 94   var out/eax: (addr handle cell) <- copy _out
 95   var out-addr/eax: (addr cell) <- lookup *out
 96   var dest-ah/ecx: (addr handle cell) <- get out-addr, left
 97   copy-handle left, dest-ah
 98   dest-ah <- get out-addr, right
 99   copy-handle right, dest-ah
100 }
101 
102 fn new-pair out: (addr handle cell), left: (handle cell), right: (handle cell) {
103   allocate-pair out
104   initialize-pair out, left, right
105 }
106 
107 fn nil out: (addr handle cell) {
108   allocate-pair out
109 }
110 
111 fn allocate-primitive-function _out: (addr handle cell) {
112   var out/eax: (addr handle cell) <- copy _out
113   allocate out
114   var out-addr/eax: (addr cell) <- lookup *out
115   var type/ecx: (addr int) <- get out-addr, type
116   copy-to *type, 4/primitive-function
117 }
118 
119 fn initialize-primitive-function _out: (addr handle cell), n: int {
120   var out/eax: (addr handle cell) <- copy _out
121   var out-addr/eax: (addr cell) <- lookup *out
122   var dest-addr/eax: (addr int) <- get out-addr, index-data
123   var src/ecx: int <- copy n
124   copy-to *dest-addr, src
125 }
126 
127 fn new-primitive-function out: (addr handle cell), n: int {
128   allocate-primitive-function out
129   initialize-primitive-function out, n
130 }
131 
132 fn allocate-screen _out: (addr handle cell) {
133   var out/eax: (addr handle cell) <- copy _out
134   allocate out
135   var out-addr/eax: (addr cell) <- lookup *out
136   var dest-ah/ecx: (addr handle screen) <- get out-addr, screen-data
137   allocate dest-ah
138   var type/ecx: (addr int) <- get out-addr, type
139   copy-to *type, 5/screen
140 }
141 
142 fn new-screen _out: (addr handle cell), width: int, height: int {
143   var out/eax: (addr handle cell) <- copy _out
144   allocate-screen out
145   var out-addr/eax: (addr cell) <- lookup *out
146   var dest-ah/eax: (addr handle screen) <- get out-addr, screen-data
147   var dest-addr/eax: (addr screen) <- lookup *dest-ah
148   initialize-screen dest-addr, width, height
149 }
150 
151 fn clear-screen-cell _self-ah: (addr handle cell) {
152   var self-ah/eax: (addr handle cell) <- copy _self-ah
153   var self/eax: (addr cell) <- lookup *self-ah
154   compare self, 0
155   {
156     break-if-!=
157     return
158   }
159   var screen-ah/eax: (addr handle screen) <- get self, screen-data
160   var screen/eax: (addr screen) <- lookup *screen-ah
161   clear-screen screen
162 }
163 
164 fn allocate-keyboard _out: (addr handle cell) {
165   var out/eax: (addr handle cell) <- copy _out
166   allocate out
167   var out-addr/eax: (addr cell) <- lookup *out
168   var dest-ah/ecx: (addr handle gap-buffer) <- get out-addr, keyboard-data
169   allocate dest-ah
170   var type/ecx: (addr int) <- get out-addr, type
171   copy-to *type, 6/keyboard
172 }
173 
174 fn new-keyboard _out: (addr handle cell), capacity: int {
175   var out/eax: (addr handle cell) <- copy _out
176   allocate-keyboard out
177   var out-addr/eax: (addr cell) <- lookup *out
178   var dest-ah/eax: (addr handle gap-buffer) <- get out-addr, keyboard-data
179   var dest-addr/eax: (addr gap-buffer) <- lookup *dest-ah
180   initialize-gap-buffer dest-addr, capacity
181 }
182 
183 fn rewind-keyboard-cell _self-ah: (addr handle cell) {
184   var self-ah/eax: (addr handle cell) <- copy _self-ah
185   var self/eax: (addr cell) <- lookup *self-ah
186   compare self, 0
187   {
188     break-if-!=
189     return
190   }
191   var keyboard-ah/eax: (addr handle gap-buffer) <- get self, keyboard-data
192   var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah
193   rewind-gap-buffer keyboard
194 }