https://github.com/akkartik/mu/blob/main/linux/tile/table.mu
  1 fn initialize-table _self: (addr table), n: int {
  2   var self/esi: (addr table) <- copy _self
  3   var data-ah/eax: (addr handle array bind) <- get self, data
  4   populate data-ah, n
  5 }
  6 
  7 fn deep-copy-table _src: (addr table), _dest: (addr table) {
  8 #?   print-string 0, "deep-copy-table\n"
  9   var src/eax: (addr table) <- copy _src
 10   var src-data-ah/eax: (addr handle array bind) <- get src, data
 11   var _src-data/eax: (addr array bind) <- lookup *src-data-ah
 12   var src-data/esi: (addr array bind) <- copy _src-data
 13   var n/ecx: int <- length src-data
 14   var dest/eax: (addr table) <- copy _dest
 15   initialize-table dest, n
 16   var dest-data-ah/eax: (addr handle array bind) <- get dest, data
 17   var _dest-data/eax: (addr array bind) <- lookup *dest-data-ah
 18   var dest-data/edi: (addr array bind) <- copy _dest-data
 19   var i/eax: int <- copy 0
 20   {
 21     compare i, n
 22     break-if->=
 23 #?     print-string 0, "iter\n"
 24     $deep-copy:element: {
 25       var offset/edx: (offset bind) <- compute-offset src-data, i
 26       var src-bind/ecx: (addr bind) <- index src-data, offset
 27       var dest-bind/edx: (addr bind) <- index dest-data, offset
 28       var src-key-ah/ebx: (addr handle array byte) <- get src-bind, key
 29       var src-key/eax: (addr array byte) <- lookup *src-key-ah
 30       compare src-key, 0
 31       break-if-=
 32       # copy key
 33       var dest-key-ah/eax: (addr handle array byte) <- get dest-bind, key
 34       copy-object src-key-ah, dest-key-ah
 35       # deep copy value
 36       var src-val-ah/eax: (addr handle value) <- get src-bind, value
 37       var _src-val/eax: (addr value) <- lookup *src-val-ah
 38       var src-val/ecx: (addr value) <- copy _src-val
 39       var dest-val-ah/eax: (addr handle value) <- get dest-bind, value
 40       allocate dest-val-ah
 41       var dest-val/eax: (addr value) <- lookup *dest-val-ah
 42 #?       print-string 0, "deep copy value {\n"
 43       deep-copy-value src-val, dest-val
 44 #?       print-string 0, "}\n"
 45     }
 46     i <- increment
 47     loop
 48   }
 49 #?   print-string 0, "end deep-copy-table\n"
 50 }
 51 
 52 fn bind-in-table _self: (addr table), key: (addr handle array byte), val: (addr value) {
 53   var self/esi: (addr table) <- copy _self
 54   var data-ah/esi: (addr handle array bind) <- get self, data
 55   var _data/eax: (addr array bind) <- lookup *data-ah
 56   var data/esi: (addr array bind) <- copy _data
 57   var next-empty-slot-index/eax: (offset bind) <- next-empty-slot data, key
 58   var dest/eax: (addr bind) <- index data, next-empty-slot-index
 59   make-binding dest, key, val
 60 }
 61 
 62 # manual test: full array of binds
 63 fn next-empty-slot _data: (addr array bind), key: (addr handle array byte) -> _/eax: (offset bind) {
 64   var data/esi: (addr array bind) <- copy _data
 65   var len/ecx: int <- length data
 66   var i/edx: int <- copy 0
 67   var result/eax: (offset bind) <- copy 0
 68   $next-empty-slot:loop: {
 69     result <- compute-offset data, i
 70     compare i, len
 71     break-if->=
 72     {
 73       var target/esi: (addr bind) <- index data, result
 74       var target2/esi: (addr handle array byte) <- get target, key
 75       var target3/eax: (addr array byte) <- lookup *target2
 76       compare target3, 0
 77       break-if-= $next-empty-slot:loop
 78       # TODO: how to indicate that key already exists? we don't want to permit rebinding
 79     }
 80     i <- increment
 81     loop
 82   }
 83   return result
 84 }
 85 
 86 fn make-number-binding _self: (addr bind), key: (addr handle array byte), _val: float {
 87   var self/esi: (addr bind) <- copy _self
 88   var dest/eax: (addr handle array byte) <- get self, key
 89   copy-object key, dest
 90   var dest2/eax: (addr handle value) <- get self, value
 91   allocate dest2
 92   var dest3/eax: (addr value) <- lookup *dest2
 93   var dest4/eax: (addr float) <- get dest3, number-data
 94   var val/xmm0: float <- copy _val
 95   copy-to *dest4, val
 96 }
 97 
 98 fn make-binding _self: (addr bind), key: (addr handle array byte), val: (addr value) {
 99   var self/esi: (addr bind) <- copy _self
100   var dest/eax: (addr handle array byte) <- get self, key
101   copy-object key, dest
102   var dest2/eax: (addr handle value) <- get self, value
103   allocate dest2
104   var dest3/eax: (addr value) <- lookup *dest2
105   copy-object val, dest3
106 }
107 
108 fn lookup-binding _self: (addr table), key: (addr array byte), out: (addr handle value) {
109   var self/esi: (addr table) <- copy _self
110   var data-ah/esi: (addr handle array bind) <- get self, data
111   var _data/eax: (addr array bind) <- lookup *data-ah
112   var data/esi: (addr array bind) <- copy _data
113   var len/edx: int <- length data
114   var i/ebx: int <- copy 0
115   $lookup-binding:loop: {
116     compare i, len
117     break-if->=
118     {
119       var offset/edx: (offset bind) <- compute-offset data, i
120       var target-bind/esi: (addr bind) <- index data, offset
121       var target2/edx: (addr handle array byte) <- get target-bind, key
122       var target3/eax: (addr array byte) <- lookup *target2
123       compare target3, 0
124       break-if-= $lookup-binding:loop
125       var match?/eax: boolean <- string-equal? target3, key
126       compare match?, 0/false
127       break-if-=
128       # found
129       var target/eax: (addr handle value) <- get target-bind, value
130       copy-object target, out
131       break $lookup-binding:loop
132     }
133     i <- increment
134     loop
135   }
136 }
137 
138 fn dump-table _self: (addr table) {
139   var self/esi: (addr table) <- copy _self
140   var data-ah/esi: (addr handle array bind) <- get self, data
141   var _data/eax: (addr array bind) <- lookup *data-ah
142   var data/esi: (addr array bind) <- copy _data
143   var len/edx: int <- length data
144   var i/ebx: int <- copy 0
145   {
146     compare i, len
147     break-if->=
148     var offset/edx: (offset bind) <- compute-offset data, i
149     var target-bind/esi: (addr bind) <- index data, offset
150     var key-ah/edx: (addr handle array byte) <- get target-bind, key
151     var key/eax: (addr array byte) <- lookup *key-ah
152     compare key, 0
153     break-if-=
154     print-string 0, key
155     print-string 0, ": "
156     var val-ah/eax: (addr handle value) <- get target-bind, value
157     var val/eax: (addr value) <- lookup *val-ah
158     var type/eax: (addr int) <- get val, type
159     print-int32-hex 0, *type
160     print-string 0, "\n"
161     i <- increment
162     loop
163   }
164   print-string 0, "\n"
165 }