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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
|
type global-table {
data: (handle array global)
final-index: int
cursor-index: int
}
type global {
name: (handle array byte)
input: (handle gap-buffer)
value: (handle cell)
}
fn initialize-globals _self: (addr global-table) {
var self/esi: (addr global-table) <- copy _self
compare self, 0
{
break-if-!=
abort "initialize globals"
return
}
var data-ah/eax: (addr handle array global) <- get self, data
populate data-ah, 0x80
initialize-primitives self
}
fn load-globals in: (addr handle cell), self: (addr global-table) {
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading globals:", 3/fg, 0/bg
var remaining-ah/esi: (addr handle cell) <- copy in
{
var _remaining/eax: (addr cell) <- lookup *remaining-ah
var remaining/ebx: (addr cell) <- copy _remaining
var done?/eax: boolean <- nil? remaining
compare done?, 0/false
break-if-!=
#? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "b", 2/fg 0/bg
var curr-ah/eax: (addr handle cell) <- get remaining, left
var _curr/eax: (addr cell) <- lookup *curr-ah
var curr/ecx: (addr cell) <- copy _curr
remaining-ah <- get remaining, right
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " ", 2/fg 0/bg
var name-ah/eax: (addr handle cell) <- get curr, left
var name/eax: (addr cell) <- lookup *name-ah
var name-data-ah/eax: (addr handle stream byte) <- get name, text-data
var _name-data/eax: (addr stream byte) <- lookup *name-data-ah
var name-data/edx: (addr stream byte) <- copy _name-data
rewind-stream name-data
draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, name-data, 3/fg, 0/bg
var value-ah/eax: (addr handle cell) <- get curr, right
var value/eax: (addr cell) <- lookup *value-ah
var value-data-ah/eax: (addr handle stream byte) <- get value, text-data
var _value-data/eax: (addr stream byte) <- lookup *value-data-ah
var value-data/ecx: (addr stream byte) <- copy _value-data
var value-gap-buffer-storage: (handle gap-buffer)
var value-gap-buffer-ah/edi: (addr handle gap-buffer) <- address value-gap-buffer-storage
allocate value-gap-buffer-ah
var value-gap-buffer/eax: (addr gap-buffer) <- lookup *value-gap-buffer-ah
initialize-gap-buffer value-gap-buffer, 0x1000/4KB
#? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "w", 2/fg 0/bg
load-gap-buffer-from-stream value-gap-buffer, value-data
#? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "x", 2/fg 0/bg
read-evaluate-and-move-to-globals value-gap-buffer-ah, self, name-data
#? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "y", 2/fg 0/bg
loop
}
move-cursor-to-left-margin-of-next-line 0/screen
#? abort "zz"
}
fn write-globals out: (addr stream byte), _self: (addr global-table) {
var self/esi: (addr global-table) <- copy _self
compare self, 0
{
break-if-!=
abort "write globals"
return
}
write out, " (globals . (\n"
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var final-index/edx: (addr int) <- get self, final-index
var curr-index/ecx: int <- copy 1/skip-0
{
compare curr-index, *final-index
break-if->
var curr-offset/ebx: (offset global) <- compute-offset data, curr-index
var curr/ebx: (addr global) <- index data, curr-offset
var curr-value-ah/edx: (addr handle cell) <- get curr, value
var curr-value/eax: (addr cell) <- lookup *curr-value-ah
var curr-type/eax: (addr int) <- get curr-value, type
{
compare *curr-type, 4/primitive-function
break-if-=
compare *curr-type, 5/screen
break-if-=
compare *curr-type, 6/keyboard
break-if-=
compare *curr-type, 3/stream # not implemented yet
break-if-=
write out, " ("
var curr-name-ah/eax: (addr handle array byte) <- get curr, name
var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
write out, curr-name
write out, " . ["
var curr-input-ah/eax: (addr handle gap-buffer) <- get curr, input
var curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah
append-gap-buffer curr-input, out
write out, "])\n"
}
curr-index <- increment
loop
}
write out, " ))\n"
}
# globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 chars
fn render-globals screen: (addr screen), _self: (addr global-table), show-cursor?: boolean {
clear-rect screen, 0/xmin, 0/ymin, 0x55/xmax, 0x2f/ymax=screen-height-without-menu, 0xdc/bg=green-bg
var self/esi: (addr global-table) <- copy _self
compare self, 0
{
break-if-!=
abort "render globals"
return
}
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var curr-index/edx: int <- copy 1
{
var curr-offset/ebx: (offset global) <- compute-offset data, curr-index
var curr/ebx: (addr global) <- index data, curr-offset
var continue?/eax: boolean <- primitive-global? curr
compare continue?, 0/false
break-if-=
curr-index <- increment
loop
}
var lowest-index/edi: int <- copy curr-index
var cursor-index/edx: (addr int) <- get self, cursor-index
var curr-index/edx: int <- copy *cursor-index
var y1: int
copy-to y1, 1/padding-top
var y2: int
copy-to y2, 1/padding-top
$render-globals:loop: {
compare curr-index, lowest-index
break-if-<
{
compare y1, 0x2f/ymax
break-if-<
compare y2, 0x2f/ymax
break-if-<
break $render-globals:loop
}
{
var show-cursor?/edi: boolean <- copy show-cursor?
{
compare show-cursor?, 0/false
break-if-=
var cursor-index/eax: (addr int) <- get self, cursor-index
compare *cursor-index, curr-index
break-if-=
show-cursor? <- copy 0/false
}
var curr-offset/edx: (offset global) <- compute-offset data, curr-index
var curr/edx: (addr global) <- index data, curr-offset
var curr-input-ah/edx: (addr handle gap-buffer) <- get curr, input
var _curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah
var curr-input/ebx: (addr gap-buffer) <- copy _curr-input
compare curr-input, 0
break-if-=
$render-globals:render-global: {
var x/eax: int <- copy 0
var y/ecx: int <- copy y1
compare y, y2
{
break-if->=
x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 1/padding-left, y1, 0x2a/xmax, 0x2f/ymax, show-cursor?, 7/fg=definition, 0xc5/bg=blue-bg
y <- add 2
copy-to y1, y
break $render-globals:render-global
}
x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 0x2b/xmin, y2, 0x54/xmax, 0x2f/ymax, show-cursor?, 7/fg=definition, 0xc5/bg=blue-bg
y <- add 2
copy-to y2, y
}
}
curr-index <- decrement
loop
}
# render primitives on top
render-primitives screen, 1/xmin=padding-left, 0x55/xmax, 0x2f/ymax
}
fn render-globals-menu screen: (addr screen), _self: (addr global-table) {
var _width/eax: int <- copy 0
var height/ecx: int <- copy 0
_width, height <- screen-size screen
var width/edx: int <- copy _width
var y/ecx: int <- copy height
y <- decrement
var height/ebx: int <- copy y
height <- increment
clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg
set-cursor-position screen, 0/x, y
draw-text-rightward-from-cursor screen, " ^r ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^s ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^g ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " go to ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^a ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " << ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " <word ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " word> ", width, 7/fg, 0xc5/bg=blue-bg
draw-text-rightward-from-cursor screen, " ^e ", width, 0/fg, 0x5c/bg=menu-highlight
draw-text-rightward-from-cursor screen, " >> ", width, 7/fg, 0xc5/bg=blue-bg
}
fn edit-globals _self: (addr global-table), key: grapheme {
var self/esi: (addr global-table) <- copy _self
# ctrl-s
{
compare key, 0x13/ctrl-s
break-if-!=
#
refresh-cursor-definition self
return
}
var cursor-index-addr/ecx: (addr int) <- get self, cursor-index
var cursor-index/ecx: int <- copy *cursor-index-addr
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var cursor-offset/ecx: (offset global) <- compute-offset data, cursor-index
var curr-global/eax: (addr global) <- index data, cursor-offset
var curr-editor-ah/eax: (addr handle gap-buffer) <- get curr-global, input
var curr-editor/eax: (addr gap-buffer) <- lookup *curr-editor-ah
edit-gap-buffer curr-editor, key
}
fn create-empty-global _self: (addr global-table), name-stream: (addr stream byte), capacity: int {
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 cursor-index-addr/eax: (addr int) <- get self, cursor-index
copy-to *cursor-index-addr, curr-index
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var curr-offset/ecx: (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
stream-to-array name-stream, curr-name-ah
var curr-input-ah/eax: (addr handle gap-buffer) <- get curr, input
allocate curr-input-ah
var curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah
initialize-gap-buffer curr-input, capacity
}
fn refresh-cursor-definition _self: (addr global-table) {
var self/esi: (addr global-table) <- copy _self
var cursor-index/edx: (addr int) <- get self, cursor-index
refresh-definition self, *cursor-index
}
fn refresh-definition _self: (addr global-table), _index: int {
var self/esi: (addr global-table) <- copy _self
var data-ah/eax: (addr handle array global) <- get self, data
var data/eax: (addr array global) <- lookup *data-ah
var index/ecx: int <- copy _index
var offset/ecx: (offset global) <- compute-offset data, index
var curr-global/ecx: (addr global) <- index data, offset
var curr-input-ah/eax: (addr handle gap-buffer) <- get curr-global, input
var curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah
var read-result-h: (handle cell)
var read-result-ah/edx: (addr handle cell) <- address read-result-h
var trace-storage: trace
var trace/ebx: (addr trace) <- address trace-storage
initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible
read-cell curr-input, read-result-ah, trace
macroexpand read-result-ah, self, trace
var nil-h: (handle cell)
{
var nil-ah/eax: (addr handle cell) <- address nil-h
allocate-pair nil-ah
}
var curr-value-ah/eax: (addr handle cell) <- get curr-global, value
debug-print "GL", 4/fg, 0/bg
evaluate read-result-ah, curr-value-ah, nil-h, self, trace, 0/no-screen-cell, 0/no-keyboard-cell, 1/call-number
debug-print "GZ", 4/fg, 0/bg
}
fn assign-or-create-global _self: (addr global-table), name: (addr array byte), value: (handle cell), trace: (addr trace) {
var self/esi: (addr global-table) <- copy _self
compare self, 0
{
break-if-!=
abort "assign global"
return
}
var curr-index/ecx: int <- find-symbol-name-in-globals self, name
{
compare curr-index, -1/not-found
break-if-!=
var final-index-addr/eax: (addr int) <- get self, final-index
increment *final-index-addr
curr-index <- copy *final-index-addr
var cursor-index-addr/eax: (addr int) <- get self, cursor-index
copy-to *cursor-index-addr, curr-index
}
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
copy-handle value, curr-value-ah
}
fn lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
var sym/eax: (addr cell) <- copy _sym
var sym-name-ah/eax: (addr handle stream byte) <- get sym, text-data
var _sym-name/eax: (addr stream byte) <- lookup *sym-name-ah
var sym-name/edx: (addr stream byte) <- copy _sym-name
var globals/esi: (addr global-table) <- copy _globals
{
compare globals, 0
break-if-=
var curr-index/ecx: int <- find-symbol-in-globals globals, sym-name
compare curr-index, -1/not-found
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 curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index
var curr/ebx: (addr global) <- index global-data, curr-offset
var curr-value/eax: (addr handle cell) <- get curr, value
copy-object curr-value, out
return
}
# if sym is "screen" and screen-cell exists, return it
{
var sym-is-screen?/eax: boolean <- stream-data-equal? sym-name, "screen"
compare sym-is-screen?, 0/false
break-if-=
compare screen-cell, 0
break-if-=
copy-object screen-cell, out
return
}
# if sym is "keyboard" and keyboard-cell exists, return it
{
var sym-is-keyboard?/eax: boolean <- stream-data-equal? sym-name, "keyboard"
compare sym-is-keyboard?, 0/false
break-if-=
compare keyboard-cell, 0
break-if-=
copy-object keyboard-cell, out
return
}
# 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-name
write-stream stream, sym-name
error-stream trace, stream
}
fn maybe-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-name-ah/eax: (addr handle stream byte) <- get sym, text-data
var _sym-name/eax: (addr stream byte) <- lookup *sym-name-ah
var sym-name/edx: (addr stream byte) <- copy _sym-name
var globals/esi: (addr global-table) <- copy _globals
{
compare globals, 0
break-if-=
var curr-index/ecx: int <- find-symbol-in-globals globals, sym-name
compare curr-index, -1/not-found
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 curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index
var curr/ebx: (addr global) <- index global-data, curr-offset
var curr-value/eax: (addr handle cell) <- get curr, value
copy-object curr-value, out
return
}
}
# return the index in globals containing 'sym'
# or -1 if not found
fn find-symbol-in-globals _globals: (addr global-table), sym-name: (addr stream byte) -> _/ecx: int {
var globals/esi: (addr global-table) <- copy _globals
compare globals, 0
{
break-if-!=
return -1/not-found
}
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-name, curr-name
compare found?, 0/false
{
break-if-=
return curr-index
}
curr-index <- decrement
loop
}
return -1/not-found
}
# return the index in globals containing 'sym'
# or -1 if not found
fn find-symbol-name-in-globals _globals: (addr global-table), sym-name: (addr array byte) -> _/ecx: int {
var globals/esi: (addr global-table) <- copy _globals
compare globals, 0
{
break-if-!=
return -1/not-found
}
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 <- string-equal? sym-name, curr-name
compare found?, 0/false
{
break-if-=
return curr-index
}
curr-index <- decrement
loop
}
return -1/not-found
}
fn mutate-binding-in-globals name: (addr stream byte), val: (addr handle cell), _globals: (addr global-table), trace: (addr trace) {
var globals/esi: (addr global-table) <- copy _globals
{
compare globals, 0
break-if-=
var curr-index/ecx: int <- find-symbol-in-globals globals, name
compare curr-index, -1/not-found
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 curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index
var curr/ebx: (addr global) <- index global-data, curr-offset
var dest/eax: (addr handle cell) <- get curr, value
copy-object val, dest
return
}
# 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 name
write-stream stream, name
error-stream trace, stream
}
# Accepts an input s-expression, naively checks if it is a definition, and if
# so saves the gap-buffer to the appropriate global, spinning up a new empty
# one to replace it with.
fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) {
# if 'definition' is not a pair, return
var definition-ah/eax: (addr handle cell) <- copy _definition-ah
var _definition/eax: (addr cell) <- lookup *definition-ah
var definition/esi: (addr cell) <- copy _definition
var definition-type/eax: (addr int) <- get definition, type
compare *definition-type, 0/pair
{
break-if-=
return
}
# if definition->left is neither "define" nor "set", return
var left-ah/eax: (addr handle cell) <- get definition, left
var _left/eax: (addr cell) <- lookup *left-ah
var left/ecx: (addr cell) <- copy _left
{
var def?/eax: boolean <- symbol-equal? left, "define"
compare def?, 0/false
break-if-!=
var set?/eax: boolean <- symbol-equal? left, "set"
compare set?, 0/false
break-if-!=
return
}
# locate the global for definition->right->left
var right-ah/eax: (addr handle cell) <- get definition, right
var right/eax: (addr cell) <- lookup *right-ah
var defined-symbol-ah/eax: (addr handle cell) <- get right, left
var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah
var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data
var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah
var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name
{
compare index, -1/not-found
break-if-!=
return
}
# stash 'gap' to it
var globals/eax: (addr global-table) <- copy _globals
compare globals, 0
{
break-if-!=
abort "stash to globals"
return
}
var global-data-ah/eax: (addr handle array global) <- get globals, data
var global-data/eax: (addr array global) <- lookup *global-data-ah
var offset/ebx: (offset global) <- compute-offset global-data, index
var dest-global/eax: (addr global) <- index global-data, offset
var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input
copy-object gap, dest-ah
# initialize a new gap-buffer in 'gap'
var dest/eax: (addr gap-buffer) <- lookup *dest-ah
var capacity/ecx: int <- gap-buffer-capacity dest
var gap2/eax: (addr handle gap-buffer) <- copy gap
allocate gap2
var gap-addr/eax: (addr gap-buffer) <- lookup *gap2
initialize-gap-buffer gap-addr, capacity
}
# Accepts an input s-expression, naively checks if it is a definition, and if
# so saves the gap-buffer to the appropriate global.
fn move-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) {
# if 'definition' is not a pair, return
var definition-ah/eax: (addr handle cell) <- copy _definition-ah
var _definition/eax: (addr cell) <- lookup *definition-ah
var definition/esi: (addr cell) <- copy _definition
var definition-type/eax: (addr int) <- get definition, type
compare *definition-type, 0/pair
{
break-if-=
return
}
# if definition->left is neither "define" nor "set", return
var left-ah/eax: (addr handle cell) <- get definition, left
var _left/eax: (addr cell) <- lookup *left-ah
var left/ecx: (addr cell) <- copy _left
{
var def?/eax: boolean <- symbol-equal? left, "define"
compare def?, 0/false
break-if-!=
var set?/eax: boolean <- symbol-equal? left, "set"
compare set?, 0/false
break-if-!=
return
}
# locate the global for definition->right->left
var right-ah/eax: (addr handle cell) <- get definition, right
var right/eax: (addr cell) <- lookup *right-ah
var defined-symbol-ah/eax: (addr handle cell) <- get right, left
var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah
var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data
var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah
var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name
{
compare index, -1/not-found
break-if-!=
return
}
# move 'gap' to it
var globals/eax: (addr global-table) <- copy _globals
compare globals, 0
{
break-if-!=
abort "move to globals"
return
}
var global-data-ah/eax: (addr handle array global) <- get globals, data
var global-data/eax: (addr array global) <- lookup *global-data-ah
var offset/ebx: (offset global) <- compute-offset global-data, index
var dest-global/eax: (addr global) <- index global-data, offset
var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input
copy-object gap, dest-ah
}
fn set-global-cursor-index _globals: (addr global-table), name-gap: (addr gap-buffer) {
var globals/esi: (addr global-table) <- copy _globals
var name-storage: (stream byte 0x40)
var name/ecx: (addr stream byte) <- address name-storage
emit-gap-buffer name-gap, name
var index/ecx: int <- find-symbol-in-globals globals, name
var dest/edi: (addr int) <- get globals, cursor-index
copy-to *dest, index
}
|