PASS1

Pass 1: parsing, symbol table and code generation. Each section's comment stands above it, each line's comments beside it; point at a name for its meaning; line numbers after GOTO, GOSUB and THEN are links.

Sections (102)
  1. 10 DECLARATIONS: INTEGER VARIABLES, ARRAYS AND THE COMMON BLOCK
  2. 200 PASS 1 OF THE COMPILER
  3. 690 START
  4. 770 STATEMENT LOOP: START A NEW LINE
  5. 780 NEXT STATEMENT ON THE LINE
  6. 1000 END
  7. 1100 FOR V=E1 TO E2 [STEP E3]
  8. 1400 NEXT [V[,V]...]
  9. 1500 DATA
  10. 1800 INPUT ["PROMPT";] V[,V]...
  11. 2100 DIM: SET THE DIMENSIONS OF EACH ARRAY (CONSTANTS ONLY); NO CODE
  12. 2200 READ A DIMENSION LIST INTO THE SYMBOL'S ENTRY; AN ARRAY MAY BE DIMENSIONED ONLY ONCE AND B
  13. 2500 READ V[,V]...
  14. 2600 PLOT X,Y / HLIN X1,X2 AT Y / VLIN Y1,Y2 AT X
  15. 2800 HPLOT [TO] X,Y [TO X,Y]...
  16. 3100 DRAW / XDRAW SHAPE [AT X,Y]
  17. 3300 ONERR GOTO LINE
  18. 3400 RESUME
  19. 3500 LET (ALSO A STATEMENT THAT BEGINS WITH A NAME)
  20. 3590 IF ... THEN LINE / GOTO LINE: BEQ OVER A JMP TO THE LINE
  21. 3650 GOTO LINE: JMP TO THE LINE (CHAINED UNTIL PASS 2 KNOWS ITS ADDRESS)
  22. 3700 RUN
  23. 3800 IF EXPRESSION THEN ...
  24. 4000 GOSUB LINE: JSR TO THE LINE
  25. 4040 IF ... THEN RETURN: BEQ OVER AN RTS
  26. 4100 RETURN: RTS
  27. 4120 AFTER AN UNCONDITIONAL TRANSFER: THE REST OF THE LINE IS NOT REACHED
  28. 4200 REM: REM! STARTS A COMPILER DIRECTIVE, ANY OTHER REMARK IS SKIPPED
  29. 4380 REM! CLEAR COMMON / REM! CLEAR CHAIN
  30. 4510 REM! USECOMMON / REM! DEFCOMMON LIST
  31. 4900 AFTER A NAME IN A DECLARATION LIST
  32. 5100 MATCH THE KEYWORD IN WL$ AGAINST THE SOURCE, LETTER BY LETTER (SPACES ALLOWED); A MISMATCH
  33. 5200 SKIP SPACES
  34. 5300 STOP / NEW: CALL THE LIBRARY; WHAT FOLLOWS ON THE LINE IS NOT REACHED
  35. 5400 ON EXPRESSION GOTO / GOSUB LINE[,LINE]...
  36. 5600 WAIT ADDRESS,MASK[,MASK]
  37. 5800 DEF FN NAME(PARAMETER)=EXPRESSION
  38. 6100 POKE ADDRESS,VALUE
  39. 6200 PRINT
  40. 6400 GET V
  41. 6500 EXPECT A COMMA, ELSE THE STATEMENT IS FINISHED
  42. 6600 CALL / HIMEM: (ONE ARGUMENT, REAL ENTRY)
  43. 6700 STATEMENTS WITH ONE ARGUMENT
  44. 6800 POP / CLEAR / STATEMENTS WITHOUT ARGUMENTS
  45. 6830 END OF THE STATEMENT
  46. 6870 END OF THE PROGRAM
  47. 6950 WARNING
  48. 7100 SKIP TO THE NEXT COLON OUTSIDE QUOTES OR THE END OF THE LINE
  49. 7200 EXPECT = / ( / ) / , / THE CHARACTER IN XF; ELSE A SYNTAX ERROR
  50. 7530 FATAL ERRORS: NAME THE KIND IN WL$
  51. 7720 REPORT A FATAL ERROR, SHOW THE LINE WITH !ERR!, PAUSE IF ASKED; NO MORE CODE IS WRITTEN
  52. 7990 CONVERT THE DIGITS IN WL$ TO A NUMBER (A BAD NUMBER SETS N5)
  53. 8100 LIST THE LINE IN THE LISTING BUFFER
  54. 8200 NEXT TOKEN
  55. 8220 START A LINE
  56. 8490 READ ONE BYTE OF THE SOURCE FILE INTO IV
  57. 8600 LINE NUMBER REFERENCE: FIND OR ENTER THE LINE'S SYMBOL
  58. 8800 SCAN A NUMBER INTO WL$
  59. 9000 NAME WITH ITS TYPE AND SUBSCRIPTS: AN OPERAND
  60. 9200 NAME WITH ITS TYPE SUFFIX: K4 = -1 FOR %, -2 FOR $, ELSE -3
  61. 9500 SCAN A NAME
  62. 9600 ARRAY ELEMENT
  63. 10100 FUNCTION ARGUMENTS, AS DESCRIBED IN F()
  64. 10500 STRING LITERAL
  65. 10900 EXPRESSIONS
  66. 11310 PARSER
  67. 12210 NUMERIC CONSTANT
  68. 12440 NUMERIC FUNCTION CALL (SGN TO LEN, VAL, ASC)
  69. 12540 FN NAME(ARGUMENT)
  70. 13200 TWO-CHARACTER RELATIONS
  71. 13500 REDUCE WHILE THE OPERATOR ON THE STACK HAS A HIGHER PRIORITY THAN THE ONE ARRIVING (OE())
  72. 14000 PARSE STACK: PUSH AN OPERATOR, POP, PUSH AND POP AN OPERAND
  73. 14400 STORE A TRIPLE IN TP()
  74. 14800 VARIABLE SYMBOL
  75. 14900 FN SYMBOL: FIND OR ENTER THE FUNCTION'S NAME IN CHAINS 1-4
  76. 15100 ALLOCATE ML WORDS OF THE SYMBOL TABLE
  77. 15300 EMIT A VARIABLE OR CONSTANT ROUTINE CALL
  78. 15400 EMIT AN OPCODE AND A CHAINED REFERENCE (LINE OR FN)
  79. 15450 EMIT A WORD
  80. 15600 EMIT A BYTE
  81. 15700 WRITE TO THE LINE NUMBER FILE / PATCH A WORD IN THE OBJECT FILE
  82. 16000 FILE HELPERS
  83. 16300 RESUME/DEBUG
  84. 16400 EMIT A JSR TO CALL TABLE ENTRY CI; THE ENTRY 3 BYTES LOWER SERVES THE OTHER ARGUMENT TYPE
  85. 16700 EMIT A JMP TO CALL TABLE ENTRY CI
  86. 16800 TEMPORARIES
  87. 16900 FREE A TEMPORARY
  88. 17000 END OF DEF FN: THE FUNCTION'S TEMPORARIES ARE NOT USED AGAIN
  89. 17100 GENERATE THE CODE OF AN ASSIGNMENT'S VALUE
  90. 17200 CODE GENERATOR
  91. 17550 BY OPERATION
  92. 17590 + * : APPLY THE OPERAND IN MEMORY TO THE ACCUMULATOR
  93. 18100 AND / OR
  94. 18400 COMPARISONS
  95. 18900 ARRAY ELEMENT: PUSH ALL SUBSCRIPTS BUT THE FIRST, LAST TO FIRST
  96. 19060 STRING COMPARISONS, LIKEWISE
  97. 19810 WHERE DOES THE RESULT GO: THE NEXT TRIPLE THAT USES IT, OR A TEMPORARY
  98. 19960 A STRING RESULT IS KEPT IF THE NEXT STRING OPERATION USES IT, ELSE SAVED IN A STRING TEMPO
  99. 20300 STORE THE RESULT OF AN EXPRESSION IN THE TARGET
  100. 20500 LOAD OR APPLY AN OPERAND
  101. 20800 SET THE FLAGS FOR IF
  102. 20900 COMPILATION TERMINATED: DELETE THE OBJECT FILE AND RESTORE DOS

10DECLARATIONS: INTEGER VARIABLES, ARRAYS AND THE COMMON BLOCK

10REM ! INTEGER MN,EL,SC

INTEGER VARIABLES

EL IS LIBRARY ROUTINE ($0947) THAT RESETS THE STACK, DROPPING EVERY PENDING GOSUB AND FOR, AND RESETS THE DATA POINTER; CALLED AFTER AN ERROR

MN IS DRIVE MOTOR-OFF SWITCH FOR THE BOOT SLOT

SC IS 1 IF THE SOURCE AND OBJECT FILES ARE ON THE BOOT DRIVE (MOTOR KEPT ON), ELSE 0

SC() IS SYMBOL TABLE: CHAIN HEADS, THEN ENTRIES LINKED THROUGH THEIR FIRST WORD

20REM ! INTEGER P8,N1,OO,O4

INTEGER VARIABLES

N1 IS RESUME/DEBUG CODE OPTION (1 = YES)

O4 IS COMPILATION LISTING OPTION (1 = YES)

OO IS PAUSE ON ERRORS OPTION (1 = YES)

P8 IS INTEGER ARITHMETIC OPTION (1 = YES)

30REM ! INTEGER QB,KV,WS,FC,C3

INTEGER VARIABLES

C3 IS COMMON KIND: -1 NONE, 0 DEFINE, 255 USE

FC IS 1 ONCE A FATAL ERROR HAS BEEN REPORTED (NO MORE CODE IS WRITTEN)

KV IS ADDRESS OF THE FIVE PACKED BYTES LEFT BY THE USR ROUTINE ($0371)

QB IS ADDRESS OF THE ROUTINE THAT READS ONE BYTE FROM THE OPEN FILE INTO IX ($037E)

WS IS ADDRESS OF THE ROUTINE THAT WRITES THE BYTE IN IX TO THE OPEN FILE ($0387)

40REM ! INTEGER VC,LB,CD,CI,SU

INTEGER VARIABLES

CD IS START OF THE COMMON BLOCK (THE PROGRAM START BEFORE COMMON MOVED IT)

CI IS INDEX OF THE ROUTINE IN THE CALL TABLE CC()

LB IS LIBRARY ADDRESS, STORED AS ADDRESS-32767

SU IS NEXT FREE PLACE FOR AN OPERATOR ON THE PARSE STACK (GROWS UP)

VC IS VARIABLES ADDRESS ASKED FOR, AS ADDRESS-32767, OR -32767 FOR END OF PROGRAM

50REM ! INTEGER VB,K4,TZ,J,OW,EO

INTEGER VARIABLES

EO IS 1 WHEN THE EXPRESSION IS COMPLETE

J IS INNER LOOP INDEX; 1 IF AN ARRAY WAS DIMENSIONED BEFORE

K4 IS TYPE CODE (-3 REAL, -2 STRING, -1 INTEGER, +22 FOR AN ARRAY), OR AN OPERATION NUMBER

OW IS BYTE TO WRITE TO THE OBJECT FILE

TZ IS SIZE OF THE SYMBOL TABLE (5350 WORDS)

VB IS VALUE PASSED TO AND FROM THE STACK AND SYMBOL ROUTINES (USUALLY A SYMBOL)

60REM ! INTEGER RN,SK,KD,FZ,UZ,NQ,D,K8,NB,SS,LH

INTEGER VARIABLES

D IS ENTRY ADJUSTMENT: 0, OR -3 FOR THE OTHER TYPE'S ENTRY

FZ IS WHICH FLAG TEST IF NEEDS: 0 INTEGER (LDA $A0/ORA $A1), 1 REAL (LDA $9D)

K8 IS LOOP INDEX

KD IS KIND OF THAT OPERAND (ITS TP(X,0) ENTRY)

LH IS NUMBER OF SOURCE LINES READ

NB IS OPERAND BEING LOADED OR APPLIED

NQ IS OPERATION CODE OF THE TRIPLE

RN IS 1 IF THE OPERANDS ARE USED AS REALS

SK IS SAVED OPERATION NUMBER

SS IS SAVED OPERATION NUMBER

UZ IS SIZE OF THE TRIPLE TABLE (100)

70REM ! INTEGER FQ,P3,BF,F,PE,RC,SJ,TG,DW

INTEGER VARIABLES

BF IS START OF THE LISTING BUFFER ($0280)

DW IS DOS STATE BYTE AT $AA52: POKED BEFORE EACH DIRECT FILE READ OR WRITE

F IS WHICH FILE DOS IS SET UP FOR: 1 SOURCE (READ), 2 OBJECT (WRITE), 3 LINE NUMBER FILE

F() IS ARGUMENT DESCRIPTION OF A FUNCTION: F(0) NUMBER, F(1..3) TYPES, F(4) ARGUMENT BEING READ

FQ IS 1 TO WRITE TO THE LINE NUMBER FILE EVEN AFTER A FATAL ERROR

P3 IS BYTE WAITING TO BE COPIED INTO THE LISTING BUFFER

PE IS LOW BYTE OF THE NEXT LINE LINK (A ZERO LINK ENDS THE PROGRAM)

RC IS 1 FOR THE STATEMENT RIGHT AFTER THEN (NO RESUME/DEBUG CALL)

SJ IS CODE ADDRESS OF THAT STORE

TG IS 1 WHEN THE EXPRESSION IS THE VALUE OF AN ASSIGNMENT

80REM ! INTEGER HW,NG,NK,NU,MX,LQ,OH,UV,S8,V3,T9,O2,N5,EP,SF

INTEGER VARIABLES

EP IS TYPE OF THE EXPRESSION: 1 INTEGER, 2 STRING, 3 REAL

HW IS LAST CHAIN HEAD IN SC(); ENTRIES ARE ALLOCATED ABOVE IT

LQ IS ADDRESS OF THE ROUTINE THAT LISTS THE TOKENIZED LINE IN THE INPUT BUFFER ($038D)

MX IS DRIVE MOTOR-ON SWITCH FOR THE BOOT SLOT ($C089+SLOT*16), TOUCHED TO KEEP THE DRIVE SPINNING

N5 IS 1 IF THE LAST SCAN FOUND NO NAME OR NO NUMBER

NG IS NUMBER OF CONSTANT HASH CHAINS (32)

NK IS NUMBER OF LINE NUMBER HASH CHAINS (32)

NU IS NUMBER OF VARIABLE HASH CHAINS IN THE SYMBOL TABLE (32)

O2 IS OPERATION CODE USED TO SELECT THE GENERATOR, OR A SUBSCRIPT COUNT

OH IS INTEGER CONSTANTS OPTION (1 = YES)

S8 IS SIZE OF THE PARSE STACK (100)

SF IS TRIPLE BEING EXAMINED WHEN DECIDING WHERE A RESULT GOES

T9 IS SCRATCH: A SYMBOL OR SIZE BEING WORKED ON

UV IS ADDRESS OF THE USR ROUTINE THAT PACKS A NUMBER INTO FIVE BYTES ($0377)

V3 IS NEXT FREE PLACE FOR AN OPERAND ON THE PARSE STACK (GROWS DOWN)

90REM ! INTEGER MJ,IZ,D3,RI,U,VO,LM,K0

INTEGER VARIABLES

D3 IS 1 AFTER AN UNCONDITIONAL TRANSFER: FURTHER STATEMENTS ON THE LINE ARE NOT REACHED

IZ IS 2 WHILE NAMES ARE BEING DECLARED INTEGER (ALSO AFTER INTEGER *), ELSE 0

K0 IS NEXT FREE WORD IN THE SYMBOL TABLE SC()

LM IS LENGTH OF THE RUNTIME LIBRARY IN BYTES (4013)

MJ IS NEXT BYTE OF THE SOURCE LINE (ONE BYTE LOOKAHEAD); -1 AT END OF PROGRAM

RI IS SAVED ID DURING AN INTEGER DECLARATION LIST

U IS OPERATION NUMBER FOR A MEMORY OPERAND, OR THE OPERAND SAVED FOR LATER

VO IS FIRST VARIABLE CHAIN HEAD IN SC() (9; 1-4 HOLD FN AND LINE SYMBOLS, 5-8 TEMPORARIES)

100REM ! INTEGER S3,XF,GZ,T5,BO,U7,N4,IX,PC,ED

INTEGER VARIABLES

BO IS START OF THE TEXT OF A STRING LITERAL OR DATA ITEM IN THE LISTING BUFFER

ED IS OBJECT FILE BASE: FILE POSITION = PC - ED (THE FILE STARTS WITH THE BSAVE HEADER)

GZ IS INSIDE DEF FN: NAME HASH OF THE PARAMETER, ELSE 0

IX IS ADDRESS OF THE ONE-BYTE TRANSFER CELL FOR QB AND WS ($0376)

N4 IS NUMBER OF DIMENSIONS IN A DIM OR DECLARATION

PC IS ADDRESS OF THE NEXT OBJECT CODE BYTE, AS ADDRESS-32767

S3 IS SAVED SYMBOL (FOR LOOP VARIABLE), OR THE NUMBER OF LINES IN AN ON LIST

T5 IS INSIDE DEF FN: THE PARAMETER'S SYMBOL

U7 IS TOKEN NUMBER OF THE STATEMENT (TOKEN-128), THEN THE CALL TABLE INDEX IT SELECTS

XF IS TOKEN OR CHARACTER EXPECTED NEXT (SYNTAX CHECK)

110REM ! INTEGER RV,LK,FD,SE,LZ,CC

INTEGER VARIABLES

CC IS ADDRESS OF THE LINK WORD OF THE LAST DATA BLOCK (DATA BLOCKS ARE CHAINED)

CC() IS CALL TABLE: ADDRESSES OF THE LIBRARY AND ROM ROUTINES, BY INDEX

FD IS 1 IF THE FLAGS ALREADY REFLECT THE RESULT (IF NEEDS NO TEST)

LK IS OPERATION OF THE LAST TRIPLE (TELLS THE STORE WHAT IS IN THE ACCUMULATOR)

LZ IS LEFT OPERAND OF THE TRIPLE

RV IS 1 IF THE RESULT IS REAL

SE IS 1 WHEN THE EXPRESSION'S VALUE MUST BE REAL (A REAL TARGET OR A FUNCTION BODY)

120REM ! INTEGER T0,IV,BM,D2,WN,TP,BX

INTEGER VARIABLES

BM IS NEXT FREE BYTE IN THE LISTING BUFFER

BX IS 1 IF THE OPERATOR BEING REDUCED TAKES TWO OPERANDS

D2 IS DECLARATION STATE: 2 BEFORE ANY STATEMENT, 1 AFTER COMMON, 0 AFTER A STATEMENT

IV IS BYTE JUST READ FROM THE SOURCE FILE

T0 IS CURRENT TOKEN OR CHARACTER OF THE SOURCE LINE

TP IS OPERATOR ON TOP OF THE PARSE STACK

TP() IS TRIPLE TABLE: TP(I,0) OPERATION OR OPERAND KIND, TP(I,1) LEFT, TP(I,2) RIGHT

WN IS TYPE THE CALL TABLE ENTRY IS FOR: 1 INTEGER, 3 REAL

130REM ! INTEGER TU,U2,XK,RH,HY,ML,BK,J3,UR,L,KX,FG,PN,TB,DP(5,1),SC(5350)

INTEGER VARIABLES

BK IS END OF THE LISTING BUFFER; A LINE THAT REACHES IT IS TOO LONG

DP() IS DOS PATCH TABLE: DP(I,0) ADDRESS (AS A SIGNED WORD, ADDRESS-65536), DP(I,1) ORIGINAL BYTE

FG IS 1 IF THE FOR LOOP VARIABLE IS REAL, 0 IF IT IS AN INTEGER

HY IS NAME HASH (99*FIRST CHARACTER+SECOND), OR LINE NUMBER-32767

J3 IS LAST VARIABLE STORED BY THE CODE (A LOAD RIGHT AFTER IT IS LEFT OUT)

KX IS FIRST CONSTANT CHAIN HEAD IN SC()

L IS FIRST LINE NUMBER CHAIN HEAD IN SC()

ML IS SCRATCH

PN IS ADDRESS TO PATCH WITH THE CURRENT CODE ADDRESS

RH IS RIGHT OPERAND OF THE TRIPLE

TB IS TRIPLE BEING GENERATED

TU IS SYMBOL OF THE EXPRESSION'S RESULT

U2 IS NUMBER OF TRIPLES IN TP() PLUS ONE

UR IS PROGRAM START, STORED AS ADDRESS-32767; MOVED UP BY COMMON DECLARATIONS

XK IS CALL TABLE INDEX FOR THE OPERANDS IN THE OTHER ORDER (SWAPPED COMPARISON)

140REM ! INTEGER OE(16,2),F(4),SZ(100),TP(101,2),CC(135)

INTEGER VARIABLES

OE() IS OPERATOR TABLE: OE(I,0) TOKEN, OE(I,1) PRIORITY ON THE STACK, OE(I,2) PRIORITY ARRIVING

SZ() IS PARSE STACK: OPERATORS FROM THE BOTTOM, OPERANDS FROM THE TOP

150REM ! USECOMMON NU,NG,NK,VO,KX,L,HW,MX,MN,DW,EL,LM,UV,KV,QB,WS,IX,LQ,LB,UR,VC,PC,LH,CD,CC,ED,SC,O4,OO,N1,P8,OH,FC,C3,DP(5,1),SC(5350),BP$,DI$,OP$,CO$,RV$,WO$,SI$,OD$,LN$,DN$,SB$,OO$

