https://github.com/akkartik/mu/blob/master/apps/tile/word.mu
  1 fn initialize-word _self: (addr word) {
  2   var self/esi: (addr word) <- copy _self
  3   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
  4   allocate data-ah
  5   var data/eax: (addr gap-buffer) <- lookup *data-ah
  6   initialize-gap-buffer data
  7   # TODO: sometimes initialize box-data rather than scalar-data
  8 }
  9 
 10 ## some helpers for creating words. mostly for tests
 11 
 12 fn initialize-word-with _self: (addr word), s: (addr array byte) {
 13   var self/esi: (addr word) <- copy _self
 14   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
 15   allocate data-ah
 16   var data/eax: (addr gap-buffer) <- lookup *data-ah
 17   initialize-gap-buffer-with data, s
 18 }
 19 
 20 fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
 21   var out/eax: (addr handle word) <- copy _out
 22   allocate out
 23   var out-addr/eax: (addr word) <- lookup *out
 24   initialize-word-with out-addr, s
 25 }
 26 
 27 # just for tests for now
 28 # TODO: handle existing next
 29 # one implication of handles: append must take a handle
 30 fn append-word-with self-h: (handle word), s: (addr array byte) {
 31   var self/eax: (addr word) <- lookup self-h
 32   var next-ah/eax: (addr handle word) <- get self, next
 33   allocate-word-with next-ah, s
 34   var next/eax: (addr word) <- lookup *next-ah
 35   var prev-ah/eax: (addr handle word) <- get next, prev
 36   copy-handle self-h, prev-ah
 37 }
 38 
 39 # just for tests for now
 40 # TODO: handle existing prev
 41 fn prepend-word-with self-h: (handle word), s: (addr array byte) {
 42   var self/eax: (addr word) <- lookup self-h
 43   var prev-ah/eax: (addr handle word) <- get self, prev
 44   allocate-word-with prev-ah, s
 45   var prev/eax: (addr word) <- lookup *prev-ah
 46   var next-ah/eax: (addr handle word) <- get prev, next
 47   copy-handle self-h, next-ah
 48 }
 49 
 50 ## real primitives
 51 
 52 fn word-equal? _self: (addr word), s: (addr array byte) -> result/eax: boolean {
 53   var self/esi: (addr word) <- copy _self
 54   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
 55   var data/eax: (addr gap-buffer) <- lookup *data-ah
 56   result <- gap-buffer-equal? data, s
 57 }
 58 
 59 fn word-length _self: (addr word) -> result/eax: int {
 60   var self/esi: (addr word) <- copy _self
 61   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
 62   var data/eax: (addr gap-buffer) <- lookup *data-ah
 63   result <- gap-buffer-length data
 64 }
 65 
 66 fn first-word _self: (addr word) -> result/eax: (addr word) {
 67   var self/esi: (addr word) <- copy _self
 68   var out/edi: (addr word) <- copy self
 69   var prev/esi: (addr handle word) <- get self, prev
 70   {
 71     var curr/eax: (addr word) <- lookup *prev
 72     compare curr, 0
 73     break-if-=
 74     out <- copy curr
 75     prev <- get curr, prev
 76     loop
 77   }
 78   result <- copy out
 79 }
 80 
 81 fn final-word _self: (addr word) -> result/eax: (addr word) {
 82   var self/esi: (addr word) <- copy _self
 83   var out/edi: (addr word) <- copy self
 84   var next/esi: (addr handle word) <- get self, next
 85   {
 86     var curr/eax: (addr word) <- lookup *next
 87     compare curr, 0
 88     break-if-=
 89     out <- copy curr
 90     next <- get curr, next
 91     loop
 92   }
 93   result <- copy out
 94 }
 95 
 96 fn first-grapheme _self: (addr word) -> result/eax: grapheme {
 97   var self/esi: (addr word) <- copy _self
 98   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
 99   var data/eax: (addr gap-buffer) <- lookup *data-ah
100   result <- first-grapheme-in-gap-buffer data
101 }
102 
103 fn add-grapheme-to-word _self: (addr word), c: grapheme {
104   var self/esi: (addr word) <- copy _self
105   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
106   var data/eax: (addr gap-buffer) <- lookup *data-ah
107   add-grapheme-at-gap data, c
108 }
109 
110 fn cursor-at-start? _self: (addr word) -> result/eax: boolean {
111   var self/esi: (addr word) <- copy _self
112   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
113   var data/eax: (addr gap-buffer) <- lookup *data-ah
114   result <- gap-at-start? data
115 }
116 
117 fn cursor-at-end? _self: (addr word) -> result/eax: boolean {
118   var self/esi: (addr word) <- copy _self
119   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
120   var data/eax: (addr gap-buffer) <- lookup *data-ah
121   result <- gap-at-end? data
122 }
123 
124 fn cursor-left _self: (addr word) {
125   var self/esi: (addr word) <- copy _self
126   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
127   var data/eax: (addr gap-buffer) <- lookup *data-ah
128   var dummy/eax: grapheme <- gap-left data
129 }
130 
131 fn cursor-right _self: (addr word) {
132   var self/esi: (addr word) <- copy _self
133   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
134   var data/eax: (addr gap-buffer) <- lookup *data-ah
135   var dummy/eax: grapheme <- gap-right data
136 }
137 
138 fn cursor-to-start _self: (addr word) {
139   var self/esi: (addr word) <- copy _self
140   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
141   var data/eax: (addr gap-buffer) <- lookup *data-ah
142   gap-to-start data
143 }
144 
145 fn cursor-to-end _self: (addr word) {
146   var self/esi: (addr word) <- copy _self
147   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
148   var data/eax: (addr gap-buffer) <- lookup *data-ah
149   gap-to-end data
150 }
151 
152 fn cursor-index _self: (addr word) -> result/eax: int {
153   var self/esi: (addr word) <- copy _self
154   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
155   var data/eax: (addr gap-buffer) <- lookup *data-ah
156   result <- gap-index data
157 }
158 
159 fn delete-before-cursor _self: (addr word) {
160   var self/esi: (addr word) <- copy _self
161   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
162   var data/eax: (addr gap-buffer) <- lookup *data-ah
163   delete-before-gap data
164 }
165 
166 fn delete-next _self: (addr word) {
167 $delete-next:body: {
168   var self/esi: (addr word) <- copy _self
169   var next-ah/edi: (addr handle word) <- get self, next
170   var next/eax: (addr word) <- lookup *next-ah
171   compare next, 0
172   break-if-= $delete-next:body
173   var next-next-ah/ecx: (addr handle word) <- get next, next
174   var self-ah/esi: (addr handle word) <- get next, prev
175   copy-object next-next-ah, next-ah
176   var new-next/eax: (addr word) <- lookup *next-next-ah
177   compare new-next, 0
178   break-if-= $delete-next:body
179   var dest/eax: (addr handle word) <- get new-next, prev
180   copy-object self-ah, dest
181 }
182 }
183 
184 fn print-word screen: (addr screen), _self: (addr word) {
185   var self/esi: (addr word) <- copy _self
186   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
187   var data/eax: (addr gap-buffer) <- lookup *data-ah
188   render-gap-buffer screen, data
189 }
190 
191 # one implication of handles: append must take a handle
192 fn append-word _self-ah: (addr handle word) {
193   var self-ah/esi: (addr handle word) <- copy _self-ah
194   var _self/eax: (addr word) <- lookup *self-ah
195   var self/ebx: (addr word) <- copy _self
196   # allocate new handle
197   var new: (handle word)
198   var new-ah/ecx: (addr handle word) <- address new
199   allocate new-ah
200   var new-addr/eax: (addr word) <- lookup new
201   initialize-word new-addr
202   # new->next = self->next
203   var src/esi: (addr handle word) <- get self, next
204   var dest/edi: (addr handle word) <- get new-addr, next
205   copy-object src, dest
206   # new->next->prev = new
207   {
208     var next-addr/eax: (addr word) <- lookup *src
209     compare next-addr, 0
210     break-if-=
211     dest <- get next-addr, prev
212     copy-object new-ah, dest
213   }
214   # new->prev = self
215   dest <- get new-addr, prev
216   copy-object _self-ah, dest
217   # self->next = new
218   dest <- get self, next
219   copy-object new-ah, dest
220 }
221 
222 fn emit-word _self: (addr word), out: (addr stream byte) {
223   var self/esi: (addr word) <- copy _self
224   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
225   var data/eax: (addr gap-buffer) <- lookup *data-ah
226   emit-gap-buffer data, out
227 }
228 
229 fn word-to-string _self: (addr word), out: (addr handle array byte) {
230   var self/esi: (addr word) <- copy _self
231   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
232   var data/eax: (addr gap-buffer) <- lookup *data-ah
233   gap-buffer-to-string data, out
234 }