about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--301array-equal.subx46
-rw-r--r--400.mu2
-rw-r--r--405screen.mu19
-rwxr-xr-xapps/mubin422150 -> 422182 bytes
-rw-r--r--apps/tile/data.mu1
-rw-r--r--apps/tile/environment.mu28
-rw-r--r--apps/tile/rpn.mu77
-rw-r--r--apps/tile/value-stack.mu64
8 files changed, 194 insertions, 43 deletions
diff --git a/301array-equal.subx b/301array-equal.subx
index c799f814..d020f5aa 100644
--- a/301array-equal.subx
+++ b/301array-equal.subx
@@ -171,7 +171,7 @@ test-compare-inequal-arrays-equal-sizes:
     5d/pop-to-ebp
     c3/return
 
-parse-array-of-ints:  # ad: (addr allocation-descriptor), s: (addr string), out: (addr handle array int)
+_parse-array-of-ints:  # ad: (addr allocation-descriptor), s: (addr array byte), out: (addr handle array int)
     # pseudocode
     #   end = &s->data[s->size]
     #   curr = s->data
@@ -216,25 +216,25 @@ parse-array-of-ints:  # ad: (addr allocation-descriptor), s: (addr string), out:
     01/add-to %edx 1/r32/ecx
     # var size/ebx: int = 0
     31/xor-with %ebx 3/r32/ebx
-$parse-array-of-ints:loop1:
+$_parse-array-of-ints:loop1:
     # if (curr >= end) break
     39/compare %ecx 2/r32/edx
-    73/jump-if-addr>= $parse-array-of-ints:break1/disp8
+    73/jump-if-addr>= $_parse-array-of-ints:break1/disp8
     # curr = skip-chars-matching-in-slice(curr, end, ' ')
     (skip-chars-matching-in-slice %ecx %edx 0x20)  # => eax
     89/<- %ecx 0/r32/eax
     # if (curr >= end) break
     39/compare %ecx 2/r32/edx
-    73/jump-if-addr>= $parse-array-of-ints:break1/disp8
+    73/jump-if-addr>= $_parse-array-of-ints:break1/disp8
     # curr = skip-chars-not-matching-in-slice(curr, end, ' ')
     (skip-chars-not-matching-in-slice %ecx %edx 0x20)  # => eax
     89/<- %ecx 0/r32/eax
     # size += 4
     81 0/subop/add %ebx 4/imm32
-    eb/jump $parse-array-of-ints:loop1/disp8
-$parse-array-of-ints:break1:
+    eb/jump $_parse-array-of-ints:loop1/disp8
+$_parse-array-of-ints:break1:
     (allocate-array *(ebp+8) %ebx *(ebp+0x10))
-$parse-array-of-ints:pass2:
+$_parse-array-of-ints:pass2:
     # var slice/edi: slice = {s->data, 0}
     68/push 0/imm32/end
     8d/copy-address *(esi+4) 7/r32/edi
@@ -244,16 +244,16 @@ $parse-array-of-ints:pass2:
     8b/-> *(ebp+0x10) 0/r32/eax
     (lookup *eax *(eax+4))  # => eax
     8d/copy-address *(eax+4) 1/r32/ecx
-$parse-array-of-ints:loop2:
+$_parse-array-of-ints:loop2:
     # if (slice->start >= end) break
     39/compare *edi 2/r32/edx
-    73/jump-if-addr>= $parse-array-of-ints:end/disp8
+    73/jump-if-addr>= $_parse-array-of-ints:end/disp8
     # slice->start = skip-chars-matching-in-slice(slice->start, end, ' ')
     (skip-chars-matching-in-slice *edi %edx 0x20)  # => eax
     89/<- *edi 0/r32/eax
     # if (slice->start >= end) break
     39/compare *edi 2/r32/edx
-    73/jump-if-addr>= $parse-array-of-ints:end/disp8
+    73/jump-if-addr>= $_parse-array-of-ints:end/disp8
     # slice->end = skip-chars-not-matching-in-slice(slice->start, end, ' ')
     (skip-chars-not-matching-in-slice *edi %edx 0x20)  # => eax
     89/<- *(edi+4) 0/r32/eax
