I've been thinking about implementing an STC version of Fleet Forth. Since I will be using a metacompiler to build the kernel, I wanted to be able to test words which will need to be modified.
Here is an idea for the DO LOOP words. They are not to be compiled inline as they will be subroutines.
To test these words, they were defined with Fleet Forth's Assembler's SUBR , which creates a word which returns its PFA (like a variable) and switches to assembling.
Code: Select all
SUBR S.(LOOP)
PLA N STA PLA N 1+ STA
PLA TAY INY
0= IF
SEC PLA 0 # ADC
LABEL (+LOOP).BRANCH
VS IF
PLA PLA
PHP RTI
THEN
PHA
THEN
TYA PHA
LABEL N.BRANCH
2 # LDY CLC
N )Y LDA PHA DEY
N )Y LDA PHA
PHP RTI
END-CODE
SUBR S.(+LOOP)
PLA N STA PLA N 1+ STA
INX INX CLC
PLA $FE ,X ADC TAY
PLA $FF ,X ADC
(+LOOP).BRANCH JMP
END-CODE
SUBR S.(DO)
PLA N STA PLA N 1+ STA
2 # LDY
N )Y LDA PHA DEY
N )Y LDA PHA CLC
3 ,X LDA $80 # ADC PHA
3 ,X STA 2 ,X LDA PHA SEC
0 ,X LDA 2 ,X SBC TAY
1 ,X LDA 3 ,X SBC PHA
TYA PHA
INX INX INX INX
CLC
N LDA 3 # ADC N STA
0= IF N 1+ INC THEN
N ) JMP END-CODE
SUBR S.(?DO)
0 ,X LDA 2 ,X CMP
S.(DO) 0= NOT BRAN
1 ,X LDA 3 ,X CMP
S.(DO) 0= NOT BRAN
PLA N STA PLA N 1+ STA
N.BRANCH JMP
END-CODE
SUBR S.UNLOOP
PLA TAY PLA N STA
PLA PLA PLA PLA
PLA PLA
N LDA PHA TYA PHA
RTS
END-CODE
SUBR S.I ( -- LOOP-INDEX )
XSAVE STX TSX CLC
$103 ,X LDA $105 ,X ADC TAY
$104 ,X LDA $106 ,X ADC
XSAVE LDX
DEX DEX
0 ,X STY 1 ,X STA
RTS
END-CODE
SUBR S.J ( -- OUTER-LOOP-INDEX )
XSAVE STX TSX
INX INX INX INX
INX INX
S.I 3 + JMP
END-CODE
SUBR S.LEAVE
PLA PLA
PLA PLA PLA PLA
PHP RTI
END-CODE
SUBR S.?LEAVE
INX INX
$FE ,X LDA $FF ,X ORA
S.LEAVE 0= NOT BRAN
RTS
END-CODE
These subroutines were given names beginning with S. so the text 'SUBR S.' can be replaced with the text 'CODE' using search and replace.
The remaining occurrences of S. such as the following:
Code: Select all
S.I 3 + JMP
can then be fixed by replacing S. with tick followed by a space.
Here are some convenient helper words for testing.
Code: Select all
SUBR S.U. ( U -- )
>FORTH
CR U. ERR
>ASSEM
RTS
END-CODE
VARIABLE INTERVAL INTERVAL ON
SUBR S.INTERVAL
>FORTH
INTERVAL @
>ASSEM
RTS
END-CODE
ERR is a deferred word normally set to NOOP . However, when set to (ERR) , it will display the contents of all three stacks.
The test words are code words in Fleet Forth.
Code: Select all
CODE DO.LOOP.TEST
S.(DO) JSR >MARK <MARK
S.I JSR
S.U. JSR
S.(LOOP) JSR <RESOLVE >RESOLVE
NEXT JMP END-CODE
CODE DO.+LOOP.TEST
S.(DO) JSR >MARK <MARK
S.I JSR
S.U. JSR
S.INTERVAL JSR
S.(+LOOP) JSR <RESOLVE >RESOLVE
NEXT JMP END-CODE
CODE LEAVE.TEST
S.(DO) JSR >MARK <MARK
S.I JSR
S.U. JSR
S.LEAVE JSR
S.(LOOP) JSR <RESOLVE >RESOLVE
NEXT JMP END-CODE
CODE ?LEAVE.TEST
S.(DO) JSR >MARK <MARK
S.I JSR
S.U. JSR
S.I JSR
S.?LEAVE JSR
S.(LOOP) JSR <RESOLVE >RESOLVE
NEXT JMP END-CODE
The mark and resolve words are used this way in Fleet Forth.
Code: Select all
: DO ( -- >SYSL <SYSL )
COMPILE (DO)
>MARK 2+ <MARK 2+ ; IMMEDIATE
: LOOP ( >SYSL <SYSL -- )
COMPILE (LOOP)
2- <RESOLVE 2- >RESOLVE ; IMMEDIATE
but with different security codes.
Here are the test results.
Code: Select all
5 0 DO.LOOP.TEST
0
1
2
3
4 OK
0 5 DO.+LOOP.TEST
5
4
3
2
1
0 OK
5 0 LEAVE.TEST
0 OK
5 0 ?LEAVE.TEST
0
1 OK