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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
type global {
name: (handle array byte)
value: (handle cell)
}
type global-table {
data: (handle array global)
final-index: int
}
fn initialize-globals _self: (addr global-table) {
var self/esi: (addr global-table) <- copy _self
var data-ah/eax: (addr handle array global) <- get self, data
populate data-ah, 0x10
append-primitive self, "+"
append-primitive self, "-"
append-primitive self, "*"
append-primitive self, "/"
}
fn append-primitive _self: (addr global-table), name: (addr array byte) {
var self/esi: (addr global-table) <- copy _self
var final-index-addr/ecx: (addr int) <- get self, final-index
increment *final-index-addr
var curr-index/ecx: int <- copy *final-index-addr
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var curr-offset/esi: (offset global) <- compute-offset data, curr-index
var curr/esi: (addr global) <- index data, curr-offset
var curr-name-ah/eax: (addr handle array byte) <- get curr, name
copy-array-object name, curr-name-ah
var curr-value-ah/eax: (addr handle cell) <- get curr, value
new-primitive-function curr-value-ah, curr-index
}
fn lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace) {
var sym/eax: (addr cell) <- copy _sym
var sym-data-ah/eax: (addr handle stream byte) <- get sym, text-data
var _sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
var sym-data/edx: (addr stream byte) <- copy _sym-data
var globals/esi: (addr global-table) <- copy _globals
{
compare globals, 0
break-if-=
var global-data-ah/eax: (addr handle array global) <- get globals, data
var global-data/eax: (addr array global) <- lookup *global-data-ah
var final-index/ecx: (addr int) <- get globals, final-index
var curr-index/ecx: int <- copy *final-index
{
compare curr-index, 0
break-if-<
var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index
var curr/ebx: (addr global) <- index global-data, curr-offset
var curr-name-ah/eax: (addr handle array byte) <- get curr, name
var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
var found?/eax: boolean <- stream-data-equal? sym-data, curr-name
{
compare found?, 0/false
break-if-=
var curr-value/eax: (addr handle cell) <- get curr, value
copy-object curr-value, out
return
}
curr-index <- decrement
loop
}
}
# otherwise error "unbound symbol: ", sym
var stream-storage: (stream byte 0x40)
var stream/ecx: (addr stream byte) <- address stream-storage
write stream, "unbound symbol: "
rewind-stream sym-data
write-stream stream, sym-data
trace trace, "error", stream
}
# a little strange; goes from value to name and selects primitive based on name
fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), _globals: (addr global-table), trace: (addr trace) {
var f/esi: (addr cell) <- copy _f
var f-index-a/ecx: (addr int) <- get f, index-data
var f-index/ecx: int <- copy *f-index-a
var globals/eax: (addr global-table) <- copy _globals
var global-data-ah/eax: (addr handle array global) <- get globals, data
var global-data/eax: (addr array global) <- lookup *global-data-ah
var f-offset/ecx: (offset global) <- compute-offset global-data, f-index
var f-value/ecx: (addr global) <- index global-data, f-offset
var f-name-ah/ecx: (addr handle array byte) <- get f-value, name
var f-name/eax: (addr array byte) <- lookup *f-name-ah
{
var is-add?/eax: boolean <- string-equal? f-name, "+"
compare is-add?, 0/false
break-if-=
apply-add args-ah, out, env-h, trace
return
}
abort "unknown primitive function"
}
fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) {
trace-text trace, "eval", "apply +"
var args-ah/eax: (addr handle cell) <- copy _args-ah
var _args/eax: (addr cell) <- lookup *args-ah
var args/esi: (addr cell) <- copy _args
var _env/eax: (addr cell) <- lookup env-h
var env/edi: (addr cell) <- copy _env
# TODO: check that args is a pair
var empty-args?/eax: boolean <- nil? args
compare empty-args?, 0/false
{
break-if-=
error trace, "+ needs 2 args but got 0"
return
}
# args->left->value
var first-ah/eax: (addr handle cell) <- get args, left
var first/eax: (addr cell) <- lookup *first-ah
var first-type/ecx: (addr int) <- get first, type
compare *first-type, 1/number
{
break-if-=
error trace, "first arg for + is not a number"
return
}
var first-value/ecx: (addr float) <- get first, number-data
# args->right->left->value
var right-ah/eax: (addr handle cell) <- get args, right
#? dump-cell right-ah
#? abort "aaa"
var right/eax: (addr cell) <- lookup *right-ah
# TODO: check that right is a pair
var second-ah/eax: (addr handle cell) <- get right, left
var second/eax: (addr cell) <- lookup *second-ah
var second-type/edx: (addr int) <- get second, type
compare *second-type, 1/number
{
break-if-=
error trace, "second arg for + is not a number"
return
}
var second-value/edx: (addr float) <- get second, number-data
# add
var result/xmm0: float <- copy *first-value
result <- add *second-value
new-float out, result
}
|