@@ -265,8 +265,8 @@ $parse-array-of-ints:loop2:
     # slice->start = slice->end
     8b/-> *(edi+4) 0/r32/eax
     89/<- *edi 0/r32/eax
-    eb/jump $parse-array-of-ints:loop2/disp8
-$parse-array-of-ints:end:
+    eb/jump $_parse-array-of-ints:loop2/disp8
+$_parse-array-of-ints:end:
     # . reclaim locals
     81 0/subop/add %esp 8/imm32
     # . restore registers
@@ -296,7 +296,7 @@ test-parse-array-of-ints:
     68/push 0xc/imm32/size
     89/<- %ecx 4/r32/esp
     #
-    (parse-array-of-ints Heap "1 2 3" %esi)
+    (_parse-array-of-ints Heap "1 2 3" %esi)
     (lookup *esi *(esi+4))  # => eax
     (array-equal? %ecx %eax)  # => eax
     (check-ints-equal %eax 1 "F - test-parse-array-of-ints")
@@ -315,7 +315,7 @@ test-parse-array-of-ints-empty:
     68/push 0/imm32
     89/<- %esi 4/r32/esp
     #
-    (parse-array-of-ints Heap "" %esi)
+    (_parse-array-of-ints Heap "" %esi)
     (lookup *esi *(esi+4))  # => eax
     (check-ints-equal *eax 0 "F - test-parse-array-of-ints-empty")
     # . epilogue
@@ -333,7 +333,7 @@ test-parse-array-of-ints-just-whitespace:
     68/push 0/imm32
     89/<- %esi 4/r32/esp
     #
-    (parse-array-of-ints Heap Space %esi)
+    (_parse-array-of-ints Heap Space %esi)
     (lookup *esi *(esi+4))  # => eax
     (check-ints-equal *eax 0 "F - test-parse-array-of-ints-just-whitespace")
     # . epilogue
@@ -356,7 +356,7 @@ test-parse-array-of-ints-extra-whitespace:
     68/push 0xc/imm32/size
     89/<- %ecx 4/r32/esp
     #
-    (parse-array-of-ints Heap " 1 2  3  " %esi)
+    (_parse-array-of-ints Heap " 1 2  3  " %esi)
     (lookup *esi *(esi+4))  # => eax
     (array-equal? %ecx %eax)  # => eax
     (check-ints-equal %eax 1 "F - test-parse-array-of-ints-extra-whitespace")
@@ -365,6 +365,18 @@ test-parse-array-of-ints-extra-whitespace:
     5d/pop-to-ebp
     c3/return
 
+parse-array-of-ints:  # s: (addr array byte), out: (addr handle array int)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    #
+    (_parse-array-of-ints Heap *(ebp+8) *(ebp+0xc))
+$parse-array-of-ints:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # helper for later tests
 # compare an array with a string representation of an array literal
 check-array-equal:  # a: (addr array int), expected: (addr string), msg: (addr string)
@@ -379,7 +391,7 @@ check-array-equal:  # a: (addr array int), expected: (addr string), msg: (addr s
     68/push 0/imm32
     89/<- %esi 4/r32/esp
     # var b/eax: (addr array int) = parse-array-of-ints(Heap, expected)
-    (parse-array-of-ints Heap *(ebp+0xc) %esi)
+    (parse-array-of-ints *(ebp+0xc) %esi)
     (lookup *esi *(esi+4))  # => eax
     #
     (array-equal? *(ebp+8) %eax)
diff --git a/400.mu b/400.mu
index 35fc88f0..87e43356 100644
--- a/400.mu
+++ b/400.mu
@@ -139,7 +139,7 @@ sig write-int out: (addr stream byte), n: int
 #sig pop s: (addr stack) -> n/eax: int
 #sig top s: (addr stack) -> n/eax: int
 sig array-equal? a: (addr array int), b: (addr array int) -> result/eax: boolean
