https://github.com/akkartik/mu/blob/main/linux/apps/arith.mu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 fn main -> _/ebx: int {
35 enable-keyboard-immediate-mode
36 var look/esi: grapheme <- copy 0
37 var n/eax: int <- copy 0
38 print-string 0/screen, "press ctrl-c or ctrl-d to exit\n"
39
40 {
41
42 print-string 0/screen, "> "
43
44 n, look <- simplify
45
46 compare look, 0
47 break-if-=
48
49 print-int32-decimal 0/screen, n
50 print-string 0/screen, "\n"
51
52 loop
53 }
54 enable-keyboard-type-mode
55 return 0
56 }
57
58 fn simplify -> _/eax: int, _/esi: grapheme {
59
60 var look/esi: grapheme <- get-char
61
62 var result/eax: int <- copy 0
63 result, look <- expression look
64 return result, look
65 }
66
67 fn expression _look: grapheme -> _/eax: int, _/esi: grapheme {
68 var look/esi: grapheme <- copy _look
69
70 var result/eax: int <- copy 0
71 result, look <- term look
72 $expression:loop: {
73
74 look <- skip-spaces look
75 {
76 var continue?/eax: boolean <- add-or-sub? look
77 compare continue?, 0/false
78 break-if-= $expression:loop
79 }
80
81 var op/ecx: grapheme <- copy 0
82 op, look <- operator look
83
84 var second/edx: int <- copy 0
85 look <- skip-spaces look
86 {
87 var tmp/eax: int <- copy 0
88 tmp, look <- term look
89 second <- copy tmp
90 }
91
92 $expression:perform-op: {
93 {
94 compare op, 0x2b/+
95 break-if-!=
96 result <- add second
97 break $expression:perform-op
98 }
99 {
100 compare op, 0x2d/minus
101 break-if-!=
102 result <- subtract second
103 break $expression:perform-op
104 }
105 }
106 loop
107 }
108 look <- skip-spaces look
109 return result, look
110 }
111
112 fn term _look: grapheme -> _/eax: int, _/esi: grapheme {
113 var look/esi: grapheme <- copy _look
114
115 look <- skip-spaces look
116 var result/eax: int <- copy 0
117 result, look <- factor look
118 $term:loop: {
119
120 look <- skip-spaces look
121 {
122 var continue?/eax: boolean <- mul-or-div? look
123 compare continue?, 0/false
124 break-if-= $term:loop
125 }
126
127 var op/ecx: grapheme <- copy 0
128 op, look <- operator look
129
130 var second/edx: int <- copy 0
131 look <- skip-spaces look
132 {
133 var tmp/eax: int <- copy 0
134 tmp, look <- factor look
135 second <- copy tmp
136 }
137
138 $term:perform-op: {
139 {
140 compare op, 0x2a/*
141 break-if-!=
142 result <- multiply second
143 break $term:perform-op
144 }
145
146
147
148
149
150
151 }
152 loop
153 }
154 return result, look
155 }
156
157 fn factor _look: grapheme -> _/eax: int, _/esi: grapheme {
158 var look/esi: grapheme <- copy _look
159 look <- skip-spaces look
160
161 compare look, 0x28/open-paren
162 {
163 break-if-=
164 var result/eax: int <- copy 0
165 result, look <- num look
166 return result, look
167 }
168
169 look <- get-char
170 var result/eax: int <- copy 0
171 result, look <- expression look
172 look <- skip-spaces look
173 look <- get-char
174 return result, look
175 }
176
177 fn mul-or-div? c: grapheme -> _/eax: boolean {
178 compare c, 0x2a/*
179 {
180 break-if-!=
181 return 1/true
182 }
183 compare c, 0x2f/slash
184 {
185 break-if-!=
186 return 1/true
187 }
188 return 0/false
189 }
190
191 fn add-or-sub? c: grapheme -> _/eax: boolean {
192 compare c, 0x2b/+
193 {
194 break-if-!=
195 return 1/true
196 }
197 compare c, 0x2d/minus
198 {
199 break-if-!=
200 return 1/true
201 }
202 return 0/false
203 }
204
205 fn operator _look: grapheme -> _/ecx: grapheme, _/esi: grapheme {
206 var op/ecx: grapheme <- copy _look
207 var look/esi: grapheme <- get-char
208 return op, look
209 }
210
211 fn num _look: grapheme -> _/eax: int, _/esi: grapheme {
212 var look/esi: grapheme <- copy _look
213 var result/edi: int <- copy 0
214 {
215 var first-digit/eax: int <- to-decimal-digit look
216 result <- copy first-digit
217 }
218 {
219 look <- get-char
220
221 var digit?/eax: boolean <- decimal-digit? look
222 compare digit?, 0/false
223 break-if-=
224
225 {
226 var ten/eax: int <- copy 0xa
227 result <- multiply ten
228 }
229
230 var digit/eax: int <- to-decimal-digit look
231 result <- add digit
232 loop
233 }
234 return result, look
235 }
236
237 fn skip-spaces _look: grapheme -> _/esi: grapheme {
238 var look/esi: grapheme <- copy _look
239 {
240 compare look, 0x20
241 break-if-!=
242 look <- get-char
243 loop
244 }
245 return look
246 }
247
248 fn get-char -> _/esi: grapheme {
249 var look/eax: grapheme <- read-key-from-real-keyboard
250 print-grapheme-to-real-screen look
251 compare look, 4
252 {
253 break-if-!=
254 print-string 0/screen, "^D\n"
255 syscall_exit
256 }
257 return look
258 }