Dealer Demo, part 8: Who compiles the compiler?
We pick up decompiling again at $148C, where we find 1+ (ONEP). It is followed by 2+ (TWOP), HERE, ALLOT, , (COMMA), C, (CCOMM), - (SUB), = (EQUAL), > (GREAT), ROT, SPACE and -DUP (DDUP). All of these are identical to the fig-Forth listing, which implements these as colon-definitions, which is expected. Although SUB, EQUAL and ROT are sometimes rewritten as primitives to speed up Forth (cf. val-Forth), optimizing these was not done in this Forth.
TRAVERSE is the next word in the listing and it is implemented completed differently. It's used to traverse a name field forwards or backwards to find start or end of the name. Here's the version from fig-Forth:
0A84: D6 07 TRAV .WORD DOCOL 0A86: 22 07 .WORD SWAP 0A88: 08 07 L1312 .WORD OVER 0A8A: 99 06 .WORD PLUS 0A8C: 67 02 .WORD CLIT 0A8E: 7F .BYTE $7F 0A8F: 08 07 .WORD OVER 0A91: 8E 07 .WORD CAT 0A93: 1F 0A .WORD LESS 0A95: 56 03 .WORD ZBRAN 0A97: F1 FF L1320 .WORD $FFF1 0A99: 22 07 .WORD SWAP 0A9B: 19 07 .WORD DROP 0A9D: 0C 06 .WORD SEMIS
and here's the smaller and faster version from Dealer Demo.
154A: 4C 15 TRAV .WORD *+2 154C: B4 00 LDY 0,X 154E: 98 TRAV1 TYA 154F: 18 CLC 1550: 75 02 ADC 2,X 1552: 95 02 STA 2,X 1554: B5 01 LDA 1,X 1556: 75 03 ADC 3,X 1558: 95 03 STA 3,X 155A: A1 02 LDA (2,X) 155C: 10 F0 BPL TRAV1 155E: 4C 4D 0E JMP POP
The Dealer Demo version is a nice improvement, perhaps motivated to speed up Forth compilation.
From here on in our decompilation we'll largely omit details where the implementation follows the fig-Forth implementation exactly
The next words, LATEST, LFA, CFA, NFA, PFA, !CSP, ?ERR, ?COMP, ?EXEC, ?PAIR, ?CSP, ?LOAD, COMP, LBRAC, RBRAC and SMUDGE are colon definitions to support the compiler. HEX and DECIMAL follow, and then more compiler/runtime support with (;CODE), ;CODE and then <BUILD, DOES> followed by some assembly code DODOE to support <BUILD … DOES> and then the word COUNT.
If we run -refs now, we'll see that (;CODE), labeled PSCOD, is the routine that finishes all the various dictionary adding definitions we've already seen (e.g. CONSTANT, VARIABLE, colon). I would have expected this routine to be a primitive, but it in fact is a colon definition:
16D4: 4C 12 PSCOD .WORD DOCOL 16D6: 85 10 .WORD RFROM 16D8: 6A 15 .WORD LATES 16DA: AC 15 .WORD PFA 16DC: 89 15 .WORD CFA 16DE: 13 12 .WORD STORE 16E0: 45 10 .WORD SEMIS
This just sets the code field of the latest word to the code that follows the PSCOD address. It's used in all definitions because all those definitions finish adding to the dictionary in the same way, so it might as well be shared code.
DODOE deserves a little study:
171E: A5 F9 DODOE LDA IP+1 1720: 48 PHA 1721: A5 F8 LDA IP 1723: 48 PHA 1724: A0 02 LDY #2 1726: B1 FB LDA (W),Y 1728: 85 F8 STA IP 172A: C8 INY 172B: B1 FB LDA (W),Y 172D: 85 F9 STA IP+1 172F: 18 CLC 1730: A5 FB LDA W 1732: 69 04 ADC #4 1734: 48 PHA 1735: A5 FC LDA W+1 1737: 69 00 ADC #0 1739: 4C 3B 0D JMP PUSH
This routine configures Forth to resume execution at the word after DODOE, but first puts the current IP on the return stack, and the address of the subsequent word on the data stack. This is similar to how DOCOL works, but in practice it means we restart execution inside another DOCOL definition (the address after a DODOE is not the start of a definition) with the top of the stack set to a particular value. In modern terms, we'd probably call this a continuation, since it allows us to continue another routine with a modified environment. In the Forth kernel, it is used only to implement particular vocabularies (e.g. FORTH, ASSEMBLER), which can configure the set of words in the dictionary available to the compiler, but the assembler itself will use this extensively to create a table driven assembler from a handful of words.
The next word that is different is TYPE. In place of a real implementation, a stub implementation is here (.WORD DOCOL, XTYPE, SEMIS), deferring the implementation to later in the listing. This is partially understandable, TYPE depends on being able to use the Atari CIO routines which have yet to be defined. But if Dealer Demo was bootstrapped using an assembler, this isn't really necessary, the assembler can handle the backward references just fine. Perhaps the implementation started by following the original fig-Forth, where XTYPE would have been a primitive defined later in the listing, but at some point it was converted to a colon definition and the original forward definition adjusted. As a result, we have two definitions of TYPE which are equivalent, which wastes some memory but otherwise works fine.
I think that's enough decompiling for this post. Let's fix up the values -refs show can now be replaced with labels, and pick up again later.
0 Comments
Recommended Comments
There are no comments to display.