-- BasicCommand.mesa -- edited by Brotz and Hilton, September 23, 1982 5:07 PM DIRECTORY BasicDefs, BasicImpDefs, BasicOps, IODefs, Storage, String; BasicCommand: PROGRAM IMPORTS BasicImpDefs, IODefs, Storage, String EXPORTS BasicImpDefs = BEGIN OPEN BasicDefs, BasicImpDefs; nCommands: CARDINAL = 43; CommandRecord: TYPE = RECORD [name: STRING, command: PROCEDURE]; commandTable: ARRAY [0 .. nCommands) OF CommandRecord _ [["!"L, RemCommand], ["AUTO"L, AutoCommand], ["CLEAR"L, ClearCommand], ["CONT"L, ContCommand], ["CODELIST"L, CodeListCommand], ["DATA"L, DataCommand], ["DEF"L, DefFnCommand], ["DEG"L, DegreeMode], ["DEL"L, DeleteCommand], ["DIM"L, DimCommand], ["DISP"L, PrintCommand], ["END"L, EndCommand], ["FNEND"L, FnEndCommand], ["FOR"L, ForCommand], ["GOSUB"L, GoSubCommand], ["GOTO"L, GoToCommand], ["HELP"L, HelpCommand], ["IF"L, IfCommand], ["IMAGE"L, ImageCommand], ["INPUT"L, InputCommand], ["LET"L, LetCommand], ["LIST"L, ListCommand], ["LOAD"L, LoadCommand], ["NEXT"L, NextCommand], ["NORMAL"L, NormalCommand], ["ON"L, OnCommand], ["OPTIONBASE"L, OptionBaseCommand], ["PAUSE"L, PauseCommand], ["PRINT"L, PrintCommand], ["QUIT"L, QuitCommand], ["RAD"L, RadianMode], ["READ"L, ReadCommand], ["REM"L, RemCommand], ["RENUMBER"L, RenumberCommand], ["RESTORE"L, RestoreCommand], ["RETURN"L, ReturnCommand], ["RUN"L, RunCommand], ["STEP"L, NulCommand], ["STOP"L, PauseCommand], ["TAB"L, TabCommand], ["TO"L, NulCommand], ["THEN"L, NulCommand], ["USING"L, NulCommand]]; AutoCommand: PROCEDURE = BEGIN IF isProgramLine THEN ParseError["AUTO command illegal in a program."L]; IF GetToken[] THEN BEGIN Expression[]; IF haveToken THEN SELECT TRUE FROM token[0] # ', => ParseError["Missing comma in AUTO command."L]; GetToken[] => Expression[]; ENDCASE => ParseError["Missing increment in AUTO command."L] ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 10]; END; END ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 10]; AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 10]; END; AppendByte[lineCodeCm, BasicOps.Auto]; END; -- of AutoCommand -- ClearCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 255]; AppendByte[lineCodeCm, BasicOps.Tab]; NextStatement[]; END; -- of ClearCommand -- CodeListCommand: PROCEDURE = BEGIN GenericListCommand[BasicOps.CodeList]; END; -- of CodeListCommand -- CommandCleanUp: PUBLIC PROCEDURE = BEGIN goSubPrevPtr: GoSubStackPtr; goSubCurPtr: GoSubStackPtr _ goSubHead; nextPrevPtr: NextStackPtr; nextcurPtr: NextStackPtr _ nextStackHead; UNTIL nextcurPtr = NIL DO nextPrevPtr _ nextcurPtr; nextcurPtr _ nextcurPtr.next; Storage.Free[nextPrevPtr]; ENDLOOP; UNTIL goSubCurPtr = NIL DO goSubPrevPtr _ goSubCurPtr; goSubCurPtr _ goSubCurPtr.next; Storage.Free[goSubPrevPtr]; ENDLOOP; END; -- of CommandCleanUp -- ContCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Cont]; END; -- of ContCommand -- DataCommand: PROCEDURE = BEGIN value: BasicValue; AppendByte[lineCodeCm, BasicOps.Data]; DO IF ~GetToken[] THEN ParseError["Missing value in DATA statement!"L]; value _ ParseConstant[]; AppendPointer[lineCodeCm, AllocateConstant[value]]; IF value.type = string THEN Storage.FreeString[value.stringValue]; IF ~haveToken THEN EXIT; IF token[0] # ', THEN ParseError["Missing comma in DATA statement!"L]; ENDLOOP; AppendPointer[lineCodeCm, LOOPHOLE[0]]; END; -- of DataCommand -- DefFnCommand: PROCEDURE = BEGIN fnVarPtr, argVarPtr: VariablePtr _ NIL; singleLine: BOOLEAN _ FALSE; IF ~isProgramLine THEN ParseError["DEF FN command illegal outside of a program!"L]; IF ~GetToken[] THEN ParseError["Missing function name!"L]; fnVarPtr _ LookUpVariable[token]; WITH v: fnVarPtr SELECT FROM userFunction => NULL; ENDCASE => ParseError["Illegal function name!"L]; AppendByte[lineCodeCm, BasicOps.DefFn]; IF GetToken[] THEN SELECT token[0] FROM '= => singleLine _ TRUE; '( => BEGIN IF ~GetToken[] THEN ParseError["Missing formal parameter name!"L]; argVarPtr _ LookUpVariable[token]; WITH v: argVarPtr SELECT FROM numeric, string => NULL; ENDCASE => ParseError["Illegal formal paramter name!"L]; IF ~GetToken[] THEN ParseError["Missing )!"L]; IF GetToken[] THEN BEGIN IF token[0] = '= THEN singleLine _ TRUE ELSE ParseError["Missing = in function definition!"L]; END; END; ENDCASE => ParseError["Illegal character after function name!"L]; AppendByte[lineCodeCm, IF singleLine THEN 1 ELSE 2]; AppendPointer[lineCodeCm, fnVarPtr]; AppendPointer[lineCodeCm, IF argVarPtr = NIL THEN LOOPHOLE[0] ELSE argVarPtr]; IF singleLine THEN BEGIN IF GetToken[] THEN BEGIN Expression[]; AppendByte[lineCodeCm, BasicOps.PopVal]; AppendPointer[lineCodeCm, fnVarPtr]; AppendByte[lineCodeCm, BasicOps.FnEnd]; END ELSE ParseError["Missing expression in function definition!"L]; END; END; -- of DefFnCommand -- DegreeMode: PROCEDURE = BEGIN trigMode _ degrees; END; -- of DegreeMode -- DeleteCommand: PROCEDURE = BEGIN IF isProgramLine THEN ParseError["DELETE command illegal in a program."L]; IF GetToken[] THEN BEGIN Expression[]; IF haveToken THEN SELECT TRUE FROM token[0] # ', => ParseError["Missing comma in DELETE command."L]; GetToken[] => Expression[]; ENDCASE => ParseError["Missing end line number in DELETE command."L] ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]; END; AppendByte[lineCodeCm, BasicOps.Delete]; END ELSE ParseError["DELETE command requires a line number."L]; END; -- of DeleteCommand -- DimCommand: PROCEDURE = BEGIN varPtr: VariablePtr; DO IF GetToken[] THEN BEGIN varPtr _ LookUpVariable[token]; WITH v: varPtr SELECT FROM string => BEGIN IF ~GetToken[] OR ~String.EquivalentString[token, "["L] THEN ParseError["Missing [."L]; IF GetToken[] THEN Expression[] ELSE ParseError["Missing string dimension!"L]; IF ~haveToken OR token[0] # '] THEN ParseError["Missing ]."L]; AppendByte[lineCodeCm, BasicOps.DimStr]; END; numeric => BEGIN IF ~GetToken[] OR ~String.EquivalentString[token, "("L] THEN ParseError["Missing (."L]; IF GetToken[] THEN Expression[] ELSE ParseError["Missing array dimension!"L]; SELECT TRUE FROM ~haveToken => ParseError["Missing comma or )."L]; token[0] = ', => IF GetToken[] THEN Expression[] ELSE ParseError["Missing array dimension!"L]; ENDCASE => {AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]}; IF ~haveToken OR token[0] # ') THEN ParseError["Missing )."L]; AppendByte[lineCodeCm, BasicOps.Dim]; END; ENDCASE => ParseError["Improper variable in DIM statement!"L]; AppendPointer[lineCodeCm, varPtr]; IF ~GetToken[] THEN EXIT; IF token[0] # ', THEN ParseError["Missing comma between itmes in DIM statement."L]; END ELSE ParseError["Missing variable in DIM statement!"L]; ENDLOOP; END; -- of DimCommand -- EndCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.End]; END; -- of EndCommand -- FnEndCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.FnEnd]; END; -- of FnEndCommand -- ForCommand: PROCEDURE = BEGIN varPtr: VariablePtr; savedLength: CARDINAL _ inputLine.length; index: CARDINAL; IF ~isProgramLine THEN ParseError["FOR command illegal outside of a program"L]; CheckForVariable[]; varPtr _ LookUpVariable[token]; CheckForEqualSign[]; index _ FindInfixReservedWord["TO"L]; IF index = 0 THEN ParseError["Missing TO in FOR statement!"L]; inputLine.length _ index; IF GetToken[] THEN Expression[] ELSE ParseError["Missing initial value in FOR statement."L]; IF haveToken THEN ParseError["Extra token before TO in FOR statement!"L]; inputLine.length _ savedLength; IF GetToken[] AND String.EquivalentString[token, "TO"L] THEN BEGIN index _ FindInfixReservedWord["STEP"L]; IF index # 0 THEN inputLine.length _ index; IF GetToken[] THEN Expression[] ELSE ParseError["Missing final value in FOR statement."L]; IF haveToken THEN ParseError["Extra token before STEP in FOR statement!"L]; inputLine.length _ savedLength; IF GetToken[] AND String.EquivalentString[token, "STEP"L] THEN BEGIN IF GetToken[] THEN Expression[] ELSE ParseError["Missing step value in FOR statement."L]; END ELSE {AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 1]}; END ELSE ParseError["Missing TO in FOR statement."L]; AppendByte[lineCodeCm, BasicOps.For]; AppendPointer[lineCodeCm, varPtr]; END; -- of ForCommand -- GenericListCommand: PROCEDURE [opCode: BasicOps.Byte] = BEGIN IF isProgramLine THEN ParseError["LIST command illegal in a program."L]; IF GetToken[] THEN BEGIN Expression[]; IF haveToken THEN SELECT TRUE FROM token[0] # ', => ParseError["Missing comma in LIST command."L]; GetToken[] => Expression[]; ENDCASE => ParseError["Missing end line number in LIST command."L] ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]; END; END ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]; AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]; END; AppendByte[lineCodeCm, opCode]; END; -- of GenericListCommand -- GoSubCommand: PROCEDURE = BEGIN IF ~isProgramLine THEN ParseError["GOSUB command illegal outside of a program"L]; AppendByte[lineCodeCm, BasicOps.GoSub]; ParseLineNumber[]; END; -- of GoSubCommand -- GoToCommand: PROCEDURE = BEGIN IF ~isProgramLine THEN ParseError["GO TO command illegal outside of a program"L]; AppendByte[lineCodeCm, BasicOps.GoTo]; ParseLineNumber[]; END; -- of GoToCommand -- ParseLineNumber: PROCEDURE = BEGIN lineNumber: INTEGER; IF GetToken[] THEN BEGIN lineNumber _ String.StringToDecimal[token ! String.InvalidNumber => GO TO bad]; IF lineNumber ~IN [0 .. 9999] THEN GO TO bad; AppendPointer[lineCodeCm, LOOPHOLE[lineNumber]]; END ELSE ParseError["Missing statement number!"L]; EXITS bad => ParseError["Illegal statement number!"L]; END; -- of ParseLineNumber -- HelpCommand: PROCEDURE = BEGIN IF isProgramLine THEN ParseError["Help command illegal in a program."L]; AppendByte[lineCodeCm, BasicOps.Help]; END; -- of HelpCommand -- IfCommand: PROCEDURE = BEGIN savedLength: CARDINAL _ inputLine.length; index: CARDINAL; IF ~isProgramLine THEN ParseError["IF command illegal outside of a program"L]; index _ FindInfixReservedWord["THEN"L]; IF index = 0 THEN index _ FindInfixReservedWord["GOSUB"L]; IF index = 0 THEN index _ FindInfixReservedWord["GOTO"L]; IF index = 0 THEN index _ FindInfixReservedWord["LET"L]; IF index = 0 THEN ParseError["Missing THEN, GOTO, GOSUB, or LET in IF statement!"L]; inputLine.length _ index; IF GetToken[] THEN Expression[] ELSE ParseError["Missing relation in IF command!"L]; IF haveToken THEN ParseError["Extra token before THEN, GOTO, GOSUB, or LET in IF statement!"L]; inputLine.length _ savedLength; IF ~GetToken[] THEN ParseError["Missing second part of IF command!"L]; AppendByte[lineCodeCm, BasicOps.IfZeroDone]; SELECT TRUE FROM String.EquivalentString[token, "GOSUB"L] => GoSubCommand[]; String.EquivalentString[token, "THEN"L], String.EquivalentString[token, "GOTO"L] => GoToCommand[]; String.EquivalentString[token, "LET"L] => LetCommand[]; ENDCASE => ParseError["Unrecognized second part of IF comand!"L]; END; -- of IfCommand -- ImageCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Image]; END; -- of ImageCommand -- InputCommand: PROCEDURE = BEGIN varPtr: VariablePtr; firstTime: BOOLEAN _ TRUE; savedIndex, nIndices: CARDINAL; DO CheckForVariable[]; varPtr _ LookUpVariable[token]; AppendByte [lineCodeCm, IF varPtr.type = string THEN BasicOps.InputStr ELSE BasicOps.InputNum]; AppendByte[lineCodeCm, IF firstTime THEN 0 ELSE 1]; nIndices _ 0; WITH v: varPtr SELECT FROM builtInFunction => ParseError["Unrecognized keyword!"L]; numeric => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '( THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; string => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '[ THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; ENDCASE; SELECT nIndices FROM 0 => AppendByte[lineCodeCm, BasicOps.PopVal]; 1 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str1Pop, ENDCASE => BasicOps.Arr1Pop]; 2 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str2Pop, ENDCASE => BasicOps.Arr2Pop]; ENDCASE => ParseError["Can't happen."L]; AppendPointer[lineCodeCm, varPtr]; IF ~GetToken[] THEN EXIT; IF token[0] # ', THEN ParseError["Missing comma in READ statement!"L]; ENDLOOP; END; -- of InputCommand -- IsReservedWord: PUBLIC PROCEDURE [s: STRING] RETURNS [BOOLEAN] = BEGIN FOR i: CARDINAL IN [0 .. nCommands) DO IF String.EquivalentString[s, commandTable[i].name] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; -- of IsReservedWord -- ParseStatement: PUBLIC PROCEDURE [savedIndex: CARDINAL] = BEGIN FOR i: CARDINAL IN [0 .. nCommands) DO IF String.EquivalentString[token, commandTable[i].name] THEN {commandTable[i].command[]; RETURN}; ENDLOOP; -- reset scanner so GetToken gets left side of bare LET statement. inputLineIndex _ savedIndex; LetCommand[]; END; -- of ParseStatement -- LetCommand: PROCEDURE = BEGIN varPtr: VariablePtr; savedIndex, nIndices: CARDINAL _ 0; CheckForVariable[]; varPtr _ LookUpVariable[token]; WITH v: varPtr SELECT FROM builtInFunction => ParseError["Unrecognized keyword!"L]; numeric => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '( THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; string => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '[ THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; ENDCASE; CheckForEqualSign[]; IF GetToken[] THEN BEGIN Expression[]; IF ~haveToken THEN BEGIN SELECT nIndices FROM 0 => AppendByte[lineCodeCm, BasicOps.PopVal]; 1 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str1Pop, ENDCASE => BasicOps.Arr1Pop]; 2 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str2Pop, ENDCASE => BasicOps.Arr2Pop]; ENDCASE => ParseError["Can't happen."L]; AppendPointer[lineCodeCm, varPtr]; END ELSE ParseError["Illegal expression within LET statemtent."L]; END ELSE ParseError["Missing assignment value within the LET statement."L]; NextStatement[]; END; -- of LetCommand -- ListCommand: PROCEDURE = -- Lists the program in numerical order BEGIN GenericListCommand[BasicOps.List]; END; -- of ListCommand -- LoadCommand: PROCEDURE = BEGIN bv: BasicValue; constPtr: VariablePtr; IF ~GetToken[] THEN ParseError["Missing module name in LOAD command."L]; bv _ BasicValue[type: string, varPart: string[stringValue: token]]; constPtr _ AllocateConstant[bv]; AppendByte[lineCodeCm, BasicOps.PushVal]; AppendPointer[lineCodeCm, constPtr]; AppendByte[lineCodeCm, BasicOps.Load]; END; -- of LoadCommand -- NextCommand: PROCEDURE = BEGIN IF ~isProgramLine THEN ParseError["NEXT command illegal outside of a program"L]; CheckForVariable[]; AppendByte[lineCodeCm, BasicOps.Next]; AppendPointer[lineCodeCm, LookUpVariable[token]]; END; -- of NextCommand -- NormalCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Normal]; END; -- of NormalCommand -- NulCommand: PROCEDURE = BEGIN -- This procedure is used as a procedure place holder within the -- command table. This enables reserved words to be put into the -- command table without actually having to execute code. END; -- of NulCommand -- OnCommand: PROCEDURE = BEGIN savedLength: CARDINAL _ inputLine.length; index: CARDINAL; IF ~isProgramLine THEN ParseError["ON GOTO/GOSUB command illegal outside of a program"L]; index _ FindInfixReservedWord["GOTO"L]; IF index = 0 THEN index _ FindInfixReservedWord["GOSUB"L]; IF index = 0 THEN ParseError["Missing GOTO or GOSUB in ON statement!"L]; inputLine.length _ index; IF GetToken[] THEN Expression[] ELSE ParseError["Missing expression in ON command!"L]; IF haveToken THEN ParseError["Extra token before GOTO or GOSUB in ON statement!"L]; inputLine.length _ savedLength; IF GetToken[] THEN SELECT TRUE FROM String.EquivalentString[token, "GOTO"L] => AppendByte[lineCodeCm, BasicOps.OnGoTo]; String.EquivalentString[token, "GOSUB"L] => AppendByte[lineCodeCm, BasicOps.OnGoSub]; ENDCASE => ParseError["Unrecognized word in ON command!"L] ELSE ParseError["Missing GOTO or GOSUB in ON command!"L]; DO ParseLineNumber[]; IF ~GetToken[] THEN EXIT; IF token[0] # ', THEN ParseError["Missing comma in ON command!"L]; ENDLOOP; AppendPointer[lineCodeCm, LOOPHOLE[0]]; END; -- of OnCommand -- OptionBaseCommand: PROCEDURE = BEGIN -- newOptionBase: CARDINAL; -- IF GetToken[] AND token[0] = '0 OR token [0] = '1 THEN -- BEGIN -- newOptionBase _ String.StringToDecimal[token]; -- IF ~optionBaseCalled THEN -- {optionBaseCalled _ TRUE; -- optionBase _ newOptionBase;} -- ELSE IF optionBaseCalled AND optionBase # newOptionBase THEN -- IODefs.WriteLine["OPTION BASE has already been set."L]; -- END -- ELSE IF ~haveToken THEN ErrorCode["Missing OPTION BASE number."L] -- ELSE ErrorCode["OPTION BASE must be 0 or 1."L]; END; -- of OptionBaseCommand -- PauseCommand: PROCEDURE = BEGIN IF ~isProgramLine THEN ParseError["STOP command illegal outside of a program"L]; AppendByte[lineCodeCm, BasicOps.Stop]; END; -- of StopCommand -- PrintCommand: PROCEDURE = BEGIN realString: STRING _ [40]; quoteString: STRING _ [60]; printBlankLine: BOOLEAN _ TRUE; DO IF GetToken[] THEN BEGIN printBlankLine _ FALSE; SELECT TRUE FROM String.EquivalentString[token, "USING"L] => UsingCommand[]; String.EquivalentString[token, "TAB"L] => TabCommand[]; charTablePtr[token[0]] = statementSeparator => EXIT; ENDCASE => {Expression[]; AppendByte[lineCodeCm, BasicOps.Print]}; SELECT TRUE FROM inputLineIndex = inputLine.length OR ~haveToken => BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 255]; AppendByte[lineCodeCm, BasicOps.Tab]; EXIT; END; token[0] = ', => BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 254]; AppendByte[lineCodeCm, BasicOps.Tab]; END; token[0] = '; => NULL; ENDCASE => ParseError["Illegal PRINT command."L]; END ELSE IF printBlankLine THEN BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 255]; AppendByte[lineCodeCm, BasicOps.Tab]; EXIT; END ELSE IF inputLineIndex = inputLine.length OR token[0] = statementSeparatorChar THEN EXIT; ENDLOOP; NextStatement[]; END; -- of PrintCommand -- QuitCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Quit]; END; -- of QuitCommand -- QuitSignal: PUBLIC SIGNAL = CODE; RadianMode: PROCEDURE = BEGIN trigMode _ radians; END; -- of RadianMode -- ReadCommand: PROCEDURE = BEGIN varPtr: VariablePtr; savedIndex, nIndices: CARDINAL; DO CheckForVariable[]; varPtr _ LookUpVariable[token]; AppendByte[lineCodeCm, BasicOps.Read]; nIndices _ 0; WITH v: varPtr SELECT FROM builtInFunction => ParseError["Unrecognized keyword!"L]; numeric => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '( THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; string => BEGIN savedIndex _ inputLineIndex; IF GetToken[] AND token[0] = '[ THEN nIndices _ ParseSubscripts[] ELSE inputLineIndex _ savedIndex; END; ENDCASE; SELECT nIndices FROM 0 => AppendByte[lineCodeCm, BasicOps.PopVal]; 1 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str1Pop, ENDCASE => BasicOps.Arr1Pop]; 2 => AppendByte[lineCodeCm, WITH varPtr SELECT FROM string => BasicOps.Str2Pop, ENDCASE => BasicOps.Arr2Pop]; ENDCASE => ParseError["Can't happen."L]; AppendPointer[lineCodeCm, varPtr]; IF ~GetToken[] THEN EXIT; IF token[0] # ', THEN ParseError["Missing comma in READ statement!"L]; ENDLOOP; END; -- of ReadCommand -- RemCommand: PROCEDURE = BEGIN END; -- of RemCommand -- RenumberCommand: PROCEDURE = -- This procedure has not been updated -- BEGIN textStartIndex: CARDINAL _ inputLineIndex; i: CARDINAL; previousPtr: ProgramLineDescPtr _ NIL; currentPtr: ProgramLineDescPtr _ programLineDescHead; numberCount: CARDINAL _ 0; firstNumber, bumpNumber: CARDINAL _ 10; startNumber, endNumber, thisNumber: CARDINAL; numberString: STRING _ [10]; FOR i _ textStartIndex, i + 1 UNTIL i = inputLine.length OR inputLine[i] IN ['0..'9] DO ENDLOOP; UNTIL i = inputLine.length DO UNTIL i = inputLine.length OR inputLine[i] ~IN ['0..'9] DO String.AppendChar[numberString, inputLine[i]]; i _ i + 1; ENDLOOP; thisNumber _ String.StringToDecimal[numberString]; numberCount _ numberCount + 1; SELECT numberCount FROM 1 => firstNumber _ thisNumber; 2 => bumpNumber _ thisNumber; 3 => startNumber _ thisNumber; 4 => endNumber _ thisNumber; ENDCASE =>BEGIN IODefs.WriteLine["Your RENUMBER command contains too many numbers!"]; RETURN; END; FOR i _ i, i + 1 UNTIL i = inputLine.length OR inputLine[i] IN ['0..'9] DO ENDLOOP; ENDLOOP; IF numberCount = 3 OR numberCount = 4 THEN UNTIL currentPtr = NIL OR currentPtr.lineNumber = startNumber DO previousPtr _ currentPtr; currentPtr _ currentPtr.next; ENDLOOP; IF currentPtr = NIL THEN BEGIN IODefs.WriteString["Your program does not contain line number "]; IODefs.WriteDecimal[startNumber]; IODefs.WriteLine[""]; RETURN; END ELSE --Renumber currentPtr.lineNumbers BEGIN currentPtr.lineNumber _ firstNumber; previousPtr _ currentPtr; currentPtr _ currentPtr.next; UNTIL currentPtr = NIL OR currentPtr.lineNumber = endNumber DO currentPtr.lineNumber _ previousPtr.lineNumber + bumpNumber; previousPtr _ currentPtr; currentPtr _ currentPtr.next; ENDLOOP; END; NextStatement[]; END; -- of RenumberCommand -- RestoreCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Restore]; END; -- of RestoreCommand -- ReturnCommand: PROCEDURE = BEGIN AppendByte[lineCodeCm, BasicOps.Return]; END; -- ReturnCommand -- RunCommand: PROCEDURE = BEGIN IF GetToken[] THEN Expression[] ELSE BEGIN AppendByte[lineCodeCm, BasicOps.PushI]; AppendByte[lineCodeCm, 0]; END; AppendByte[lineCodeCm, BasicOps.Run]; END; -- of RunCommand -- TabCommand: PROCEDURE = BEGIN IF GetToken[] AND token[0] = '( THEN BEGIN Expression[]; -- token should now be a comma or semicolon -- IF token[0] # ', AND token[0] # '; THEN BEGIN inputLineIndex _ inputLine.length; ParseError["TAB statement missing a comma (,) or a semicolon (;)"L]; END; AppendByte[lineCodeCm, BasicOps.Tab]; END ELSE ParseError["TAB statement missing left parenthesis."L]; END; -- of TabCommand -- UsingCommand: PROCEDURE = BEGIN IF ~GetToken[] THEN ParseError["Missing USING line number!"L]; IF token[0] = '" THEN Storage.FreeString[ScanQuotedString[]]; [] _ GetToken[]; END; -- of UsingCommand -- END. -- of BasicCommand --(1792)\f1