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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
type program {
defs: (handle function)
sandboxes: (handle sandbox)
}
type sandbox {
setup: (handle line)
data: (handle line)
next: (handle sandbox)
prev: (handle sandbox)
}
type function {
name: (handle array byte)
args: (handle word) # in reverse order
body: (handle line)
# some sort of indication of spatial location
next: (handle function)
}
type line {
name: (handle array byte)
data: (handle word)
result: (handle result) # might be cached
next: (handle line)
prev: (handle line)
}
type word {
# at most one of these will be non-null
scalar-data: (handle gap-buffer)
text-data: (handle array byte)
box-data: (handle line) # recurse
# other metadata attached to this word
display-subsidiary-stack?: boolean
next: (handle word)
prev: (handle word)
}
type value {
scalar-data: int
text-data: (handle array byte)
box-data: (handle line)
}
type table {
data: (handle array bind)
next: (handle table)
}
type bind {
key: (handle array byte)
value: (handle value) # I'd inline this but we sometimes want to return a specific value from a table
}
type result {
data: value-stack
error: (handle array byte) # single error message for now
}
# if 'out' is non-null, save the first word of the program there
fn initialize-program _program: (addr program), out: (addr handle word) {
var program/esi: (addr program) <- copy _program
var defs/eax: (addr handle function) <- get program, defs
create-primitive-defs defs
var sandbox-ah/eax: (addr handle sandbox) <- get program, sandboxes
allocate sandbox-ah
var sandbox/eax: (addr sandbox) <- lookup *sandbox-ah
initialize-sandbox sandbox, out
}
# if 'out' is non-null, save the first word of the sandbox there
fn initialize-sandbox _sandbox: (addr sandbox), out: (addr handle word) {
var sandbox/esi: (addr sandbox) <- copy _sandbox
var line-ah/eax: (addr handle line) <- get sandbox, data
allocate line-ah
var line/eax: (addr line) <- lookup *line-ah
initialize-line line, out
}
# initialize line with a single empty word
# if 'out' is non-null, save the word there as well
fn initialize-line _line: (addr line), out: (addr handle word) {
var line/esi: (addr line) <- copy _line
var word-ah/eax: (addr handle word) <- get line, data
allocate word-ah
{
compare out, 0
break-if-=
var dest/edi: (addr handle word) <- copy out
copy-object word-ah, dest
}
var word/eax: (addr word) <- lookup *word-ah
initialize-word word
}
fn create-primitive-defs _self: (addr handle function) {
# x 2* = x 2 *
var self/esi: (addr handle function) <- copy _self
allocate self
var _f/eax: (addr function) <- lookup *self
var f/esi: (addr function) <- copy _f
var name-ah/eax: (addr handle array byte) <- get f, name
populate-text-with name-ah, "2*"
var args-ah/eax: (addr handle word) <- get f, args
allocate args-ah
var args/eax: (addr word) <- lookup *args-ah
initialize-word-with args, "x"
var body-ah/eax: (addr handle line) <- get f, body
allocate body-ah
var body/eax: (addr line) <- lookup *body-ah
initialize-line body, 0
var curr-word-ah/ecx: (addr handle word) <- get body, data
allocate curr-word-ah
var curr-word/eax: (addr word) <- lookup *curr-word-ah
initialize-word-with curr-word, "x"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "2"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "*"
# x 1+ = x 1 +
var next/esi: (addr handle function) <- get f, next
allocate next
var _f/eax: (addr function) <- lookup *next
var f/esi: (addr function) <- copy _f
var name-ah/eax: (addr handle array byte) <- get f, name
populate-text-with name-ah, "1+"
var args-ah/eax: (addr handle word) <- get f, args
allocate args-ah
var args/eax: (addr word) <- lookup *args-ah
initialize-word-with args, "x"
var body-ah/eax: (addr handle line) <- get f, body
allocate body-ah
var body/eax: (addr line) <- lookup *body-ah
initialize-line body, 0
var curr-word-ah/ecx: (addr handle word) <- get body, data
allocate curr-word-ah
var curr-word/eax: (addr word) <- lookup *curr-word-ah
initialize-word-with curr-word, "x"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "1"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "+"
# x 2+ = x 1+ 1+
var next/esi: (addr handle function) <- get f, next
allocate next
var _f/eax: (addr function) <- lookup *next
var f/ecx: (addr function) <- copy _f
var name-ah/eax: (addr handle array byte) <- get f, name
populate-text-with name-ah, "2+"
var args-ah/eax: (addr handle word) <- get f, args
allocate args-ah
var args/eax: (addr word) <- lookup *args-ah
initialize-word-with args, "x"
var body-ah/eax: (addr handle line) <- get f, body
allocate body-ah
var body/eax: (addr line) <- lookup *body-ah
initialize-line body, 0
var curr-word-ah/ecx: (addr handle word) <- get body, data
allocate curr-word-ah
var curr-word/eax: (addr word) <- lookup *curr-word-ah
initialize-word-with curr-word, "x"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "1+"
curr-word-ah <- get curr-word, next
allocate curr-word-ah
curr-word <- lookup *curr-word-ah
initialize-word-with curr-word, "1+"
# TODO: populate prev pointers
}
fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) {
var in/esi: (addr array byte) <- copy _in
var n/ecx: int <- length in
var out/edx: (addr handle array byte) <- copy _out
populate out, n
var _out-addr/eax: (addr array byte) <- lookup *out
var out-addr/edx: (addr array byte) <- copy _out-addr
var i/eax: int <- copy 0
{
compare i, n
break-if->=
var src/esi: (addr byte) <- index in, i
var val/ecx: byte <- copy-byte *src
var dest/edi: (addr byte) <- index out-addr, i
copy-byte-to *dest, val
i <- increment
loop
}
}
|