-sig parse-array-of-ints ad: (addr allocation-descriptor), s: (addr string), out: (addr handle array int)
+sig parse-array-of-ints s: (addr array byte), out: (addr handle array int)
 sig check-array-equal a: (addr array int), expected: (addr string), msg: (addr string)
 #sig push-n-zero-bytes n: int
 sig kernel-string-to-string ad: (addr allocation-descriptor), in: (addr kernel-string), out: (addr handle array byte)
diff --git a/405screen.mu b/405screen.mu
index ba854e4a..201caba8 100644
--- a/405screen.mu
+++ b/405screen.mu
@@ -203,6 +203,25 @@ $print-string:body: {
 }
 }
 
+fn print-array-of-ints-in-decimal screen: (addr screen), _a: (addr array int) {
+  var a/esi: (addr array int) <- copy _a
+  var max/ecx: int <- length a
+  var i/eax: int <- copy 0
+  {
+    compare i, max
+    break-if->=
+    {
+      compare i, 0
+      break-if-=
+      print-string screen, " "
+    }
+    var x/ecx: (addr int) <- index a, i
+    print-int32-decimal screen, *x
+    i <- increment
+    loop
+  }
+}
+
 fn print-grapheme screen: (addr screen), c: grapheme {
 $print-grapheme:body: {
   compare screen, 0
diff --git a/apps/mu b/apps/mu
index 236b5d2a..d3607682 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/tile/data.mu b/apps/tile/data.mu
index f69ed645..7575461c 100644
--- a/apps/tile/data.mu
+++ b/apps/tile/data.mu
@@ -37,6 +37,7 @@ type value {
   type: int
   int-data: int  # if type = 0
   text-data: (handle array byte)  # if type = 1
+  array-data: (handle array int)  # if type = 2
 }
 
 type table {
diff --git a/apps/tile/environment.mu b/apps/tile/environment.mu
index bdf9574c..e37b32ba 100644
--- a/apps/tile/environment.mu
+++ b/apps/tile/environment.mu
@@ -424,6 +424,7 @@ $process-sandbox:body: {
       break $process-sandbox:body
     }
     # if start of word is quote and grapheme before cursor is not, just insert it as usual
+    # TODO: support string escaping
     {
       var first-grapheme/eax: grapheme <- first-grapheme cursor-word
       compare first-grapheme, 0x22  # double quote
@@ -433,6 +434,17 @@ $process-sandbox:body: {
       break-if-=
       break $process-sandbox:space
     }
+    # if start of word is '[' and grapheme before cursor is not ']', just insert it as usual
+    # TODO: support nested arrays
+    {
+      var first-grapheme/eax: grapheme <- first-grapheme cursor-word
+      compare first-grapheme, 0x5b  # '['
+      break-if-!=
+      var final-grapheme/eax: grapheme <- grapheme-before-cursor cursor-word
+      compare final-grapheme, 0x5d  # ']'
+      break-if-=
+      break $process-sandbox:space
+    }
     # otherwise insert word after and move cursor to it for the next key
     # (but we'll continue to track the current cursor-word for the rest of this function)
     append-word cursor-word-ah
@@ -1352,6 +1364,14 @@ fn render-column screen: (addr screen), functions: (addr handle function), bindi
             print-string screen, val
             break $render-column:render-value
           }
+          {
+            compare *val-type, 2  # array
+            break-if-!=
+            var val-ah/eax: (addr handle array int) <- get val-addr, array-data
+            var val/eax: (addr array int) <- lookup *val-ah
+            render-array screen, val
+            break $render-column:render-value
+          }
           # render ints by default for now
           var val-addr2/eax: (addr int) <- get val-addr, int-data
           render-integer screen, *val-addr2, max-width
@@ -1410,6 +1430,14 @@ fn render-integer screen: (addr screen), val: int, max-width: int {
   print-grapheme screen, 0x20  # space
 }
 
+fn render-array screen: (addr screen), val: (addr array int) {
+  start-color screen, 0, 7
+  # don't surround in spaces
+  print-grapheme screen, 0x5b  # '['
+  print-array-of-ints-in-decimal screen, val
+  print-grapheme screen, 0x5d  # ']'
+}
+
 fn hash-color val: int -> result/eax: int {
   result <- try-modulo val, 7  # assumes that 7 is always the background color
 }
diff --git a/apps/tile/rpn.mu b/apps/tile/rpn.mu
index 847a3a8c..ef53bb7e 100644
--- a/apps/tile/rpn.mu
+++ b/apps/tile/rpn.mu
@@ -65,30 +65,42 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
         top <- decrement
         var dest-offset/edx: (offset value) <- compute-offset data, top
         var target-val/edx: (addr value) <- index data, dest-offset
-        # check target-val is a string
+        # check target-val is a string or array
         var target-type-addr/eax: (addr int) <- get target-val, type
-#?         print-string 0, "checking type: "
-#?         {
-#?           var foo/eax: int <- copy target-type-addr
-#?           print-int32-hex 0, foo
-#?         }
-#?         print-string 0, "\n"
         compare *target-type-addr, 1  # string
-        break-if-!=
-#?         print-string 0, "is string\n"
-        # compute length
-        var src-ah/eax: (addr handle array byte) <- get target-val, text-data
-        var src/eax: (addr array byte) <- lookup *src-ah
-        var result/ebx: int <- length src
-        # save result into target-val
-        var type-addr/eax: (addr int) <- get target-val, type
-        copy-to *type-addr, 0  # int
-        var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
-        var empty: (handle array byte)
-        copy-handle empty, target-string-ah
-        var target/eax: (addr int) <- get target-val, int-data
-        copy-to *target, result
-        break $evaluate:process-word
+        {
+          break-if-!=
+          # compute length
+          var src-ah/eax: (addr handle array byte) <- get target-val, text-data
+          var src/eax: (addr array byte) <- lookup *src-ah
+          var result/ebx: int <- length src
+          # save result into target-val
+          var type-addr/eax: (addr int) <- get target-val, type
+          copy-to *type-addr, 0  # int
+          var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
+          var empty: (handle array byte)
+          copy-handle empty, target-string-ah
+          var target/eax: (addr int) <- get target-val, int-data
+          copy-to *target, result
+          break $evaluate:process-word
+        }
+        compare *target-type-addr, 2  # array of ints
+        {
+          break-if-!=
+          # compute length
+          var src-ah/eax: (addr handle array int) <- get target-val, array-data
+          var src/eax: (addr array int) <- lookup *src-ah
+          var result/ebx: int <- length src
+          # save result into target-val
+          var type-addr/eax: (addr int) <- get target-val, type
+          copy-to *type-addr, 0  # int
+          var target-array-ah/eax: (addr handle array int) <- get target-val, array-data
+          var empty: (handle array int)
+          copy-handle empty, target-array-ah
+          var target/eax: (addr int) <- get target-val, int-data
+          copy-to *target, result
+          break $evaluate:process-word
+        }
       }
       # if curr-stream defines a binding, save top of stack to bindings
       {
@@ -152,7 +164,7 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
         push-value-stack out, val
         break $evaluate:process-word
       }
-      # if the word starts with a quote and ends with a quote, return it directly
+      # if the word starts with a quote and ends with a quote, turn it into a string
       {
         var start/eax: byte <- stream-first curr-stream
         compare start, 0x22  # double-quote
@@ -166,6 +178,25 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
         push-string-to-value-stack out, *s
         break $evaluate:process-word
       }
+      # if the word starts with a '[' and ends with a ']', turn it into an array
+      {
+        var start/eax: byte <- stream-first curr-stream
+        compare start, 0x5b  # '['
+        break-if-!=
+        var end/eax: byte <- stream-final curr-stream
+        compare end, 0x5d  # ']'
+        break-if-!=
+        # wastefully create a new string to strip quotes
+        var h: (handle array int)
+        var tmp-ah/eax: (addr handle array byte) <- address h
+        unquote-stream-to-string curr-stream, tmp-ah  # leak
+        var tmp/eax: (addr array byte) <- lookup *tmp-ah
+        var h2: (handle array int)
+        var array-ah/ecx: (addr handle array int) <- address h2
+        parse-array-of-ints tmp, array-ah  # leak
+        push-array-to-value-stack out, *array-ah
+        break $evaluate:process-word
+      }
       # otherwise assume it's a literal int and push it
       {
         var n/eax: int <- parse-decimal-int-from-stream curr-stream
diff --git a/apps/tile/value-stack.mu b/apps/tile/value-stack.mu
index 093e8846..dbe25b74 100644
--- a/apps/tile/value-stack.mu
+++ b/apps/tile/value-stack.mu
@@ -55,6 +55,27 @@ fn push-string-to-value-stack _self: (addr value-stack), val: (handle array byte
   increment *top-addr
 }
 
+fn push-array-to-value-stack _self: (addr value-stack), val: (handle array int) {
+  var self/esi: (addr value-stack) <- copy _self
+  var top-addr/ecx: (addr int) <- get self, top
+  var data-ah/edx: (addr handle array value) <- get self, data
+  var data/eax: (addr array value) <- lookup *data-ah
+  var top/edx: int <- copy *top-addr
+  var dest-offset/edx: (offset value) <- compute-offset data, top
+  var dest-addr/edx: (addr value) <- index data, dest-offset
+  var dest-addr2/eax: (addr handle array int) <- get dest-addr, array-data
+  copy-handle val, dest-addr2
+  var dest-addr3/eax: (addr int) <- get dest-addr, type
+#?   print-string 0, "setting type to 1: "
+#?   {
+#?     var foo/eax: int <- copy dest-addr3
+#?     print-int32-hex 0, foo
+#?   }
+#?   print-string 0, "\n"
+  copy-to *dest-addr3, 2  # type array
+  increment *top-addr
+}
+
 fn push-value-stack _self: (addr value-stack), val: (addr value) {
   var self/esi: (addr value-stack) <- copy _self
   var top-addr/ecx: (addr int) <- get self, top
@@ -123,7 +144,7 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
     var g/edx: (addr value) <- index data, o
     var type/eax: (addr int) <- get g, type
     {
-      compare *type, 0
+      compare *type, 0  # int
       break-if-!=
       var g2/edx: (addr int) <- get g, int-data
       var w/eax: int <- decimal-size *g2
@@ -132,7 +153,7 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
       copy-to out, w
     }
     {
-      compare *type, 1
+      compare *type, 1  # string
       break-if-!=
       var s-ah/eax: (addr handle array byte) <- get g, text-data
       var s/eax: (addr array byte) <- lookup *s-ah
@@ -143,8 +164,47 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
       break-if-<=
       copy-to out, w
     }
+    {
+      compare *type, 2  # array
+      break-if-!=
+      var a-ah/eax: (addr handle array int) <- get g, array-data
+      var a/eax: (addr array int) <- lookup *a-ah
+      compare a, 0
+      break-if-=
+      var w/eax: int <- array-decimal-size a
+      compare w, out
+      break-if-<=
+      copy-to out, w
+    }
+    i <- increment
+    loop
+  }
+  result <- copy out
+}
+
+# keep sync'd with print-array-of-ints
+fn array-decimal-size _a: (addr array int) -> result/eax: int {
+  var a/esi: (addr array int) <- copy _a
+  var max/ecx: int <- length a
+  var i/eax: int <- copy 0
+  var out/edi: int <- copy 0
+  {
+    compare i, max
+    break-if->=
+    {
+      compare i, 0
+      break-if-=
+      out <- increment  # for space
+    }
+    var x/ecx: (addr int) <- index a, i
+    {
+      var w/eax: int <- decimal-size *x
+      out <- add w
+    }
     i <- increment
     loop
   }
   result <- copy out
+  # we won't add 2 for surrounding brackets since we don't surround arrays in
+  # spaces like other value types
 }