; > Execute ; Program execute dispatch loop ; Error handler ; ============= ; Generate inline error .Error mov (sp)+,r0 ; Pop return address .ErrorHandler mov SV_LINE,SV_ERL ; Save current error line clr SV_LINE ; Clear current line number mov r0,SV_FAULT ; Current error movb (r0),r0 ; Get current error number movb r0,SV_ERR ; Save current error number jsr pc,IO_AckEsc ; Acknowledge any pending Escape state tstb SV_ERR beq ErrorFatal ; If ERR=0, ignore ON ERROR mov SV_HIMEM,sp ; Clear machine stack mov sp,SV_STACK ; Clear BASIC stack mov SV_ONERR,r5 ; Get ON ERROR handler ; Should check for (r5)=tknLOCAL, clear stack if absent, step past if present bne Execute ; If set, jump to execute this code .ErrorFatal jsr pc,cmdREPORT ; Display error message mov SV_ERL,r0 ; Get error line beq ErrorNoErl ; Avoid printing 'at line 0' jsr pc,PrintInline equb " at line ",0 align mov SV_ERL,r0 jsr pc,PrintLineNum ; Print line number with no space padding .ErrorNoErl jsr pc,IO_NEWL jmp Immediate ; Drop to immediate mode ; REPORT - Display current error message ; ====================================== .cmdREPORT jsr pc,IO_NEWL ; Print newline mov SV_FAULT,r1 ; Get current error block inc r1 ; Step past error number jmp PrintR1 ; Print via token expansion ; RUN [str$] ; ========== ; Run program in memory or chain program from file .cmdRUN jsr pc,CheckEndToken ; Any parameters? beq RunProgram ; No, RUN program ; CHAIN str$ ; ========== ; Fetch CR-string ; Call LoadProgram ; Continue into RUN .cmdCHAIN jsr pc,EvalStringCR ; Get cr-string parameter ; ChainStartup ; ------------ ; Chain program, name already at R4 .ChainStartup mov SV_HIMEM,SP ; Put stack at top of memory jsr pc,LoadProgram ; Load file as a program ; RUN - Run program in memory ; =========================== ; LOMEM=TOP ; VAREND=TOP ; DATAPTR=PAGE ; STACK=HIMEM ; Clear dynamic variables ; LPTR=PAGE ; Enter Execution loop .RunProgram jsr pc,VarsHeapInit ; LOMEM=TOP, VAREND=TOP, DATAPTR=PAGE, STACK=HIMEM mov SV_HIMEM,SP ; Put system stack at top of memory mov SV_PAGE,R5 ; Point to start of program inc R5 ; Step past ; Step past line header after or at start of program ; ------------------------------------------------------- .ExecLineEnd jsr pc,ExecPastCR ; Step past line header ; Continue executing ; Execute program code ; ===================== ; R5=BASIC program pointer ; R4/R3=32-bit accumulator ; R2=value type/exponent ; R1/R0=working ; .Execute mov r5,SV_LPTR ; Store program pointer jsr pc,IO_Escape ; Check Escape state .ExecLineNext movb (r5)+,r0 ; Step past space cmpb r0,#&20 beq ExecLineNext ; Point to next char cmpb r0,#&3A ; Is current char a colon? beq ExecLineNext ; Move past colons cmpb r0,#tknTHEN ; Start of THEN clause? beq ExecLineNext ; Move past it cmpb r0,#13 ; End of line? beq ExecLineEnd ; Step past jsr pc,ExecByte ; Execute this byte jmp Execute ; Execute next statement ; Step past line header, checking for end of program ; -------------------------------------------------- ; r0=13, r5=>after .ExecPastCR add #3,r5 ; Step past line header movb &FFFD(r5),r0 ; Get byte after cmpb r0,#&FF ; Program terminator? beq cmdEND ; End of program mov SV_TRACE,r1 ; Get TRACE status beq ExecNoTrace ; Return if TRACE OFF mov &FFFE(r5),r2 ; Get line number sub r1,r2 ; Compare line number with trace line bcc ExecNoTrace ; linecurrent char, r0=current char jmp (r1) ; Jump to command routine ; Not a command token ; ------------------- .ExecNotCommand cmpb r0,#tknELSE-&C0 ; Current char 'ELSE'? beq cmdELSE cmpb r0,#tknOFF-&C0 ; Current char 'OFF'? beq cmdOFF_ cmpb r0,#ASC"="-&C0 ; Current char '='? beq cmdEquals_ cmpb r0,#ASC"["-&C0 ; Current char '[' beq cmdAssem_ mov r0,r1 jsr pc,SkipSpaces ; r5=>next char, r0=next char cmpb r1,#tknLINENUM ; Current char a line number marker after a THEN? beq cmdGOTO_ cmpb r1,#tknERROR-&C0 ; Current char 'ERROR'? beq cmdERROR_ cmpb r1,#tknEXT-&C0 ; Current char 'EXT'? beq cmdEXT_ cmpb r1,#ASC"*"-&C0 ; Current char '*'? bne cmdAssign_ ; Not '*', must be variable assignment ; Fall through to '*' command ; *command ; ======== mov r5,r0 ; Point to *command jsr pc,IO_CLI ; Pass to CLI ; Skip past a line, *command, REM, etc ; ------------------------------------ .SkipLine .cmdELSE .cmdREM .cmdDEF .cmdDATA movb (r5)+,r0 ; Get character cmpb r0,#13 bne SkipLine ; Loop until dec r5 ; Point to rts pc ; Bounce off to routines ; ---------------------- .cmdEquals_ jmp cmdEquals .cmdAssem_ jmp cmdAssem .cmdAssign_ jmp cmdAssign .cmdERROR_ jmp cmdERROR .cmdGOTO_ jmp cmdGOTO .cmdOFF_ jmp cmdOFF .cmdEXT_ jmp cmdEXT ; Various parsing routines ; ======================== ; Check for end of statement, returns Z if end of statement ; --------------------------------------------------------- .CheckEndStatement movb (r5)+,r0 cmpb r0,#&20 beq CheckEndStatement ; Skip any spaces dec r5 .CheckEndToken cmpb r0,#tknELSE bcc CheckEndStRet .CheckColon cmp r0,#&3A bcc CheckEndStRet cmp r0,#&0D .CheckEndStRet rts pc ; Fetch next non-space character ; ------------------------------ .FetchNextChar inc r5 ; Step past current character ; ; Skip past any spaces, and return current character ; -------------------------------------------------- .SkipSpaces movb (r5)+,r0 cmpb r0,#&20 beq SkipSpaces ; Loop until non-space dec r5 ; Point back to current character bic #&FF00,r0 ; Ensure 8-bit byte rts pc ; Check for numeric characters ; ---------------------------- .CheckHexDigit jsr pc,CheckDigit ; Is it decimal digit? bcc CheckDigitExit ; CC=digit bic #&20,r0 cmp r0,#ASC"A" bcs CheckDigitExit cmp #ASC"F",r0 rts pc ; CC=digit ; Returns CC if digit, CS if nondigit .CheckDigit cmp r0,#ASC"0" ; r0<'0' C=1, r0>='0' C=0 bcs CheckDigitExit ; Exit with CS if <'0' cmp #ASC"9",r0 ; '9'=r0 C=0 ; r0>'9' C=1, r0<='9' C=0 .CheckDigitExit ; Exit with CS if >'9' rts pc ; Check for closing bracket ; ------------------------- ; r5=>current char .CheckClose jsr pc,SkipSpaces .CheckClose1 cmpb r0,#ASC")" bne errMissingClose inc r5 rts pc .errMissingClose jsr pc,Error equb 27,"Missing )",0 align