COMMON BLOCK, IN THE ORDER IT IS LAID OUT: NUMBERS FIRST, THEN STRINGS. THE PASSES SHARE IT, SO EVERY PASS DECLARES IT THE SAME WAY

BP$ IS TWO BELLS, SOUNDED BEFORE EACH ERROR MESSAGE

CO$ IS DOS CLOSE COMMAND

DI$ IS CONTROL-D, THE DOS COMMAND PREFIX

DN$ IS SLOT AND DRIVE OF THE BOOT DRIVE (",S6,D1")

LN$ IS NAME OF THE LINE NUMBER FILE ("CLINENUM")

OD$ IS OBJECT FILE NAME

OO$ IS SLOT AND DRIVE OF THE OBJECT FILE

OP$ IS DOS OPEN COMMAND

RV$ IS DOS READ COMMAND

SB$ IS SLOT AND DRIVE OF THE SOURCE FILE

SI$ IS SOURCE FILE NAME

WO$ IS DOS WRITE COMMAND

200PASS 1 OF THE COMPILER: READS THE TOKENIZED SOURCE PROGRAM A BYTE AT A TIME, CHECKS ITS SYNTAX, BUILDS THE SYMBOL TABLE IN SC() AND WRITES THE OBJECT CODE. REFERENCES THAT ARE NOT YET KNOWN (LINES, VARIABLE ROUTINES) ARE WRITTEN AS BACKWARD CHAINS FOR PASS 2. SET UP THE BUFFERS AND TABLES

200WL$ = "COPYRIGHT(C)1981,MICROSOFT"

THE COPYRIGHT NOTICE; WL$ IS THEN THE WORK STRING

WL$ IS WORK STRING: KEYWORD BEING MATCHED, DIGITS OF A NUMBER, NAME OF AN ERROR

210BF = 640

THE LISTING BUFFER IS THE INPUT BUFFER $0280-$036F

220BK = 880

THE LISTING BUFFER ENDS AT $036F; A LINE THAT FILLS IT IS TOO LONG

230TZ = 5350

THE SYMBOL TABLE SC() HAS 5350 WORDS

240K0 = HW + 1

SYMBOL TABLE ENTRIES ARE ALLOCATED FROM THE WORD AFTER THE LAST CHAIN HEAD

250UZ = 100

AT MOST 100 TRIPLES PER EXPRESSION

260U2 = 1

THE TRIPLE TABLE IS EMPTY; TRIPLES ARE NUMBERED FROM 1

270SU = 0

THE OPERATOR SIDE OF THE PARSE STACK IS EMPTY

280S8 = 100:V3 = S8

THE PARSE STACK HAS 100 PLACES; THE OPERAND SIDE STARTS AT THE TOP AND GROWS DOWN

290GZ = 0

NOT INSIDE DEF FN

300U2 = 1

(THE TRIPLE TABLE IS EMPTIED AGAIN)

310CC = - 32767

NO DATA STATEMENT YET: THE DATA CHAIN IS EMPTY

320FOR K8 = 0 TO 135

COPY THE CALL TABLE OUT OF THE COMMON SYMBOL TABLE AREA WHERE PASS 0 LEFT IT

330CC(K8) = SC(150 + K8)

ENTRY K8 OF THE CALL TABLE, FROM SC(150) TO SC(285)

340NEXT K8
350FOR K8 = 0 TO 16

COPY THE OPERATOR TABLE LIKEWISE

360FOR J = 0 TO 2

THREE VALUES FOR EACH OF THE 17 OPERATORS

370OE(K8,J) = SC(K8 * 3 + 300 + J)

FROM SC(300) TO SC(350): TOKEN, STACK PRIORITY, ARRIVING PRIORITY

380NEXT J,K8
390DEF FN LT(X) = X >= 65 AND X <= 90

FN LT(X): TRUE IF X IS A LETTER

400DEF FN DG(X) = X >= 48 AND X <= 57

FN DG(X): TRUE IF X IS A DIGIT

410DEF FN OS(X) = X >= 200 AND X <= 209 OR X = 198 OR X >= 235

FN OS(X): TRUE IF X IS AN OPERATOR TOKEN (+ - * / ^ AND OR > = < NOT, OR A TWO-CHARACTER RELATION)

420DEF FN OE(X) = FN OS(X) OR X = 40 OR X = 41 OR X = 0

FN OE(X): TRUE IF X IS AN OPERATOR, A PARENTHESIS OR THE END OF THE LINE

430DEF FN NU(X) = X >= 210 AND X <= 227 OR X = 229 OR X = 230

FN NU(X): TRUE IF X IS A NUMERIC FUNCTION TOKEN (SGN TO LEN, VAL, ASC)

440DEF FN SF(X) = X >= 231 AND X <= 234 OR X = 228

FN SF(X): TRUE IF X IS A STRING FUNCTION TOKEN (STR$, CHR$, LEFT$, RIGHT$, MID$)

450DEF FN ES(X) = X = 58 OR X = 0

FN ES(X): TRUE IF X ENDS A STATEMENT (COLON OR END OF LINE)

460DEF FN UB(X) = X + 32767

FN UB(X): X STORED AS A WORD (X+32767)

470DEF FN IV(X) = TP(X,0) = - 8 OR TP(X,0) = - 9 OR TP(X,0) = - 1

FN IV(X): TRUE IF TRIPLE X GIVES AN INTEGER (INTEGER TEMPORARY, INTEGER VARIABLE OR RESULT)

480DEF FN LO(X) = X < 14 OR X > 28 OR X = 17

FN LO(X): TRUE IF OPERATION X TAKES ITS LEFT OPERAND FROM THE ACCUMULATOR

490DEF FN RT(X) = X < 16 OR X >= 19 AND X <= 21 OR X = 18 OR X > 50

FN RT(X): TRUE IF OPERATION X TAKES ITS RIGHT OPERAND FROM THE ACCUMULATOR

500DEF FN IA(X) = TP(X,0) = - 5 OR TP(X,0) = - 9

FN IA(X): TRUE IF TRIPLE X IS IN THE ACCUMULATOR

510PRINT OP$;SI$;SB$

OPEN THE SOURCE FILE ON ITS DRIVE

520PRINT OP$;OD$;OO$

OPEN THE OBJECT FILE ON ITS DRIVE

530PRINT OP$;LN$;DN$

OPEN THE LINE NUMBER FILE ON THE BOOT DRIVE

540F = 0

NO FILE IS SET UP FOR READING OR WRITING YET

550FQ = 0

LINE NUMBER FILE RECORDS ARE WRITTEN ONLY WHILE FQ IS SET

560FC = 0

NO FATAL ERROR YET

570LH = 0

NO SOURCE LINES READ YET

580D2 = 2

DECLARATIONS (REM! LINES) ARE ALLOWED UNTIL THE FIRST STATEMENT

590CD = UR

THE COMMON BLOCK BEGINS AT THE PROGRAM START; EACH COMMON DECLARATION MOVES UR UP PAST IT

600C3 = - 1

NO COMMON DECLARATION YET

610SE = 0

NO STORE THROUGH AN ARRAY ELEMENT ADDRESS IS PENDING

620TG = 0

NOT COMPILING AN ASSIGNMENT

630ED = UR - 4

THE OBJECT FILE BEGINS WITH THE 4-BYTE ADDRESS AND LENGTH OF A BINARY FILE, SO THE PROGRAM'S FIRST BYTE IS AT FILE POSITION 4

640PC = - 32767

COUNT FROM ADDRESS 0 WHILE THE FIRST BYTES OF THE FILE ARE RESERVED

650OW = 0

24 ZERO BYTES RESERVE THE FILE'S ADDRESS AND LENGTH AND THE PROGRAM'S FIRST 20 BYTES (THE CALL TO THE LIBRARY AND THE HEADER), WHICH ARE WRITTEN AT THE END OF THE COMPILATION

660FOR K8 = 1 TO 24

K8 COUNTS THE 24 BYTES

670GOSUB 15620

WRITE ONE ZERO BYTE

680NEXT K8

690START: THE CODE BEGINS 20 BYTES INTO THE PROGRAM (AFTER THE CALL TO THE LIBRARY AND THE HEADER); READ THE FIRST LINE'S LINK AND NUMBER

690PC = UR + 20
700GOSUB 8490

THE TWO LENGTH BYTES AT THE START OF THE PROGRAM FILE ARE READ AND NOT USED

710GOSUB 8490

THE SECOND LENGTH BYTE

720GOSUB 8490

THE LOW BYTE OF THE FIRST LINE'S LINK

730GOSUB 8450

THE HIGH BYTE OF THE LINK (A ZERO LINK MEANS NO LINES) AND THE LOW BYTE OF THE LINE NUMBER

740IF - 1 = MJ THEN GOSUB 16000: PRINT : PRINT : PRINT BP$;"*****ERROR": PRINT "EMPTY PROGRAM FILE": PRINT : PRINT : GOTO 20900

NO LINES: REPORT IT AND STOP THE COMPILATION

750P3 = 0

THERE IS NO PREVIOUS TOKEN TO COPY INTO THE LISTING BUFFER

760BM = BF

THE LISTING BUFFER IS EMPTY

770STATEMENT LOOP: START A NEW LINE

770GOSUB 8220

READ THE LINE NUMBER AND THE FIRST TOKEN

780NEXT STATEMENT ON THE LINE

780RC = 0

THIS STATEMENT IS NOT THE ONE RIGHT AFTER THEN

790IF FN ES(T0) THEN 6840

COLON OR END OF LINE: AN EMPTY STATEMENT

800IF T0 <> 178 THEN D2 = 0

ANY STATEMENT BUT REM ENDS THE DECLARATIONS

810IF T0 < 128 OR T0 > 191 THEN 910

NOT A KEYWORD: AN ASSIGNMENT

820IF D3 AND (T0 <> 131 AND T0 <> 178) THEN 6950

NOT REACHED: SKIP IT WITH A WARNING (DATA AND REM ARE STILL COMPILED)

830CI = T0 - 128:U7 = CI

CI AND U7 = TOKEN-128: FOR MOST STATEMENTS THE CALL TABLE ENTRY WITH THIS INDEX IS THE STATEMENT'S LIBRARY OR ROM ROUTINE (FOR EXAMPLE 10 = PR#, 23 = HOME, 61 = CLEAR)

840ML = T0 - 127

ML = 1 FOR END (128) UP TO 64 FOR NEW (191)

850GOSUB 8200

READ THE TOKEN AFTER THE KEYWORD

DISPATCH ON THE KEYWORD

870ML = ML - 21

THE NEXT 21 KEYWORDS: XDRAW (149) TO SPEED= (169)

890ML = ML - 21

THE LAST 22: LET (170) TO NEW (191); DEL, SHLOAD, TRACE, NOTRACE, LOMEM:, RECALL, STORE, &, LOAD, SAVE, CONT AND LIST ARE NOT SUPPORTED (6950)

910IF FN LT(T0) THEN 3500

A LETTER STARTS AN ASSIGNMENT WITHOUT LET

920GOTO 7530

ANYTHING ELSE CANNOT START A STATEMENT

1000END: JMP TO THE LIBRARY'S END ROUTINE; WHAT FOLLOWS ON THE LINE IS NOT REACHED

1000GOSUB 16700

JMP TO CALL TABLE ENTRY 0, THE LIBRARY'S END ROUTINE ($1363)

1010GOTO 4120

THE REST OF THE LINE IS NOT REACHED

