https://github.com/akkartik/mu/blob/main/515parse-float.mu
1
2 fn parse-float-decimal in: (addr stream byte) -> _/xmm1: float {
3 var zero: float
4 var result/xmm1: float <- copy zero
5 var first-iter?/ecx: int <- copy 1/true
6 rewind-stream in
7 var negative?/edx: int <- copy 0/false
8
9 var ten/eax: int <- copy 0xa
10 var ten-f/xmm2: float <- convert ten
11 {
12 var done?/eax: boolean <- stream-empty? in
13 compare done?, 0/false
14 break-if-!=
15 var key/eax: byte <- read-byte in
16 compare key, 0x2e/decimal-point
17 break-if-=
18 $parse-float-decimal:body: {
19 compare key, 0x2d/-
20 {
21 break-if-!=
22 compare first-iter?, 0/false
23 {
24 break-if-!=
25 abort "parse-float-decimal: '-' only allowed in first position"
26 }
27 negative? <- copy 1/true
28 break $parse-float-decimal:body
29 }
30 compare key, 0x30/0
31 {
32 break-if->=
33 abort "parse-float-decimal: invalid character < '0'"
34 }
35 compare key, 0x39/9
36 {
37 break-if-<=
38 abort "parse-float-decimal: invalid character > '9'"
39 }
40
41 var digit-value/eax: int <- copy key
42 digit-value <- subtract 0x30
43 var digit-value-f/xmm3: float <- convert digit-value
44 result <- multiply ten-f
45 result <- add digit-value-f
46 }
47 first-iter? <- copy 0/false
48 loop
49 }
50
51 var current-position/xmm0: float <- rational 1, 0xa
52 {
53 var done?/eax: boolean <- stream-empty? in
54 compare done?, 0/false
55 break-if-!=
56 var key/eax: byte <- read-byte in
57 compare key, 0x30/0
58 {
59 break-if->=
60 abort "parse-float-decimal: invalid fraction character < '0'"
61 }
62 compare key, 0x39/9
63 {
64 break-if-<=
65 abort "parse-float-decimal: invalid fraction character > '9'"
66 }
67
68 var digit-value/eax: int <- copy key
69 digit-value <- subtract 0x30
70 var digit-value-f/xmm3: float <- convert digit-value
71 digit-value-f <- multiply current-position
72 result <- add digit-value-f
73 current-position <- divide ten-f
74
75 first-iter? <- copy 0/false
76 loop
77 }
78
79 compare negative?, 0/false
80 {
81 break-if-=
82 var minus-one/eax: int <- copy -1
83 var minus-one-f/xmm2: float <- convert minus-one
84 result <- multiply minus-one-f
85 }
86 return result
87 }
88
89 fn test-parse-float-decimal-zero {
90 var s-storage: (stream byte 0x10)
91 var s/esi: (addr stream byte) <- address s-storage
92 write s, "00"
93 var x/xmm1: float <- parse-float-decimal s
94 var expected/eax: int <- copy 0
95 var expected-f/xmm0: float <- convert expected
96 compare x, expected-f
97 {
98 break-if-=
99 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-zero", 3/fg 0/bg
100 move-cursor-to-left-margin-of-next-line 0/screen
101 count-test-failure
102 }
103 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
104 }
105
106 fn test-parse-float-decimal-integer {
107 var s-storage: (stream byte 0x10)
108 var s/esi: (addr stream byte) <- address s-storage
109 write s, "34"
110 var x/xmm1: float <- parse-float-decimal s
111 var expected/eax: int <- copy 0x22/34
112 var expected-f/xmm0: float <- convert expected
113 compare x, expected-f
114 {
115 break-if-=
116 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-integer", 3/fg 0/bg
117 move-cursor-to-left-margin-of-next-line 0/screen
118 count-test-failure
119 }
120 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
121 }
122
123 fn test-parse-float-decimal-negative-integer {
124 var s-storage: (stream byte 0x10)
125 var s/esi: (addr stream byte) <- address s-storage
126 write s, "-34"
127 var x/xmm1: float <- parse-float-decimal s
128 var expected/eax: int <- copy -0x22/-34
129 var expected-f/xmm0: float <- convert expected
130 compare x, expected-f
131 {
132 break-if-=
133 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-integer", 3/fg 0/bg
134 move-cursor-to-left-margin-of-next-line 0/screen
135 count-test-failure
136 }
137 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
138 }
139
140 fn test-parse-float-decimal-fraction {
141 var s-storage: (stream byte 0x10)
142 var s/esi: (addr stream byte) <- address s-storage
143 write s, "3.4"
144 var x/xmm1: float <- parse-float-decimal s
145 var expected-f/xmm0: float <- rational 0x22/34, 0xa/10
146 compare x, expected-f
147 {
148 break-if-=
149 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-fraction", 3/fg 0/bg
150 move-cursor-to-left-margin-of-next-line 0/screen
151 count-test-failure
152 }
153 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
154 }
155
156 fn test-parse-float-decimal-negative-fraction {
157 var s-storage: (stream byte 0x10)
158 var s/esi: (addr stream byte) <- address s-storage
159 write s, "-3.4"
160 var x/xmm1: float <- parse-float-decimal s
161 var expected-f/xmm0: float <- rational -0x22/-34, 0xa/10
162 compare x, expected-f
163 {
164 break-if-=
165 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "F - test-parse-float-decimal-negative-fraction", 3/fg 0/bg
166 move-cursor-to-left-margin-of-next-line 0/screen
167 count-test-failure
168 }
169 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
170 }