https://github.com/akkartik/mu/blob/master/apps/tile/grapheme-stack.mu
  1 type grapheme-stack {
  2   data: (handle array grapheme)
  3   top: int
  4 }
  5 
  6 fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int {
  7   var self/esi: (addr grapheme-stack) <- copy _self
  8   var d/edi: (addr handle array grapheme) <- get self, data
  9   populate d, n
 10   var top/eax: (addr int) <- get self, top
 11   copy-to *top, 0
 12 }
 13 
 14 fn clear-grapheme-stack _self: (addr grapheme-stack) {
 15   var self/esi: (addr grapheme-stack) <- copy _self
 16   var top/eax: (addr int) <- get self, top
 17   copy-to *top, 0
 18 }
 19 
 20 fn grapheme-stack-empty? _self: (addr grapheme-stack) -> result/eax: boolean {
 21 $grapheme-stack-empty?:body: {
 22   var self/esi: (addr grapheme-stack) <- copy _self
 23   var top/eax: (addr int) <- get self, top
 24   compare *top, 0
 25   {
 26     break-if-!=
 27     result <- copy 1  # true
 28     break $grapheme-stack-empty?:body
 29   }
 30   result <- copy 0  # false
 31 }
 32 }
 33 
 34 fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme {
 35   var self/esi: (addr grapheme-stack) <- copy _self
 36   var top-addr/ecx: (addr int) <- get self, top
 37   var data-ah/edx: (addr handle array grapheme) <- get self, data
 38   var data/eax: (addr array grapheme) <- lookup *data-ah
 39   var top/edx: int <- copy *top-addr
 40   var dest-addr/edx: (addr grapheme) <- index data, top
 41   var val/eax: grapheme <- copy _val
 42   copy-to *dest-addr, val
 43   add-to *top-addr, 1
 44 }
 45 
 46 fn pop-grapheme-stack _self: (addr grapheme-stack) -> val/eax: grapheme {
 47 $pop-grapheme-stack:body: {
 48   var self/esi: (addr grapheme-stack) <- copy _self
 49   var top-addr/ecx: (addr int) <- get self, top
 50   {
 51     compare *top-addr, 0
 52     break-if->
 53     val <- copy -1
 54     break $pop-grapheme-stack:body
 55   }
 56   subtract-from *top-addr, 1
 57   var data-ah/edx: (addr handle array grapheme) <- get self, data
 58   var data/eax: (addr array grapheme) <- lookup *data-ah
 59   var top/edx: int <- copy *top-addr
 60   var result-addr/eax: (addr grapheme) <- index data, top
 61   val <- copy *result-addr
 62 }
 63 }
 64 
 65 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) {
 66   var src/esi: (addr grapheme-stack) <- copy _src
 67   var data-ah/edi: (addr handle array grapheme) <- get src, data
 68   var _data/eax: (addr array grapheme) <- lookup *data-ah
 69   var data/edi: (addr array grapheme) <- copy _data
 70   var top-addr/ecx: (addr int) <- get src, top
 71   var i/eax: int <- copy 0
 72   {
 73     compare i, *top-addr
 74     break-if->=
 75     var g/edx: (addr grapheme) <- index data, i
 76     push-grapheme-stack dest, *g
 77     i <- increment
 78     loop
 79   }
 80 }
 81 
 82 # dump stack to screen from bottom to top
 83 # don't move the cursor or anything
 84 fn render-stack-from-bottom _self: (addr grapheme-stack), screen: (addr screen) {
 85   var self/esi: (addr grapheme-stack) <- copy _self
 86   var data-ah/edi: (addr handle array grapheme) <- get self, data
 87   var _data/eax: (addr array grapheme) <- lookup *data-ah
 88   var data/edi: (addr array grapheme) <- copy _data
 89   var top-addr/ecx: (addr int) <- get self, top
 90   var i/eax: int <- copy 0
 91   {
 92     compare i, *top-addr
 93     break-if->=
 94     var g/edx: (addr grapheme) <- index data, i
 95     print-grapheme screen, *g
 96     i <- increment
 97     loop
 98   }
 99 }
100 
101 # dump stack to screen from top to bottom
102 # don't move the cursor or anything
103 fn render-stack-from-top _self: (addr grapheme-stack), screen: (addr screen) {
104   var self/esi: (addr grapheme-stack) <- copy _self
105   var data-ah/edi: (addr handle array grapheme) <- get self, data
106   var _data/eax: (addr array grapheme) <- lookup *data-ah
107   var data/edi: (addr array grapheme) <- copy _data
108   var top-addr/ecx: (addr int) <- get self, top
109   var i/eax: int <- copy *top-addr
110   i <- decrement
111   {
112     compare i, 0
113     break-if-<
114     var g/edx: (addr grapheme) <- index data, i
115     print-grapheme screen, *g
116     i <- decrement
117     loop
118   }
119 }
120 
121 # compare from bottom
122 # beware: modifies 'stream', which must be disposed of after a false result
123 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean {
124 $prefix-match?:body: {
125   var self/esi: (addr grapheme-stack) <- copy _self
126   var data-ah/edi: (addr handle array grapheme) <- get self, data
127   var _data/eax: (addr array grapheme) <- lookup *data-ah
128   var data/edi: (addr array grapheme) <- copy _data
129   var top-addr/ecx: (addr int) <- get self, top
130   var i/ebx: int <- copy 0
131   {
132     compare i, *top-addr
133     break-if->=
134     # if curr != expected, return false
135     {
136       var curr-a/edx: (addr grapheme) <- index data, i
137       var expected/eax: grapheme <- read-grapheme s
138       {
139         compare expected, *curr-a
140         break-if-=
141         result <- copy 0  # false
142         break $prefix-match?:body
143       }
144     }
145     i <- increment
146     loop
147   }
148   result <- copy 1   # true
149 }
150 }
151 
152 # compare from bottom
153 # beware: modifies 'stream', which must be disposed of after a false result
154 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean {
155 $suffix-match?:body: {
156   var self/esi: (addr grapheme-stack) <- copy _self
157   var data-ah/edi: (addr handle array grapheme) <- get self, data
158   var _data/eax: (addr array grapheme) <- lookup *data-ah
159   var data/edi: (addr array grapheme) <- copy _data
160   var top-addr/eax: (addr int) <- get self, top
161   var i/ebx: int <- copy *top-addr
162   i <- decrement
163   {
164     compare i, 0
165     break-if-<
166     {
167       var curr-a/edx: (addr grapheme) <- index data, i
168       var expected/eax: grapheme <- read-grapheme s
169       # if curr != expected, return false
170       {
171         compare expected, *curr-a
172         break-if-=
173         result <- copy 0  # false
174         break $suffix-match?:body
175       }
176     }
177     i <- decrement
178     loop
179   }
180   result <- copy 1   # true
181 }
182 }
183 
184 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> result/eax: boolean {
185   var self/esi: (addr grapheme-stack) <- copy _self
186   var data-ah/eax: (addr handle array grapheme) <- get self, data
187   var _data/eax: (addr array grapheme) <- lookup *data-ah
188   var data/edx: (addr array grapheme) <- copy _data
189   var top-addr/ecx: (addr int) <- get self, top
190   var i/ebx: int <- copy 0
191   $grapheme-stack-is-integer?:loop: {
192     compare i, *top-addr
193     break-if->=
194     var g/edx: (addr grapheme) <- index data, i
195     result <- is-decimal-digit? *g
196     compare result, 0  # false
197     break-if-=
198     i <- increment
199     loop
200   }
201 }