https://github.com/akkartik/mu/blob/master/apps/tile/data.mu
  1 type program {
  2   defs: (handle function)
  3   sandboxes: (handle sandbox)
  4 }
  5 
  6 type sandbox {
  7   setup: (handle line)
  8   data: (handle line)
  9   next: (handle sandbox)
 10   prev: (handle sandbox)
 11 }
 12 
 13 type function {
 14   name: (handle array byte)
 15   args: (handle word)  # in reverse order
 16   body: (handle line)
 17   # some sort of indication of spatial location
 18   next: (handle function)
 19 }
 20 
 21 type line {
 22   name: (handle array byte)
 23   data: (handle word)
 24   result: (handle result)  # might be cached
 25   next: (handle line)
 26   prev: (handle line)
 27 }
 28 
 29 type word {
 30   # at most one of these will be non-null
 31   scalar-data: (handle gap-buffer)
 32   text-data: (handle array byte)
 33   box-data: (handle line)  # recurse
 34   # other metadata attached to this word
 35   display-subsidiary-stack?: boolean
 36   next: (handle word)
 37   prev: (handle word)
 38 }
 39 
 40 type value {
 41   scalar-data: int
 42   text-data: (handle array byte)
 43   box-data: (handle line)
 44 }
 45 
 46 type table {
 47   data: (handle array bind)
 48   next: (handle table)
 49 }
 50 
 51 type bind {
 52   key: (handle array byte)
 53   value: (handle value)  # I'd inline this but we sometimes want to return a specific value from a table
 54 }
 55 
 56 type result {
 57   data: value-stack
 58   error: (handle array byte)  # single error message for now
 59 }
 60 
 61 # if 'out' is non-null, save the first word of the program there
 62 fn initialize-program _program: (addr program), out: (addr handle word) {
 63   var program/esi: (addr program) <- copy _program
 64   var defs/eax: (addr handle function) <- get program, defs
 65   create-primitive-defs defs
 66   var sandbox-ah/eax: (addr handle sandbox) <- get program, sandboxes
 67   allocate sandbox-ah
 68   var sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
 69   initialize-sandbox sandbox, out
 70 }
 71 
 72 # if 'out' is non-null, save the first word of the sandbox there
 73 fn initialize-sandbox _sandbox: (addr sandbox), out: (addr handle word) {
 74   var sandbox/esi: (addr sandbox) <- copy _sandbox
 75   var line-ah/eax: (addr handle line) <- get sandbox, data
 76   allocate line-ah
 77   var line/eax: (addr line) <- lookup *line-ah
 78   initialize-line line, out
 79 }
 80 
 81 # initialize line with a single empty word
 82 # if 'out' is non-null, save the word there as well
 83 fn initialize-line _line: (addr line), out: (addr handle word) {
 84   var line/esi: (addr line) <- copy _line
 85   var word-ah/eax: (addr handle word) <- get line, data
 86   allocate word-ah
 87   {
 88     compare out, 0
 89     break-if-=
 90     var dest/edi: (addr handle word) <- copy out
 91     copy-object word-ah, dest
 92   }
 93   var word/eax: (addr word) <- lookup *word-ah
 94   initialize-word word
 95 }
 96 
 97 fn create-primitive-defs _self: (addr handle function) {
 98   # x 2* = x 2 *
 99   var self/esi: (addr handle function) <- copy _self
100   allocate self
101   var _f/eax: (addr function) <- lookup *self
102   var f/esi: (addr function) <- copy _f
103   var name-ah/eax: (addr handle array byte) <- get f, name
104   populate-text-with name-ah, "2*"
105   var args-ah/eax: (addr handle word) <- get f, args
106   allocate args-ah
107   var args/eax: (addr word) <- lookup *args-ah
108   initialize-word-with args, "x"
109   var body-ah/eax: (addr handle line) <- get f, body
110   allocate body-ah
111   var body/eax: (addr line) <- lookup *body-ah
112   initialize-line body, 0
113   var curr-word-ah/ecx: (addr handle word) <- get body, data
114   allocate curr-word-ah
115   var curr-word/eax: (addr word) <- lookup *curr-word-ah
116   initialize-word-with curr-word, "x"
117   curr-word-ah <- get curr-word, next
118   allocate curr-word-ah
119   curr-word <- lookup *curr-word-ah
120   initialize-word-with curr-word, "2"
121   curr-word-ah <- get curr-word, next
122   allocate curr-word-ah
123   curr-word <- lookup *curr-word-ah
124   initialize-word-with curr-word, "*"
125   # x 1+ = x 1 +
126   var next/esi: (addr handle function) <- get f, next
127   allocate next
128   var _f/eax: (addr function) <- lookup *next
129   var f/esi: (addr function) <- copy _f
130   var name-ah/eax: (addr handle array byte) <- get f, name
131   populate-text-with name-ah, "1+"
132   var args-ah/eax: (addr handle word) <- get f, args
133   allocate args-ah
134   var args/eax: (addr word) <- lookup *args-ah
135   initialize-word-with args, "x"
136   var body-ah/eax: (addr handle line) <- get f, body
137   allocate body-ah
138   var body/eax: (addr line) <- lookup *body-ah
139   initialize-line body, 0
140   var curr-word-ah/ecx: (addr handle word) <- get body, data
141   allocate curr-word-ah
142   var curr-word/eax: (addr word) <- lookup *curr-word-ah
143   initialize-word-with curr-word, "x"
144   curr-word-ah <- get curr-word, next
145   allocate curr-word-ah
146   curr-word <- lookup *curr-word-ah
147   initialize-word-with curr-word, "1"
148   curr-word-ah <- get curr-word, next
149   allocate curr-word-ah
150   curr-word <- lookup *curr-word-ah
151   initialize-word-with curr-word, "+"
152   # x 2+ = x 1+ 1+
153   var next/esi: (addr handle function) <- get f, next
154   allocate next
155   var _f/eax: (addr function) <- lookup *next
156   var f/ecx: (addr function) <- copy _f
157   var name-ah/eax: (addr handle array byte) <- get f, name
158   populate-text-with name-ah, "2+"
159   var args-ah/eax: (addr handle word) <- get f, args
160   allocate args-ah
161   var args/eax: (addr word) <- lookup *args-ah
162   initialize-word-with args, "x"
163   var body-ah/eax: (addr handle line) <- get f, body
164   allocate body-ah
165   var body/eax: (addr line) <- lookup *body-ah
166   initialize-line body, 0
167   var curr-word-ah/ecx: (addr handle word) <- get body, data
168   allocate curr-word-ah
169   var curr-word/eax: (addr word) <- lookup *curr-word-ah
170   initialize-word-with curr-word, "x"
171   curr-word-ah <- get curr-word, next
172   allocate curr-word-ah
173   curr-word <- lookup *curr-word-ah
174   initialize-word-with curr-word, "1+"
175   curr-word-ah <- get curr-word, next
176   allocate curr-word-ah
177   curr-word <- lookup *curr-word-ah
178   initialize-word-with curr-word, "1+"
179   # TODO: populate prev pointers
180 }
181 
182 fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) {
183   var in/esi: (addr array byte) <- copy _in
184   var n/ecx: int <- length in
185   var out/edx: (addr handle array byte) <- copy _out
186   populate out, n
187   var _out-addr/eax: (addr array byte) <- lookup *out
188   var out-addr/edx: (addr array byte) <- copy _out-addr
189   var i/eax: int <- copy 0
190   {
191     compare i, n
192     break-if->=
193     var src/esi: (addr byte) <- index in, i
194     var val/ecx: byte <- copy-byte *src
195     var dest/edi: (addr byte) <- index out-addr, i
196     copy-byte-to *dest, val
197     i <- increment
198     loop
199   }
200 }