about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-07-30 19:34:29 -0700
committerKartik Agaram <vc@akkartik.com>2020-07-30 19:34:29 -0700
commit30012350281844611bda2f4668f6a0b318a95b36 (patch)
tree56ac2b67b2dd02c3caa4aa02f47be9ea492349ad
parentca237761bf0f9b16838e2d3f7079d1725e3bd87b (diff)
downloadmu-30012350281844611bda2f4668f6a0b318a95b36.tar.gz
6687 - stream-empty? and stream-full?
-rw-r--r--309stream.subx52
-rw-r--r--400.mu3
-rw-r--r--401test.mu11
-rw-r--r--403stream.mu25
-rwxr-xr-xapps/mubin365432 -> 366124 bytes
-rw-r--r--apps/mu.subx66
6 files changed, 154 insertions, 3 deletions
diff --git a/309stream.subx b/309stream.subx
index 3d38eda9..8e6d0fbf 100644
--- a/309stream.subx
+++ b/309stream.subx
@@ -1,7 +1,55 @@
 # Some unsafe methods not intended to be used directly in SubX, only through
 # Mu after proper type-checking.
 
-write-to-stream:  # s: (addr stream), in: (addr byte), n: int
+stream-empty?:  # s: (addr stream _) -> result/eax: boolean
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    56/push-esi
+    # result = false
+    b8/copy-to-eax 0/imm32/false
+    # esi = s
+    8b/-> *(ebp+8) 6/r32/esi
+    # return s->read >= s->write
+    8b/-> *esi 1/r32/ecx
+    39/compare-with *(esi+4) 1/r32/ecx
+    0f 9d/set-if->= %al
+$stream-empty?:end:
+    # . restore registers
+    5e/pop-to-esi
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+stream-full?:  # s: (addr stream _) -> result/eax: boolean
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    56/push-esi
+    # result = false
+    b8/copy-to-eax 0/imm32/false
+    # esi = s
+    8b/-> *(ebp+8) 6/r32/esi
+    # return s->write >= s->size
+    8b/-> *(esi+8) 1/r32/ecx
+    39/compare-with *esi 1/r32/ecx
+    0f 9d/set-if->= %al
+$stream-full?:end:
+    # . restore registers
+    5e/pop-to-esi
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+write-to-stream:  # s: (addr stream _), in: (addr byte), n: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -54,7 +102,7 @@ $write-to-stream:abort:
     (syscall_exit)
     # never gets here
 
-read-from-stream:  # s: (addr stream), out: (addr byte), n: int
+read-from-stream:  # s: (addr stream _), out: (addr byte), n: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
diff --git a/400.mu b/400.mu
index 369e29cd..bf63e87c 100644
--- a/400.mu
+++ b/400.mu
@@ -157,3 +157,6 @@ sig enable-keyboard-type-mode
 sig read-key -> result/eax: byte
 sig open filename: (addr array byte), write?: boolean, out: (addr handle buffered-file)
 #sig size in: (addr array _) -> result/eax: int
