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
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
|
type global-table {
data: (handle array global)
final-index: int
render-list: (handle array int) # sequence of globals to render on the left side
# no pagination or scrolling
}
type global {
name: (handle array byte)
input: (handle gap-buffer)
value: (handle cell)
trace: (handle trace)
}
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
var render-ah/eax: (addr handle array int) <- get self, render-list
populate render-ah, 0x20/render-size
}
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-!=
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
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-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " ", 3/fg 0/bg
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, 0x40000/256KB
load-gap-buffer-from-stream value-gap-buffer, value-data
load-lexical-scope value-gap-buffer-ah, self
loop
}
move-cursor-to-left-margin-of-next-line 0/screen
}
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-=
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
{
compare curr-input, 0
break-if-!=
abort "null gap buffer"
}
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 data/ebx: (addr array global) <- copy _data
var curr-index/edx: int <- copy 0
var y1: int
copy-to y1, 1/padding-top
var y2: int
copy-to y2, 1/padding-top
$render-globals:loop: {
compare curr-index, 0x20/render-size
break-if->=
{
compare y1, 0x2f/ymax
break-if-<
compare y2, 0x2f/ymax
break-if-<
break $render-globals:loop
}
$render-globals:iter: {
var cursor-in-current-line?: boolean
{
compare show-cursor?, 0/false
break-if-=
compare curr-index, 0
break-if-!=
copy-to cursor-in-current-line?, 1/true
}
var render-list-ah/eax: (addr handle array int) <- get self, render-list
var render-list/eax: (addr array int) <- lookup *render-list-ah
var global-id-a/eax: (addr int) <- index render-list, curr-index
var global-id/eax: int <- copy *global-id-a
compare global-id, 0
break-if-=
var global-offset/edx: (offset global) <- compute-offset data, global-id
var curr/edx: (addr global) <- index data, global-offset
{
var render-image?/eax: boolean <- render-image? curr, cursor-in-current-line?
compare render-image?, 0/false
break-if-=
var y/ecx: int <- render-image-definition screen, curr, 0/x y1
y <- increment # padding
copy-to y1, y
break $render-globals:iter
}
var curr-input-ah/eax: (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-=
var curr-trace-ah/eax: (addr handle trace) <- get curr, trace
var _curr-trace/eax: (addr trace) <- lookup *curr-trace-ah
var curr-trace/edx: (addr trace) <- copy _curr-trace
$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, cursor-in-current-line?, 7/fg=definition, 0xc5/bg=blue-bg
y <- increment
y <- render-trace screen, curr-trace, 1/padding-left, y, 0x2a/xmax, 0x2f/ymax, 0/no-cursor
y <- increment
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, cursor-in-current-line?, 7/fg=definition, 0xc5/bg=blue-bg
y <- increment
y <- render-trace screen, curr-trace, 0x2b/xmin, y, 0x54/xmax, 0x2f/ymax, 0/no-cursor
y <- increment
copy-to y2, y
}
}
curr-index <- increment
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/ecx: int <- cursor-global self
compare cursor-index, 0
{
break-if-!=
return
}
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 render-list-ah/eax: (addr handle array int) <- get self, render-list
var render-list/eax: (addr array int) <- lookup *render-list-ah
slide-down render-list, 0/start 0x1f/penultimate, 1/target
var curr-index/ecx: int <- copy *final-index-addr
var dest/eax: (addr int) <- index render-list, 0
copy-to *dest, 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
var trace-ah/eax: (addr handle trace) <- get curr, trace
allocate trace-ah
var trace/eax: (addr trace) <- lookup *trace-ah
initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible
}
fn refresh-cursor-definition _self: (addr global-table) {
var self/esi: (addr global-table) <- copy _self
var render-list-ah/eax: (addr handle array int) <- get self, render-list
var render-list/eax: (addr array int) <- lookup *render-list-ah
var cursor-index/edx: (addr int) <- index render-list, 0
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/ebx: int <- copy _index
var offset/ebx: (offset global) <- compute-offset data, index
var curr-global/ebx: (addr global) <- index data, offset
var curr-input-ah/edx: (addr handle gap-buffer) <- get curr-global, input
var curr-trace-ah/eax: (addr handle trace) <- get curr-global, trace
var curr-trace/eax: (addr trace) <- lookup *curr-trace-ah
clear-trace curr-trace
var curr-value-ah/edi: (addr handle cell) <- get curr-global, value
var definitions-created-storage: (stream int 0x10)
var definitions-created/ecx: (addr stream int) <- address definitions-created-storage
read-and-evaluate-and-save-gap-buffer-to-globals curr-input-ah, curr-value-ah, self, definitions-created, curr-trace, 0/no-screen, 0/no-keyboard
}
fn assign-or-create-global _self: (addr global-table), name: (addr array byte), value: (handle cell), index-updated: (addr int), trace: (addr trace) {
var self/esi: (addr global-table) <- copy _self
compare self, 0
{
break-if-!=
abort "assign global"
}
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 arr-ah/eax: (addr handle array int) <- get self, render-list
var arr/eax: (addr array int) <- lookup *arr-ah
slide-down arr, 0/start 0x1e/penultimate, 1/target
var dest/eax: (addr int) <- index arr, 0
copy-to *dest, 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
var index-updated/edi: (addr int) <- copy index-updated
copy-to *index-updated, curr-index
var trace-ah/eax: (addr handle trace) <- get curr, trace
allocate trace-ah
var trace/eax: (addr trace) <- lookup *trace-ah
initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible
}
fn bump-global _globals: (addr global-table), global-id: int {
var globals/esi: (addr global-table) <- copy _globals
var render-list-ah/eax: (addr handle array int) <- get globals, render-list
var render-list/eax: (addr array int) <- lookup *render-list-ah
var idx/ecx: int <- find-slide-down-slot-in-array render-list, global-id
{
compare idx, 0
break-if-!=
return
}
slide-down render-list, 0/start idx, 1/target
var dest/eax: (addr int) <- index render-list, 0
var val/ecx: int <- copy global-id
copy-to *dest, val
}
fn cursor-global _globals: (addr global-table) -> _/ecx: int {
var globals/esi: (addr global-table) <- copy _globals
var render-list-ah/eax: (addr handle array int) <- get globals, render-list
var render-list/eax: (addr array int) <- lookup *render-list-ah
var dest/eax: (addr int) <- index render-list, 0
return *dest
}
fn lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace), inner-screen-var: (addr handle cell), inner-keyboard-var: (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 inner-screen-var exists, return it
{
var sym-is-screen?/eax: boolean <- stream-data-equal? sym-name, "screen"
compare sym-is-screen?, 0/false
break-if-=
compare inner-screen-var, 0
break-if-=
copy-object inner-screen-var, out
return
}
# if sym is "keyboard" and inner-keyboard-var exists, return it
{
var sym-is-keyboard?/eax: boolean <- stream-data-equal? sym-name, "keyboard"
compare sym-is-keyboard?, 0/false
break-if-=
compare inner-keyboard-var, 0
break-if-=
copy-object inner-keyboard-var, 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
}
fn stash-gap-buffer-to-globals _globals: (addr global-table), definitions: (addr stream int), gap: (addr handle gap-buffer) {
var globals/eax: (addr global-table) <- copy _globals
compare globals, 0
{
break-if-!=
return
}
var global-data-ah/eax: (addr handle array global) <- get globals, data
var global-data/eax: (addr array global) <- lookup *global-data-ah
rewind-stream definitions
{
{
var done?/eax: boolean <- stream-empty? definitions
compare done?, 0/false
}
break-if-!=
var index: int
var index-addr/ecx: (addr int) <- address index
read-from-stream definitions, index-addr
var index/ecx: int <- copy *index-addr
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
loop
}
}
# load all bindings in a single lexical scope, aka gap buffer of the environment, aka file of the file system
fn load-lexical-scope in-ah: (addr handle gap-buffer), _globals: (addr global-table) {
var globals/esi: (addr global-table) <- copy _globals
var definitions-created-storage: (stream int 0x10)
var definitions-created/ebx: (addr stream int) <- address definitions-created-storage
var trace-h: (handle trace)
var trace-ah/edx: (addr handle trace) <- address trace-h
allocate trace-ah
var trace/eax: (addr trace) <- lookup *trace-ah
initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible
var dummy-result-h: (handle cell)
var dummy-result-ah/ecx: (addr handle cell) <- address dummy-result-h
read-and-evaluate-and-save-gap-buffer-to-globals in-ah, dummy-result-ah, globals, definitions-created, trace, 0/no-inner-screen-var, 0/no-inner-keyboard-var
#
# save trace to all needed globals as well
rewind-stream definitions-created
var globals-data-ah/eax: (addr handle array global) <- get globals, data
var _globals-data/eax: (addr array global) <- lookup *globals-data-ah
var globals-data/edi: (addr array global) <- copy _globals-data
{
var no-definitions?/eax: boolean <- stream-empty? definitions-created
compare no-definitions?, 0/false
break-if-!=
var curr-index: int
var curr-index-a/eax: (addr int) <- address curr-index
read-from-stream definitions-created, curr-index-a
var curr-offset/eax: (offset global) <- compute-offset globals-data, curr-index
var curr-global/ecx: (addr global) <- index globals-data, curr-offset
var curr-trace-ah/eax: (addr handle trace) <- get curr-global, trace
copy-object trace-ah, curr-trace-ah
loop
}
}
fn render-image? _self: (addr global), cursor-in-definition?: boolean -> _/eax: boolean {
{
compare cursor-in-definition?, 0/false
break-if-=
# if the cursor is in this definition we need to be able to edit raw data
return 0/false
}
var self/esi: (addr global) <- copy _self
var value-ah/eax: (addr handle cell) <- get self, value
var value/eax: (addr cell) <- lookup *value-ah
compare value, 0
{
break-if-!=
# unparsed buffers can't be rendered; either they're uninitialized or they have errors
return 0/false
}
{
var pair?/eax: boolean <- pair? value
compare pair?, 0/false
break-if-!=
# not a pair? not an image
return 0/false
}
var first-ah/eax: (addr handle cell) <- get value, left
var first/eax: (addr cell) <- lookup *first-ah
var litimg?/eax: boolean <- litimg? first
return litimg?
}
fn render-image-definition screen: (addr screen), _self: (addr global), x: int, _y: int -> _/ecx: int {
var self/esi: (addr global) <- copy _self
var y/ecx: int <- copy _y
set-cursor-position 0/screen, 0x20 0x20
draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 4/fg 0/bg
{
var name-ah/eax: (addr handle array byte) <- get self, name
var _name/eax: (addr array byte) <- lookup *name-ah
var name/edx: (addr array byte) <- copy _name
var x/eax: int <- draw-text-rightward-over-full-screen screen, "define ", x y, 7/fg=definition, 0xc5/bg=blue-bg
x <- draw-text-rightward-over-full-screen screen, name, x y, 7/fg=definition, 0xc5/bg=blue-bg
}
y <- increment # skip definition line
# y is now in pixels
y <- shift-left 4/log2fontheight
add-to x, 4
shift-left x, 3/log2fontwidth
var value-ah/eax: (addr handle cell) <- get self, value
var value/eax: (addr cell) <- lookup *value-ah
var rest-ah/eax: (addr handle cell) <- get value, right
var rest/eax: (addr cell) <- lookup *rest-ah
var second-ah/eax: (addr handle cell) <- get rest, left
var second/eax: (addr cell) <- lookup *second-ah
var img-data-ah/eax: (addr handle stream byte) <- get second, text-data
var img-data/eax: (addr stream byte) <- lookup *img-data-ah
var img-h: (handle cell)
var img-cell-ah/edx: (addr handle cell) <- address img-h
new-image img-cell-ah, img-data
var img-cell/eax: (addr cell) <- lookup *img-cell-ah
var img-ah/eax: (addr handle image) <- get img-cell, image-data
var img/eax: (addr image) <- lookup *img-ah
var height/ebx: int <- scale-image-height img, 0x80/width
render-image screen, img, x y, 0x80/width height
y <- add height
# switch y back to characters
y <- scale-down-and-round-up y, 0x10/font-height
return y
}
|