Thanks to feedback on several forums, I have come to an understanding of how the FOR and NEXT statements commonly behave in interpreters so that they can finally be implemented in my compiler.
viewtopic.php?f=2&t=6182https://talk.dallasmakerspace.org/t/a-t ... asic/72013The following code has been written to approximate what the compiler can be expected to generate for this program:
Code:
10 FOR I = 1 TO 3
20 PRINT I
30 NEXT I
Code:
00068 * 00010 FOR I = 1 TO 3
010D 00069 L00010
010D BD 0248 [9] 00070 jsr ForPush ; Get new FOR context
00071
0110 86 01 [2] 00072 ldaa #T00001>>8 ; Store top of loop address
0112 A7 04 [6] 00073 staa 4,X
0114 86 26 [2] 00074 ldaa #T00001&$FF
0116 A7 05 [6] 00075 staa 5,X
00076
0118 86 06 [2] 00077 ldaa #I>>8 ; Store variable address
011A A7 06 [6] 00078 staa 6,X
011C 86 0F [2] 00079 ldaa #I&$FF
011E A7 07 [6] 00080 staa 7,X
00081
0120 86 00 [2] 00082 ldaa #1>>8 ; Initialize variable
0122 C6 01 [2] 00083 ldab #1&$FF
00084
0124 20 21 (0147) [4] 00085 bra T00003 ; Execute the body of the loop
00086
0126 00087 T00001
0126 B6 060F [4] 00088 ldaa I ; Load variable
0129 F6 0610 [4] 00089 ldab I+1
00090
012C CB 01 [2] 00091 addb #1&$FF ; Add step
012E 89 00 [2] 00092 adca #1>>8
00093
0130 81 00 [2] 00094 cmpa #3>>8 ; Compare with limit
0132 22 06 (013A) [4] 00095 bhi T00002 ; Higher, exit loop
0134 25 11 (0147) [4] 00096 blo T00003 ; Lower, iterate loop
0136 C1 03 [2] 00097 cmpb #3&$FF
0138 23 0D (0147) [4] 00098 bls T00003 ; Not higher, iterate loop
00099
013A 00100 T00002
013A FE 0611 [5] 00101 ldx ForTop ; Address context
00102
013D A6 09 [5] 00103 ldaa 9,X ; Push address of bottom of loop
013F 36 [4] 00104 psha
0140 A6 08 [5] 00105 ldaa 8,X
0142 36 [4] 00106 psha
00107
0143 BD 027B [9] 00108 jsr ForPull ; Remove FOR context
00109
0146 39 [5] 00110 rts ; "Jump" to bottom of loop
00111
0147 00112 T00003
0147 B7 060F [5] 00113 staa I ; Update variable
014A F7 0610 [5] 00114 stab I+1
00115
00116 * 00020 PRINT I
014D 00117 L00020
014D FE 060F [5] 00118 ldx I
0150 BD 0428 [9] 00119 jsr PInt
00120
0153 BD 04CB [9] 00121 jsr NewLine
00122
00123 * 00030 NEXT I
0156 00124 L00030
0156 86 06 [2] 00125 ldaa #I>>8 ; Address the variable
0158 C6 0F [2] 00126 ldab #I&$FF
00127
015A BD 0225 [9] 00128 jsr Next
00129
015D 00130 End_
Three subroutines provide support for a FOR-NEXT loop:
ForPush - Create a new loop context
ForPull - Remove a loop context
Next - Process the bottom of a loop
Only Next is interesting; when the specified variable does not match the one at the top of the loop, contexts are discarded until a matching one is found or there are none left.
Code:
. 00354 ******************************************************************************
. 00355 *
. 00356 * Next - Process NEXT
. 00357 *
. 00358 * Input:
. 00359 * A:B = variable address
. 00360 *
.0225 00361 Next
.0225 FE 0611 [5] 00362 ldx ForTop ; Point to current context
.0228 27 12 (023C) [4] 00363 beq Next1 ; Not within a FOR loop
. 00364
.022A 00365 Next0
.022A A1 06 [5] 00366 cmpa 6,X ; Compare variable address
.022C 26 0E (023C) [4] 00367 bne Next1 ; Loop variable mismatch
.022E E1 07 [5] 00368 cmpb 7,X
.0230 26 0A (023C) [4] 00369 bne Next1
. 00370
.0232 32 [4] 00371 pula ; Get and save bottom of loop
.0233 A7 08 [6] 00372 staa 8,X
.0235 32 [4] 00373 pula
.0236 A7 09 [6] 00374 staa 9,X
. 00375
.0238 EE 04 [6] 00376 ldx 4,X ; Jump to top of loop
.023A 6E 00 [4] 00377 jmp ,X
. 00378
.023C 00379 Next1
.023C EE 02 [6] 00380 ldx 2,X ; Get previous context
.023E FF 0611 [6] 00381 stx ForTop ; Save it
.0241 26 E7 (022A) [4] 00382 bne Next0 ; Retry if valid
. 00383
.0243 86 3E [2] 00384 ldaa #62 ; Report FOR-NEXT nesting error
.0245 7E 0284 [3] 00385 jmp ErrH