+
+sig stream-empty? s: (addr stream _) -> result/eax: boolean
+sig stream-full? s: (addr stream _) -> result/eax: boolean
diff --git a/401test.mu b/401test.mu
new file mode 100644
index 00000000..65b765df
--- /dev/null
+++ b/401test.mu
@@ -0,0 +1,11 @@
+# Some helpers for Mu tests.
+
+fn check-true val: boolean, msg: (addr array byte) {
+  var tmp/eax: int <- copy val
+  check-ints-equal tmp, 1, msg
+}
+
+fn check-false val: boolean, msg: (addr array byte) {
+  var tmp/eax: int <- copy val
+  check-ints-equal tmp, 0, msg
+}
diff --git a/403stream.mu b/403stream.mu
index e7661658..10e9e212 100644
--- a/403stream.mu
+++ b/403stream.mu
@@ -4,12 +4,37 @@ fn test-stream {
   # write an int to a stream, then read it back
   var s: (stream int 4)
   var s2/ecx: (addr stream int 4) <- address s
+  var tmp/eax: boolean <- stream-empty? s2
+  check-true tmp, "F - test-stream/empty?/0"
+  tmp <- stream-full? s2
+  check-false tmp, "F - test-stream/full?/0"
   var x: int
   copy-to x, 0x34
   var x2/edx: (addr int) <- address x
   write-to-stream s2, x2
+  tmp <- stream-empty? s2
+  check-false tmp, "F - test-stream/empty?/1"
+  tmp <- stream-full? s2
+  check-false tmp, "F - test-stream/full?/1"
   var y: int
   var y2/ebx: (addr int) <- address y
   read-from-stream s2, y2
   check-ints-equal y, 0x34, "F - test-stream"
+  tmp <- stream-empty? s2
+  check-true tmp, "F - test-stream/empty?/2"
+  tmp <- stream-full? s2
+  check-false tmp, "F - test-stream/full?/2"
+}
+
+fn test-stream-full {
+  # write an int to a stream of capacity 1
+  var s: (stream int 1)
+  var s2/ecx: (addr stream int 1) <- address s
+  var tmp/eax: boolean <- stream-full? s2
+  check-false tmp, "F - test-stream-full?/pre"
+  var x: int
+  var x2/edx: (addr int) <- address x
+  write-to-stream s2, x2
+  tmp <- stream-full? s2
+  check-true tmp, "F - test-stream-full?"
 }
diff --git a/apps/mu b/apps/mu
index a86811c9..8db17e84 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 3c64c467..2cc5d82a 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -1665,6 +1665,51 @@ test-convert-function-call-with-inout-with-multiple-type-parameters:
     5d/pop-to-ebp
     c3/return
 
+test-type-parameter-matches-rest-of-type:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    (clear-stream _test-error-stream)
+    (clear-stream $_test-error-buffered-file->buffer)
+    # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
+    68/push 0/imm32
+    68/push 0/imm32
+    89/<- %edx 4/r32/esp
+    (tailor-exit-descriptor %edx 0x10)
+    #
+    (write _test-input-stream "fn f {\n")
+    (write _test-input-stream "  var x: (addr array int)\n")
+    (write _test-input-stream "  g x\n")
+    (write _test-input-stream "}\n")
+    (write _test-input-stream "fn g a: (addr _) {\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
+    # registers except esp clobbered at this point
+    # restore ed
+    89/<- %edx 4/r32/esp
+    (flush _test-output-buffered-file)
+    (flush _test-error-buffered-file)
+#?     # dump _test-error-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-error-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-error-stream)
+#?     # }}}
+    # no errors
+    (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
+    # don't bother checking the generated code
+    # don't restore from ebp
+    81 0/subop/add %esp 8/imm32
+    # . epilogue
+    5d/pop-to-ebp
+    c3/return
+
 test-convert-function-call-with-inout-with-incompatible-type-parameters:
     # . prologue
     55/push-ebp
@@ -12780,7 +12825,7 @@ $type-component-match?:compare-addr:
     39/compare %edx 0/r32/eax  # Var-type
     b8/copy-to-eax 1/imm32/true
     0f 84/jump-if-= $type-component-match?:end/disp32
-    # if def is a type parameter, return true
+    # if def is a type parameter, just check in type-parameters
     {
 $type-component-match?:check-type-parameter:
       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
@@ -12791,6 +12836,25 @@ $type-component-match?:type-parameter:
       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
       e9/jump $type-component-match?:end/disp32
     }
+    # if def is a list containing just a type parameter, just check in type-parameters
+    {
+$type-component-match?:check-list-type-parameter:
+      # if def is a list..
+      81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
+      75/jump-if-!= break/disp8
+      #   ..that's a singleton
+      81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
+      75/jump-if-!= break/disp8
+      #   ..and whose head is a type parameter
+      (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
+      81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
+      74/jump-if-= break/disp8
+      81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
+      75/jump-if-!= break/disp8
+$type-component-match?:list-type-parameter:
+      (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
+      e9/jump $type-component-match?:end/disp32
+    }
 $type-component-match?:compare-atom-state:
     # if (def->is-atom? != call->is-atom?) return false
     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom