about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--403unicode.mu8
-rw-r--r--411string.mu86
-rw-r--r--apps/tile/environment.mu24
-rw-r--r--apps/tile/main.mu4
-rw-r--r--apps/tile/value-stack.mu5
5 files changed, 124 insertions, 3 deletions
diff --git a/403unicode.mu b/403unicode.mu
index dcb1e658..6de29bde 100644
--- a/403unicode.mu
+++ b/403unicode.mu
@@ -159,6 +159,14 @@ fn test-to-grapheme-four-bytes-max {
 # read the next grapheme from a stream of bytes
 fn read-grapheme in: (addr stream byte) -> out/eax: grapheme {
 $read-grapheme:body: {
+  # if at eof, return EOF
+  {
+    var eof?/eax: boolean <- stream-empty? in
+    compare eof?, 0  # false
+    break-if-=
+    out <- copy 0xffffffff
+    break $read-grapheme:body
+  }
   var c/eax: byte <- read-byte in
   var num-trailers/ecx: int <- copy 0
   $read-grapheme:compute-length: {
diff --git a/411string.mu b/411string.mu
new file mode 100644
index 00000000..978b2094
--- /dev/null
+++ b/411string.mu
@@ -0,0 +1,86 @@
+# read up to 'len' graphemes after skipping the first 'start' ones
+fn substring in: (addr array byte), start: int, len: int, out-ah: (addr handle array byte) {
+  var in-stream: (stream byte 0x100)
+  var in-stream-addr/esi: (addr stream byte) <- address in-stream
+  write in-stream-addr, in
+  var out-stream: (stream byte 0x100)
+  var out-stream-addr/edi: (addr stream byte) <- address out-stream
+  $substring:core: {
+    # skip 'start' graphemes
+    var i/eax: int <- copy 0
+    {
+      compare i, start
+      break-if->=
+      {
+        var dummy/eax: grapheme <- read-grapheme in-stream-addr
+        compare dummy, 0xffffffff  # end-of-file
+        break-if-= $substring:core
+      }
+      i <- increment
+      loop
+    }
+    # copy 'len' graphemes
+    i <- copy 0
+    {
+      compare i, len
+      break-if->=
+      {
+        var g/eax: grapheme <- read-grapheme in-stream-addr
+        compare g, 0xffffffff  # end-of-file
+        break-if-= $substring:core
+        write-grapheme out-stream-addr, g
+      }
+      i <- increment
+      loop
+    }
+  }
+  stream-to-array out-stream-addr, out-ah
+}
+
+fn test-substring {
+  var out-h: (handle array byte)
+  var out-ah/edi: (addr handle array byte) <- address out-h
+  # prefix substrings
+  substring 0, 0, 3, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "", "F - test-substring/null"
+  substring "", 0, 3, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+#?   print-string-to-real-screen out
+#?   print-string-to-real-screen "\n"
+  check-strings-equal out, "", "F - test-substring/empty"
+  #
+  substring "abcde", 0, 3, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+#?   print-string-to-real-screen out
+#?   print-string-to-real-screen "\n"
+  check-strings-equal out, "abc", "F - test-substring/truncate"
+  #
+  substring "abcde", 0, 5, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "abcde", "F - test-substring/all"
+  #
+  substring "abcde", 0, 7, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "abcde", "F - test-substring/too-small"
+  # substrings outside string
+  substring "abcde", 6, 1, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "", "F - test-substring/start-too-large"
+  # trim prefix
+  substring "", 2, 3, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "", "F - test-substring/middle-empty"
+  #
+  substring "abcde", 1, 2, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "bc", "F - test-substring/middle-truncate"
+  #
+  substring "abcde", 1, 4, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "bcde", "F - test-substring/middle-all"
+  #
+  substring "abcde", 1, 5, out-ah
+  var out/eax: (addr array byte) <- lookup *out-ah
+  check-strings-equal out, "bcde", "F - test-substring/middle-too-small"
+}
diff --git a/apps/tile/environment.mu b/apps/tile/environment.mu
index 94fe8476..d006d245 100644
--- a/apps/tile/environment.mu
+++ b/apps/tile/environment.mu
@@ -1415,13 +1415,31 @@ $render-value:body: {
     break-if-!=
     var val-ah/eax: (addr handle array byte) <- get val, text-data
     var val-string/eax: (addr array byte) <- lookup *val-ah
+    compare val-string, 0
+    break-if-=
+    var orig-len/ecx: int <- length val-string
+    var truncated: (handle array byte)
+    var truncated-ah/esi: (addr handle array byte) <- address truncated
+    substring val-string, 0, 0xc, truncated-ah
+    var truncated-string/eax: (addr array byte) <- lookup *truncated-ah
+#?     {
+#?       var foo/eax: int <- copy truncated-string
+#?       print-int32-hex 0, foo
+#?       print-string 0, "\n"
+#?     }
+    var len/edx: int <- length truncated-string
     start-color screen, 0xf2, 7
-    print-code-point screen, 0x275d
+    print-code-point screen, 0x275d  # open-quote
     reset-formatting screen
     start-color screen, 0, 7
-    print-string screen, val-string
+    print-string screen, truncated-string
     start-color screen, 0xf2, 7
-    print-code-point screen, 0x275e
+    compare len, orig-len
+    {
+      break-if-=
+      print-code-point screen, 0x2026  # ellipses
+    }
+    print-code-point screen, 0x275e  # close-quote
     reset-formatting screen
     break $render-value:body
   }
diff --git a/apps/tile/main.mu b/apps/tile/main.mu
index 08e6532b..b02dc386 100644
--- a/apps/tile/main.mu
+++ b/apps/tile/main.mu
@@ -77,6 +77,10 @@ fn test {
   initialize-environment-with-fake-screen env, 5, 0xa
   var g/eax: grapheme <- copy 0x22  # '"'
   process env, g
+  g <- copy 0x61  # 'a'
+  process env, g
+  g <- copy 0x22  # '"'
+  process env, g
   render env
 }
 
diff --git a/apps/tile/value-stack.mu b/apps/tile/value-stack.mu
index a6ba4f0f..99e013bb 100644
--- a/apps/tile/value-stack.mu
+++ b/apps/tile/value-stack.mu
@@ -172,6 +172,11 @@ fn value-width _v: (addr value) -> result/eax: int {
       break-if-=
       var _out/eax: int <- length s
       out <- copy _out
+      compare out, 0xd  # max string size
+      {
+        break-if-<=
+        out <- copy 0xd
+      }
       break $value-width:body
     }
     {