1100FOR V=E1 TO E2 [STEP E3]: INITIAL VALUE (WITH THE LOOP VARIABLE'S ADDRESS), LIMIT, STEP; INTEGER LOOPS USE THE INTEGER ENTRIES

1100GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

1110GOSUB 9400

THE LOOP VARIABLE (A SIMPLE NUMERIC VARIABLE); VB = ITS SYMBOL, K4 = ITS TYPE

1120S3 = VB

SAVE THE LOOP VARIABLE'S SYMBOL WHILE THE EXPRESSION IS COMPILED

1130FG = - 1 <> K4

FG = 1 FOR A REAL LOOP VARIABLE, 0 FOR AN INTEGER ONE

1140GOSUB 7200

EXPECT =

1150GOSUB 10900

THE INITIAL VALUE

1160K4 = 20 + FG + EP

THE OPERATION NUMBER OF THE CALL THAT STARTS THE LOOP: 21 INTEGER VARIABLE AND INTEGER VALUE, 22 REAL VARIABLE AND INTEGER VALUE, 23 INTEGER VARIABLE AND REAL VALUE, 24 BOTH REAL

1170VB = S3

THE LOOP VARIABLE AGAIN

1180GOSUB 15340

OPERATION K4 ON THE LOOP VARIABLE: PASS 2 MAKES IT A JSR TO THE LIBRARY'S LOOP START ENTRY FOR THAT OPERATION

1190GOSUB 15500

TWO MORE BYTES, FILLED BY PASS 2 WITH THE LOOP VARIABLE'S ADDRESS

1200XF = 193

EXPECT TO

1210GOSUB 7520
1220GOSUB 10900

THE LIMIT

1230IF FG THEN CI = 5: GOSUB 16400: GOTO 1260

REAL LOOP: CALL TABLE ENTRY 5, THE LIMIT FOR A REAL LOOP (REAL ENTRY, OR 3 LOWER FOR AN INTEGER LIMIT)

1240CI = 125

INTEGER LOOP: CALL TABLE ENTRY 125, THE LIMIT FOR AN INTEGER LOOP

1250GOSUB 16500

(INTEGER ENTRY, OR 3 LOWER FOR A REAL LIMIT)

1260IF T0 <> 199 THEN CI = 129 + FG: GOTO 6820

NO STEP: ENTRY 129 (INTEGER LOOP) OR 130 (REAL LOOP), A STEP OF 1

1270GOSUB 8200

SKIP STEP

1280GOSUB 10900

THE STEP

1290IF FG THEN CI = 3: GOTO 6630

REAL LOOP: ENTRY 3, THE STEP FOR A REAL LOOP

1300CI = 126

INTEGER LOOP: ENTRY 126, THE STEP FOR AN INTEGER LOOP

1310GOTO 6730

1400NEXT [V[,V]...]: ONE CALL PER VARIABLE, EACH FOLLOWED BY THE VARIABLE'S ADDRESS (0 FOR A BARE NEXT)

1400GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

1410IF FN ES(T0) THEN GOSUB 16530: GOTO 1450

NEXT WITHOUT A VARIABLE: JSR TO CALL TABLE ENTRY 2 (THE LIBRARY'S NEXT, $0A31), THEN A ZERO WORD

1420GOSUB 9400

THE NEXT VARIABLE IN THE LIST

1430K4 = 25

OPERATION 25 ON THE VARIABLE: PASS 2 MAKES IT A JSR TO THE LIBRARY'S NEXT

1440GOSUB 15340

[OPERATION 25][LINK TO THE PREVIOUS REFERENCE]

1450WF = 0

A WORD, THE VARIABLE'S ADDRESS (PASS 2 FILLS IT IN), OR 0 FOR A BARE NEXT

WF IS WORD TO WRITE TO THE OBJECT FILE (A LINK OR ADDRESS)

1460GOSUB 15500

(THE WORD)

1470GOSUB 6500

A COMMA CONTINUES THE LIST; ANYTHING ELSE ENDS THE STATEMENT

1480GOTO 1420

1500DATA: JUMP OVER THE ITEMS, EACH STORED AS LENGTH AND TEXT, ENDED BY 255 AND A LINK TO THE NEXT DATA BLOCK

1500GOSUB 15600

A JMP OVER THE ITEMS

1510WF = CC

ITS ADDRESS WORD IS CHAINED TO THE PREVIOUS DATA LINK THROUGH CC; PASS 2 RESOLVES THE CHAIN

1520CC = PC

CC = THE ADDRESS OF THIS WORD, THE LATEST LINK IN THE CHAIN

1530GOSUB 15450

WRITE THE WORD

1540GOSUB 5200

SKIP SPACES BEFORE THE NEXT ITEM

1550ML = 0

ML = 1 FOR A QUOTED ITEM

1560IF T0 = 34 THEN GOSUB 8200:ML = 1

A QUOTE OPENS A QUOTED ITEM

1570BO = BM

THE ITEM'S TEXT STARTS HERE IN THE LISTING BUFFER

1580IF T0 = 0 OR ML AND T0 = 34 OR (T0 = 44 OR T0 = 58) AND NOT ML THEN 1610

AN ITEM ENDS AT THE END OF THE LINE, AT ITS CLOSING QUOTE, OR (UNQUOTED) AT A COMMA OR COLON

1590GOSUB 8200

ANOTHER CHARACTER OF THE ITEM

1600GOTO 1580
1610GOSUB 10580

WRITE THE ITEM AS ITS LENGTH AND TEXT (QUOTES LEFT OUT)

1620GOSUB 5200

SPACES MAY FOLLOW THE ITEM

1630IF T0 = 44 THEN GOSUB 8200: GOTO 1540

A COMMA: ANOTHER ITEM

1640OW = 255

255 ENDS THE BLOCK

1650GOSUB 15620

WRITE THE 255

1660WF = CC

THE LINK TO THE NEXT DATA BLOCK, CHAINED THROUGH CC LIKE THE JMP

1670CC = PC

THIS WORD IS NOW THE LATEST LINK

1680GOSUB 15450
1690GOTO 6830

1800INPUT ["PROMPT";] V[,V]...

1800GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

1810GOSUB 16530

JSR TO CALL TABLE ENTRY CI (4, THE LIBRARY'S INPUT START, WHICH SAVES THE STATEMENT'S ADDRESS FOR A REENTER)

1820U7 = 39

CALL TABLE ENTRY 39 READS THE FIRST NUMBER, 40 THE FIRST STRING

1830IF T0 <> 34 THEN 1920

NO PROMPT

1840U7 = U7 + 3

AFTER A PROMPT: ENTRIES 42 (NUMBER) AND 43 (STRING)

1850GOSUB 10500

THE PROMPT, A STRING LITERAL; VB = ITS ADDRESS

1860CI = 28

JSR TO ENTRY 28, THE LIBRARY ROUTINE THAT PRINTS THE PROMPT, FOLLOWED BY THE LITERAL'S ADDRESS

1870GOSUB 16530

(JSR TO ENTRY 28)

1880WF = VB

THE LITERAL'S ADDRESS ...

1890GOSUB 15450

... AS A WORD

1900XF = 59

EXPECT ;

1910GOSUB 7520
1920GOSUB 9000

THE VARIABLE TO READ INTO

1930GOSUB 17100

ITS TYPE IN EP, AND THE CODE FOR AN ARRAY ELEMENT'S ADDRESS

1940CI = U7

THE READ ROUTINE FOR A NUMBER ...

1950IF EP = 2 THEN CI = U7 + 1

... OR A STRING (THE NEXT ENTRY)

1960GOSUB 16530

JSR TO THE READ ROUTINE

1970GOSUB 20300

STORE THE VALUE IN THE VARIABLE

1980IF T0 <> 44 THEN CI = 48: GOTO 6820

END OF THE LIST: ENTRY 48, THE LIBRARY ROUTINE THAT ENDS INPUT (?EXTRA IGNORED)

1990GOSUB 8200

SKIP THE COMMA

2000U7 = 44

FURTHER ITEMS: ENTRIES 44 (NUMBER) AND 45 (STRING)

2010GOTO 1920

2100DIM: SET THE DIMENSIONS OF EACH ARRAY (CONSTANTS ONLY); NO CODE

2100GOSUB 9200

THE ARRAY'S NAME AND TYPE

2110GOSUB 7300

EXPECT (

2120GOSUB 2200

ITS DIMENSIONS

2130GOSUB 6500

A COMMA CONTINUES THE LIST

2140GOTO 2100

2200READ A DIMENSION LIST INTO THE SYMBOL'S ENTRY; AN ARRAY MAY BE DIMENSIONED ONLY ONCE AND BEFORE IT IS USED WITH A DIFFERENT NUMBER OF SUBSCRIPTS

2200N4 = 0

N4 COUNTS THE DIMENSIONS

2210K4 = K4 + 22

THE ARRAY TYPE CODE (TYPE+22)

2220GOSUB 8800

THE DIGITS OF THE NEXT DIMENSION

2230IF N5 THEN 7570

NOT A NUMBER: THE DIMENSION MUST BE A CONSTANT

2240N4 = N4 + 1

COUNT THE DIMENSION

2250K8 = 1

CONVERT IT (RETURNING TO 2300)

2260GOTO 7990
2300IF N5 OR L1 < 0 OR L1 > 32767 THEN 7570

A DIMENSION FROM 0 TO 32767

2310IF N4 > 88 THEN 7570

AT MOST 88 DIMENSIONS

2320VB = L1

KEEP THE DIMENSION ON THE PARSE STACK

2330GOSUB 14200

(PUSH IT)

2340IF T0 = 44 THEN GOSUB 8200: GOTO 2220

A COMMA: ANOTHER DIMENSION

2350GOSUB 14800

FIND OR ENTER THE ARRAY'S SYMBOL

2360J = 0

J = 0: NOT DIMENSIONED BEFORE

2370IF K0 - 4 = VB THEN SC(K0) = N4:ML = N4 + 1: GOSUB 15200: GOTO 2400

A NEW SYMBOL (THE LAST ENTRY ALLOCATED): STORE THE NUMBER OF DIMENSIONS AND MAKE ROOM FOR THEM

2380IF SC(VB + 4) <> N4 THEN 7570

AN OLD SYMBOL MUST HAVE THE SAME NUMBER OF SUBSCRIPTS

2390IF SC(VB + 5) <> - 1 THEN J = 1

ITS FIRST DIMENSION IS SET (NOT -1): IT WAS DIMENSIONED BEFORE

2400T9 = VB

T9 = THE SYMBOL

2410FOR K8 = 1 TO N4

THE DIMENSIONS COME OFF THE STACK LAST FIRST

2420GOSUB 14300

THE NEXT DIMENSION FROM THE STACK

2430IF J AND SC(T9 + K8 + 4) <> VB THEN 7690

DIMENSIONED BEFORE WITH OTHER DIMENSIONS: REDEFINED

2440SC(T9 + K8 + 4) = VB

STORE THE DIMENSION IN THE SYMBOL'S ENTRY

2450NEXT K8
2460GOSUB 7400

EXPECT )

2470VB = T9

RETURN THE SYMBOL IN VB

2480RETURN

2500READ V[,V]...

2500GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

2510GOSUB 9000

THE VARIABLE TO READ INTO

2520GOSUB 17100

ITS TYPE IN EP, AND THE CODE FOR AN ARRAY ELEMENT'S ADDRESS

2530CI = U7

CALL TABLE ENTRY 7 READS A STRING ...

2540IF EP = 1 OR EP = 3 THEN CI = U7 - 1

... ENTRY 6 A NUMBER

2550GOSUB 16530

JSR TO THE READ ROUTINE

2560GOSUB 20300

STORE THE VALUE IN THE VARIABLE

2570GOSUB 6500

A COMMA CONTINUES THE LIST

2580GOTO 2510

2600PLOT X,Y / HLIN X1,X2 AT Y / VLIN Y1,Y2 AT X

2600GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

2610GOSUB 10900

THE FIRST VALUE (X, OR X1 / Y1)

2620CI = 60

CALL TABLE ENTRY 60 SAVES IT

2630GOSUB 16500
2640GOSUB 7500

EXPECT ,

2650IF U7 = 13 THEN 6710

PLOT: THE SECOND VALUE AND THEN ENTRY 13, PLOT

2660GOSUB 10900

HLIN / VLIN: THE SECOND VALUE

2670CI = 120

ENTRY 120 SAVES IT

2680GOSUB 16500
2690XF = 197

EXPECT AT

2700GOSUB 7520
2710GOTO 6710

THE THIRD VALUE AND THEN ENTRY 14 (HLIN) OR 15 (VLIN)

2800HPLOT [TO] X,Y [TO X,Y]...

2800GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

2810IF T0 = 193 THEN 2850

HPLOT TO: NO FIRST POINT

2820GOSUB 3000

THE FIRST POINT

2830CI = U7

CALL TABLE ENTRY 19 PLOTS IT

2840GOSUB 16500
2850XF = 193

EACH TO ...

2860GOSUB 6520

EXPECT TO, ELSE THE STATEMENT IS FINISHED

2870GOSUB 3000

... X,Y

2880CI = 59

ENTRY 59 DRAWS THE LINE TO IT

2890GOSUB 16500
2900GOTO 2850
3000GOSUB 10900

A POINT X,Y: X, THEN ENTRY 122 SAVES IT, THEN Y

3010CI = 122

CALL TABLE ENTRY 122 SAVES X

3020GOSUB 16500
3030GOSUB 7500
3040GOTO 10900

THEN Y, LEFT IN THE ACCUMULATOR FOR THE CALLER'S ROUTINE

3100DRAW / XDRAW SHAPE [AT X,Y]

3100GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

3110GOSUB 10900

THE SHAPE NUMBER

3120IF T0 <> 197 THEN 6720

NO AT: CALL TABLE ENTRY 20 (DRAW) OR 21 (XDRAW)

3130CI = 86

ENTRY 86 SAVES THE SHAPE NUMBER

3140GOSUB 16500
3150GOSUB 8200

SKIP AT

3160GOSUB 10900

X, THEN ENTRY 122 SAVES IT

3170CI = 122

ENTRY 122 SAVES X

3180GOSUB 16500
3190GOSUB 7500

EXPECT ,

3200U7 = U7 + 6

Y, THEN ENTRY 26 (DRAW AT) OR 27 (XDRAW AT)

3210GOTO 6710

3300ONERR GOTO LINE: CALL WITH THE HANDLER'S ADDRESS; WHAT FOLLOWS ON THE LINE IS NOT REACHED

3300XF = 171

EXPECT GOTO (ONERR GETS NO RESUME/DEBUG CALL)

3310GOSUB 7520
3320GOSUB 16530

JSR TO CALL TABLE ENTRY 37, THE LIBRARY'S ONERR ROUTINE

3330GOSUB 8600

THE HANDLER'S LINE NUMBER

3340GOSUB 15420

ITS ADDRESS WORD, CHAINED TO THE LINE'S SYMBOL

3350GOTO 4120

3400RESUME: A JUMP TO THE LIBRARY ONLY WITH THE RESUME/DEBUG OPTION, OTHERWISE IGNORED WITH A WARNING

3400IF N1 THEN GOSUB 16700: GOTO 4120
3410GOTO 6950

WITHOUT THE OPTION RESUME IS IGNORED WITH A WARNING

3500LET (ALSO A STATEMENT THAT BEGINS WITH A NAME): COMPILE THE TARGET, THEN THE EXPRESSION OF ITS TYPE, THEN THE STORE

3500GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

3510GOSUB 9000

THE TARGET VARIABLE OR ARRAY ELEMENT

3520GOSUB 7200

EXPECT =

3530GOSUB 17100

ITS TYPE IN EP, AND THE CODE FOR AN ARRAY ELEMENT'S ADDRESS

3540ON EP GOSUB 10900,11000,10800

THE VALUE BY THE TARGET'S TYPE: 1 INTEGER, A NUMERIC EXPRESSION (LEFT AS AN INTEGER IF IT IS ONE); 2 STRING; 3 REAL, A NUMERIC EXPRESSION MADE REAL

3550TG = 1

MARK THE STORE AS AN ASSIGNMENT

3560GOSUB 20300

STORE THE VALUE IN THE TARGET

3570TG = 0

THE STORE IS DONE

3580GOTO 6830

3590IF ... THEN LINE / GOTO LINE: BEQ OVER A JMP TO THE LINE

3590GOSUB 8200

SKIP THE GOTO AFTER THEN

3600OW = 240

BEQ *+5: OVER THE JMP WHEN THE CONDITION IS FALSE

3610GOSUB 15620
3620OW = 3

*+5: THE BRANCH SKIPS THE THREE BYTES OF THE JMP

3630GOSUB 15620

3650GOTO LINE: JMP TO THE LINE (CHAINED UNTIL PASS 2 KNOWS ITS ADDRESS)

3650GOSUB 8600

THE LINE NUMBER

3660OW = 76

JMP, ITS ADDRESS CHAINED TO THE LINE'S SYMBOL

3670GOSUB 15400
3680GOTO 4120

3700RUN: JMP $03F5 (THE & VECTOR, WHICH THE LIBRARY POINTS AT THE PROGRAM); RUN LINE: CLEAR, THEN GOTO

3700GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

3710IF FN ES(T0) THEN GOSUB 15600:WF = 1013: GOSUB 15500: GOTO 4120

RUN ALONE: JMP $03F5

3720CI = 61

RUN LINE: JSR TO CALL TABLE ENTRY 61, CLEAR, THEN A JMP TO THE LINE

3730GOSUB 16530
3740GOTO 3650

3800IF EXPRESSION THEN ...: SET THE FLAGS FROM THE RESULT, THEN DECIDE THE FORM

3800GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

3810GOSUB 10900

THE CONDITION

3820IF NOT FD THEN FZ = RV: GOSUB 20800

IF ITS CODE DID NOT LEAVE THE FLAGS SET, TEST THE ACCUMULATOR (FZ = 1: LDA $9D, 0: LDA $A0 / ORA $A1)

3830IF T0 = 171 THEN 3590

IF ... GOTO LINE

3840XF = 196

EXPECT THEN

3850GOSUB 7520
3860IF T0 = 171 THEN 3590

IF ... THEN GOTO LINE

3870IF FN DG(T0) THEN 3600

IF ... THEN LINE

3880IF T0 = 177 THEN 4040

IF ... THEN RETURN

3890OW = 208

IF ... THEN STATEMENTS: BNE OVER A JMP TO THE NEXT LINE

3900GOSUB 15620

BNE *+5

3910OW = 3

*+5: SKIP THE JMP

3920GOSUB 15620
3930GOSUB 15600

A JMP TO THE NEXT LINE

3940VB = PC

ITS ADDRESS WORD WAITS ON THE PARSE STACK UNTIL THE NEXT LINE STARTS, WHEN IT IS PATCHED WITH THAT LINE'S ADDRESS

3950GOSUB 14200
3960GOSUB 15500

TWO BYTES FOR THE ADDRESS

3970RC = 1

THE STATEMENT AFTER THEN GETS NO RESUME/DEBUG CALL

3980GOTO 790

COMPILE THE STATEMENTS AFTER THEN AS PART OF THE LINE

4000GOSUB LINE: JSR TO THE LINE

4000GOSUB 8600

THE LINE NUMBER

4010OW = 32

JSR, ITS ADDRESS CHAINED TO THE LINE'S SYMBOL

4020GOSUB 15400
4030GOTO 6830

JSR ... RETURNS HERE: THE LINE GOES ON

4040IF ... THEN RETURN: BEQ OVER AN RTS

4040GOSUB 8200

SKIP THE RETURN AFTER THEN

4050OW = 240

BEQ *+3: OVER THE RTS WHEN THE CONDITION IS FALSE

4060GOSUB 15620
4070OW = 1

*+3: SKIP THE RTS

4080GOSUB 15620

4100RETURN: RTS

4100OW = 96
4110GOSUB 15620

(THE RTS)

4120AFTER AN UNCONDITIONAL TRANSFER: THE REST OF THE LINE IS NOT REACHED

4120D3 = 1

FURTHER KEYWORD STATEMENTS ON THE LINE ARE IGNORED WITH A WARNING

4130GOTO 6830

4200REM: REM! STARTS A COMPILER DIRECTIVE, ANY OTHER REMARK IS SKIPPED

4200GOSUB 5200

SPACES MAY FOLLOW REM

4210IF T0 <> 33 THEN 5150

AN ORDINARY REMARK: SKIP THE REST OF THE LINE

4220GOSUB 8200

SKIP !

4230GOSUB 5200

SPACES MAY FOLLOW !

4240IF T0 <> 73 THEN 4380

NOT I: TRY CLEAR

4250WL$ = "INTEGER"

INTEGER

4260GOSUB 5120
4270IF D2 <> 2 THEN 7550

ONLY BEFORE ANY OTHER STATEMENT

4280IF T0 = 42 THEN IZ = 2: GOSUB 8200: GOSUB 5200: GOTO 4930

INTEGER *: EVERY REAL NAME FROM HERE ON IS AN INTEGER; NOTHING MAY FOLLOW

4290GOSUB 9200

THE NEXT NAME

4300RI = IZ

SAVE IZ

4310IZ = 2

THE NAME IS DECLARED INTEGER

4320IF T0 <> 40 THEN GOSUB 14800: GOTO 4350

... A SIMPLE VARIABLE, OR ...

4330GOSUB 8200

... AN ARRAY WITH ITS DIMENSIONS

4340GOSUB 2200

THE DIMENSIONS GO INTO THE NAME'S SYMBOL

4350IZ = RI

BACK TO THE STATE BEFORE THIS NAME (ALSO 2 AFTER INTEGER *)

4360GOSUB 4900

A COMMA CONTINUES THE LIST; THE END OF THE LINE ENDS IT

4370GOTO 4290

THE NEXT NAME

4380REM! CLEAR COMMON / REM! CLEAR CHAIN: A CALL TO THE LIBRARY; MUST END THE LINE

4380IF T0 <> 67 THEN 4510

NOT C: TRY USECOMMON

4390WL$ = "CLEAR"

CLEAR

4400GOSUB 5120
4410IF T0 <> 67 THEN 5150

CLEAR MUST BE FOLLOWED BY COMMON OR CHAIN, ELSE THE LINE IS A REMARK

4420IF MJ = 79 THEN GOSUB 5100:CI = 127: GOTO 4460

CLEAR COMMON OR CLEAR CHAIN

4430WL$ = "CHAIN"

CHAIN

4440GOSUB 5120
4450CI = 128

CALL TABLE ENTRY 128, THE LIBRARY'S CLEAR CHAIN ROUTINE

4460GOSUB 16300

RESUME/DEBUG CALL BEFORE THE CALL

4470D2 = 0

NO MORE DECLARATIONS

4480GOSUB 16530

JSR TO THE ROUTINE

4490GOSUB 5200

SPACES MAY FOLLOW

4500GOTO 4930

THE LINE MUST END HERE

4510REM! USECOMMON / REM! DEFCOMMON LIST: ALLOCATE THE COMMON BLOCK AT THE PROGRAM START IN DECLARATION ORDER AND MOVE THE PROGRAM START UP

4510IF T0 <> 85 THEN 4560

NOT U: TRY DEFCOMMON

4520WL$ = "USE"

USE, THEN COMMON

4530GOSUB 5120
4540ML = 255

ML = 255: THE PROGRAM USES A COMMON BLOCK DEFINED BY AN EARLIER PROGRAM

4550GOTO 4590
4560WL$ = "DEF"

DEF, THEN COMMON

4570GOSUB 5120
4580ML = 0

ML = 0: THE PROGRAM DEFINES THE COMMON BLOCK

4590GOSUB 5100

MATCH COMMON

4600IF - 1 <> C3 AND C3 <> ML OR D2 = 0 THEN 7550

A DECLARATION ERROR IF USECOMMON AND DEFCOMMON ARE MIXED OR A STATEMENT CAME BEFORE

4610D2 = 1

FROM HERE ON ONLY OTHER COMMON DECLARATIONS ARE ALLOWED

4620C3 = ML

REMEMBER WHICH KIND OF COMMON THIS PROGRAM HAS

4630GOSUB 9200

THE NEXT NAME

4640IF T0 <> 40 THEN GOSUB 14800:L1 = 1: GOTO 4710

A SIMPLE VARIABLE: ONE ELEMENT

L1 IS NUMERIC VALUE OF A LINE NUMBER, DIMENSION OR CONSTANT

4650GOSUB 8200

AN ARRAY: ITS DIMENSIONS

4660GOSUB 2200

THE DIMENSIONS GO INTO THE NAME'S SYMBOL

4670L1 = 1

L1 = THE NUMBER OF ELEMENTS, THE PRODUCT OF (DIMENSION+1)

4680FOR K8 = VB + 5 TO VB + 4 + SC(VB + 4)

THE DIMENSIONS ARE STORED AFTER THE COUNT IN THE ARRAY'S ENTRY

4690L1 = (SC(K8) + 1) * L1
4700NEXT K8
4710K8 = 2

2 BYTES AN ELEMENT FOR AN INTEGER OR A STRING ...

4720IF - 3 = K4 OR K4 = 19 THEN K8 = 5

... 5 FOR A REAL

4730L1 = L1 * K8

L1 = THE SIZE IN BYTES

4740IF UR + L1 + 20 > 16384 THEN 7610

THE PROGRAM MAY NOT START ABOVE $BFFF

4750UR = UR + L1

MOVE THE PROGRAM START UP PAST THE VARIABLE

4760PC = UR + 20

THE CODE BEGINS 20 BYTES AFTER THE PROGRAM START

4770ED = UR - 4

AND THE OBJECT FILE'S BASE MOVES WITH IT

4780T9 = VB

APPEND THE SYMBOL TO THE LIST OF COMMON DECLARATIONS AT SC(0)

4790VB = 0

START AT THE HEAD OF THE LIST

4800IF SC(VB) = 0 THEN ML = 2: GOSUB 15100:SC(VB) = T9: GOSUB 4900: GOTO 4630

AT THE END OF THE LIST: A TWO-WORD ENTRY (LINK, SYMBOL)

4810VB = SC(VB): IF SC(VB + 1) = T9 THEN 7550

THE NEXT ENTRY; THE SAME SYMBOL DECLARED TWICE IS AN ERROR

4820GOTO 4800

4900AFTER A NAME IN A DECLARATION LIST: A COMMA CONTINUES IT, THE END OF THE LINE ENDS IT

4900GOSUB 5200

SPACES MAY FOLLOW THE NAME

4910IF T0 = 44 THEN GOSUB 8200: GOTO 5200

A COMMA: SKIP IT AND ANY SPACES AND RETURN FOR THE NEXT NAME

4920POP

THE LIST HAS ENDED: DROP THE RETURN TO THE LIST

4930IF T0 <> 0 THEN 7530

THE DECLARATION MUST END THE LINE

4940GOSUB 16000

LIST A RECOGNIZED DIRECTIVE LINE ON THE SCREEN

4950PRINT
4960PRINT "RECOGNIZED ";

AFTER THE WORD RECOGNIZED ...

4970GOSUB 8100

... THE LINE ITSELF

4980PRINT
4990GOTO 6850

GO ON WITH THE CONTROL-C CHECK AND THE NEXT LINE

5100MATCH THE KEYWORD IN WL$ AGAINST THE SOURCE, LETTER BY LETTER (SPACES ALLOWED); A MISMATCH IGNORES THE REST OF THE REMARK

5100WL$ = "COMMON"

ENTRY: MATCH THE WORD COMMON

5120FOR K8 = 1 TO LEN (WL$)

EACH LETTER OF WL$ MUST BE THE CURRENT CHARACTER; SPACES BETWEEN LETTERS ARE SKIPPED

5130IF ASC ( MID$ (WL$,K8)) = T0 THEN GOSUB 8200: GOSUB 5200: NEXT K8: RETURN

WHEN ALL LETTERS MATCH, RETURN

5140POP

A MISMATCH: DROP THE RETURN TO THE CALLER

5150IF T0 <> 0 THEN GOSUB 8200: GOTO 5150

THE LINE IS AN ORDINARY REMARK: SKIP TO THE END OF THE LINE

5160GOTO 6840

AND GO ON WITH THE NEXT LINE

5200SKIP SPACES

5200IF T0 = 32 THEN GOSUB 8200: GOTO 5200

SPACE IS 32

5210RETURN

5300STOP / NEW: CALL THE LIBRARY; WHAT FOLLOWS ON THE LINE IS NOT REACHED

5300GOSUB 16530

JSR TO THE LIBRARY: CALL TABLE ENTRY 51 FOR STOP, 63 (END, $1363) FOR NEW

5310GOTO 4120

THE REST OF THE LINE IS NOT REACHED

5400ON EXPRESSION GOTO / GOSUB LINE[,LINE]...: CALL WITH THE COUNT AND THE LINE ADDRESSES

5400GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

5410GOSUB 10900

THE INDEX EXPRESSION

5420CI = U7

CALL TABLE ENTRY 52 IS ON ... GOSUB ...

5430IF T0 = 171 THEN CI = CI + 3: GOSUB 8200: GOTO 5460

... ENTRY 55 ON ... GOTO

5440XF = 176

EXPECT GOSUB

5450GOSUB 7520
5460GOSUB 16500

JSR TO THE ROUTINE (INTEGER ENTRY, OR 3 LOWER FOR A REAL INDEX)

5470PN = PC

THE COUNT BYTE, PATCHED WHEN THE LIST IS COMPLETE

5480GOSUB 15620

(A PLACE FOR THE COUNT)

5490S3 = 0

S3 COUNTS THE LINES

5500GOSUB 8600

EACH LINE NUMBER ...

5510GOSUB 15420

... BECOMES A WORD CHAINED TO THE LINE'S SYMBOL

5520S3 = S3 + 1

COUNT IT

5530IF T0 = 44 THEN GOSUB 8200: GOTO 5500

A COMMA: ANOTHER LINE

5540OW = S3

PATCH THE COUNT BYTE

5550GOSUB 15800

THE COUNT IS PATCHED INTO THE BYTE AFTER THE JSR

5560GOTO 6830

5600WAIT ADDRESS,MASK[,MASK]

5600GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

5610GOSUB 10900

THE ADDRESS

5620CI = 49

CALL TABLE ENTRY 49 SAVES THE ADDRESS (REAL ENTRY, OR 3 LOWER FOR AN INTEGER)

5630GOSUB 16400
5640GOSUB 7500

EXPECT ,

5650GOSUB 10900

THE MASK

5660IF T0 <> 44 THEN 6720

NO SECOND MASK: ENTRY 53, WAIT

5670CI = 119

ENTRY 119 SAVES THE MASK

5680GOSUB 16500
5690GOSUB 8200

SKIP THE COMMA

5700U7 = U7 + 1

THE SECOND MASK, THEN ENTRY 54, WAIT WITH TWO MASKS

5710GOTO 6710

5800DEF FN NAME(PARAMETER)=EXPRESSION: JUMP OVER THE BODY; THE BODY STORES THE ARGUMENT IN THE PARAMETER, COMPUTES THE EXPRESSION AND RETURNS

5800XF = 194

EXPECT FN (DEF GETS NO RESUME/DEBUG CALL)

5810GOSUB 7520
5820GOSUB 9500

THE FUNCTION'S NAME

5830IF N5 THEN 7530

NOT A NAME

5840GOSUB 14900

FIND OR ENTER THE FUNCTION'S SYMBOL

5850IF SC(VB + 2) <> - 32767 THEN 7690

ITS ADDRESS IS ALREADY SET: A FUNCTION IS DEFINED ONLY ONCE

5860GOSUB 15600

A JMP OVER THE BODY

5870PN = PC

ITS ADDRESS WORD IS PATCHED AT THE END OF THE BODY

5880GOSUB 15500

(TWO BYTES FOR THE ADDRESS)

5890SC(VB + 2) = PC

THE BODY STARTS HERE: THE FUNCTION'S ADDRESS

5900GOSUB 7300

EXPECT (

5910GOSUB 9300

THE PARAMETER'S NAME

5920GZ = HY

WHILE THE BODY IS COMPILED THIS NAME MEANS THE PARAMETER

5930K4 = - 3

THE PARAMETER IS A REAL TEMPORARY OF ITS OWN (FROM CHAIN 8)

5940GOSUB 16800

A REAL TEMPORARY FROM THE FUNCTION'S OWN CHAIN

5950T5 = VB

T5 = THE PARAMETER'S SYMBOL

5960K4 = 1

THE BODY STARTS BY STORING THE ARGUMENT (IN THE FLOATING POINT ACCUMULATOR) IN THE PARAMETER: OPERATION 1

5970J3 = VB

A LOAD OF THE PARAMETER RIGHT AFTER THIS STORE IS LEFT OUT

5980SJ = PC

(THE ADDRESS OF THE STORE)

5990GOSUB 15300

EMIT THE STORE

6000GOSUB 7400

EXPECT )

6010GOSUB 7200

EXPECT =

6020GOSUB 10800

THE BODY'S EXPRESSION, A REAL VALUE LEFT IN THE ACCUMULATOR

6030OW = 96

RTS

6040GOSUB 15620

(THE RTS)

6050GOSUB 15700

PATCH THE JMP WITH THE ADDRESS AFTER THE BODY

6060GZ = 0

THE PARAMETER'S NAME IS AN ORDINARY NAME AGAIN

6070GOSUB 17000

THE FUNCTION'S TEMPORARIES ARE KEPT FOR IT ALONE

6080GOTO 6830

6100POKE ADDRESS,VALUE

6100GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

6110GOSUB 10900

THE ADDRESS

6120CI = 49

CALL TABLE ENTRY 49 SAVES THE ADDRESS (REAL ENTRY, OR 3 LOWER FOR AN INTEGER)

6130GOSUB 16400
6140GOSUB 7500

EXPECT ,

6150GOTO 6710

THE VALUE, THEN ENTRY 57, POKE

6200PRINT: EACH ITEM BY TYPE; ; NOTHING, , A TAB TO THE NEXT FIELD, TAB( AND SPC( CALLS; A CARRIAGE RETURN UNLESS THE STATEMENT ENDS WITH ; , TAB( OR SPC(

6200GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

6210IF FN ES(T0) THEN CI = 58: GOTO 6820

AFTER AN ITEM (OR FOR PRINT ALONE) AT THE END OF THE STATEMENT: JSR TO CALL TABLE ENTRY 58, THE ROM'S CARRIAGE RETURN (CRDO, $DAFB)

6220IF FN ES(T0) THEN 6830

AFTER ; , TAB( OR SPC( AT THE END OF THE STATEMENT: NO CARRIAGE RETURN

6230IF T0 = 59 THEN GOSUB 8200: GOTO 6220

; PRINTS NOTHING

6240IF T0 = 44 THEN GOSUB 8200:CI = 56: GOSUB 16530: GOTO 6220

, JSR TO ENTRY 56, THE TAB TO THE NEXT PRINT FIELD

6250IF T0 = 192 THEN U7 = 121: GOTO 6280

TAB(: ENTRY 121

6260IF T0 <> 195 THEN 6340

NOT SPC(: AN EXPRESSION

6270U7 = 84

SPC(: ENTRY 84

6280GOSUB 8200

SKIP TAB( OR SPC(

6290GOSUB 10900

THE ARGUMENT

6300GOSUB 7400

EXPECT )

6310CI = U7

JSR TO THE ENTRY (INTEGER ENTRY, OR 3 LOWER FOR A REAL ARGUMENT)

6320GOSUB 16500
6330GOTO 6220
6340GOSUB 10700

AN EXPRESSION OF EITHER TYPE

6350IF EP = 2 THEN CI = 50: GOSUB 16530: GOTO 6210

A STRING: ENTRY 50 PRINTS IT

6360CI = 82

A NUMBER: ENTRY 82 (REAL ENTRY, OR 3 LOWER FOR AN INTEGER)

6370GOSUB 16400
6380GOTO 6210

6400GET V

6400GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

6410GOSUB 9000

THE VARIABLE

6420GOSUB 17100

ITS TYPE IN EP, AND THE CODE FOR AN ARRAY ELEMENT'S ADDRESS

6430CI = U7

CALL TABLE ENTRY 62 GETS A NUMBER (A KEY'S DIGIT VALUE) ...

6440IF EP = 2 THEN CI = 64

... ENTRY 64 A ONE-CHARACTER STRING

6450GOSUB 16530
6460GOSUB 20300

STORE THE VALUE IN THE VARIABLE

6470GOSUB 6500

A COMMA CONTINUES THE LIST

6480GOTO 6410

6500EXPECT A COMMA, ELSE THE STATEMENT IS FINISHED

6500XF = 44
6520IF T0 = XF THEN 8200

SKIP THE EXPECTED CHARACTER AND RETURN

6530POP

NOT THERE: DROP THE RETURN TO THE STATEMENT ...

6540GOTO 6830

... WHICH IS FINISHED

6600CALL / HIMEM: (ONE ARGUMENT, REAL ENTRY)

6600GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

6610GOSUB 10900

THE ARGUMENT

6620CI = U7

THE ROUTINE IS CALL TABLE ENTRY TOKEN-128: 12 CALL, 35 HIMEM:

6630GOSUB 16400

JSR, REAL ENTRY OR 3 LOWER FOR AN INTEGER ARGUMENT

6640GOTO 6830

6700STATEMENTS WITH ONE ARGUMENT: VTAB HTAB COLOR= HCOLOR= SPEED= ROT= SCALE= IN# PR#

6700GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT

6710GOSUB 10900

THE ARGUMENT

6720CI = U7

THE ROUTINE IS CALL TABLE ENTRY TOKEN-128 (ALSO THE LAST CALL OF PLOT, HLIN, VLIN, DRAW, WAIT, POKE)

6730GOSUB 16500

JSR, INTEGER ENTRY OR 3 LOWER FOR A REAL ARGUMENT

6740GOTO 6830

6800POP / CLEAR / STATEMENTS WITHOUT ARGUMENTS

6800GOSUB 16300

RESUME/DEBUG CALL BEFORE THE STATEMENT (POP, CLEAR)

6820GOSUB 16530

JSR TO CALL TABLE ENTRY TOKEN-128; GR, TEXT, HGR, HGR2, HOME, NORMAL, INVERSE, FLASH AND RESTORE COME HERE DIRECTLY, WITHOUT A RESUME/DEBUG CALL

6830END OF THE STATEMENT: LIST THE LINE IF ASKED, CHECK FOR CONTROL-C, GO ON WITH THE NEXT STATEMENT OR LINE

6830IF NOT FN ES(T0) THEN 7530

THE STATEMENT MUST END HERE

6840IF O4 THEN GOSUB 8100: IF T0 = 0 THEN PRINT

LIST THE LINE WHEN IT IS COMPLETE

6850IF PEEK ( - 16384) = 131 THEN POKE - 16368,0: GOTO 20900

CONTROL-C TERMINATES THE COMPILATION

6860IF T0 <> 0 OR - 1 <> MJ THEN BM = BF: GOSUB 8200: GOTO 780

MORE ON THE LINE, OR ANOTHER LINE: READ ON AND COMPILE THE NEXT STATEMENT

6870END OF THE PROGRAM: PATCH THE REFERENCES STILL WAITING ON THE STACK, CLOSE THE FILES AND RUN PASS 2

6870IF V3 <> S8 THEN GOSUB 14300:PN = VB: GOSUB 15700: GOTO 6870

THE IF STATEMENTS OF THE LAST LINE STILL WAIT FOR THE ADDRESS OF THE NEXT LINE: PATCH THEM WITH THE END OF THE PROGRAM

6880CI = 0

THE PROGRAM ENDS WITH A JMP TO CALL TABLE ENTRY 0, THE LIBRARY'S END ROUTINE

6890GOSUB 16700

(THE JMP)

6900POKE DW,5

SET DOS'S OUTPUT STATE TO THE START OF A WRITE LINE, SO THE NEXT CONTROL-D STARTS A COMMAND

6910PRINT CO$

CLOSE ALL FILES

6920REM ! CLEAR CHAIN

STRING STORAGE IS SET UP SO THAT THE COMMON STRINGS SURVIVE THE CHAIN TO PASS 2

6930PRINT DI$;"BRUNPASS2";DN$

RUN PASS 2

6950WARNING: LINE NUMBER N IGNORED (AN UNSUPPORTED KEYWORD, OR A STATEMENT AFTER AN UNCONDITIONAL TRANSFER); SKIP TO THE NEXT COLON OUTSIDE QUOTES

6950GOSUB 16000

END THE DIRECT FILE OUTPUT

6960PRINT
6970PRINT
6980PRINT BP$;"*****WARNING"

TWO BELLS

6990PRINT "LINE NUMBER ";JS

THE NUMBER OF THE LINE BEING COMPILED

7000PRINT "IGNORED"
7010PRINT
7020GOSUB 7100

SKIP THE STATEMENT

7030PRINT
7040GOTO 6850

CHECK FOR CONTROL-C, THEN GO ON

7100SKIP TO THE NEXT COLON OUTSIDE QUOTES OR THE END OF THE LINE

7100K8 = 1

K8 = 1 OUTSIDE QUOTES, 0 INSIDE

7110IF T0 = 34 THEN K8 = NOT K8

A QUOTE SWITCHES

7120IF K8 AND T0 = 58 THEN 7140

A COLON OUTSIDE QUOTES ENDS THE STATEMENT

7130IF T0 <> 0 THEN GOSUB 8200: GOTO 7110

THE END OF THE LINE ALSO ENDS IT

7140GOSUB 8100

LIST THE LINE SO FAR

7150PRINT
7160PRINT
7170RETURN

7200EXPECT = / ( / ) / , / THE CHARACTER IN XF; ELSE A SYNTAX ERROR

7200XF = 208

EXPECT = (TOKEN 208)

7210GOTO 7520
7300XF = 40

EXPECT (

7310GOTO 7520
7400XF = 41

EXPECT )

7410GOTO 7520
7500XF = 44

EXPECT A COMMA

7520IF T0 = XF THEN 8200

THE EXPECTED CHARACTER: SKIP IT AND RETURN; ANYTHING ELSE IS A SYNTAX ERROR

7530FATAL ERRORS: NAME THE KIND IN WL$

7530WL$ = "SYNTAX"

A STATEMENT THAT DOES NOT FOLLOW THE RULES

7540GOTO 7720
7550WL$ = "DECLARATION"

A DECLARATION OUT OF PLACE, MIXED OR REPEATED

7560GOTO 7720
7570WL$ = "SUBSCRIPT"

A BAD DIMENSION OR NUMBER OF SUBSCRIPTS

7580GOTO 7720
7590WL$ = "TOO COMPLEX"

THE PARSE STACK OR THE TRIPLE TABLE IS FULL

7600GOTO 7720
7610WL$ = "TOO LONG"

A SOURCE LINE TOO LONG FOR THE LISTING BUFFER, OR A PROGRAM THAT WOULD PASS $BFFF

7620GOTO 7720
7630WL$ = "SYMBOL TABLE FULL"

NO ROOM LEFT IN SC()

7640GOTO 7720
7650WL$ = "INCOMPLETE"

AN EXPRESSION THAT ENDS TOO SOON

7660GOTO 7720
7670WL$ = "OPERAND"

A NUMBER THAT CANNOT BE CONVERTED, OR SOMETHING THAT IS NOT AN OPERAND

7680GOTO 7720
7690WL$ = "REDEFINED"

AN ARRAY DIMENSIONED AGAIN OR A FUNCTION DEFINED AGAIN

7700GOTO 7720
7710WL$ = "TYPE MISMATCH"

A STRING WHERE A NUMBER IS NEEDED, OR THE REVERSE

7720REPORT A FATAL ERROR, SHOW THE LINE WITH !ERR!, PAUSE IF ASKED; NO MORE CODE IS WRITTEN

7720GOSUB 16000

END THE DIRECT FILE OUTPUT

7730FC = 1

FROM NOW ON NO CODE IS WRITTEN; PARSING GOES ON TO FIND MORE ERRORS

7740PRINT
7750PRINT
7760PRINT BP$;"*****FATAL ERROR"

TWO BELLS

7770PRINT "LINE NUMBER ";JS
7780PRINT WL$

WHICH ERROR, FROM WL$

7790PRINT
7800GOSUB 8100

THE LINE UP TO THE ERROR ...

7810PRINT " !ERR! ";

... THE MARK ...

7820GOSUB 7100

... AND THE REST OF THE STATEMENT

7830IF NOT OO THEN 7910

WITHOUT THE PAUSE OPTION, GO ON AT ONCE

7840POKE MN,0

STOP THE DRIVE MOTOR WHILE WAITING

7850POKE - 16368,0

CLEAR THE KEYBOARD STROBE

7860PRINT "TYPE CNTRL-C TO ABORT,"

THE PROMPT

7870PRINT "ANY OTHER KEY TO CONTINUE:"
7880K8 = PEEK ( - 16384): IF K8 < 128 THEN 7880

WAIT FOR A KEY

7890POKE - 16368,0

CLEAR THE KEYBOARD STROBE

7900IF K8 = 131 THEN 20900

CONTROL-C ENDS THE COMPILATION

7910PRINT
7920PRINT
7930CALL EL

THE ERROR MAY HAVE COME FROM DEEP INSIDE SUBROUTINES: RESET THE STACK

7940SU = 0

AND EMPTY THE PARSE STACK, THE TRIPLE TABLE AND THE DEF FN STATE

7950V3 = S8
7960GZ = 0
7970U2 = 1
7980GOTO 6860

GO ON WITH THE NEXT STATEMENT OR LINE

7990CONVERT THE DIGITS IN WL$ TO A NUMBER (A BAD NUMBER SETS N5)

7990ONERR GOTO 8040

A NUMBER TOO LARGE FOR VAL GIVES AN ERROR, CAUGHT HERE

8000L1 = VAL (WL$)

VAL CONVERTS THE DIGITS (THE INTERPRETER'S OWN NUMBER CONVERSION)

8010POKE 216,0

TURN ONERR OFF AGAIN (ERRFLG, $D8)

8020N5 = 0

A GOOD NUMBER

8030ON K8 GOTO 2300,8700,12200

RETURN TO THE CALLER: K8 = 1 A DIMENSION (2300), 2 A LINE NUMBER (8700), 3 A CONSTANT (12200)

8040POKE 216,0

AN ERROR IN VAL: TURN ONERR OFF ...

8050CALL EL

... AND RESET THE STACK

8060N5 = 1

A BAD NUMBER

8070GOTO 8030

8100LIST THE LINE IN THE LISTING BUFFER

8100IF BM = BF THEN RETURN

NOTHING TO LIST

8110GOSUB 16000

END THE DIRECT FILE OUTPUT

8120POKE BM,0

A ZERO ENDS THE TOKENIZED LINE

8130BM = BF

THE BUFFER IS EMPTY AGAIN

8140CALL LQ

THE ROUTINE AT $038D LISTS THE LINE, EXPANDING THE TOKENS INTO KEYWORDS

8150RETURN

8200NEXT TOKEN: T0 = NEXT BYTE OF THE LINE, MJ = THE ONE AFTER IT, COPYING EACH INTO THE LISTING BUFFER

8200IF P3 <> 0 THEN 8400

THE PREVIOUS TOKEN WAS NOT THE END OF THE LINE

8220START A LINE: READ ITS NUMBER, DEFINE ITS LINE SYMBOL AT THE CURRENT CODE ADDRESS, RECORD IT IN THE LINE NUMBER FILE

8220J3 = 0

ENTRY AT THE START OF A LINE: NO STORE TO REMEMBER ...

8230D3 = 0

... AND THE NEW LINE IS REACHED

8240JS = IV

THE LINE NUMBER, LOW BYTE ...

JS IS CURRENT SOURCE LINE NUMBER

8250GOSUB 8490

THE HIGH BYTE OF THE LINE NUMBER

8260L1 = 256:JS = L1 * IV + JS

... AND HIGH BYTE

8270GOSUB 8490

THE FIRST BYTE OF THE LINE'S TEXT

8280IF O4 THEN GOSUB 16000: PRINT JS;" ";

WITH THE LISTING OPTION, PRINT THE LINE NUMBER

8290IF F <> 3 THEN POKE DW,5: PRINT WO$;LN$:F = 3

THE LINE NUMBER FILE TAKES A RECORD FOR EACH LINE: ITS NUMBER AND THE ADDRESS OF ITS CODE

8300FQ = 1

WRITE THE RECORD EVEN AFTER A FATAL ERROR

8310WF = JS

THE LINE NUMBER, AS A WORD

8320GOSUB 15520

(THE NUMBER, LOW BYTE FIRST)

8330WF = PC

THE ADDRESS WHERE THE LINE'S CODE BEGINS

8340GOSUB 15470

(THE ADDRESS, LOW BYTE FIRST)

8350FQ = 0

NORMAL OBJECT OUTPUT AGAIN

8360LH = LH + 1

COUNT THE LINE

8370MJ = IV

THE FIRST TOKEN OF THE LINE BECOMES THE LOOKAHEAD

8380GOSUB 8490

AND THE BYTE AFTER IT IS READ

8390IF V3 <> S8 THEN GOSUB 14300:PN = VB: GOSUB 15700: GOTO 8390

THE IF STATEMENTS OF THE PREVIOUS LINE ARE WAITING FOR THIS LINE'S ADDRESS: PATCH THEIR JMP ADDRESSES

8400IF BM = BK THEN 7610

THE LISTING BUFFER IS FULL: THE LINE IS TOO LONG

8410IF P3 <> 0 THEN POKE BM,P3:BM = BM + 1

COPY THE PREVIOUS TOKEN INTO THE LISTING BUFFER

8420T0 = MJ:P3 = T0

THE LOOKAHEAD BECOMES THE CURRENT TOKEN

8430IF T0 <> 0 THEN MJ = IV: GOTO 8490

NOT THE END OF THE LINE: THE BYTE JUST READ BECOMES THE LOOKAHEAD, AND THE NEXT BYTE IS READ

8450PE = IV

THE END OF THE LINE: THE NEXT TWO BYTES ARE THE NEXT LINE'S LINK

8460GOSUB 8490

THE HIGH BYTE OF THE LINK

8470IF PE + IV = 0 THEN MJ = - 1

A ZERO LINK ENDS THE PROGRAM; THEN READ THE LOW BYTE OF THE NEXT LINE NUMBER

8490READ ONE BYTE OF THE SOURCE FILE INTO IV

8490IF F <> 1 THEN POKE DW,5: PRINT RV$;SI$:F = 1

THE SOURCE FILE MUST BE SET UP FOR READING

8500CALL QB

THE ROUTINE AT $037E READS ONE BYTE OF THE FILE INTO $0376

8510GOSUB 16100

KEEP THE DRIVE RUNNING

8520IV = PEEK (IX)

IV = THE BYTE READ

8530RETURN

8600LINE NUMBER REFERENCE: FIND OR ENTER THE LINE'S SYMBOL

8600GOSUB 8800

THE DIGITS OF THE LINE NUMBER

8610IF N5 THEN 7530

NOT A NUMBER

8620K8 = 2

CONVERT IT (RETURNING TO 8700)

8630GOTO 7990
8700IF N5 OR L1 < 0 OR L1 > 65534 THEN 7530

A LINE NUMBER FROM 0 TO 65534

8710L1 = L1 - 32767:HY = L1

LINE SYMBOLS HOLD THE NUMBER-32767

8720VB = L + L1 - INT (L1 / NK) * NK

ITS CHAIN: L + NUMBER MOD NK

8730IF SC(VB) = 0 THEN ML = 3: GOSUB 15100:SC(VB + 1) = HY: RETURN

THE END OF THE CHAIN: A NEW THREE-WORD ENTRY (LINK, REFERENCE CHAIN, NUMBER); VB POINTS AT ITS REFERENCE CHAIN

8740VB = SC(VB): IF SC(VB + 2) = HY THEN VB = VB + 1: RETURN

THE NEXT ENTRY; THE SAME NUMBER IS THE LINE'S SYMBOL

8750GOTO 8730

NOT THIS ONE: GO ON ALONG THE CHAIN

8800SCAN A NUMBER INTO WL$

8800WL$ = ""

WL$ COLLECTS THE DIGITS

8820IF NOT FN DG(T0) THEN N5 = 1: RETURN

NO DIGIT: NO NUMBER

8830N5 = 0
8840GOSUB 8900

ADD THE DIGIT AND READ ON

8850IF FN DG(T0) THEN 8840

WHILE THERE ARE DIGITS

8860RETURN
8900WL$ = WL$ + CHR$ (T0)

ADD THE CHARACTER TO WL$ AND GO TO THE NEXT TOKEN

8910GOTO 8200

9000NAME WITH ITS TYPE AND SUBSCRIPTS: AN OPERAND

9000GOSUB 9200

THE NAME AND ITS TYPE

9010GOSUB 9600

A SIMPLE VARIABLE OR AN ARRAY ELEMENT

9020GOTO 14100

RETURN ITS TRIPLE IN VB

9100GOSUB 14500

AN OPERAND TRIPLE: KIND K4, LEFT = THE SYMBOL VB; IT GOES ON THE PARSE STACK

9110VB = K4

THE TRIPLE'S KIND IS THE OPERAND'S TYPE CODE

9120GOSUB 14400
9130GOTO 13900

9200NAME WITH ITS TYPE SUFFIX: K4 = -1 FOR %, -2 FOR $, ELSE -3

9200GOSUB 9300

THE NAME

9210IF T0 = 37 THEN K4 = - 1: GOTO 8200

% : AN INTEGER

9220IF T0 = 36 THEN K4 = - 2: GOTO 8200

$ : A STRING

9230RETURN
9300GOSUB 9500

A NAME, REAL UNLESS A SUFFIX FOLLOWS

9310IF N5 THEN 7530

NO NAME

9320K4 = - 3

K4 = -3: REAL

9330RETURN
9400GOSUB 9300

A SIMPLE REAL NAME AND ITS SYMBOL (FOR AND NEXT VARIABLES); AN INTEGER-DECLARED NAME IS FOUND AS AN INTEGER

9410GOTO 14800

9500SCAN A NAME: HY = 99*FIRST CHARACTER+SECOND; LATER LETTERS AND DIGITS ARE SKIPPED

9500IF NOT FN LT(T0) THEN N5 = 1: RETURN

A NAME STARTS WITH A LETTER

9510N5 = 0
9520HY = T0 * 99

99 TIMES THE FIRST CHARACTER ...

9530GOSUB 8200

READ THE SECOND CHARACTER

9540IF FN DG(T0) OR FN LT(T0) THEN HY = HY + T0

... PLUS THE SECOND, A LETTER OR DIGIT

9550IF FN DG(T0) OR FN LT(T0) THEN GOSUB 8200: GOTO 9550

THE REST OF THE NAME IS SKIPPED

9560RETURN

9600ARRAY ELEMENT: SUBSCRIPTS AS EXPRESSIONS, CHECKED AGAINST THE ARRAY'S DIMENSIONS

9600IF T0 <> 40 THEN GOSUB 14800: GOTO 9100

NO ( : A SIMPLE VARIABLE; ITS TRIPLE GOES ON THE STACK

9610VB = HY

KEEP THE NAME HASH AND THE ARRAY TYPE CODE ON THE STACK

9620GOSUB 14200

(PUSH THE HASH)

9630VB = K4 + 22

THE ARRAY TYPE CODE: 19 REAL, 20 STRING, 21 INTEGER

9640GOSUB 14200

SKIP (

9650GOSUB 8200
9660VB = 1

ONE SUBSCRIPT SO FAR

9670GOSUB 14200
9680GOSUB 11200

A SUBSCRIPT: A NUMERIC EXPRESSION, LEFT ON THE STACK AS A TRIPLE

9690IF T0 <> 44 THEN 9790

A COMMA: ANOTHER SUBSCRIPT

9700GOSUB 8200

SKIP THE COMMA, AND COUNT THE SUBSCRIPT UNDER THE ONES BEFORE IT ON THE STACK

9710T9 = VB
9720GOSUB 14300

THE COUNT, UNDER THE SUBSCRIPT JUST PARSED

9730ML = VB + 1: IF ML > 88 THEN 7570

AT MOST 88 SUBSCRIPTS

9740VB = T9
9750GOSUB 14200
9760VB = ML
9770GOSUB 14200
9780GOTO 9680

THE NEXT SUBSCRIPT

9790ML = VB

THE LAST SUBSCRIPT

9800GOSUB 7400

EXPECT )

9810GOSUB 14300

O2 = THE NUMBER OF SUBSCRIPTS

9820O2 = VB

THE COUNT

9830T9 = U2

T9 = THE ARRAY'S OWN TRIPLE

9840VB = ML
9850ML = 1
9860FOR K8 = 1 TO O2

THE ARRAY'S TRIPLE TAKES THE LAST SUBSCRIPT AS ITS RIGHT OPERAND; THE OTHERS GO, LAST TO FIRST, TWO TO A TRIPLE WITH OPERATION 22 (A MISSING SECOND ONE IS 0)

9870TP(U2,ML + 1) = VB
9880IF ML AND K8 <> O2 THEN GOSUB 14700:VB = 22: GOSUB 14400

AFTER EACH RIGHT OPERAND BUT THE LAST: A NEW TRIPLE WITH OPERATION 22

9890ML = NOT ML
9900GOSUB 14300

THE NEXT SUBSCRIPT FROM THE STACK

9910NEXT K8
9920K4 = VB

THE ARRAY TYPE CODE

9930IF ML = 1 THEN VB = 0: GOSUB 14600

AN EVEN COUNT LEAVES THE LAST PAIR'S RIGHT OPERAND EMPTY

9940GOSUB 14700

THE NEXT FREE TRIPLE

9950GOSUB 14300

THE NAME HASH

9960HY = VB
9970GOSUB 14800

FIND OR ENTER THE ARRAY'S SYMBOL

9980IF K0 - 4 = VB THEN SC(K0) = O2:ML = O2 + 1: GOSUB 15200:SC(VB + 5) = - 1: GOTO 10000

A NEW ARRAY: STORE ITS NUMBER OF SUBSCRIPTS AND MARK IT NOT DIMENSIONED (-1); IT GETS 10 PER SUBSCRIPT

9990IF SC(VB + 4) <> O2 THEN 7570

AN OLD ONE MUST HAVE THE SAME NUMBER OF SUBSCRIPTS

10000TP(T9,0) = K4

THE ARRAY'S TRIPLE: KIND = THE ARRAY TYPE (19 REAL, 20 STRING, 21 INTEGER), LEFT = THE SYMBOL

10010TP(T9,1) = VB

(THE SYMBOL)

10020VB = U2 - 1

IT GOES ON THE STACK

10030GOTO 14020

10100FUNCTION ARGUMENTS, AS DESCRIBED IN F()

10100GOSUB 7300

EXPECT (

10120GOSUB 14200

KEEP THE FUNCTION'S OPERATION ON THE STACK

10130F(4) = 1

THE FIRST ARGUMENT

10140FOR K8 = 4 TO 0 STEP - 1

SAVE F() ON THE STACK (THE ARGUMENT MAY CALL ANOTHER FUNCTION)

10150VB = F(K8)
10160GOSUB 14200
10170NEXT K8
10180IF F(F(4)) = 1 THEN GOSUB 11200: GOTO 10210

THE ARGUMENT'S TYPE: 1 NUMERIC, 2 STRING, 3 EITHER

10190IF F(F(4)) = 2 THEN GOSUB 11300: GOTO 10210

STRING, OR EITHER TYPE

10200GOSUB 11100
10210ML = VB

ML = THE ARGUMENT'S TRIPLE

10220FOR K8 = 0 TO 4

GET F() BACK

10230GOSUB 14300
10240F(K8) = VB

(EACH VALUE)

10250NEXT K8
10260F(F(4)) = ML

THE ARGUMENT'S TRIPLE REPLACES ITS TYPE

10270IF F(4) = F(0) THEN 10300

ALL ARGUMENTS READ

10280IF T0 = 44 THEN GOSUB 8200:F(4) = F(4) + 1: GOTO 10140

A COMMA: THE NEXT ARGUMENT

10290IF F(4) <> 2 THEN 7530

FEWER ARGUMENTS ARE ALLOWED ONLY FOR MID$ WITH TWO

10300GOSUB 14300

THE FUNCTION'S TRIPLE: ITS OPERATION, THE FIRST ARGUMENT AS LEFT, THE SECOND AS RIGHT (0 IF NONE)

10310GOSUB 14400
10320VB = F(1)

(THE FIRST ARGUMENT)

10330GOSUB 14500
10340VB = F(2)

(THE SECOND ARGUMENT)

10350IF F(0) = 1 THEN VB = 0
10360GOSUB 14600
10370GOSUB 14700
10380IF F(4) = 3 THEN VB = 17: GOSUB 14400:VB = F(3): GOSUB 14500:VB = 0: GOSUB 14600: GOSUB 14700

A THIRD ARGUMENT GOES INTO A FOLLOWING TRIPLE WITH OPERATION 17

10390VB = U2 - 1

THE FUNCTION'S TRIPLE GOES ON THE STACK

10400GOSUB 14020
10410GOTO 7400

EXPECT )

10500STRING LITERAL: JUMP OVER ITS LENGTH AND TEXT; THE CODE REFERS TO IT BY ADDRESS

10500GOSUB 8200

SKIP THE OPENING QUOTE

10510BO = BM

THE TEXT STARTS HERE IN THE LISTING BUFFER

10520IF T0 <> 0 AND T0 <> 34 THEN GOSUB 8200: GOTO 10520

THE TEXT ENDS AT THE CLOSING QUOTE OR THE END OF THE LINE

10530GOSUB 15600

A JMP ...

10540WF = PC + 3 + BM - BO

... TO THE ADDRESS AFTER THE TEXT: 2 FOR THE ADDRESS, 1 FOR THE LENGTH, THEN THE TEXT

10550GOSUB 15450

(THE ADDRESS AFTER THE TEXT)

10560VB = PC

VB = THE LITERAL'S ADDRESS (ITS LENGTH BYTE)

10580OW = BM - BO

ENTRY: WRITE THE LENGTH AND THE TEXT, COPIED FROM THE LISTING BUFFER

10590GOSUB 15620
10600IF OW <> 0 THEN FOR K8 = BO TO BM - 1:OW = PEEK (K8): GOSUB 15620: NEXT K8

THE TEXT, BYTE BY BYTE

10610IF T0 = 34 THEN GOSUB 8200

SKIP THE CLOSING QUOTE

10620RETURN
10700GOSUB 11100

AN EXPRESSION OF EITHER TYPE, THEN ITS CODE

10710GOTO 10910
10800GOSUB 11200

A NUMERIC EXPRESSION WHOSE VALUE IS WANTED AS A REAL (A REAL TARGET OR A FUNCTION BODY)

10810SE = 1

THE VALUE MUST BE REAL

10820GOSUB 17200
10830SE = 0
10840RETURN

10900EXPRESSIONS: PARSE INTO TRIPLES, THEN GENERATE THE CODE (EP GIVES THE TYPE)

10900GOSUB 11200

A NUMERIC EXPRESSION AND ITS CODE

10910GOSUB 17200

ITS CODE

10920IF NOT RV THEN EP = 1

AN INTEGER RESULT LEFT AS AN INTEGER: EP = 1

10930RETURN
11000GOSUB 11300

A STRING EXPRESSION AND ITS CODE

11010GOTO 17200

ITS CODE

11100VB = 0

PARSE AN EXPRESSION OF EITHER TYPE ...

11110GOTO 11310
11200VB = 3

... A NUMERIC ONE ...

11210GOTO 11310
11300VB = 2

... OR A STRING ONE

11310PARSER: BOTTOM UP WITH THE OPERATOR AND OPERAND STACK; OPERANDS AND REDUCED OPERATORS BECOME TRIPLES IN TP()

11310GOSUB 14200

KEEP THE TYPE WANTED ON THE STACK

11320VB = 0

0 MARKS THE BOTTOM OF THIS EXPRESSION'S OPERATORS

11330GOSUB 14000

(THE BOTTOM MARK)

11340IF T0 = 40 THEN VB = T0: GOSUB 14000: GOSUB 8200: GOTO 11340

OPENING PARENTHESES

11350IF T0 = 34 THEN GOSUB 12820: GOTO 11480

A STRING LITERAL ...

11360IF FN SF(T0) THEN GOSUB 12880: GOTO 11480

... A STRING FUNCTION ...

11370GOSUB 9500

... OR A NAME

11380IF N5 THEN GOSUB 11800: GOTO 11410

NOT A NAME: A NUMERIC OPERAND (NUMBER, FUNCTION, SIGN OR NOT)

11390IF T0 = 36 THEN GOSUB 13000: GOTO 11480

A STRING VARIABLE

11400GOSUB 11910

A NUMERIC VARIABLE

11410ML = VB

A NUMERIC EXPRESSION IS COMPLETE: ML = ITS RESULT

11420GOSUB 14100

TAKE IT OFF THE STACK, WITH THE TYPE WANTED

11430GOSUB 14300

THE TYPE WANTED, FROM UNDER THE RESULT

11440IF VB = 2 THEN 7710

A STRING WAS WANTED

11450VB = ML
11460EP = 3

EP = 3: NUMERIC

11470RETURN

VB = THE RESULT'S TRIPLE

11480GOSUB 13200

AFTER A STRING OPERAND: A RELATION?

11490IF NOT N5 THEN GOSUB 14020: GOSUB 11680: GOTO 11410

YES: A STRING COMPARISON, WHOSE RESULT IS NUMERIC

11500ML = VB

A STRING EXPRESSION IS COMPLETE

11510GOSUB 14100

THE RESULT

11520IF NOT EO THEN 7650

IT MUST BE COMPLETE

11530GOSUB 14300

THE TYPE WANTED

11540IF VB = 3 THEN 7710

A NUMBER WAS WANTED

11550VB = ML
11560EP = 2

EP = 2: STRING

11570RETURN

VB = THE RESULT'S TRIPLE

11580IF T0 = 34 THEN GOSUB 12820: GOTO 11640

ENTRY AFTER AND / OR, WHERE A STRING COMPARISON MAY FOLLOW: A STRING LITERAL ...

11590IF FN SF(T0) THEN GOSUB 12880: GOTO 11640

... A STRING FUNCTION ...

11600GOSUB 9500

... A NAME ...

11610IF N5 THEN 11800

... OR A NUMERIC OPERAND

11620IF T0 <> 36 THEN 11910

A NUMERIC VARIABLE

11630GOSUB 13000

A STRING VARIABLE

11640GOSUB 14020

KEEP THE STRING OPERAND ON THE STACK

11650GOSUB 13200

A STRING OPERAND HERE MUST BE COMPARED

11660IF N5 THEN 7710

NO RELATION: A STRING CANNOT STAND HERE

11680VB = T0 + 38

STRING RELATIONS ARE THE RELATION TOKEN+38 (245 >, 246 =, 247 <, 273 >=, 274 <=, 275 <>)

11690GOSUB 14000

PUSH THE STRING RELATION

11700GOSUB 8200

SKIP THE RELATION

11710GOSUB 11300

THE RIGHT-HAND STRING EXPRESSION

11720GOSUB 14020

KEEP ITS RESULT ON THE STACK

11730GOTO 12680

GO ON AS AFTER A NUMERIC OPERAND

11800IF T0 = 40 THEN VB = T0: GOSUB 14000: GOSUB 8200: GOTO 11580

A NUMERIC OPERAND: OPENING PARENTHESES ...

11810IF T0 = 200 THEN GOSUB 8200: GOTO 11800

... A UNARY + IS SKIPPED ...

11820IF T0 = 201 THEN T0 = 239: GOTO 11840

... A UNARY - BECOMES THE NEGATION OPERATOR 239 ...

11830IF T0 <> 198 THEN 11880

... AND NOT (198) IS AN OPERATOR TOO

11840VB = T0

PUSH THE OPERATOR

11850GOSUB 14000
11860GOSUB 8200
11870GOTO 11800
11880GOSUB 9500

A NAME?

11890IF N5 THEN 11950
11910K4 = - 3

A NUMERIC VARIABLE: REAL, OR INTEGER WITH %

11920IF T0 = 37 THEN GOSUB 8200:K4 = - 1

% : AN INTEGER VARIABLE

11930GOSUB 9600

SIMPLE OR ARRAY ELEMENT

11940GOTO 12680

THEN AN OPERATOR OR THE END

11950GOSUB 8800

A NUMBER: ITS DIGITS ...

11960IF N5 AND T0 <> 46 THEN 12440

NO DIGITS AND NO POINT: A FUNCTION

11970IF T0 = 46 THEN GOSUB 8900: GOSUB 8820

... A POINT AND ITS FRACTION ...

11980IF T0 <> 69 THEN 12030

... AND AN EXPONENT, E WITH AN OPTIONAL SIGN

11990GOSUB 8900

THE E

12000IF T0 = 200 THEN GOSUB 8200: GOTO 12020

+ IS LEFT OUT

12010IF T0 = 201 THEN T0 = 45: GOSUB 8900

- IS PUT IN AS THE CHARACTER -

12020GOSUB 8820

THE EXPONENT'S DIGITS

12030GOSUB 12100

CONVERT AND ENTER THE CONSTANT

12040GOSUB 9100

ITS OPERAND TRIPLE

12050GOTO 12680
12100K8 = 3

CONVERT WL$ (RETURNING TO 12200)

12110GOTO 7990
12200IF N5 THEN 7670

A NUMBER VAL CANNOT CONVERT

12210NUMERIC CONSTANT: AN INTEGER IF INTEGER CONSTANTS ARE ON AND THE VALUE IS A WHOLE NUMBER UP TO 32767, ELSE REAL, PACKED BY THE USR ROUTINE; ENTERED IN ITS CONSTANT CHAIN (VALUE OR EXPONENT MOD 32)

12210IF OH AND INT (L1) = L1 AND L1 <= 32767 THEN K4 = - 1: GOTO 12260

AN INTEGER CONSTANT, CHAINED BY ITS VALUE MOD 32

12230K4 = - 3

A REAL CONSTANT

12240L1 = USR (L1)

THE USR ROUTINE PACKS THE VALUE INTO 5 BYTES AT $0371 (ROUNDED AS THE ROM STORES A NUMBER)

12250L1 = PEEK (KV)

CHAINED BY ITS EXPONENT BYTE MOD 32

12260VB = KX + L1 - INT (L1 / NG) * NG

ITS CHAIN: KX + KEY MOD NG

12270IF SC(VB) <> 0 THEN 12350

NOT AT THE END OF THE CHAIN: COMPARE WITH THE NEXT ENTRY

12280IF - 3 = K4 THEN ML = 8: GOSUB 15100:SC(VB + 1) = 0: FOR K8 = 0 TO 4:SC(VB + K8 + 2) = PEEK (KV + K8): NEXT K8: RETURN

A NEW REAL CONSTANT: AN EIGHT-WORD ENTRY (LINK, REFERENCE CHAIN, OPERATION MASK, THE 5 BYTES)

12290ML = 5

A NEW INTEGER CONSTANT: A FIVE-WORD ENTRY (LINK, REFERENCE CHAIN, OPERATION MASK, -10 TO MARK AN INTEGER, THE VALUE)

12300GOSUB 15100

(THE ENTRY)

12310SC(VB + 1) = 0

NO OPERATIONS USED YET

12320SC(VB + 2) = - 10

-10 MARKS AN INTEGER CONSTANT

12330SC(VB + 3) = L1

THE VALUE

12340RETURN
12350VB = SC(VB)

THE NEXT ENTRY

12360IF - 3 = K4 THEN 12390

A REAL CONSTANT IS COMPARED BYTE BY BYTE

12370IF SC(VB + 3) < 0 AND SC(VB + 4) = L1 THEN 12420

AN INTEGER CONSTANT MATCHES AN INTEGER ENTRY WITH THE SAME VALUE

12380GOTO 12270
12390FOR K8 = 0 TO 4

THE SAME 5 BYTES?

12400IF SC(VB + K8 + 3) <> PEEK (KV + K8) THEN 12270

A DIFFERENT BYTE: GO ON ALONG THE CHAIN

12410NEXT K8
12420VB = VB + 1

FOUND: VB POINTS AT ITS REFERENCE CHAIN

12430RETURN

12440NUMERIC FUNCTION CALL (SGN TO LEN, VAL, ASC)

12440IF NOT FN NU(T0) THEN 12540

NOT A NUMERIC FUNCTION: FN

12450VB = T0 - 181

THE FUNCTION'S OPERATION IS TOKEN-181 (SGN = 29 ... ASC = 49)

12460F(0) = 1

ONE ARGUMENT ...

12470IF T0 = 214 OR T0 = 217 THEN F(1) = 3: GOTO 12510

... OF EITHER TYPE FOR FRE AND POS (IT IS NOT EVALUATED)

12480IF T0 >= 210 AND T0 <= 226 THEN F(1) = 1: GOTO 12500

... NUMERIC FOR SGN TO PEEK ...

12490F(1) = 2

... A STRING FOR LEN, VAL AND ASC

12500IF T0 = 215 THEN GOSUB 8200:F(0) = 2:F(2) = 1: GOSUB 10120: GOTO 12680

SCRN( : TWO NUMERIC ARGUMENTS; THE ( IS PART OF THE TOKEN

12510GOSUB 8200

SKIP THE FUNCTION'S TOKEN

12520GOSUB 10100

THE ARGUMENT IN PARENTHESES

12530GOTO 12680

12540FN NAME(ARGUMENT)

12540IF T0 <> 194 THEN 7670

FN

12550GOSUB 8200

SKIP FN

12560GOSUB 9500

THE FUNCTION'S NAME

12570IF N5 THEN 7530

NO NAME

12580GOSUB 7300

EXPECT (

12590GOSUB 14900

THE FUNCTION'S SYMBOL, KEPT ON THE STACK

12600GOSUB 14200

(PUSH THE SYMBOL)

12610GOSUB 11200

THE ARGUMENT, A NUMERIC EXPRESSION

12620GOSUB 14600

IT IS THE TRIPLE'S RIGHT OPERAND

12630GOSUB 14300
12640K4 = 18

OPERATION 18 CALLS THE FUNCTION: LEFT = ITS SYMBOL

12650GOSUB 9100

THE TRIPLE GOES ON THE STACK

12660GOSUB 7400

EXPECT )

12670GOTO 12680
12680GOSUB 13200

AFTER AN OPERAND: A RELATION?

12690GOSUB 13500

REDUCE WHAT THE NEXT OPERATOR ALLOWS

12700IF NOT FN OS(T0) THEN 12760

NOT AN OPERATOR

12710VB = T0

PUSH THE OPERATOR

12720GOSUB 14000
12730GOSUB 8200

SKIP THE OPERATOR

12740IF VB = 205 OR VB = 206 THEN 11580

AFTER AND / OR A STRING COMPARISON MAY FOLLOW

12750GOTO 11800

ANOTHER NUMERIC OPERAND

12760IF EO THEN GOSUB 14100: RETURN

THE EXPRESSION IS COMPLETE: RETURN ITS RESULT

12770IF T0 = 41 THEN VB = T0: GOSUB 14000: GOSUB 8200: GOTO 12680

A CLOSING PARENTHESIS

12780GOTO 7650

ANYTHING ELSE: THE EXPRESSION IS INCOMPLETE

12790IF T0 = 40 THEN VB = T0: GOSUB 14000: GOSUB 8200: GOTO 12790

A STRING OPERAND: OPENING PARENTHESES ...

12800IF T0 <> 34 THEN 12860

... A LITERAL ...

12820GOSUB 10500

ENTRY: A STRING LITERAL; ITS TRIPLE HAS KIND -4 AND THE LITERAL'S ADDRESS

12830K4 = - 4

KIND -4: A STRING LITERAL

12840GOSUB 9100
12850GOTO 13040
12860IF NOT FN SF(T0) THEN 12970

... A STRING FUNCTION ...

12880VB = T0 - 181

ENTRY: A STRING FUNCTION; ITS OPERATION IS TOKEN-181 (STR$ = 47, CHR$ = 50, LEFT$ = 51, RIGHT$ = 52, MID$ = 53)

12890IF T0 = 228 OR T0 = 231 THEN F(0) = 1:F(1) = 1: GOTO 12940

STR$ AND CHR$: ONE NUMERIC ARGUMENT

12900F(0) = 2

LEFT$ AND RIGHT$: A STRING AND A NUMBER

12910F(1) = 2
12920F(2) = 1
12930IF T0 = 234 THEN F(0) = 3:F(3) = 1

MID$: A STRING AND ONE OR TWO NUMBERS

12940GOSUB 8200

SKIP THE FUNCTION'S TOKEN

12950GOSUB 10100

THE ARGUMENTS IN PARENTHESES

12960GOTO 13040

THEN REDUCE

12970GOSUB 9500

... OR A STRING VARIABLE

12980IF N5 OR T0 <> 36 THEN 7670

THE NAME MUST END WITH $

13000GOSUB 8200

ENTRY AFTER A NAME AND $: A STRING VARIABLE

13010K4 = - 2

KIND -2: A STRING VARIABLE

13020GOSUB 9600

SIMPLE OR ARRAY ELEMENT

13030GOTO 13040
13040GOSUB 13500

AFTER A STRING OPERAND: REDUCE

13050IF T0 = 200 THEN VB = 238: GOSUB 14000: GOSUB 8200: GOTO 12790

+ JOINS STRINGS (CONCATENATION, 238)

13060IF EO THEN GOSUB 14100: RETURN

THE EXPRESSION IS COMPLETE

13070IF T0 = 41 THEN VB = T0: GOSUB 14000: GOSUB 8200: GOTO 13040

A CLOSING PARENTHESIS

13080IF TP = 40 OR TP = 205 OR TP = 206 THEN GOSUB 14100: RETURN

A STRING OPERAND ALSO ENDS AT AN OPEN PARENTHESIS OR AFTER AND / OR (A COMPARISON FOLLOWS)

13090GOTO 7650

ANYTHING ELSE: INCOMPLETE

13200TWO-CHARACTER RELATIONS: >= OR => (235), <= OR =< (236), <> OR >< (237)

13200N5 = 0

N5 = 0: A RELATION

13210IF T0 <> 207 THEN 13300

>

13220IF MJ <> 208 THEN 13260

>= : 235

13230GOSUB 8200
13240T0 = 235
13250RETURN
13260IF MJ <> 209 THEN RETURN

>< : 237

13270GOSUB 8200
13280T0 = 237
13290RETURN
13300IF T0 <> 209 THEN 13370

<

13310IF MJ <> 208 THEN 13350

<= : 236

13320GOSUB 8200
13330T0 = 236
13340RETURN
13350IF MJ = 207 THEN 13270

<> : 237

13360RETURN
13370IF T0 <> 208 THEN N5 = 1: RETURN

NOT A RELATION

13380IF MJ = 207 THEN 13230

=> : 235

13390IF MJ = 209 THEN 13320

=< : 236

13400RETURN

13500REDUCE WHILE THE OPERATOR ON THE STACK HAS A HIGHER PRIORITY THAN THE ONE ARRIVING (OE())

13500EO = 0

THE EXPRESSION IS NOT COMPLETE YET

13510IF TP = 0 THEN EO = 1: RETURN

NO OPERATOR LEFT: THE EXPRESSION IS COMPLETE

13520IF T0 = 40 THEN RETURN

( IS ALWAYS PUSHED

13530IF FN OS(T0) OR T0 = 41 THEN 13560

AN OPERATOR OR ) ARRIVING: COMPARE PRIORITIES

13540IF TP = 40 THEN 7650

THE END OF THE EXPRESSION: AN OPEN PARENTHESIS IS INCOMPLETE

13550GOTO 13650

OTHERWISE REDUCE

13560F(0) = TP

THE OPERATOR ON THE STACK

13570IF TP = 238 OR TP >= 245 THEN F(0) = TP - 38

CONCATENATION AND THE STRING RELATIONS HAVE THE PRIORITIES OF + AND OF THE NUMERIC RELATIONS

13580F(1) = T0

THE OPERATOR ARRIVING

13590FOR J = 0 TO 1

LOOK BOTH UP IN OE(): THE STACK PRIORITY OF THE ONE ON THE STACK, THE ARRIVING PRIORITY OF THE OTHER

13600FOR K8 = 0 TO 16
13610IF F(J) = OE(K8,0) THEN F(J) = OE(K8,J + 1): GOTO 13630

(THE PRIORITY REPLACES THE TOKEN)

13620NEXT K8
13630NEXT J
13640IF F(0) <= F(1) THEN RETURN

NOT HIGHER: STOP REDUCING (THE ARRIVING OPERATOR WILL BE PUSHED)

13650IF TP <> 41 THEN 13730

A ) ON THE STACK: REMOVE IT AND ITS (, KEEPING THE OPERAND BETWEEN THEM

13660GOSUB 14100
13670GOSUB 14100
13680ML = VB
13690GOSUB 14100
13700VB = ML
13710GOSUB 14020
13720GOTO 13510
13730BX = 1

A BINARY OPERATOR ...

13740IF TP = 239 OR TP = 198 THEN BX = 0

... BUT NEGATION AND NOT TAKE ONE OPERAND

13750GOSUB 14100

THE RIGHT OPERAND

13760GOSUB 14600
13770GOSUB 14100

THE OPERATOR, AS AN OPERATION NUMBER:

13780IF VB >= 200 AND VB <= 209 THEN VB = VB - 199: GOTO 13850

+ - * / ^ AND OR > = < BECOME 1 TO 10

13790IF VB >= 235 AND VB <= 237 THEN VB = VB - 224: GOTO 13850

>= <= <> BECOME 11 TO 13

13800IF VB = 198 THEN VB = 14: GOTO 13850

NOT BECOMES 14

13810IF VB = 239 THEN VB = 15: GOTO 13850

NEGATION BECOMES 15

13820IF VB = 238 THEN VB = 16: GOTO 13850

CONCATENATION BECOMES 16

13830IF VB >= 245 AND VB <= 247 THEN VB = VB - 222: GOTO 13850

STRING > = < BECOME 23 TO 25

13840VB = VB - 247

STRING >= <= <> BECOME 26 TO 28

13850GOSUB 14400

THE OPERATION IN THE NEW TRIPLE

13860IF BX THEN GOSUB 14100: GOSUB 14500

AND ITS LEFT OPERAND

13870GOSUB 13900

THE TRIPLE GOES ON THE STACK AS AN OPERAND

13880GOTO 13510

AND REDUCE FURTHER

13900VB = U2

ENTRY: PUSH THE TRIPLE BEING BUILT AND START THE NEXT

13910GOSUB 14020
13920GOSUB 14700
13930RETURN

14000PARSE STACK: PUSH AN OPERATOR, POP, PUSH AND POP AN OPERAND

14000TP = VB

PUSH AN OPERATOR: IT IS THE NEW TOP OPERATOR

14020SZ(SU) = VB

PUSH ON THE OPERATOR SIDE (OPERATORS AND OPERAND TRIPLES)

14030SU = SU + 1

(ONE MORE)

14040IF V3 < SU THEN 7590

THE TWO SIDES MET: TOO COMPLEX

14050RETURN
14100SU = SU - 1:VB = SZ(SU)

POP FROM THE OPERATOR SIDE

14110IF NOT FN OE(VB) OR SU = 0 THEN RETURN

AN OPERAND WAS POPPED, OR THE STACK IS EMPTY: THE TOP OPERATOR IS UNCHANGED

14120TP = SZ(SU - 1)

OTHERWISE FIND THE NEW TOP OPERATOR, ONE OR TWO PLACES DOWN

14130IF FN OE(TP) THEN RETURN
14140TP = SZ(SU - 2)

(THE OPERATOR IS UNDER AN OPERAND)

14150RETURN
14200SZ(V3) = VB

PUSH ON THE OPERAND SIDE (VALUES KEPT FOR LATER)

14210V3 = V3 - 1: IF V3 < SU THEN 7590

THE TWO SIDES MET: TOO COMPLEX

14220RETURN
14300V3 = V3 + 1:VB = SZ(V3)

POP FROM THE OPERAND SIDE

14310RETURN

14400STORE A TRIPLE IN TP()

14400TP(U2,0) = VB

THE TRIPLE'S OPERATION OR OPERAND KIND

14410RETURN
14500TP(U2,1) = VB

ITS LEFT OPERAND

14510RETURN
14600TP(U2,2) = VB

ITS RIGHT OPERAND

14610RETURN
14700U2 = U2 + 1: IF U2 > UZ THEN 7590

THE NEXT TRIPLE; AT MOST 100

14710RETURN

14800VARIABLE SYMBOL: FIND OR ENTER THE NAME IN CHAIN (HASH+TYPE) MOD 32, AT THE END OF THE CHAIN; INSIDE DEF FN THE PARAMETER'S NAME MEANS THE PARAMETER

14800IF HY = GZ AND - 3 = K4 THEN VB = T5: RETURN

INSIDE DEF FN THE PARAMETER'S NAME MEANS THE PARAMETER

14810L1 = HY + K4

THE KEY: NAME HASH PLUS TYPE CODE

14820VB = VO + L1 - INT (L1 / NU) * NU

ITS CHAIN: VO + KEY MOD NU

14830IF SC(VB) = 0 THEN ML = 5: GOSUB 15100:SC(VB + 1) = 0:SC(VB + 2) = HY:K4 = ( - 3 = K4 OR K4 = 19) * IZ + K4:SC(VB + 3) = K4: RETURN

THE END OF THE CHAIN: A NEW FIVE-WORD ENTRY (LINK, REFERENCE CHAIN, OPERATION MASK, NAME HASH, TYPE); WHILE DECLARING INTEGERS A REAL NAME IS ENTERED AS AN INTEGER (TYPE+2), STILL IN THE REAL NAME'S CHAIN

14840VB = SC(VB): IF SC(VB + 3) <> HY THEN 14830

THE NEXT ENTRY: THE SAME NAME HASH?

14850K8 = SC(VB + 4): IF K8 = K4 OR ( - 3 = K4 OR K4 = 19) AND K4 + 2 = K8 THEN K4 = K8:VB = VB + 1: RETURN

THE SAME TYPE, OR A REAL NAME FOUND AS AN INTEGER-DECLARED ONE: K4 = THE TYPE FOUND, VB POINTS AT THE REFERENCE CHAIN

14860GOTO 14830

NOT THIS ONE: GO ON ALONG THE CHAIN

14900FN SYMBOL: FIND OR ENTER THE FUNCTION'S NAME IN CHAINS 1-4

14900VB = 1 + HY - INT (HY / 4) * 4

ITS CHAIN: 1 + NAME HASH MOD 4

14910IF SC(VB) = 0 THEN ML = 4: GOSUB 15100:SC(VB + 1) = HY:SC(VB + 2) = - 32767: RETURN

THE END OF THE CHAIN: A NEW FOUR-WORD ENTRY (LINK, REFERENCE CHAIN, NAME HASH, ADDRESS); -32767 = NOT DEFINED YET

14920VB = SC(VB): IF SC(VB + 2) = HY THEN VB = VB + 1: RETURN

THE NEXT ENTRY; THE SAME NAME IS THE FUNCTION'S SYMBOL

14930GOTO 14910

NOT THIS ONE: GO ON ALONG THE CHAIN

15000OW = 32

CALL OF A FUNCTION: JSR TO ITS BODY ...

15010WF = SC(VB + 2)

... WHOSE ADDRESS IS KNOWN IF THE DEF FN CAME FIRST ...

15020IF - 32767 <> WF THEN GOSUB 15620: GOTO 15450

... OTHERWISE THE ADDRESS IS CHAINED TO THE FUNCTION'S SYMBOL FOR PASS 2

15030GOTO 15400

15100ALLOCATE ML WORDS OF THE SYMBOL TABLE

15100SC(VB) = K0

LINK A NEW ENTRY TO THE END OF THE CHAIN AT VB

15110SC(K0) = 0

IT ENDS THE CHAIN

15120VB = K0 + 1

RESERVE ITS ML WORDS; VB POINTS AT ITS SECOND WORD

15130GOSUB 15200

(RESERVE THE WORDS)

15140SC(VB) = - 32767

WHICH IS ITS REFERENCE CHAIN, EMPTY FOR NOW

15150RETURN
15200K0 = K0 + ML: IF K0 > TZ THEN 7630

SYMBOL TABLE FULL?

15210RETURN

15300EMIT A VARIABLE OR CONSTANT ROUTINE CALL: MARK THE OPERATION USED, WRITE THE OPERATION NUMBER AND LINK THE REFERENCE INTO THE SYMBOL'S CHAIN

15300ML = 2 ^ (K4 + 1)

ENTRY: OPERATION K4 ON SYMBOL VB: PASS 2 WRITES A ROUTINE ENTRY ONLY FOR THE OPERATIONS MARKED IN THE SYMBOL'S MASK (BIT K4)

15310T9 = INT (SC(VB + 1) / ML)

THE BIT IS SET IF SC(VB+1) MOD 2^(K4+1) >= 2^K4

15320IF SC(VB + 1) - T9 * ML < ML / 2 THEN SC(VB + 1) = SC(VB + 1) + ML / 2

SET THE BIT IF IT IS NOT SET YET

15340OW = K4

ENTRY WITHOUT THE MASK (STRING VARIABLES AND TEMPORARIES ALWAYS HAVE ALL THEIR ENTRIES): THE OPERATION NUMBER ...

15350WF = SC(VB)

... AND THE PREVIOUS REFERENCE TO THE SYMBOL; THIS REFERENCE BECOMES THE LATEST

15360SC(VB) = PC

THE SYMBOL'S CHAIN NOW STARTS AT THIS REFERENCE

15370GOSUB 15620

WRITE THE OPERATION NUMBER

15380GOTO 15450

THEN THE LINK

15400EMIT AN OPCODE AND A CHAINED REFERENCE (LINE OR FN)

15400GOSUB 15620

ENTRY: AN OPCODE (JMP OR JSR) ...

15420WF = SC(VB)

ENTRY: ... AND A WORD CHAINED TO THE SYMBOL: IT HOLDS THE PREVIOUS REFERENCE, AND THE SYMBOL NOW HOLDS THIS ONE

15430SC(VB) = PC

THE SYMBOL'S CHAIN NOW STARTS AT THIS WORD

15450EMIT A WORD

15450GOSUB 16200

ENTRY: A WORD WF KEPT AS ADDRESS-32767, WRITTEN AS THE ADDRESS

15470WF = FN UB(WF)

ENTRY: THE SAME, WITHOUT ADVANCING PC

15480GOTO 15520
15500GOSUB 16200

ENTRY: A WORD WRITTEN AS IT IS

15520HE = INT (WF / 256):OW = WF - HE * 256

ENTRY: THE SAME, WITHOUT ADVANCING PC: LOW BYTE ...

HE IS HIGH BYTE OF THAT WORD

15530GOSUB 15640
15540OW = HE

... THEN HIGH BYTE

15550GOTO 15640

15600EMIT A BYTE

15600OW = 76

ENTRY: A JMP OPCODE

15620GOSUB 16220

ENTRY: THE BYTE OW

15640IF FQ OR NOT FC THEN POKE DW,4: POKE IX,OW: CALL WS: GOSUB 16100

ENTRY: WRITE OW WITHOUT ADVANCING PC; AFTER A FATAL ERROR ONLY LINE NUMBER FILE RECORDS ARE WRITTEN. DOS'S OUTPUT STATE 4 SENDS EVERY CHARACTER TO THE FILE; THE ROUTINE AT $0387 WRITES THE BYTE IN $0376

15650RETURN

15700WRITE TO THE LINE NUMBER FILE / PATCH A WORD IN THE OBJECT FILE

15700HE = 2

ENTRY: PATCH THE WORD AT PN WITH THE CURRENT CODE ADDRESS

15710GOTO 15810
15800HE = 1

ENTRY: PATCH THE BYTE AT PN WITH OW

15810IF FC THEN RETURN

NOTHING IS WRITTEN AFTER A FATAL ERROR

15820POKE DW,5

DOS'S OUTPUT STATE 5: A CONTROL-D STARTS A COMMAND

15830L1 = ED

POSITION THE OBJECT FILE AT THE BYTE TO PATCH

15840PRINT WO$;OD$;",B";PN - L1

DOS WRITE WITH A BYTE POSITION, RELATIVE TO THE FILE'S START

15850F = 2

THE OBJECT FILE IS SET UP FOR WRITING

15860IF HE = 2 THEN WF = PC: GOSUB 15470: GOTO 15880

WRITE THE WORD ...

15870GOSUB 15640

... OR THE BYTE

15880POKE DW,5

AND POSITION THE FILE AT ITS END AGAIN

15890L1 = ED
15900PRINT WO$;OD$;",B";PC - L1

(THE FILE'S END)

15910RETURN

16000FILE HELPERS

16000POKE DW,5

END THE DIRECT FILE INPUT OR OUTPUT: A CONTROL-D ALONE

16010PRINT DI$

CONTROL-D AND A RETURN END THE DIRECT INPUT OR OUTPUT

16020F = 0

NO FILE IS SET UP NOW

16030RETURN
16100IF SC THEN POKE MX,0

KEEP THE DRIVE RUNNING IF ALL FILES ARE ON THE BOOT DRIVE

16110RETURN
16200GOSUB 16240

ENTRY: ADVANCE PC BY 2 FOR A WORD ...

16220IF F <> 2 THEN POKE DW,5: PRINT WO$;OD$:F = 2

ENTRY: ... OR BY 1 FOR A BYTE, SETTING UP THE OBJECT FILE FOR WRITING IF NEEDED

16240PC = PC + 1

ONE MORE BYTE

16250IF PC > 16384 THEN 7610

THE CODE MAY NOT PASS $BFFF

16260RETURN

16300RESUME/DEBUG: A CALL TO THE LIBRARY'S DEBUG ROUTINE BEFORE THE STATEMENT, EXCEPT RIGHT AFTER THEN

16300IF N1 AND NOT RC THEN ML = CI:CI = 85: GOSUB 16530:CI = ML

SAVE CI, EMIT THE CALL TO ENTRY 85 ($1423), RESTORE CI

16310RETURN

16400EMIT A JSR TO CALL TABLE ENTRY CI; THE ENTRY 3 BYTES LOWER SERVES THE OTHER ARGUMENT TYPE

16400WN = 3

ENTRY: THE CALL TABLE HOLDS THE REAL ENTRY (WN = 3)

16410GOTO 16510
16500WN = 1

ENTRY: THE CALL TABLE HOLDS THE INTEGER ENTRY (WN = 1)

16510IF WN <> EP THEN 16600

THE EXPRESSION'S TYPE IS THE OTHER ONE: USE THE ENTRY 3 BYTES LOWER

16530D = 0

ENTRY: THE ENTRY AS IT IS

16540GOTO 16610
16600D = - 3

ENTRY: THE ENTRY 3 BYTES LOWER

16610OW = 32

JSR

16620GOTO 16720

16700EMIT A JMP TO CALL TABLE ENTRY CI

16700OW = 76
16710D = 0

THE ENTRY AS IT IS

16720GOSUB 15620

WRITE THE OPCODE

16730WF = CC(CI) + D

THEN THE ROUTINE'S ADDRESS

16740GOTO 15450

16800TEMPORARIES: TAKE THE FIRST FREE ONE OF THE TYPE FROM ITS CHAIN (5 INTEGER, 6 STRING, 7 REAL, 8 ALL TYPES INSIDE DEF FN), ELSE MAKE A NEW ONE

16800VB = - K4 + 4

CHAIN 5 FOR AN INTEGER, 6 A STRING, 7 A REAL

16810IF GZ <> 0 THEN VB = 8

INSIDE DEF FN ALL OF THE FUNCTION'S TEMPORARIES COME FROM CHAIN 8

16820IF SC(VB) = 0 THEN ML = 4: GOSUB 15100:SC(VB + 1) = 0:SC(VB + 2) = K4 - 3: RETURN

THE END OF THE CHAIN: A NEW FOUR-WORD ENTRY (LINK, REFERENCE CHAIN, OPERATION MASK, TYPE); A TEMPORARY IN USE HAS ITS TYPE-3

16830VB = SC(VB): IF SC(VB + 3) = K4 THEN SC(VB + 3) = K4 - 3:VB = VB + 1: RETURN

THE NEXT ENTRY: A FREE TEMPORARY OF THIS TYPE IS TAKEN AND MARKED IN USE

16840GOTO 16820

16900FREE A TEMPORARY

16900SC(VB + 2) = SC(VB + 2) + 3

THE TYPE GOES BACK FROM TYPE-3 TO TYPE

16910RETURN

17000END OF DEF FN: THE FUNCTION'S TEMPORARIES ARE NOT USED AGAIN

17000VB = 8

EACH TEMPORARY IN CHAIN 8 ...

17010IF SC(VB) = 0 THEN RETURN
17020VB = SC(VB):ML = SC(VB + 3)

... THAT IS FREE ...

17030FOR K8 = - 3 TO - 1
17040IF ML = K8 THEN SC(VB + 3) = K8 - 3

... IS MARKED IN USE FOR GOOD

17050NEXT K8
17060GOTO 17010

17100GENERATE THE CODE OF AN ASSIGNMENT'S VALUE

17100EP = ABS (K4 - (K4 > 0) * 22)

EP = THE TARGET'S TYPE: 1 INTEGER, 2 STRING, 3 REAL (ARRAY TYPE CODES ARE 22 HIGHER)

17110TG = 1

THE TARGET'S TRIPLE IS LEFT FOR THE STORE (AN ARRAY ELEMENT GETS THE CODE OF ITS ADDRESS)

17120GOSUB 17200

(THE TARGET'S CODE)

17130TG = 0
17140RETURN

17200CODE GENERATOR: FOR EACH TRIPLE, DECIDE WHETHER ITS OPERANDS ARE INTEGER OR REAL, THEN GENERATE IT; A RESULT THAT IS NOT USED BY THE NEXT TRIPLE GOES TO A TEMPORARY

17200IF FC THEN U2 = 1: RETURN

AFTER A FATAL ERROR NO CODE IS GENERATED

17210TB = 1

THE FIRST TRIPLE

17220TP(U2,0) = 0

A ZERO AFTER THE LAST ONE

17230IF TB >= U2 THEN 20130

ALL TRIPLES DONE

17240K4 = 0

OPERATION 0 (LOAD) UNLESS SET BELOW

17250NQ = TP(TB,0)

THE TRIPLE'S OPERATION AND LEFT OPERAND

17260LZ = TP(TB,1)
17270RN = 1

OPERANDS AND RESULT REAL UNLESS DECIDED BELOW

17280RV = 1
17290FZ = FD

FZ = 1 IF THE PREVIOUS TRIPLE LEFT THE FLAGS SET

17300FD = 0

THE FLAGS DO NOT REFLECT THIS TRIPLE YET

17310IF NQ < 0 THEN 20110

AN OPERAND TRIPLE GENERATES NO CODE BY ITSELF

17320O2 = NQ:CI = O2 + 64:XK = CI

THE CALL TABLE ENTRY FOR AN OPERATION IS ITS NUMBER+64 (2 - IS 66, FSUBT; 8 > IS 72; 29 SGN IS 93 ...)

17330RH = TP(TB,2)

THE RIGHT OPERAND

17340NB = LZ
17350RN = 1
17360RV = 1
17370IF NQ <= 13 THEN IF FN IV(LZ) AND FN IV(RH) THEN 17390

+ - * / ^ AND THE RELATIONS WITH TWO INTEGER OPERANDS:

17380GOTO 17410
17390IF P8 AND NQ <= 3 THEN RN = 0:RV = 0

WITH THE INTEGER ARITHMETIC OPTION + - * ARE INTEGER OPERATIONS

17400IF NQ >= 8 AND NQ <= 13 THEN RN = 0

THE RELATIONS ALWAYS COMPARE INTEGERS AS INTEGERS

17410IF NQ >= 19 AND NQ <= 21 OR NQ = 14 OR NQ = 6 OR NQ = 7 THEN RN = 0: IF NQ = 21 THEN RV = 0

ARRAY ELEMENTS, AND, OR AND NOT USE THEIR OPERANDS AS THEY ARE; AN INTEGER ARRAY ELEMENT IS AN INTEGER

17420IF P8 AND NQ = 15 AND FN IV(RH) OR NQ = 45 OR NQ = 34 OR NQ = 35 THEN RN = 0:RV = 0

NEGATION OF AN INTEGER (WITH THE OPTION), PEEK, SCRN( AND PDL: INTEGER OPERANDS AND RESULT

17430IF NQ >= 50 THEN RN = 0

CHR$, LEFT$, RIGHT$, MID$: INTEGER ARGUMENTS

17440IF NQ = 46 OR NQ = 49 OR NQ = 36 THEN RV = 0

LEN, ASC AND POS GIVE INTEGERS

17450IF NOT RN THEN 17550

OPERANDS USED AS REALS:

17460KD = LZ

AN INTEGER RESULT LEFT IN THE INTEGER ACCUMULATOR BY THE PREVIOUS TRIPLE MUST BE MADE REAL FIRST

17470IF FN LO(NQ) THEN IF TP(LZ,0) = - 9 THEN 17510

THE LEFT OPERAND, IF THE OPERATION TAKES IT FROM THE ACCUMULATOR AND IT IS AN INTEGER LEFT THERE (KIND -9)

17480KD = RH
17490IF FN RT(NQ) THEN IF TP(RH,0) = - 9 THEN 17510

OR THE RIGHT ONE LIKEWISE

17500GOTO 17550
17510TP(KD,0) = - 5

IT IS NOW A REAL IN THE ACCUMULATOR

17520CI = 131

JSR TO CALL TABLE ENTRY 131, WHICH FLOATS THE INTEGER ACCUMULATOR

17530GOSUB 16530
17540CI = XK

(THE ENTRY FOR THE OPERATION AGAIN)

17550BY OPERATION: 1 + 2 - 3 * 4 / 5 ^ 6 AND 7 OR 8-13 RELATIONS 14 NOT 15 NEGATION 16 CONCATENATION 18 FN 19-21 ARRAY ELEMENTS

17560O2 = O2 - 20

23-28 STRING RELATIONS, 29-53 FUNCTIONS (17 AND 22 NEVER COME HERE)

17590+ * : APPLY THE OPERAND IN MEMORY TO THE ACCUMULATOR

17590K4 = 2

+ IS OPERATION 2 OF A VARIABLE ROUTINE

17600GOTO 17710
17700K4 = 4

* IS OPERATION 4

17710IF FN IA(RH) THEN 19750

THE RIGHT OPERAND IS IN THE ACCUMULATOR: APPLY THE LEFT ONE

17720GOSUB 20520

OTHERWISE LOAD THE LEFT OPERAND AND APPLY THE RIGHT ONE

17730GOTO 19740
17800U = 3

- : OPERATION 3 SUBTRACTS THE ACCUMULATOR FROM THE OPERAND

17810GOTO 17910
17900U = 7

/ : OPERATION 7 DIVIDES THE OPERAND BY THE ACCUMULATOR

17910IF FN IA(LZ) THEN 18010

THE LEFT OPERAND IS IN THE ACCUMULATOR: MOVE IT ASIDE

17920K4 = U

OTHERWISE KEEP THE OPERATION, LOAD THE RIGHT OPERAND ...

17930GOSUB 20500

(OPERATION 0 FOR THE LOAD, K4 KEPT)

17940NB = LZ

... AND APPLY THE LEFT ONE WITH THE OPERATION

17950GOTO 19750
18000IF NOT FN IA(LZ) THEN GOSUB 20500:NB = LZ:K4 = 6: GOTO 19780

^ : LOAD THE RIGHT OPERAND, LOAD THE LEFT ONE INTO THE SECOND ACCUMULATOR (OPERATION 6) AND CALL ENTRY 69, FPWRT

18010CI = 83

THE LEFT OPERAND IS IN THE ACCUMULATOR: MOVE IT TO THE SECOND ACCUMULATOR (ENTRY 83, MOVAF) ...

18020IF NOT RN THEN CI = 133:XK = 134

... OR, FOR INTEGERS, ENTRY 133, THE INTEGER MOVE, AND THEN ENTRY 134, THE INTEGER SUBTRACT

18030GOSUB 16530
18040CI = XK

THEN LOAD THE RIGHT OPERAND AND CALL

18050GOTO 19770

18100AND / OR: TEST THE OPERAND IN MEMORY (LDA, AND ORA FOR AN INTEGER), THEN CALL

18100FD = 1

THE RESULT SETS THE FLAGS

18110IF FN IA(LZ) THEN U = RH: GOTO 18140

THE LEFT OPERAND IS IN THE ACCUMULATOR: TEST THE RIGHT ONE IN MEMORY

18120GOSUB 20500

OTHERWISE LOAD THE RIGHT ONE AND TEST THE LEFT ONE

18130U = LZ
18140IF FN IV(NB) THEN CI = CI + 53

FOR AN INTEGER IN THE ACCUMULATOR THE INTEGER ROUTINES, ENTRIES 123 AND 124

18150NB = U

OPERATION 20: PASS 2 MAKES IT AN LDA OF THE VARIABLE (AND AN ORA OF ITS SECOND BYTE FOR AN INTEGER)

18160K4 = 20

OPERATION 20: THE TEST

18170GOTO 19780
18200GOSUB 20500

NOT: LOAD THE OPERAND

18210IF FN IA(RH) AND NOT FZ THEN FZ = NOT FN IV(RH): GOSUB 20800

IF IT WAS ALREADY IN THE ACCUMULATOR WITHOUT THE FLAGS SET, SET THEM

18220FD = 1

THEN CALL ENTRY 78 (EQUAL TO ZERO)

18230GOTO 19800
18300IF NOT RN THEN CI = 132

NEGATION: ENTRY 79 (NEGOP), OR 132 FOR AN INTEGER

18310GOSUB 20500

LOAD THE OPERAND AND CALL

18320GOTO 19800

18400COMPARISONS: IF THE RIGHT OPERAND IS IN THE ACCUMULATOR, COMPARE WITH THE LEFT ONE AND USE THE OPPOSITE RELATION

18400XK = CI + 2

> : THE SWAPPED RELATION IS <

18410GOTO 18720
18500XK = CI - 2

< : THE SWAPPED RELATION IS >

18510GOTO 18720
18600XK = CI + 1

>= : THE SWAPPED RELATION IS <= (FOR CONCATENATION, THE ROUTINE THAT SWAPS ITS OPERANDS)

18610GOTO 18720
18700XK = CI - 1

<= : THE SWAPPED RELATION IS >=

18720FD = 1

THE RESULT SETS THE FLAGS

18730IF NQ > 13 THEN 19060

STRING OPERATIONS

18740K4 = 5

OPERATION 5 COMPARES THE OPERAND WITH THE ACCUMULATOR

18750IF FN IA(RH) THEN CI = XK: GOTO 19780

THE RIGHT OPERAND IS IN THE ACCUMULATOR: COMPARE WITH THE LEFT ONE AND USE THE SWAPPED RELATION

18760GOSUB 20520

OTHERWISE LOAD THE LEFT ONE, COMPARE WITH THE RIGHT ONE AND CALL

18770GOTO 19770
18800GOSUB 20500

FN: LOAD THE ARGUMENT

18810VB = LZ
18820GOSUB 15000

JSR TO THE FUNCTION'S BODY

18830GOTO 19810

18900ARRAY ELEMENT: PUSH ALL SUBSCRIPTS BUT THE FIRST, LAST TO FIRST

18900U = LZ

U = THE ARRAY'S SYMBOL; CALL TABLE ENTRY 65 PUSHES A SUBSCRIPT

18910CI = 65

(ENTRY 65)

18920GOSUB 20500

LOAD THE LAST SUBSCRIPT

18930IF TP(TB + 1,0) <> 22 THEN 19000

MORE SUBSCRIPTS IN A FOLLOWING TRIPLE (OPERATION 22):

18940GOSUB 19720

PUSH THE ONE LOADED

18950TB = TB + 1

THE NEXT PAIR

18960LZ = TP(TB,1):NB = LZ

THE PAIR'S FIRST AND SECOND SUBSCRIPTS

18970RH = TP(TB,2)
18980GOSUB 20520

LOAD ITS FIRST SUBSCRIPT

18990IF RH THEN GOSUB 19720: GOTO 18920

IF THE PAIR HAS A SECOND ONE, PUSH AND LOAD IT TOO

19000IF NOT FN IV(NB) THEN CI = 1: GOSUB 16530

THE FIRST SUBSCRIPT STAYS IN THE ACCUMULATOR; A REAL ONE IS MADE AN INTEGER BY ENTRY 1, AYINT

19010VB = U

THE ARRAY'S ROUTINE

19020IF TG AND TB + 1 = U2 THEN LK = NQ:K4 = 1:U2 = 1: GOTO 15340

THE TARGET OF AN ASSIGNMENT: OPERATION 1, WHICH LEAVES THE ELEMENT'S ADDRESS FOR THE STORE; THE TRIPLES ARE DONE

19030FD = 1

A VALUE: OPERATION 0 LOADS THE ELEMENT

19040GOSUB 15340

(THE CALL TO THE ARRAY'S ROUTINE)

19050GOTO 19810

19060STRING COMPARISONS, LIKEWISE

19060IF FN IA(LZ) THEN 19770

THE LEFT STRING IS THE RESULT JUST COMPUTED: LOAD THE RIGHT ONE AND CALL

19070IF FN IA(RH) THEN CI = XK: GOTO 19780

THE RIGHT STRING IS THE RESULT JUST COMPUTED: LOAD THE LEFT ONE AND CALL THE ROUTINE FOR THE SWAPPED ORDER

19080XK = CI

NEITHER: LOAD THE LEFT STRING, PUSH IT WITH ENTRY 47, LOAD THE RIGHT ONE AND CALL

19090GOSUB 20600
19100CI = 47

ENTRY 47 PUSHES THE LOADED STRING

19110GOSUB 16530
19120CI = XK
19130GOTO 19770
19200GOSUB 19700

SCRN( : LOAD X AND PUSH IT AS A BYTE (ENTRY 98), THEN LOAD Y AND CALL ENTRY 135

19210NB = RH
19220CI = 135

ENTRY 135: SCRN(

19230GOTO 19600
19300GOSUB 20520

ONE-ARGUMENT FUNCTIONS: LOAD THE ARGUMENT AND CALL

19310GOTO 19800
19400GOSUB 20520

LEFT$, RIGHT$, MID$: LOAD THE STRING, THEN THE NUMBER

19410GOSUB 20500
19420IF NQ = 53 AND TP(TB + 1,0) = 17 THEN CI = 98: GOSUB 19720:CI = XK + 1:TB = TB + 1:NB = TP(TB,1): GOSUB 20520

MID$ WITH THREE ARGUMENTS: PUSH THE SECOND AS A BYTE (ENTRY 98), LOAD THE THIRD (FROM THE OPERATION 17 TRIPLE) AND CALL ENTRY 118 INSTEAD OF 117

19430GOSUB 19720

JSR, INTEGER OR REAL ENTRY BY THE TYPE OF THE NUMBER

19440GOTO 19810
19500GOSUB 20520

PEEK: LOAD THE ADDRESS; AN INTEGER ADDRESS USES THE ENTRY 3 BYTES LOWER

19510IF FN IV(NB) THEN GOSUB 16600: GOTO 19810

(THE ENTRY 3 BYTES LOWER)

19520GOSUB 16530
19530GOTO 19810
19600GOSUB 19700

PDL, CHR$: LOAD THE ARGUMENT AND CALL, INTEGER OR REAL ENTRY

19610GOTO 19810
19700GOSUB 20520

ENTRY: LOAD THE OPERAND, THEN ...

19720IF FN IV(NB) THEN 16530

ENTRY: ... JSR, THE ENTRY AS IT IS FOR AN INTEGER OPERAND, 3 BYTES LOWER FOR A REAL ONE

19730GOTO 16600
19740NB = RH

ENTRY: APPLY THE RIGHT OPERAND

19750GOSUB 20600

ENTRY: APPLY THE OPERAND IN NB WITH OPERATION K4

19760GOTO 19810
19770NB = RH

ENTRY: APPLY THE RIGHT OPERAND, THEN CALL

19780GOSUB 20600

ENTRY: APPLY NB, THEN CALL

19800GOSUB 16530

ENTRY: JSR TO CALL TABLE ENTRY CI (ALSO FRE AND POS, WHOSE ARGUMENT IS NOT LOADED)

19810WHERE DOES THE RESULT GO: THE NEXT TRIPLE THAT USES IT, OR A TEMPORARY

19810SF = TB + 1

LOOK AT THE TRIPLES AFTER THIS ONE

19820IF NQ = 16 OR NQ = 20 OR NQ = 47 OR NQ > 49 THEN 19960

CONCATENATION, STRING ARRAY ELEMENTS, STR$, CHR$, LEFT$, RIGHT$ AND MID$ GIVE STRINGS

19830IF SF >= U2 THEN 20110

THE LAST TRIPLE: THE RESULT STAYS IN THE ACCUMULATOR

19840NQ = TP(SF,0): IF NQ < 0 OR NQ = 16 THEN SF = SF + 1: GOTO 19830

THE NEXT OPERATION (OPERANDS AND CONCATENATIONS ARE PASSED OVER)

19850IF FN LO(NQ) AND TP(SF,1) = TB THEN 20070

IT TAKES THIS RESULT FROM THE ACCUMULATOR AS ITS LEFT OPERAND ...

19860IF FN RT(NQ) AND TP(SF,2) = TB THEN 20070

... OR AS ITS RIGHT ONE: KEEP IT THERE

19870K4 = - 1

OTHERWISE STORE IT IN A TEMPORARY: AN INTEGER ONE (KIND -8) ...

19880K8 = - 8

(KIND -8)

19890IF RV THEN K4 = - 3:K8 = - 6

... OR A REAL ONE (KIND -6)

19900TP(TB,0) = K8

THE TRIPLE NOW STANDS FOR THE TEMPORARY

19910GOSUB 16800

TAKE A FREE TEMPORARY OF THE TYPE

19920TP(TB,1) = VB

(ITS SYMBOL)

19930K4 = 1

OPERATION 1 STORES THE RESULT IN IT

19940GOSUB 15300

(THE STORE)

19950GOTO 20110

19960A STRING RESULT IS KEPT IF THE NEXT STRING OPERATION USES IT, ELSE SAVED IN A STRING TEMPORARY

19960IF SF >= U2 THEN 20110

A STRING RESULT: THE LAST TRIPLE KEEPS IT

19970NQ = TP(SF,0): IF NQ < 16 OR NQ > 16 AND NQ < 23 AND NQ <> 20 OR NQ > 28 AND NQ < 46 THEN SF = SF + 1: GOTO 19960

THE NEXT TRIPLE THAT WORKS ON STRINGS

19980IF (NQ = 16 OR NQ > 22 AND NQ < 29) AND (TP(SF,1) = TB OR TP(SF,2) = TB) THEN 20090

A CONCATENATION OR STRING RELATION THAT USES IT KEEPS IT

19990IF NQ > 45 AND TP(SF,1) = TB THEN 20090

SO DOES A STRING FUNCTION THAT TAKES IT AS ITS STRING

20000K4 = - 2

OTHERWISE IT GOES TO A STRING TEMPORARY (KIND -7)

20010TP(TB,0) = - 7

(KIND -7)

20020GOSUB 16800

TAKE A FREE STRING TEMPORARY

20030TP(TB,1) = VB
20040K4 = 1

OPERATION 1 STORES IT

20050GOSUB 15340

(THE STORE, NO MASK NEEDED)

20060GOTO 20110
20070K8 = - 9

THE RESULT STAYS IN THE ACCUMULATOR: KIND -9 FOR AN INTEGER ...

20080IF NOT RV THEN 20100
20090K8 = - 5

... -5 FOR A REAL OR A STRING

20100TP(TB,0) = K8

THE TRIPLE'S NEW KIND

20110TB = TB + 1

THE NEXT TRIPLE

20120GOTO 17230

THE NEXT TRIPLE

20130NB = U2 - 1

ALL TRIPLES DONE: NB = THE LAST ONE

20140U2 = 1

THE TRIPLE TABLE IS EMPTY AGAIN

20150K8 = TP(NB,0)

ITS KIND OR OPERATION

20160IF TG THEN TU = LZ:LK = NQ: RETURN

THE TARGET OF AN ASSIGNMENT: KEEP ITS SYMBOL AND KIND FOR THE STORE

20170IF K8 > 0 THEN 20210

AN OPERATION: ITS RESULT IS IN THE ACCUMULATOR

20180FD = 1

A SINGLE OPERAND: LOADING IT SETS THE FLAGS

20190IF - 1 = K8 AND NOT SE THEN RV = 0:RN = 0

A SINGLE INTEGER OPERAND STAYS AN INTEGER UNLESS A REAL IS WANTED

20200GOTO 20600

LOAD IT

20210IF SE AND NOT RV THEN CI = 131: GOTO 16530

AN INTEGER RESULT WHERE A REAL IS WANTED: FLOAT IT (ENTRY 131)

20220RETURN

20300STORE THE RESULT OF AN EXPRESSION IN THE TARGET

20300IF LK < 0 THEN 20340

THE TARGET IS A SIMPLE VARIABLE

20310IF LK = 21 AND NOT (TG AND EP = 1) THEN CI = 1: GOSUB 16530

AN ARRAY ELEMENT: A VALUE FOR AN INTEGER ARRAY THAT IS NOT ALREADY AN INTEGER (FROM INPUT, READ, GET OR A REAL EXPRESSION) IS MADE AN INTEGER (ENTRY 1, AYINT)

20320CI = 67

THEN ENTRY 67 STORES IT AT THE ELEMENT'S ADDRESS

20330GOTO 16530

(THE CALL)

20340K4 = 1

OPERATION 1 STORES THE ACCUMULATOR ...

20350IF - 1 = LK AND NOT (TG AND EP = 1) THEN K4 = 7

... OPERATION 7 STORES THE FLOATING POINT ACCUMULATOR IN AN INTEGER VARIABLE

20360VB = TU

THE TARGET'S SYMBOL

20370IF K4 = 1 THEN J3 = VB:SJ = PC

REMEMBER A PLAIN STORE: A LOAD OF THE SAME VARIABLE RIGHT AFTER IT IS LEFT OUT

20380IF - 2 = LK THEN 15340

A STRING VARIABLE NEEDS NO MASK

20390GOTO 15300

(EMIT THE STORE)

20500LOAD OR APPLY AN OPERAND

20500NB = RH

ENTRY: LOAD THE RIGHT OPERAND ...

20520IF NOT FN IA(NB) THEN SS = K4:K4 = 0: GOSUB 20600:K4 = SS

ENTRY: ... OR NB, UNLESS IT IS ALREADY IN THE ACCUMULATOR (OPERATION 0, KEEPING K4)

20530RETURN
20600VB = TP(NB,1)

ENTRY: APPLY NB WITH OPERATION K4: ITS SYMBOL ...

20610KD = TP(NB,0)

... AND KIND

20620IF - 8 <= KD AND - 6 >= KD THEN GOSUB 16900

A TEMPORARY IS FREE AGAIN ONCE IT IS USED

20630IF - 4 = KD THEN KD = CI:CI = 36: GOSUB 16530:CI = KD:WF = VB: GOTO 15450

A STRING LITERAL: JSR TO ENTRY 36 AND THE LITERAL'S ADDRESS

20640IF RN AND FN IV(NB) AND K4 <= 7 THEN K4 = K4 + 6: IF SC(VB + 2) = - 10 THEN SK = K4:L1 = SC(VB + 3): GOSUB 12230:K4 = SK - 6

AN INTEGER USED AS A REAL TAKES THE OPERATION+6; AN INTEGER CONSTANT IS REPLACED BY ITS REAL FORM, ENTERED NOW IF NEEDED

20650IF (K4 = 0 OR K4 = 20) AND J3 = VB AND PC - 3 = SJ THEN RETURN

A LOAD (OR AND/OR TEST) OF THE VARIABLE JUST STORED IS LEFT OUT WHEN THE STORE WAS THE LAST CODE WRITTEN

20660IF - 7 = KD OR - 2 = KD THEN 15340

STRING VARIABLES AND TEMPORARIES NEED NO MASK

20670IF K4 <> 20 THEN 15300

A LOAD OR OTHER OPERATION, MARKED IN THE MASK

20680GOSUB 15340

AN AND / OR TEST: OPERATION 20

20690IF FN IV(NB) THEN GOSUB 15620: GOSUB 15500

AN INTEGER TAKES THREE MORE BYTES FOR THE ORA OF ITS SECOND BYTE (PASS 2 FILLS THEM IN)

20700RETURN

20800SET THE FLAGS FOR IF

20800IF FZ THEN WF = 40357: GOTO 15500

A REAL: LDA $9D (THE EXPONENT IS ZERO ONLY FOR ZERO)

20810WF = 41125

AN INTEGER: LDA $A0 ...

20820GOSUB 15500
20830WF = 41221

... ORA $A1

20840GOTO 15500

20900COMPILATION TERMINATED: DELETE THE OBJECT FILE AND RESTORE DOS

20900GOSUB 16000

END THE DIRECT FILE OUTPUT

20910PRINT CO$

CLOSE ALL FILES

20920PRINT DI$;"DELETE";OD$;OO$

AND DELETE THE UNFINISHED OBJECT FILE

20930PRINT
20940PRINT
20950PRINT "*****COMPILATION TERMINATED"

(THE FILES STAY CLOSED)

20960PRINT
20970FOR K8 = 0 TO 5

PUT BACK THE SIX BYTES OF DOS THAT PASS 0 CHANGED

20980POKE DP(K8,0),DP(K8,1)

THE ADDRESS AND THE ORIGINAL BYTE

20990NEXT K8
21000PRINT OP$;LN$;DN$

OPEN AND CLOSE THE LINE NUMBER FILE; THE PROGRAM ENDS HERE

21010PRINT CO$

Variables

NAMETYPEDEFINEDCOMMONMEANING
BFINTEGER70START OF THE LISTING BUFFER ($0280)
BKINTEGER130END OF THE LISTING BUFFER; A LINE THAT REACHES IT IS TOO LONG
BMINTEGER120NEXT FREE BYTE IN THE LISTING BUFFER
BOINTEGER100START OF THE TEXT OF A STRING LITERAL OR DATA ITEM IN THE LISTING BUFFER
BP$STRING15037TWO BELLS, SOUNDED BEFORE EACH ERROR MESSAGE
BXINTEGER1201 IF THE OPERATOR BEING REDUCED TAKES TWO OPERANDS
C3INTEGER3034COMMON KIND: -1 NONE, 0 DEFINE, 255 USE
CCINTEGER11025ADDRESS OF THE LINK WORD OF THE LAST DATA BLOCK (DATA BLOCKS ARE CHAINED)
CC(135)INTEGER()110CALL TABLE: ADDRESSES OF THE LIBRARY AND ROM ROUTINES, BY INDEX
CDINTEGER4024START OF THE COMMON BLOCK (THE PROGRAM START BEFORE COMMON MOVED IT)
CIINTEGER40INDEX OF THE ROUTINE IN THE CALL TABLE CC()
CO$STRING15040DOS CLOSE COMMAND
DINTEGER60ENTRY ADJUSTMENT: 0, OR -3 FOR THE OTHER TYPE'S ENTRY
D2INTEGER120DECLARATION STATE: 2 BEFORE ANY STATEMENT, 1 AFTER COMMON, 0 AFTER A STATEMENT
D3INTEGER901 AFTER AN UNCONDITIONAL TRANSFER: FURTHER STATEMENTS ON THE LINE ARE NOT REACHED
DI$STRING15038CONTROL-D, THE DOS COMMAND PREFIX
DN$STRING15046SLOT AND DRIVE OF THE BOOT DRIVE (",S6,D1")
DP(5,1)INTEGER()13035DOS PATCH TABLE: DP(I,0) ADDRESS (AS A SIGNED WORD, ADDRESS-65536), DP(I,1) ORIGINAL BYTE
DWINTEGER7010DOS STATE BYTE AT $AA52: POKED BEFORE EACH DIRECT FILE READ OR WRITE
EDINTEGER10026OBJECT FILE BASE: FILE POSITION = PC - ED (THE FILE STARTS WITH THE BSAVE HEADER)
ELINTEGER1011LIBRARY ROUTINE ($0947) THAT RESETS THE STACK, DROPPING EVERY PENDING GOSUB AND FOR, AND RESETS THE DATA POINTER; CALLED AFTER AN ERROR
EOINTEGER501 WHEN THE EXPRESSION IS COMPLETE
EPINTEGER80TYPE OF THE EXPRESSION: 1 INTEGER, 2 STRING, 3 REAL
FINTEGER70WHICH FILE DOS IS SET UP FOR: 1 SOURCE (READ), 2 OBJECT (WRITE), 3 LINE NUMBER FILE
F(4)INTEGER()70ARGUMENT DESCRIPTION OF A FUNCTION: F(0) NUMBER, F(1..3) TYPES, F(4) ARGUMENT BEING READ
FCINTEGER30331 ONCE A FATAL ERROR HAS BEEN REPORTED (NO MORE CODE IS WRITTEN)
FDINTEGER1101 IF THE FLAGS ALREADY REFLECT THE RESULT (IF NEEDS NO TEST)
FGINTEGER1301 IF THE FOR LOOP VARIABLE IS REAL, 0 IF IT IS AN INTEGER
FQINTEGER701 TO WRITE TO THE LINE NUMBER FILE EVEN AFTER A FATAL ERROR
FZINTEGER60WHICH FLAG TEST IF NEEDS: 0 INTEGER (LDA $A0/ORA $A1), 1 REAL (LDA $9D)
GZINTEGER100INSIDE DEF FN: NAME HASH OF THE PARAMETER, ELSE 0
HEREAL15520HIGH BYTE OF THAT WORD
HWINTEGER807LAST CHAIN HEAD IN SC(); ENTRIES ARE ALLOCATED ABOVE IT
HYINTEGER130NAME HASH (99*FIRST CHARACTER+SECOND), OR LINE NUMBER-32767
IVINTEGER120BYTE JUST READ FROM THE SOURCE FILE
IXINTEGER10017ADDRESS OF THE ONE-BYTE TRANSFER CELL FOR QB AND WS ($0376)
IZINTEGER902 WHILE NAMES ARE BEING DECLARED INTEGER (ALSO AFTER INTEGER *), ELSE 0
JINTEGER50INNER LOOP INDEX; 1 IF AN ARRAY WAS DIMENSIONED BEFORE
J3INTEGER130LAST VARIABLE STORED BY THE CODE (A LOAD RIGHT AFTER IT IS LEFT OUT)
JSREAL8240CURRENT SOURCE LINE NUMBER
K0INTEGER90NEXT FREE WORD IN THE SYMBOL TABLE SC()
K4INTEGER50TYPE CODE (-3 REAL, -2 STRING, -1 INTEGER, +22 FOR AN ARRAY), OR AN OPERATION NUMBER
K8INTEGER60LOOP INDEX
KDINTEGER60KIND OF THAT OPERAND (ITS TP(X,0) ENTRY)
KVINTEGER3014ADDRESS OF THE FIVE PACKED BYTES LEFT BY THE USR ROUTINE ($0371)
KXINTEGER1305FIRST CONSTANT CHAIN HEAD IN SC()
LINTEGER1306FIRST LINE NUMBER CHAIN HEAD IN SC()
L1REAL4640NUMERIC VALUE OF A LINE NUMBER, DIMENSION OR CONSTANT
LBINTEGER4019LIBRARY ADDRESS, STORED AS ADDRESS-32767
LHINTEGER6023NUMBER OF SOURCE LINES READ
LKINTEGER110OPERATION OF THE LAST TRIPLE (TELLS THE STORE WHAT IS IN THE ACCUMULATOR)
LMINTEGER9012LENGTH OF THE RUNTIME LIBRARY IN BYTES (4013)
LN$STRING15045NAME OF THE LINE NUMBER FILE ("CLINENUM")
LQINTEGER8018ADDRESS OF THE ROUTINE THAT LISTS THE TOKENIZED LINE IN THE INPUT BUFFER ($038D)
LZINTEGER110LEFT OPERAND OF THE TRIPLE
MJINTEGER90NEXT BYTE OF THE SOURCE LINE (ONE BYTE LOOKAHEAD); -1 AT END OF PROGRAM
MLINTEGER130SCRATCH
MNINTEGER109DRIVE MOTOR-OFF SWITCH FOR THE BOOT SLOT
MXINTEGER808DRIVE MOTOR-ON SWITCH FOR THE BOOT SLOT ($C089+SLOT*16), TOUCHED TO KEEP THE DRIVE SPINNING
N1INTEGER2030RESUME/DEBUG CODE OPTION (1 = YES)
N4INTEGER100NUMBER OF DIMENSIONS IN A DIM OR DECLARATION
N5INTEGER801 IF THE LAST SCAN FOUND NO NAME OR NO NUMBER
NBINTEGER60OPERAND BEING LOADED OR APPLIED
NGINTEGER802NUMBER OF CONSTANT HASH CHAINS (32)
NKINTEGER803NUMBER OF LINE NUMBER HASH CHAINS (32)
NQINTEGER60OPERATION CODE OF THE TRIPLE
NUINTEGER801NUMBER OF VARIABLE HASH CHAINS IN THE SYMBOL TABLE (32)
O2INTEGER80OPERATION CODE USED TO SELECT THE GENERATOR, OR A SUBSCRIPT COUNT
O4INTEGER2028COMPILATION LISTING OPTION (1 = YES)
OD$STRING15044OBJECT FILE NAME
OE(16,2)INTEGER()140OPERATOR TABLE: OE(I,0) TOKEN, OE(I,1) PRIORITY ON THE STACK, OE(I,2) PRIORITY ARRIVING
OHINTEGER8032INTEGER CONSTANTS OPTION (1 = YES)
OOINTEGER2029PAUSE ON ERRORS OPTION (1 = YES)
OO$STRING15048SLOT AND DRIVE OF THE OBJECT FILE
OP$STRING15039DOS OPEN COMMAND
OWINTEGER50BYTE TO WRITE TO THE OBJECT FILE
P3INTEGER70BYTE WAITING TO BE COPIED INTO THE LISTING BUFFER
P8INTEGER2031INTEGER ARITHMETIC OPTION (1 = YES)
PCINTEGER10022ADDRESS OF THE NEXT OBJECT CODE BYTE, AS ADDRESS-32767
PEINTEGER70LOW BYTE OF THE NEXT LINE LINK (A ZERO LINK ENDS THE PROGRAM)
PNINTEGER130ADDRESS TO PATCH WITH THE CURRENT CODE ADDRESS
QBINTEGER3015ADDRESS OF THE ROUTINE THAT READS ONE BYTE FROM THE OPEN FILE INTO IX ($037E)
RCINTEGER701 FOR THE STATEMENT RIGHT AFTER THEN (NO RESUME/DEBUG CALL)
RHINTEGER130RIGHT OPERAND OF THE TRIPLE
RIINTEGER90SAVED ID DURING AN INTEGER DECLARATION LIST
RNINTEGER601 IF THE OPERANDS ARE USED AS REALS
RVINTEGER1101 IF THE RESULT IS REAL
RV$STRING15041DOS READ COMMAND
S3INTEGER100SAVED SYMBOL (FOR LOOP VARIABLE), OR THE NUMBER OF LINES IN AN ON LIST
S8INTEGER80SIZE OF THE PARSE STACK (100)
SB$STRING15047SLOT AND DRIVE OF THE SOURCE FILE
SCINTEGER10271 IF THE SOURCE AND OBJECT FILES ARE ON THE BOOT DRIVE (MOTOR KEPT ON), ELSE 0
SC(5350)INTEGER()1036SYMBOL TABLE: CHAIN HEADS, THEN ENTRIES LINKED THROUGH THEIR FIRST WORD
SEINTEGER1101 WHEN THE EXPRESSION'S VALUE MUST BE REAL (A REAL TARGET OR A FUNCTION BODY)
SFINTEGER80TRIPLE BEING EXAMINED WHEN DECIDING WHERE A RESULT GOES
SI$STRING15043SOURCE FILE NAME
SJINTEGER70CODE ADDRESS OF THAT STORE
SKINTEGER60SAVED OPERATION NUMBER
SSINTEGER60SAVED OPERATION NUMBER
SUINTEGER40NEXT FREE PLACE FOR AN OPERATOR ON THE PARSE STACK (GROWS UP)
SZ(100)INTEGER()140PARSE STACK: OPERATORS FROM THE BOTTOM, OPERANDS FROM THE TOP
T0INTEGER120CURRENT TOKEN OR CHARACTER OF THE SOURCE LINE
T5INTEGER100INSIDE DEF FN: THE PARAMETER'S SYMBOL
T9INTEGER80SCRATCH: A SYMBOL OR SIZE BEING WORKED ON
TBINTEGER130TRIPLE BEING GENERATED
TGINTEGER701 WHEN THE EXPRESSION IS THE VALUE OF AN ASSIGNMENT
TPINTEGER120OPERATOR ON TOP OF THE PARSE STACK
TP(101,2)INTEGER()120TRIPLE TABLE: TP(I,0) OPERATION OR OPERAND KIND, TP(I,1) LEFT, TP(I,2) RIGHT
TUINTEGER130SYMBOL OF THE EXPRESSION'S RESULT
TZINTEGER50SIZE OF THE SYMBOL TABLE (5350 WORDS)
UINTEGER90OPERATION NUMBER FOR A MEMORY OPERAND, OR THE OPERAND SAVED FOR LATER
U2INTEGER130NUMBER OF TRIPLES IN TP() PLUS ONE
U7INTEGER100TOKEN NUMBER OF THE STATEMENT (TOKEN-128), THEN THE CALL TABLE INDEX IT SELECTS
URINTEGER13020PROGRAM START, STORED AS ADDRESS-32767; MOVED UP BY COMMON DECLARATIONS
UVINTEGER8013ADDRESS OF THE USR ROUTINE THAT PACKS A NUMBER INTO FIVE BYTES ($0377)
UZINTEGER60SIZE OF THE TRIPLE TABLE (100)
V3INTEGER80NEXT FREE PLACE FOR AN OPERAND ON THE PARSE STACK (GROWS DOWN)
VBINTEGER50VALUE PASSED TO AND FROM THE STACK AND SYMBOL ROUTINES (USUALLY A SYMBOL)
VCINTEGER4021VARIABLES ADDRESS ASKED FOR, AS ADDRESS-32767, OR -32767 FOR END OF PROGRAM
VOINTEGER904FIRST VARIABLE CHAIN HEAD IN SC() (9; 1-4 HOLD FN AND LINE SYMBOLS, 5-8 TEMPORARIES)
WFREAL1450WORD TO WRITE TO THE OBJECT FILE (A LINK OR ADDRESS)
WL$STRING200WORK STRING: KEYWORD BEING MATCHED, DIGITS OF A NUMBER, NAME OF AN ERROR
WNINTEGER120TYPE THE CALL TABLE ENTRY IS FOR: 1 INTEGER, 3 REAL
WO$STRING15042DOS WRITE COMMAND
WSINTEGER3016ADDRESS OF THE ROUTINE THAT WRITES THE BYTE IN IX TO THE OPEN FILE ($0387)
XFINTEGER100TOKEN OR CHARACTER EXPECTED NEXT (SYNTAX CHECK)
XKINTEGER130CALL TABLE INDEX FOR THE OPERANDS IN THE OTHER ORDER (SWAPPED COMPARISON)
FN LTREALTRUE IF X IS A LETTER
FN DGREALTRUE IF X IS A DIGIT
FN OSREALTRUE IF X IS AN OPERATOR TOKEN (+ - * / ^ AND OR > = < NOT, OR A TWO-CHARACTER RELATION)
FN OEREALTRUE IF X IS AN OPERATOR, A PARENTHESIS OR THE END OF THE LINE
FN NUREALTRUE IF X IS A NUMERIC FUNCTION TOKEN (SGN TO LEN, VAL, ASC)
FN SFREALTRUE IF X IS A STRING FUNCTION TOKEN (STR$, CHR$, LEFT$, RIGHT$, MID$)
FN ESREALTRUE IF X ENDS A STATEMENT (COLON OR END OF LINE)
FN UBREALX STORED AS A WORD (X+32767)
FN IVREALTRUE IF TRIPLE X GIVES AN INTEGER (INTEGER TEMPORARY, INTEGER VARIABLE OR RESULT)
FN LOREALTRUE IF OPERATION X TAKES ITS LEFT OPERAND FROM THE ACCUMULATOR
FN RTREALTRUE IF OPERATION X TAKES ITS RIGHT OPERAND FROM THE ACCUMULATOR
FN IAREALTRUE IF TRIPLE X IS IN THE ACCUMULATOR
XREALPARAMETER OF THE DEF FN FUNCTIONS (EACH FUNCTION HAS ITS OWN)