about summary refs log tree commit diff stats
path: root/515parse-float.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-10-12 22:31:57 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-10-12 22:31:57 -0700
commitd280bd8dac5555a6dd8fdc34b8e423f120f05887 (patch)
treefe8be37328a65e7ec3f503cce790b033baed6b51 /515parse-float.mu
parent72d104d1693ee7671ef5a956d0ae93540a792da7 (diff)
downloadmu-d280bd8dac5555a6dd8fdc34b8e423f120f05887.tar.gz
parse float from text
Diffstat (limited to '515parse-float.mu')
-rw-r--r--515parse-float.mu170
1 files changed, 170 insertions, 0 deletions
diff --git a/515parse-float.mu b/515parse-float.mu
new file mode 100644
index 00000000..40bbb194
--- /dev/null
+++ b/515parse-float.mu
@@ -0,0 +1,170 @@
+# no support for scientific notation yet
+fn parse-float-decimal in: (addr stream byte) -> _/xmm1: float {
+  var zero: float
+  var result/xmm1: float <- copy zero
+  var first-iter?/ecx: int <- copy 1/true
+  rewind-stream in
+  var negative?/edx: int <- copy 0/false
+  # first loop: integer part
+  var ten/eax: int <- copy 0xa
+  var ten-f/xmm2: float <- convert ten
+  {
+    var done?/eax: boolean <- stream-empty? in
+    compare done?, 0/false
+    break-if-!=
+    var key/eax: byte <- read-byte in
+    compare key, 0x2e/decimal-point
+    break-if-=
+    $parse-float-decimal:body: {
+      compare key, 0x2d/-
+      {
+        break-if-!=
+        compare first-iter?, 0/false
+        {
+          break-if-!=
+          abort "parse-float-decimal: '-' only allowed in first position"
+        }
+        negative? <- copy 1/true
+        break $parse-float-decimal:body
+      }
+      compare key, 0x30/0
+      {
+        break-if->=
+        abort "parse-float-decimal: invalid character < '0'"
+      }
+      compare key, 0x39/9
+      {
+        break-if-<=
+        abort "parse-float-decimal: invalid character > '9'"
+      }
+      # key is now a digit
+      var digit-value/eax: int <- copy key
+      digit-value <- subtract 0x30
+      var digit-value-f/xmm3: float <- convert digit-value
+      result <- multiply ten-f
+      result <- add digit-value-f
+    }
+    first-iter? <- copy 0/false
+    loop
+  }
+  # second loop: fraction
+  var current-position/xmm0: float <- rational 1, 0xa
+  {
+    var done?/eax: boolean <- stream-empty? in
+    compare done?, 0/false
+    break-if-!=
+    var key/eax: byte <- read-byte in
+    compare key, 0x30/0
+    {
+      break-if->=
+      abort "parse-float-decimal: invalid fraction character < '0'"
+    }
+    compare key, 0x39/9
+    {
+      break-if-<=
+      abort "parse-float-decimal: invalid fraction character > '9'"
+    }
+    # key is now a digit
+    var digit-value/eax: int <- copy key
+    digit-value <- subtract 0x30
+    var digit-value-f/xmm3: float <- convert digit-value
+    digit-value-f <- multiply current-position
+    result <- add digit-value-f
+    current-position <- divide ten-f
+    #
+    first-iter? <- copy 0/false
+    loop
+  }
+  # finally, the sign
+  compare negative?, 0/false
+  {
+    break-if-=
+    var minus-one/eax: int <- copy -1
+    var minus-one-f/xmm2: float <- convert minus-one
+    result <- multiply minus-one-f
+  }
+  return result
+}
+
+fn test-parse-float-decimal-zero {
+  var s-storage: (stream byte 0x10)
+  var s/esi: (addr stream byte) <- address s-storage
+  write s, "00"
+  var x/xmm1: float <- parse-float-decimal s
+  var expected/eax: int <- copy 0
+  var expected-f/xmm0: float <- convert expected
+  compare x, expected-f
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-zero", 3/fg 0/bg
+    move-cursor-to-left-margin-of-next-line 0/screen
+    count-test-failure
+  }
+  draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
+}
+
+fn test-parse-float-decimal-integer {
+  var s-storage: (stream byte 0x10)
+  var s/esi: (addr stream byte) <- address s-storage
+  write s, "34"
+  var x/xmm1: float <- parse-float-decimal s
+  var expected/eax: int <- copy 0x22/34
+  var expected-f/xmm0: float <- convert expected
+  compare x, expected-f
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-integer", 3/fg 0/bg
+    move-cursor-to-left-margin-of-next-line 0/screen
+    count-test-failure
+  }
+  draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
+}
+
+fn test-parse-float-decimal-negative-integer {
+  var s-storage: (stream byte 0x10)
+  var s/esi: (addr stream byte) <- address s-storage
+  write s, "-34"
+  var x/xmm1: float <- parse-float-decimal s
+  var expected/eax: int <- copy -0x22/-34
+  var expected-f/xmm0: float <- convert expected
+  compare x, expected-f
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-integer", 3/fg 0/bg
+    move-cursor-to-left-margin-of-next-line 0/screen
+    count-test-failure
+  }
+  draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
+}
+
+fn test-parse-float-decimal-fraction {
+  var s-storage: (stream byte 0x10)
+  var s/esi: (addr stream byte) <- address s-storage
+  write s, "3.4"
+  var x/xmm1: float <- parse-float-decimal s
+  var expected-f/xmm0: float <- rational 0x22/34, 0xa/10
+  compare x, expected-f
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-fraction", 3/fg 0/bg
+    move-cursor-to-left-margin-of-next-line 0/screen
+    count-test-failure
+  }
+  draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
+}
+
+fn test-parse-float-decimal-negative-fraction {
+  var s-storage: (stream byte 0x10)
+  var s/esi: (addr stream byte) <- address s-storage
+  write s, "-3.4"
+  var x/xmm1: float <- parse-float-decimal s
+  var expected-f/xmm0: float <- rational -0x22/-34, 0xa/10
+  compare x, expected-f
+  {
+    break-if-=
+    draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-fraction", 3/fg 0/bg
+    move-cursor-to-left-margin-of-next-line 0/screen
+    count-test-failure
+  }
+  draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
+}