forked from Folds/osmosian
-
Notifications
You must be signed in to change notification settings - Fork 2
/
the compiler
4311 lines (3764 loc) · 200 KB
/
the compiler
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
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\ copyright © 2006 the osmosian order (3040)
\ firstparam=esp+4/ebp+8, secondparam=esp+8/ebp+12, etc...
an abort message is a string.
to abort with a string:
if the compiler's abort flag is set, exit.
set the compiler's abort flag.
put the string into the compiler's abort message.
to abort with a string and a byte pointer:
if the compiler's abort flag is set, exit.
set the compiler's abort flag.
put the string into the compiler's abort message.
find the compiler's abort path and the compiler's abort row# given the byte pointer.
if the compiler's abort path is blank, exit.
extract a file name from the compiler's abort path.
prepend "Error in " then the file name then ". " to the compiler's abort message.
to abort with a string and a rider:
if the rider's token is not blank, abort with the string and the rider's token's first; exit.
abort with the string and the rider's source's last.
to add the allocate and deallocate and finalize and destroy routines:
if the compiler's abort flag is set, exit.
get a type from the types.
if the type is nil, exit.
add the finalize routine for the type.
add the allocate routine for the type.
add the deallocate routine for the type.
add the destroy routine for the type.
repeat.
to add the allocate routine for a type:
if the type is nil, exit.
if the compiler's abort flag is set, exit.
if the type cannot be reduced to "pointer", exit.
if the type's target type is nil, exit.
add a routine to the routines given nil.
append "allocate memory for a " then the type's name to the routine's header string.
append "assign the " then the type's name then " given " to the routine's body string.
append the type's target type's length then "." to the routine's body string.
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add and compile the initialize before run and run and finalize after run routine:
if the compiler's abort flag is set, exit.
add a routine to the routines given nil.
append "~initialize before run and run and finalize after run" to the routine's header string.
append "initialize before run. " to the routine's body string.
append the global initializers to the routine's body string.
append "run. " to the routine's body string.
append the global finalizers to the routine's body string.
append "finalize after run. " to the routine's body string.
append "call ""kernel32.dll"" ""ExitProcess"" with 0. " to the routine's body string.
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
compile the body of the routine.
to add a built-in type given a name and a plural name and a length:
add the built-in type to the types given the name and the plural name and the name.
put the length into the built-in type's length.
put the built-in type into the built-in type's base type.
index the built-in type.
to add the built-in types:
add a built-in type given "byte" and "bytes" and 1.
add another built-in type given "record" and "records" and 0.
to add the deallocate routine for a type:
if the type is nil, exit.
if the compiler's abort flag is set, exit.
if the type cannot be reduced to "pointer", exit.
if the type's target type is nil, exit.
add a routine to the routines given nil.
append "deallocate a " then the type's name to the routine's header string.
append "if the " then the type's name then " is nil, exit. " to the routine's body string.
if the type's target type should be finalized, append "~finalize the " then the type's name then "'s target. " to the routine's body string.
append "unassign the " then the type's name then "." to the routine's body string.
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add the destroy routine for a type:
if the type is nil, exit.
if the compiler's abort flag is set, exit.
if the type should not be forgotten, exit.
if the type can be reduced to "things", add the destroy routine for the type (things); exit.
if the type can be reduced to "pointer", add the destroy routine for the type (pointer); exit.
to add the destroy routine for a type (pointer):
if the type is nil, exit.
if the compiler's abort flag is set, exit.
put "destroy [" then the type's name then "]" into a moniker.
if the moniker is in the routine index, exit.
add a routine to the routines given nil.
append "destroy a " then the type's name to the routine's header string.
append "if the " then the type's name then " is nil, exit. " to the routine's body string.
if the type's target type can be reduced to "pointer", append "destroy the " then the type's name then "'s target. " to the routine's body string.
if the type's target type can be reduced to "things", append "destroy the " then the type's name then "'s target. " to the routine's body string.
loop.
get a field from the type's target type's fields.
if the field is nil, break.
if the field's reference flag is set, repeat.
if the field's type should not be forgotten, repeat.
append "destroy the " then the type's name then "'s " then the field's name then ". " to the routine's body string.
repeat.
append "deallocate the " then the type's name then ". " to the routine's body string.
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add the destroy routine for a type (things):
if the type is nil, exit.
if the compiler's abort flag is set, exit.
if the type's fields' first is nil, abort with "Internal error - add the forget routine for a type (things)"; exit.
if the type's fields' first's type is nil, abort with "Internal error 2 - add the forget routine for a type (things)"; exit.
put "destroy [" then the type's name then "]" into a moniker.
if the moniker is in the routine index, exit.
add a routine to the routines given nil.
append "destroy a " then the type's name to the routine's header string.
append "if the " then the type's name then "'s first is nil, exit. " to the routine's body string.
put the type's fields' first's type's name into a name.
append "put the " then the type's name then "'s first into a " then the name then ". " to the routine's body string.
append "remove the " then the name then " from the " then the type's name then ". " to the routine's body string.
append "destroy the " then the name then ". " to the routine's body string.
append "repeat. " to the routine's body string.
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add an entry to some imports given an import name and an entry name:
find an import given the import name.
if the import is nil, add the import to the imports given the import name.
find the entry given the entry name and the import's entries.
if the entry is not nil, exit.
create the entry.
append the entry to the import's entries.
put the entry name into the entry's name.
to add a field to some fields given a name and a nickname and a type name and a reference flag:
add the field to the fields given "field" and nil.
put the name into the field's name.
put the nickname into the field's nickname.
put the type name into the field's type name.
put the reference flag into the field's reference flag.
to add the finalize routine for a type:
if the type is nil, exit.
if the compiler's abort flag is set, exit.
if the type should not be finalized, exit.
if the type's name is "string", add the finalize routine for the type (string); exit.
if the type can be reduced to "string", exit. \ prevents generation of finalizer for derived string types
add the finalize routine for the type (record).
to add the finalize routine for a type (record):
if the type is nil, exit.
if the compiler's abort flag is set, exit.
add a routine to the routines given nil.
append "~finalize a " then the type's name to the routine's header string.
append "intel $50. " to the routine's body string. \ push eax
loop.
get a field from the type's fields.
if the field is nil, break.
if the field's type should not be finalized, repeat.
append "~finalize the " then the type's name then "'s " then the field's name then ". " to the routine's body string.
repeat.
append "intel $58." to the routine's body string. \ pop eax
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add the finalize routine for a type (string):
if the type is nil, exit.
if the compiler's abort flag is set, exit.
add a routine to the routines given nil.
append "~finalize a " then the type's name to the routine's header string.
append "intel $50. " to the routine's body string. \ push eax
append "unassign the string's first. " to the routine's body string.
append "intel $58." to the routine's body string. \ pop eax
slap the routine's routine header on the routine's header string.
slap the routine's routine body on the routine's body string.
compile the header of the routine.
to add a fragment given a tag:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
to add a fragment given a tag and an entry:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
put the entry into the fragment's entry.
to add a fragment given a tag and a routine:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
put the routine into the fragment's routine.
compile the body of the routine.
to add a fragment given a tag and a variable:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
put the variable into the fragment's variable.
set the compiled flag in the variable.
to add a fragment given a tag and a variable and another variable:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
put the variable into the fragment's variable.
put the other variable into the fragment's other variable.
set the compiled flag in the variable.
set the compiled flag in the other variable.
to add a fragment given a tag and a variable and a number:
if the current routine is nil, void the fragment; exit.
create the fragment given the tag.
append the fragment to the current routine's fragments.
put the variable into the fragment's variable.
put the number into the fragment's number.
set the compiled flag in the variable.
to add an import to some imports given an import name:
create the import.
append the import to the imports.
put the import name into the import's name.
to add an intermediate given a type name and a locus:
if the current routine is nil, void the intermediate; exit.
add the intermediate to the current routine's locals given "local" and the locus.
generate the intermediate's name given "~I".
put the type name into the intermediate's type name.
resolve the intermediate.
to add a literal to some variables given a locus:
add the literal as a variable to the variables given "literal" and the locus.
generate the literal's name given "~L".
to add a monikette to some monikettes given an expression:
create the monikette.
append the monikette to the monikettes.
put the expression's phrase into the monikette's string.
put the expression's variable into the monikette's variable.
if the expression's variable is not nil, put the expression's type into the monikette's type.
to add a monikette to some monikettes given a string:
create the monikette.
append the monikette to the monikettes.
\ from/given/with/using
if the string is "from", put "from/given/with/using" into the monikette's string; exit.
if the string is "given", put "from/given/with/using" into the monikette's string; exit.
if the string is "with", put "from/given/with/using" into the monikette's string; exit.
if the string is "using", put "from/given/with/using" into the monikette's string; exit.
\ in/into/to
if the string is "in", put "in/into/to" into the monikette's string; exit.
if the string is "into", put "in/into/to" into the monikette's string; exit.
if the string is "to", put "in/into/to" into the monikette's string; exit.
\ is/are
if the string is "are", put "is/are" into the monikette's string; exit.
if the string is "is", put "is/are" into the monikette's string; exit.
\ aren't/isn't
if the string is "isn't", put "is/aren't" into the monikette's string; exit.
if the string is "aren't", put "is/aren't" into the monikette's string; exit.
\ other
put the string into the monikette's string.
to add a monikette to some monikettes given a type:
create the monikette.
append the monikette to the monikettes.
put the type into the monikette's type.
to add push fragments given some monikettes:
if the current routine is nil, exit.
loop.
get a monikette from the monikettes (backwards).
if the monikette is nil, exit.
if the monikette's variable is nil, repeat.
if the monikette's current substring is not blank, repeat.
if the monikette's current type is nil, repeat.
add a fragment given the push address tag and the monikette's variable.
repeat.
to add the put or convert fragments given a variable and another variable and a locus:
add a fragment given the push address tag and the other variable.
add another fragment given the push address tag and the variable.
find a routine given "put" and the variable's type and "into" and the other variable's type.
if the routine is nil, find the routine given "convert" and the variable's type and "to" and the other variable's type.
if the routine is not nil, add a third fragment given the call internal tag and the routine; exit.
\ error message
add a monikette to some monikettes given "put/convert".
add another monikette to the monikettes given the variable's type.
add a third monikette to the monikettes given "into/to".
add a fourth monikette to the monikettes given the other variable's type.
convert the monikettes to a moniker.
destroy the monikettes.
abort with "I don't know how to '" then the moniker then "'." and the locus.
to add a routine to some routines given a locus:
create the routine.
append the routine to the routines.
put the locus into the routine's locus.
to add a scratch given a type name and a locus:
if the current routine is nil, void the scratch; exit.
add the scratch to the current routine's locals given "scratch" and the locus.
generate the scratch's name given "~S".
put the type name into the scratch's type name.
resolve the scratch.
to add several fragments given a string and a variable and another string and another variable and a locus:
add a fragment given the push address tag and the other variable.
add another fragment given the push address tag and the variable.
add a monikette to some monikettes given the string.
add another monikette to the monikettes given the variable's type.
add a third monikette to the monikettes given the other string.
add a fourth monikette to the monikettes given the other variable's type.
find a routine given the monikettes.
if the routine is nil, convert the monikettes to a moniker.
destroy the monikettes.
if the routine is nil, abort with "I don't know how to '" then the moniker then "'." and the locus; exit.
add a third fragment given the call internal tag and the routine.
to add several fragments given a string and a variable and another string and another variable and a third string and a third variable and a byte pointer:
add a fragment given the push address tag and the third variable.
add another fragment given the push address tag and the other variable.
add a third fragment given the push address tag and the variable.
add a monikette to some monikettes given the string.
add another monikette to the monikettes given the variable's type.
add a third monikette to the monikettes given the other string.
add a fourth monikette to the monikettes given the other variable's type.
add a fifth monikette to the monikettes given the third string.
add a sixth monikette to the monikettes given the third variable's type.
find a routine given the monikettes.
if the routine is nil, convert the monikettes to a moniker.
destroy the monikettes.
if the routine is nil, abort with "I don't know how to '" then the moniker then "'." and the byte pointer; exit.
add a fourth fragment given the call internal tag and the routine.
to add a source file to some source files given a path:
create the source file.
append the source file to the source files.
put the path into the source file's path.
to add two fragments given a string and a variable and a locus:
add a fragment given the push address tag and the variable.
add a monikette to some monikettes given the string.
add another monikette to the monikettes given the variable's type.
find a routine given the monikettes.
if the routine is nil, convert the monikettes to a moniker.
destroy the monikettes.
if the routine is nil, abort with "I don't know how to '" then the moniker then "'." and the locus; exit.
add another fragment given the call internal tag and the routine.
to add a type to some types given a locus:
create the type.
append the type to the types.
put the locus into the type's locus.
to add a type to some types given a name and a plural name and a base name:
add the type to the types given the name and the plural name and the base name and nil.
to add a type to some types given a name and a plural name and a base name and a locus:
create the type.
append the type to the types.
put the locus into the type's locus.
put the name into the type's name.
put the plural name into the type's plural name.
put the base name into the type's base name.
to add a variable to some variables given a kind and a locus:
create the variable given the kind.
append the variable to the variables.
put the locus into the variable's locus.
the adding built-in memory routines timer is a timer.
the adding built-in startup routine timer is a timer.
to address some entries:
get an entry from the entries.
if the entry is nil, exit.
address the entry.
repeat.
to address an entry:
put the current name address into the entry's name address.
put the entry's name's length plus 3 into a number.
round the number up to the nearest multiple of 2.
add the number to the current name address.
put the current thunk address into the entry's thunk address.
put the image base plus the current thunk address into the entry's address.
add 4 to the current thunk address.
to address a fragment given an address:
if the compiler's abort flag is set, exit.
if the fragment is nil, exit.
put the image base plus the address into the fragment's address.
if the fragment's tag is the push address tag, add 7 to the address; exit.
if the fragment's tag is the call internal tag, add 5 to the address; exit.
if the fragment's tag is the load address tag, add 12 to the address; exit.
if the fragment's tag is the increment tag, add 10 to the address; exit.
if the fragment's tag is the dereference tag, add 14 to the address; exit.
if the fragment's tag is the jump false tag, add 9 to the address; exit.
if the fragment's tag is the not tag, add 3 to the address; exit.
if the fragment's tag is the exit tag, add 5 to the address; exit.
if the fragment's tag is the repeat tag, add 5 to the address; exit.
if the fragment's tag is the break tag, add 5 to the address; exit.
if the fragment's tag is the prolog tag, address the fragment given the address (prolog); exit.
if the fragment's tag is the epilog tag, address the fragment given the address (epilog); exit.
if the fragment's tag is the intel tag, add the fragment's code's length to the address; exit.
if the fragment's tag is the push value tag, address the fragment given the address (push value); exit.
if the fragment's tag is the call external tag, add 6 to the address; exit.
if the fragment's tag is the load eax tag, add 8 to the address; exit.
if the fragment's tag is the save eax tag, address the fragment given the address (save eax); exit.
if the fragment's tag is the call indirect tag, add 8 to the address; exit.
if the fragment's tag is the routine address tag, add 12 to the address; exit.
to address a fragment given an address (epilog):
if the current routine's callback flag is set, add 3 to the address.
add 6 to the address.
to address a fragment given an address (prolog):
add 3 to the address.
if the current routine's local size is not 0, add 10 to the address.
if the current routine's callback flag is set, add 3 to the address.
to address a fragment given an address (push value):
add 6 to the address.
if the fragment's variable is nil, abort with "Internal error - address a fragment given an address (push value)"; exit.
if the fragment's variable's type is nil, abort with "Internal error 2 - address a fragment given an address (push value)"; exit.
put the fragment's variable's type's length into a length.
if the length is 4, add 2 to the address; exit.
if the length is 2, add 3 to the address; exit.
if the length is 1, add 4 to the address; exit.
abort with "Internal error 3 - address a fragment given an address (push value)".
to address a fragment given an address (save eax):
add 6 to the address.
if the fragment's variable is nil, abort with "Internal error - address a fragment given an address (push value)"; exit.
if the fragment's variable's type is nil, abort with "Internal error 2 - address a fragment given an address (push value)"; exit.
put the fragment's variable's type's length into a length.
if the length is 4, add 2 to the address; exit.
if the length is 2, add 3 to the address; exit.
if the length is 1, add 2 to the address; exit.
abort with "Internal error 3 - address a fragment given an address (push value)".
to address some fragments given an address:
if the compiler's abort flag is set, exit.
get a fragment from the fragments.
if the fragment is nil, exit.
address the fragment given the address.
repeat.
to address an import:
put the current name address into the import's name address.
put the current header address into the import's header address.
put the current name address into the import's import header's name memory address.
put the import's name's length plus 1 into a number.
round the number up to the nearest multiple of 2.
add the number to the current name address.
add an import header's magnitude to the current header address.
put the current thunk address into the import's import header's first thunk memory address.
address the import's entries.
add 4 to the current thunk address.
to address some imports given an address:
put the address into the current header address.
put the imports' count into a count.
add 1 to the count.
multiply the count by an import header's magnitude.
put the address plus the count into the current thunk address.
get another count given the imports (all entries plus markers).
multiply the other count by 4.
put the current thunk address plus the other count into the current name address.
loop.
get an import from the imports.
if the import is nil, break.
address the import.
repeat.
put the current name address minus the address into a number.
add the number to the address.
an address is a number.
to address a routine given an address:
if the compiler's abort flag is set, exit.
if the routine is nil, exit.
if the routine's employs moniker is not blank, exit.
if the routine's compiled flag is not set, exit.
put the routine into the current routine.
put the image base plus the address into the routine's address.
address the routine's fragments given the address.
round the address up to the nearest multiple of 4.
to address some routines given an address:
if the compiler's abort flag is set, exit.
get a routine from the routines.
if the routine is nil, break.
address the routine given the address.
repeat.
to address a variable given an address:
if the compiler's abort flag is set, exit.
if the variable is nil, exit.
if the variable's compiled flag is not set, exit.
put the image base plus the address into the variable's address.
add the variable's type's length to the address.
if the variable's type can be reduced to "string", add the variable's data's length plus 1 to the address.
round the address up to the nearest multiple of 4.
to address some variables given an address:
if the compiler's abort flag is set, exit.
get a variable from the variables.
if the variable is nil, exit.
address the variable given the address.
repeat.
the addressing timer is a timer.
to advance a buffer:
append the return byte to the buffer.
append the linefeed byte to the buffer.
to advance a buffer (twice):
advance the buffer.
advance the buffer.
to append an entry to a buffer (with separator):
if the entry is nil, append "" to the buffer (with separator); exit.
append the entry's name to the buffer (with separator).
to append a flag to a buffer (with separator):
convert the flag to a string.
append the string to the buffer (with separator).
to append the global finalizers to a string:
get a global from the globals.
if the global is nil, exit.
if the global's compiled flag is not set, repeat.
if the global's type should not be finalized, repeat.
append "~finalize the " then the global's name then ". " to the string.
repeat.
to append the global initializers to a string:
get a global from the globals.
if the global is nil, exit.
if the global's literal is nil, repeat.
if the global's compiled flag is not set, repeat.
clear a flag.
append the global's initializer string to the string.
repeat.
to append a monikette to a moniker:
if the monikette is nil, exit.
if the moniker is not blank, append the space byte to the moniker.
if the monikette's type is not nil, append "[" and the monikette's type's name and "]" to the moniker (fast); exit.
if the monikette's string is not blank, append the monikette's string to the moniker; exit.
to append a monikette to a moniker (while bubbling):
if the monikette is nil, exit.
if the moniker is not blank, append the space byte to the moniker.
if the monikette's current substring is not blank, append the monikette's current substring to the moniker; exit.
if the monikette's current type is not nil, append "[" and the monikette's current type's name and "]" to the moniker (fast); exit.
to append a number to a buffer (as hex with separator):
convert the number to a nibble string.
append the nibble string to the buffer (with separator).
to append a number to a buffer (with separator):
convert the number to a string.
append the string to the buffer (with separator).
to append a ratio to a buffer (with separator):
convert the ratio to a string.
append the string to the buffer (with separator).
to append a routine to a buffer (with separator):
if the routine is nil, append "" to the buffer (with separator); exit.
append the routine's moniker to the buffer (with separator).
to append a string and another string and a third string to a fourth string (fast):
put the fourth string's length into a length.
add the string's length to the length.
add the other string's length to the length.
add the third string's length to the length.
reassign a pointer given the length.
put the pointer into a byte pointer.
copy bytes from the fourth string's first to the byte pointer for the fourth string's length.
add the fourth string's length to the byte pointer.
copy bytes from the string's first to the byte pointer for the string's length.
add the string's length to the byte pointer.
copy bytes from the other string's first to the byte pointer for the other string's length.
add the other string's length to the byte pointer.
copy bytes from the third string's first to the byte pointer for the third string's length.
unassign the fourth string's first.
put the pointer into the fourth string's first.
put the pointer plus the length minus 1 into the fourth string's last.
to append a string to a buffer (with separator):
append the string to the buffer.
append "/" to the buffer.
to append a tag to a buffer (as a fragment tag string with separator):
if the tag is the break tag, append "break" to the buffer (with separator); exit.
if the tag is the call external tag, append "call external" to the buffer (with separator); exit.
if the tag is the call indirect tag, append "call indirect" to the buffer (with separator); exit.
if the tag is the call internal tag, append "call internal" to the buffer (with separator); exit.
if the tag is the dereference tag, append "dereference" to the buffer (with separator); exit.
if the tag is the end if tag, append "end if" to the buffer (with separator); exit.
if the tag is the epilog tag, append "epilog" to the buffer (with separator); exit.
if the tag is the exit tag, append "exit" to the buffer (with separator); exit.
if the tag is the finalize tag, append "finalize" to the buffer (with separator); exit.
if the tag is the increment tag, append "increment" to the buffer (with separator); exit.
if the tag is the intel tag, append "intel" to the buffer (with separator); exit.
if the tag is the jump false tag, append "jump false" to the buffer (with separator); exit.
if the tag is the load address tag, append "load address" to the buffer (with separator); exit.
if the tag is the load eax tag, append "load eax" to the buffer (with separator); exit.
if the tag is the loop tag, append "loop" to the buffer (with separator); exit.
if the tag is the not tag, append "not" to the buffer (with separator); exit.
if the tag is the prolog tag, append "prolog" to the buffer (with separator); exit.
if the tag is the push address tag, append "push address" to the buffer (with separator); exit.
if the tag is the push value tag, append "push value" to the buffer (with separator); exit.
if the tag is the save eax tag, append "save eax" to the buffer (with separator); exit.
if the tag is the repeat tag, append "repeat" to the buffer (with separator); exit.
if the tag is the routine address tag, append "routine address" to the buffer (with separator); exit.
append "?" to the buffer (with separator).
to append a type to a buffer (with separator):
if the type is nil, append "" to the buffer (with separator); exit.
append the type's name to the buffer (with separator).
to append a variable to a buffer (with separator):
if the variable is nil, append "" to the buffer (with separator); exit.
append the variable's name to the buffer (with separator).
to attach address loading code to a hex string given a variable: \ loads into edx
if the variable is nil, attach $C7C200000000 to the hex string; exit. \ mov edx,0
if the variable's kind is "global", attach $C7C2 and the variable's address to the hex string; exit. \ mov edx,the variable's address
if the variable's kind is "literal", attach $C7C2 and the variable's address to the hex string; exit. \ mov edx,the variable's address
if the variable's kind is "local", attach $8D95 and the variable's offset to the hex string; exit. \ lea edx,[ebp+the variable's offset]
if the variable's kind is "scratch", attach $8B95 and the variable's offset to the hex string; exit. \ mov edx,[ebp+the variable's offset]
if the variable's kind is not "parameter", abort with "Internal error - attach address loading code to a hex string given a variable"; exit.
if the variable's by-value flag is set, attach $8D95 and the variable's offset to the hex string; exit. \ lea edx,[ebp+the variable's offset]
attach $8B95 and the variable's offset to the hex string. \ mov edx,[ebp+the variable's offset]
to attach an hex string and an address to a fragment: \ call or jump
put the address into a number.
subtract the fragment's address from the number.
subtract the fragment's code's length from the number.
subtract the hex string's length from the number.
subtract 4 from the number.
attach the hex string and the number to the fragment's code.
to attach a hex string and a number and another hex string to a third hex string:
append the hex string to the third hex string.
convert the number to a fourth hex string.
append the fourth hex string to the third hex string.
append the other hex string to the third hex string.
to attach a hex string and a number and another number to another hex string:
append the hex string to the other hex string.
convert the number to a third hex string.
append the third hex string to the other hex string.
convert the other number to a fourth hex string.
append the fourth hex string to the other hex string.
to attach a hex string and a number to another hex string:
append the hex string to the other hex string.
convert the number to a third hex string.
append the third hex string to the other hex string.
to attach a hex string to another hex string: employ append a string to another string.
to blurt bytes given a pointer and a length and a buffer and an offset:
put the buffer's first plus the offset into another pointer.
copy bytes from the pointer to the other pointer for the length.
to blurt a dos header into a buffer:
blurt bytes given the dos header's whereabouts and the dos header's magnitude and the buffer and 0.
to blurt some entries into a buffer:
get an entry from the entries.
if the entry is nil, exit.
blurt the entry into the buffer.
repeat.
to blurt an entry into a buffer:
blurt bytes given the entry's name address's whereabouts and 4 and the buffer and the entry's thunk address.
put the entry's name address plus 2 into an address.
blurt the entry's name into the buffer at the address.
to blurt a fragment into a buffer:
if the fragment's code is blank, exit.
put the fragment's address minus the image base into an address.
blurt the fragment's code into the buffer at the address.
to blurt some fragments into a buffer:
get a fragment from the fragments.
if the fragment is nil, exit.
blurt the fragment into the buffer.
repeat.
to blurt an import into a buffer:
blurt bytes given the import's import header's whereabouts and the import's import header's magnitude and the buffer and the import's header address.
blurt the import's name into the buffer at the import's name address.
blurt the import's entries into the buffer.
to blurt some imports into a buffer:
get an import from the imports.
if the import is nil, exit.
blurt the import into the buffer.
repeat.
to blurt a pe header into a buffer:
blurt bytes given the pe header's whereabouts and the pe header's magnitude and the buffer and 256.
to blurt a routine into a buffer:
if the routine's compiled flag is not set, exit.
blurt the routine's fragments into the buffer.
to blurt some routines into a buffer:
get a routine from the routines.
if the routine is nil, exit.
blurt the routine into the buffer.
repeat.
to blurt a string into a buffer at an address:
blurt bytes given the string's first and the string's length and the buffer and the address.
to blurt a variable into a buffer:
if the variable's compiled flag is not set, exit.
if the variable's type can be reduced to "string", blurt the variable into the buffer (as a string); exit.
put the variable's address minus the image base into an address.
blurt the variable's data into the buffer at the address.
to blurt a variable into a buffer (as a string):
put the variable's address minus the image base into an address.
put the variable's data's length into a length.
put the address into another address.
add a prototype string's magnitude to the other address.
add the image base to the other address.
put 0 into the prototype string's first.
put -1 into the prototype string's last.
if the length is not 0, put the other address into the prototype string's first.
if the length is not 0, put the prototype string's first plus the length minus 1 into the prototype string's last.
blurt bytes given the prototype string's whereabouts and the prototype string's magnitude and the buffer and the address.
add the prototype string's magnitude to the address.
blurt the variable's data into the buffer at the address.
to blurt some variables into a buffer:
get a variable from the variables.
if the variable is nil, exit.
blurt the variable into the buffer.
repeat.
a borough has a base address, a length and a size.
the break tag is a tag equal to 1.
to bubble a monikette:
if the monikette is nil, exit.
if the monikette's current substring is not blank, clear the monikette's current substring; exit.
if the monikette's current type is nil, exit.
if the monikette's current type is any built-in type, put nil into the monikette's current type; exit.
put the monikette's current type's base type into the monikette's current type.
a built-in type is a type.
to calculate the length of a type:
if the type is nil, exit.
if the type's length is not -1, exit.
calculate the length of the type's base type.
if the type's fields are empty, put the type's base type's length into the type's length; exit.
put 0 into the type's length.
loop.
if the compiler's abort flag is set, exit.
get a field from the type's fields.
if the field is nil, exit.
if the field's redefinition target name is not blank, repeat.
calculate the length of the field's type.
add the field's type's length times the field's count to the type's length.
repeat.
to calculate the lengths of some types:
if the compiler's abort flag is set, exit.
get a type from the types.
if the type is nil, exit.
calculate the length of the type.
repeat.
to calculate the offsets in a type:
if the type is nil, exit.
put 0 into an offset.
loop.
if the compiler's abort flag is set, exit.
get a field from the type's fields.
if the field is nil, exit.
if the field's redefinition target name is not blank, repeat.
put the offset into the field's offset.
add the field's type's length times the field's count to the offset.
repeat.
to calculate the offsets in some types:
if the compiler's abort flag is set, exit.
get a type from the types.
if the type is nil, exit.
calculate the offsets in the type.
repeat.
to calculate the redefinition offsets in a type:
if the type is nil, exit.
loop.
if the compiler's abort flag is set, exit.
get a field from the type's fields.
if the field is nil, exit.
if the field's redefinition target name is blank, repeat.
find another field given the field's redefinition target name and the type's fields.
if the other field is nil, abort with "Invalid redefine. I can't find the '" then the field's redefinition target name then "' field." and the field's locus; exit.
put the other field's offset into the field's offset.
repeat.
to calculate the redefinition offsets in some types:
if the compiler's abort flag is set, exit.
get a type from the types.
if the type is nil, exit.
calculate the redefinition offsets in the type.
repeat.
the calculating timer is a timer.
the call external tag is a tag equal to 2.
the call indirect tag is a tag equal to 3.
the call internal tag is a tag equal to 4.
to check for invalid optional info on a type:
if the compiler's abort flag is set, exit.
if the type is nil, exit.
if the type's target name is not blank, check for invalid optional info on the type (target).
if the type's fields are not empty, check for invalid optional info on the type (fields).
if the type's scale is not 0, check for invalid optional info on the type (scale).
to check for invalid optional info on a type (fields):
if the compiler's abort flag is set, exit.
if the type cannot be reduced to "record", abort with "Optional 'with' info is only allowed on record types." and the type's locus; exit.
to check for invalid optional info on a type (scale):
if the compiler's abort flag is set, exit.
if the type cannot be reduced to "number", abort with "Scales are only allowed on number types." and the type's locus; exit.
to check for invalid optional info on a type (target):
if the compiler's abort flag is set, exit.
if the type cannot be reduced to "pointer", abort with "Optional 'to' info is only allowed on pointer types." and the type's locus; exit.
to clear a field term:
fill bytes with the null byte starting at the field term's whereabouts for the field term's magnitude.
to clear a term:
void the term's variable.
clear the term's phrase.
the code borough is a borough.
to compile the bodies of the routines:
compile the body of the routine called "initialize before run".
compile the body of the routine called "run".
compile the body of the routine called "finalize after run".
to compile the body of a routine:
if the routine is nil, exit.
if the compiler's abort flag is set, exit.
if the routine's compiled flag is set, exit.
set the routine's compiled flag.
slap a rider on the routine's routine body.
move the rider (compiler rules).
if the rider's token is "employ", compile the body of the routine given the rider (employ); exit.
put the current routine into a saved routine.
put the routine into the current routine.
create the routine's nickname index given 101.
eliminate duplicate nicknames from the routine's parameters given the routine's nickname index.
compile the body of the routine (prolog).
loop.
if the compiler's abort flag is set, exit.
if the rider's token is blank, break.
compile the next statement given the rider.
repeat.
compile the body of the routine (epilog).
put the saved routine into the current routine.
to compile the body of a routine (epilog):
if the routine is nil, exit.
if the compiler's abort flag is set, exit.
add a fragment given the finalize tag.
loop.
get a variable from the routine's locals.
if the variable is nil, break.
if the variable's kind is "scratch", repeat.
if the variable's type should not be finalized, repeat.
add another fragment given the push address tag and the variable.
find another routine given "~finalize" and the variable's type.
if the other routine is nil, abort with "Internal error - compile the body of a routine (epilog)"; exit.
add a third fragment given the call internal tag and the other routine.
repeat.
add a fourth fragment given the epilog tag.
to compile the body of a routine (prolog):
if the routine is nil, exit.
if the compiler's abort flag is set, exit.
add a fragment given the prolog tag.
add another fragment given the loop tag.
to compile the body of the routine called a string:
if the compiler's abort flag is set, exit.
find a routine given the string and the routine index.
if the routine is nil, abort with "I need a routine to '" then the string then "'."; exit.
compile the body of the routine.
to compile the body of a routine given a rider (employ):
move the rider (compiler rules).
compile a routine reference given the rider.
convert the routine reference to the routine's employs moniker.
destroy the routine reference.
if the rider's token is not ".", abort with "Employ statments should end with a period not '" then the rider's token then "'." and the rider; exit.
move the rider (compiler rules).
if the rider's token is not blank, abort with "Once an employ, only an employ" and the rider; exit.
find another routine given the routine's employs moniker and the routine index.
if the other routine is nil, abort with "I can't find the '" then the routine's employs moniker then "' routine you're trying to employ." and the routine's locus; exit.
compile the body of the other routine.
to compile the call'd part given a rider and a variable:
if the compiler's abort flag is set, exit.
if the variable is nil, exit.
put the variable's name into the variable's type name.
move the rider (compiler rules).
scan the variable's name given the rider.
to compile a directory:
compile the directory (start).
compile the directory (read the source files).
compile the directory (scan the source files).
compile the directory (resolve the types).
compile the directory (resolve the globals).
compile the directory (compile the headers of the routines).
compile the directory (calculate lengths and offsets of types).
compile the directory (add the built-in memory routines).
compile the directory (index the routines for utility use).
compile the directory (compile the bodies of the routines).
compile the directory (add and compile the built-in startup routine).
compile the directory (offset parameters and variables).
compile the directory (address).
compile the directory (transmogrify).
compile the directory (link).
compile the directory (write the exe).
compile the directory (stop).
to compile a directory (add and compile the built-in startup routine):
if the compiler's abort flag is set, exit.
show status "Adding...".
start the adding built-in startup routine timer.
add and compile the initialize before run and run and finalize after run routine.
stop the adding built-in startup routine timer.
to compile a directory (add the built-in memory routines):
if the compiler's abort flag is set, exit.
show status "Adding...".
start the adding built-in memory routines timer.
add the allocate and deallocate and finalize and destroy routines.
stop the adding built-in memory routines timer.
to compile a directory (address):
if the compiler's abort flag is set, exit.
show status "Addressing...".
start the addressing timer.
put 4096 into an address.
put the address into the import borough's base.
address the imports given the address.
put the address minus the import borough's base into the import borough's length.
round the address up to the nearest multiple of 4096.
put the address into the data borough's base.
address the globals given the address.
address the literals given the address.
put the address minus the data borough's base into the data borough's length.
round the address up to the nearest multiple of 4096.
put the address into the code borough's base.
address the routines given the address.
put the address minus the code borough's base into the code borough's length.
stop the addressing timer.
to compile a directory (calculate lengths and offsets of types):
if the compiler's abort flag is set, exit.
show status "Calculating...".
start the calculating timer.