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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
fn main -> exit-status/ebx: int {
var look/esi: byte <- copy 0 # lookahead
var n/eax: int <- copy 0 # result of each expression
# read-eval-print loop
{
# print prompt
print-string "> "
# read and eval
n, look <- simplify
# if (look == 0) break
compare look, 0
break-if-=
# print
print-int32-to-screen n
print-string "\n"
#
loop
}
exit-status <- copy 0
}
fn simplify -> result/eax: int, look/esi: byte {
# prime the pump
look <- get-char # prime the pump
look <- skip-spaces look
result, look <- term look
$simplify:loop: {
# operator
var op/ecx: byte <- copy 0
look <- skip-spaces look
compare look, 0
break-if-=
compare look, 0xa
break-if-=
op, look <- operator look
# second arg
var second/edx: int <- copy 0
look <- skip-spaces look
{
var tmp/eax: int <- copy 0
tmp, look <- term look
second <- copy tmp
}
# perform op
$simplify:perform-op: {
{
compare op, 0x2b # '+'
break-if-!=
result <- add second
break $simplify:perform-op
}
{
compare op, 0x2d # '-'
break-if-!=
result <- subtract second
break $simplify:perform-op
}
}
loop
}
look <- skip-spaces look
}
fn term _look: byte -> result/eax: int, look/esi: byte {
look <- copy _look # should be a no-op
result, look <- num look
}
fn operator _look: byte -> op/ecx: byte, look/esi: byte {
op <- copy _look
look <- get-char
}
fn num _look: byte -> result/eax: int, look/esi: byte {
look <- copy _look # should be a no-op; guaranteed to be a digit
var out/edi: int <- copy 0
{
var first-digit/eax: int <- to-decimal-digit look
out <- copy first-digit
}
{
look <- get-char
# done?
var digit?/eax: bool <- is-decimal-digit? look
compare digit?, 0 # false
break-if-=
# out *= 10
{
var ten/eax: int <- copy 0xa
out <- multiply ten
}
# out += digit(look)
var digit/eax: int <- to-decimal-digit look
out <- add digit
loop
}
result <- copy out
}
fn skip-spaces _look: byte -> look/esi: byte {
look <- copy _look # should be a no-op
{
compare look, 0x20
break-if-!=
look <- get-char
loop
}
}
fn get-char -> look/esi: byte {
var tmp/eax: byte <- read-key
look <- copy tmp
compare look, 0
{
break-if-!=
print-string "^D\n"
syscall_exit
}
}
|