This bug was discovered here:
viewtopic.php?f=1&t=5198&start=150#p61372Quote:
The "result" for EhBasic using: 40 IF INT(C/D)*D = C THEN NEXT C : GOTO 90
yields: "NEXT without FOR Error in line 40"
This is true not only for a NEXT but also for LOOP and RETURN. All of these keywords need to find their FOR, DO or GOSUB structure on the stack. Since EhBASIC allows for an ELSE the call to interpret a basic statement after THEN must return to IF to be able to skip the program past ELSE. This puts a return address on the stack and breaks the offset to FOR, DO and GOSUB structures on the stack. Interestingly Lee already fixed this for RETURN since there is no need to skip anything after a RETURN.
The fix I have is to simply discard the original call to the "interpret statement" routine (The one that executed the IF) and replace the final RTS with a JMP to the interpreter loop. This also eliminates the need to have a separate fix for RETURN. To my big surprise even nested IFs work correctly.
Code:
; perform IF
LAB_IF
JSR LAB_EVEX ; evaluate the expression
JSR LAB_GBYT ; scan memory
CMP #TK_THEN ; compare with THEN token
BEQ LAB_174B ; if it was THEN go do IF
; wasn't IF .. THEN so must be IF .. GOTO
CMP #TK_GOTO ; compare with GOTO token
BNE LAB_16FC ; if it wasn't GOTO go do syntax error
LDX Bpntrl ; save the basic pointer low byte
LDY Bpntrh ; save the basic pointer high byte
JSR LAB_IGBY ; increment and scan memory
BCS LAB_16FC ; if not numeric go do syntax error
STX Bpntrl ; restore the basic pointer low byte
STY Bpntrh ; restore the basic pointer high byte
LAB_174B
LDA FAC1_e ; get FAC1 exponent
BEQ LAB_174E ; if the result was zero go look for an ELSE
JSR LAB_IGBY ; else increment and scan memory
BCS LAB_174D ; if not numeric go do var or keyword
LAB_174C
JMP LAB_GOTO ; else was numeric so do GOTO n
; is var or keyword
LAB_174D
; *** patch allow NEXT, LOOP & RETURN to find FOR, DO or GOSUB structure on stack
; *** replace
; CMP #TK_RETURN ; compare the byte with the token for RETURN
; BNE LAB_174G ; if it wasn't RETURN go interpret BASIC code from (Bpntrl)
; ; and return to this code to process any following code
;
; JMP LAB_1602 ; else it was RETURN so interpret BASIC code from (Bpntrl)
; ; but don't return here
;
;LAB_174G
; JSR LAB_15FF ; interpret BASIC code from (Bpntrl)
;
;; the IF was executed and there may be a following ELSE so the code needs to return
;; here to check and ignore the ELSE if present
;
; LDY #$00 ; clear the index
; LDA (Bpntrl),Y ; get the next BASIC byte
; CMP #TK_ELSE ; compare it with the token for ELSE
; BEQ LAB_DATA ; if ELSE ignore the following statement
;
;; there was no ELSE so continue execution of IF <expr> THEN <stat> [: <stat>]. any
;; following ELSE will, correctly, cause a syntax error
;
; RTS ; else return to the interpreter inner loop
;
; *** with
PLA ; discard interpreter loop return address
PLA ; so data structures are at the correct stack offset
JSR LAB_GBYT ; restore token or variable
JSR LAB_15FF ; interpret BASIC code from (Bpntrl)
; the IF was executed and there may be a following ELSE so the code needs to return
; here to check and ignore the ELSE if present
LDY #$00 ; clear the index
LDA (Bpntrl),Y ; get the next BASIC byte
CMP #TK_ELSE ; compare it with the token for ELSE
BNE LAB_no_ELSE ; no - continue on this line
JSR LAB_DATA ; yes - skip the rest of the line
; there was no ELSE so continue execution of IF <expr> THEN <stat> [: <stat>]. any
; following ELSE will, correctly, cause a syntax error
LAB_no_ELSE
JMP LAB_15C2 ; return to the interpreter inner loop
; *** end patch allow NEXT, LOOP & RETURN to find FOR, DO or GOSUB structure on stack
; perform ELSE after IF
LAB_174E