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