1 REM================================== 2 REM MINI-COMP 3 REM RUPERT REPORT #59 4 REM A MINIMAL COMPILER FOR THE C-64 5 REM======= RUN 2000 TO COMPILE ====== 8 REM THESE ARE ALL ALLOWED TYPES OF STATEMENTS 9 REM A AND A% BOTH REPRESENT THE SAME INTEGER 10 A=50 20 B=-10 30 C=A 40 D=A+B 50 IF A=B THEN 60 60 GOTO 70 70 PRINT 80 PRINT A 90 PRINT B; 100 PRINT CHR$(C) 110 PRINT CHR$(D); 120 A$=CHR$(C) 130 B$="HELLO" 140 C$=A$ 150 B$=B$+A$ 160 PRINT A$ 170 PRINT B$; 999 END 1000 REM --- COMMON ROUTINES --- 1100 C=PEEK(M): M=M+1: PRINT C,: IF C=32 THEN 1100: REM IGNORE SPACES 1110 IF C=0 THEN PRINT 1120 RETURN 1300 VT=0: REM VT=0, NOT A VARIABLE; VT=1, INTEGER; VT=2, STRING 1310 IF C<65 OR C>90 THEN RETURN :REM NOT A VARIABLE 1320 VN=C: C1=PEEK(M): M=M+1: REM VN=VAR NAME 1330 IF C1=36 THEN VT=2: PRINT C1,: RETURN: REM '$ STRING VAR 1340 IF C1=37 THEN VT=1: GOTO 1360: PRINT C1,: REM '% INTEGER VAR 1350 VT=1: M=M-1: GOTO 1360: REM DEFAULT=INTEGER 1355 M=M-1: RETURN: REM NOT A VARIABLE 1360 AD=(VN-65)*2+VM 1370 NX=AD: GOSUB 1400: A0=NL: A1=NH 1380 NX=AD+1: GOSUB 1400: A2=NL: A3=NH 1390 RETURN 1400 NH=INT(NX/256) 1410 NL=NX-256*NH 1420 RETURN 1500 FOR KK=1 TO N 1510 IF CM>EM THEN PRINT"OUT OF MEMORY - COMPILED PRGM TOO LARGE": END 1520 POKE CM,C(KK) 1530 PRINT CM;":";C(KK) 1540 CM=CM+1: NEXT 1550 RETURN 1600 REM GET ADDR OF STRING VAR WITH NAME IN VN 1620 SV=VN-65 :REM STRING VARIABLE # 1630 IF SV<0 OR SV>25 THEN EC=65: GOSUB 10000: STOP 1640 IF SB(SV)=0 THEN GOTO 1660 :REM NEW STRING 1650 MEM=EM-SB(SV)*256+1: GOTO 1690 1660 NB=NB+1: IF NB>26 THEN PRINT"TOO MANY STRING VARIABLES": STOP 1670 SB(SV)=NB :REM BLOCK # 1680 MEM=EM-NB*256+1: IF (MEM-CM)<256 THEN PRINT"OUT OF STRING SPACE": STOP 1690 NX=MEM: GOSUB 1400: RETURN :REM ADDR IN NL/NH 2000 REM === INITIALIZATION ====== 2010 DIM LL(50,2) :REM LL(N,1)=LINE # OF NTH LINE 2015 :REM LL(N,2)=COMPILED MEM LOCATION OF THIS LINE 2020 DIM C(100) :REM STORES OBJECT CODE BYTES 2030 FALSE=0: TRUE=NOT FALSE 2040 DEF FNPTR(M)=PEEK(M)+256*PEEK(M+1) 2050 VM=49152 :REM $C000 START OF VARIABLE MEM 2060 PM=49408 :REM $C100 START OF OBJECT MEMORY 2070 EM=53247 :REM $CFFF END OF OBJECT MEMORY 2075 DIM SB(25), S(255): SM=52992: NB=0 :REM STRING VARIABLES 2080 BT=2049 :REM $0800 START OF BASIC TEXT 2085 GOSUB 11000 :REM PUT PRINT RTN IN MEM 2090 M=BT :REM NEXT SOURCE MEMORY TO PEEK 2100 SN=1 :REM CURRENT SOURCE STATEMENT NUMBER 2110 CM=PM :REM NEXT OBJECT MEMORY TO POKE 2120 FOR N=VM TO VM+51: POKE N,0: NEXT : REM CLR VAR'S 2125 REM ============= MAIN ============ 2130 PTR=FNPTR(M): M=M+2 :REM NEXT LINE PTR 2140 LN=FNPTR(M): M=M+2 :REM CURRENT LINE # 2150 IF LN>999 THEN PRINT "=== END OF PASS 1 ===": GOTO 2400 2160 PRINT " CURRENT LINE # ="; LN 2170 LL(SN,1)=LN :REM CURRENT LINE # 2180 LL(SN,2)=CM :REM START OBJ MEM LOC 2190 SN=SN+1 :REM # SOURCE STATEMENTS 2200 REM --- GET BYTE --- 2210 GOSUB 1100 :REM FETCH NEXT BYTE 2220 GOSUB 1300: IF VT=1 THEN GOSUB 3000 : GOTO 2290: REM 'VARIABLE 2225 IF VT=2 THEN GOSUB 9000: GOTO 2290 :REM STRING VARIABLE 2230 IF C=139 THEN GOSUB 4000: GOTO 2290: REM 'IF 2240 IF C=137 THEN GOSUB 5000: GOTO 2290: REM 'GOTO 2250 IF C=153 THEN GOSUB 6000: GOTO 2290: REM 'PRINT 2260 IF C=128 THEN GOSUB 7000: GOTO 2290: REM 'END 2270 IF C=143 THEN GOSUB 8000: GOTO 2290: REM 'REM 2280 PRINT "UNKNOWN COMMAND CODE";C;"IN LINE";LL(SN,1):STOP 2290 IF C>0 THEN EC=0: GOSUB 10000: STOP :REM 'EOL 2300 GET K$:IF K$="" THEN 2130 :REM BACK FOR MORE 2310 GET K$:IF K$="" THEN 2310 2320 GOTO 2130 2400 REM - PASS 2 - FIX JUMP ADDRESSES 2410 IF JI=0 THEN 2570 :REM NO JUMPS 2420 FOR N=1 TO JI :REM CHECK ITEMS IN JUMP TABLE 2430 :MM=JT(N,1) :REM REFERENCED LINE # 2440 :FOR J=1 TO SN :REM CHECK ACTUAL LINE #S 2445 :REM - GET OBJ MEM TARGET ADDRESS AND JMP ADDRESS: 2450 :IF MM=LL(J,1) THEN TADDR=JT(N,2): JADDR=LL(J,2): GOTO 2490 2460 :NEXT J 2470 :REM NO MATCH FOUND 2480 :EC=1: LN=JT(N,0): GOSUB 10000:STOP 2490 :NX=JADDR :REM ADDR OF LINE # MM 2530 :GOSUB 1400 :REM CONVERT LINE # 2540 :POKE TADDR,NL :REM USE ADDR IN JUMP TABLE 2550 :POKE TADDR+1,NH 2560 NEXT N :REM NEXT JUMP TABLE ITEM 2570 PRINT"=== END OF PASS 2 ===" 2580 PRINT"TO EXECUTE THE COMPILED PROGRAM, ENTER" 2590 PRINT" SYS"; PM 2595 PRINT"OBJECT CODE RESIDES FROM";PM;"TO";CM-1 2600 END 3000 REM <<< A=(-)NN, A=B, A=B+C >>> 3010 D0=A0: D1=A1 :REM ADDR OF A'S LSB 3020 D2=A2: D3=A3 :REM A'S MSB 3030 GOSUB 1100: IF C<>178 THEN 9000 :REM NOT '= 3040 GOSUB 1100 :REM '-, NN, OR B 3050 GOSUB 1300: IF VT=1 THEN 3400 3055 REM <<< A=(-)NN >>> 3060 IF C=171 THEN C$="-" :REM '- 3065 IF C<>171 THEN C$=" "+CHR$(C) :REM '0-9 3070 GOSUB 1100 :REM GET DIGITS OF NN 3080 IF C=0 THEN 3120 3085 IF CHR$(C)<"0" OR CHR$(C)>"9" THEN EC=48: GOSUB 10000: STOP 3090 C$=C$+CHR$(C) 3100 GOTO 3070 3120 NN=VAL(C$) 3130 NN%=NN :REM ERROR CHECK 3140 IF NN<0 THEN NN=NN+65536 :REM CONVERT (-32768,32767) TO (0,65535) 3150 NX=NN: GOSUB 1400 3170 MSB=NH: LSB=NL 3175 :REM LDA #NN(LSB), STA A(LSB), LDA #NN(MSB), STA A(MSB) 3180 N=10: C(1)=169: C(2)=LSB: C(3)=141: C(4)=D0: C(5)=D1 3190 C(6)=169: C(7)=MSB: C(8)=141: C(9)=D2: C(10)=D3 3200 GOSUB 1500 :REM POKE VALUES INTO OBJECT MEMORY 3210 RETURN 3400 REM <<< A=B OR A=B+C >>> 3410 S0=A0: S1=A1 :REM B'S LSB ADDR 3420 S2=A2: S3=A3 :REM B'S MSB 3430 GOSUB 1100 3440 IF C=0 THEN 3600 :REM A=B 3450 REM <<< A=B+C >>> 3460 IF C<>170 THEN EC=170: EC$=" + ": GOSUB 10000: STOP :REM TEST '+ 3470 GOSUB 1100: GOSUB 1300: IF VT<>1 THEN EC=65: GOSUB 10000: STOP: REM 'C 3480 GOSUB 1100: IF C>0 THEN EC=0: GOSUB 10000: STOP :REM 'EOL 3490 S4=A0: S5=A1 :REM ADDR C'S LSB 3500 S6=A2: S7=A3 :REM C'S MSB 3530 REM CLC, LDA B(LSB), ADC C(LSB),STA A(LSB) 3535 REM LDA B(MSB), ADC C(MSB), STA A(MSB) 3540 N=19: C(1)=24: C(2)=173: C(3)=S0: C(4)=S1 3550 C(5)=109: C(6)=S4: C(7)=S5: C(8)=141: C(9)=D0: C(10)=D1 3560 C(11)=173: C(12)=S2: C(13)=S3: C(14)=109: C(15)=S6: C(16)=S7 3570 C(17)=141: C(18)=D2: C(19)=D3 3580 GOSUB 1500 3590 RETURN 3600 REM <<< A=B >>> 3610 REM LDA B(LSB), STA A(LSB), LDA B(MSB), STA A(MSB) 3620 N=12: C(1)=173: C(2)=S0: C(3)=S1: C(4)=141: C(5)=D0: C(6)=D1 3630 C(7)=173: C(8)=S2: C(9)=S3: C(10)=141: C(11)=D2: C(12)=D3 3640 GOSUB 1500 3650 RETURN 4000 REM <<< IF A=B THEN MM >>> 4010 GOSUB 1100 :REM 'A 4020 GOSUB 1300: IF VT<>1 THEN EC=65: GOSUB 10000: STOP 4030 S0=A0: S1=A1: S2=A2: S3=A3 4040 GOSUB 1100: IF C<>178 THEN EC=178: GOSUB 10000: STOP :REM '= 4050 GOSUB 1100 :REM 'B 4060 GOSUB 1300: IF VT<>1 THEN EC=65: GOSUB 10000: STOP 4070 GOSUB 1100 :REM 'THEN 4080 IF C<>167 THEN EC=167: GOSUB 10000: STOP 4090 C$="" 4100 GOSUB 1100: IF C=0 THEN 4120 :REM GET MM 4110 C$=C$+CHR$(C): GOTO 4100 4120 MM=VAL(C$) 4130 IF MM<0 OR MM>999 THEN EC=1: GOSUB 10000: STOP 4140 JI=JI+1 :REM JUMP TABLE INDEX 4150 JT(JI,0)=LN :REM CURRENT LINE # 4160 JT(JI,1)=MM :REM TARGET LINE # 4170 JT(JI,2)=CM+17 :REM MEM LOC AFTER 'JMP 4180 REM LDA A(MSB), CMP B(MSB), BNE EXIT, 4185 REM LDA A(LSB), CMP B(LSB), BNE EXIT, JMP MM 4190 N=19: C(1)=173: C(2)=S2: C(3)=S3 4200 C(4)=205: C(5)=A2: C(6)=A3 4210 C(7)=208: C(8)=11: C(9)=173: C(10)=S0: C(11)=S1 4220 C(12)=205: C(13)=A0: C(14)=A1 4230 C(15)=208: C(16)=3: C(17)=76: C(18)=0: C(19)=0 4240 GOSUB 1500 4250 RETURN 5000 REM <<< GOTO MM >>> 5010 C$="" 5020 GOSUB 1100: REM GET DIGITS OF MM 5030 IF C=0 THEN 5060 5040 C$=C$+CHR$(C) 5050 GOTO 5020 5060 MM=VAL(C$) 5070 IF MM<0 OR MM>999 THEN EC=1: GOSUB 10000: STOP 5080 JI=JI+1 :REM JUMP TABLE INDEX 5085 JT(JI,0)=LN :REM SOURCE LINE# 5090 JT(JI,1)=MM :REM TARGET LINE# 5100 JT(JI,2)=CM+1 :REM OBJ MEM LOCATION AFTER 'JMP' 5110 REM JMP MM 5120 N=3: C(1)=76: C(2)=0: C(3)=0 5130 GOSUB 1500 5140 RETURN 6000 REM <<< PRINT, PRINT A[;], OR PRINT CHR$(A)[;] >>> 6010 GOSUB 1100: IF C=199 THEN 6300 :REM 'CHR$ 6020 IF C=0 THEN PC=13: GOSUB 6200: RETURN: REM 'PRINT 6030 GOSUB 1300: IF VT=2 THEN 9700 6035 IF VT<>1 THEN EC=65: GOSUB 10000: STOP 6040 REM <<< PRINT A >>> 6050 REM LDX $A(MSB), LDY $A(LSB), JSR $C0E0 6060 PRINT: N=9: C(1)=174: C(2)=A0: C(3)=A1 6070 C(4)=172: C(5)=A2: C(6)=A3 6080 C(7)=32: C(8)=224: C(9)=192 6090 GOSUB 1500 6095 PC=32: GOSUB 6200 :REM ADD SPACE AFTER DIGITS 6100 GOSUB 1100: IF C=0 THEN PC=13: GOSUB 6200: RETURN :REM PRINT CR 6110 IF C<>59 THEN EC=59: GOSUB 10000: STOP :REM ' ; 6120 GOSUB 1100: IF C>0 THEN EC=0: GOSUB 10000: STOP 6130 RETURN 6200 REM --- PRINT CHARACTER PC --- 6210 REM LDA #PC, JSR $FFD2 6220 PRINT:N=5: C(1)=169: C(2)=PC: C(3)=32 6230 C(4)=210: C(5)=255: GOSUB 1500 6240 RETURN 6300 REM <<< PRINT CHR$(A) [;] >>> 6310 GOSUB 1100: IF C<>40 THEN EC=40: GOSUB 10000: STOP :REM '( 6320 GOSUB 1100: GOSUB 1300: IF VT<>1 THEN EC=65: GOSUB 10000: STOP 6330 REM LDA A(LSB), JSR $FFD2 6340 PRINT: N=6: C(1)=173: C(2)=A0: C(3)=A1 6350 C(4)=32: C(5)=210: C(6)=255 6360 GOSUB 1500 6370 GOSUB 1100: IF C<>41 THEN EC=41: GOSUB 10000: STOP : REM ') 6380 GOSUB 1100: IF C>0 THEN 6400 6390 PRINT: PC=13: GOSUB 6200: RETURN 6400 IF C<>59 THEN EC=59: GOSUB 10000: STOP :REM '; 6410 GOSUB 1100: IF C<>0 THEN EC=0:GOSUB 10000: STOP 6420 RETURN 7000 REM <<< END >>> 7005 REM RTS 7010 N=1: C(1)=96: GOSUB 1500 7020 GOSUB 1100: IF C<>0 THEN EC=0:GOSUB 10000: STOP 7030 RETURN 8000 REM <<< REM >>> 8010 GOSUB 1100: IF C>0 THEN 8010 8020 RETURN 8999 REM << STRINGS >> 9000 REM << STRING VARIABLES >> 9010 GOSUB 1600 :D0=NL: D1=NH: REM GET DEST VAR ADDR 9020 GOSUB 1100: IF C<>178 THEN EC=178: EC$=" = ": GOSUB 10000: STOP 9030 GOSUB 1100 9040 GOSUB 1300: IF VT=2 THEN 9400 :REM A$=B$... 9050 IF C=34 THEN 9200 :REM '"LITERAL" 9060 IF C<>199 THEN EC=199: EC$="CHR$": GOSUB 10000: STOP 9100 REM << A$=CHR$(N) >> 9110 GOSUB 1100: IF C<>40 THEN EC=40: EC$="(": GOSUB 10000: STOP 9120 GOSUB 1100: GOSUB 1300: IF VT<>1 THEN EC=65: GOSUB 10000: STOP 9130 GOSUB 1100: IF C<>41 THEN EC=41: EC$=")": GOSUB 10000: STOP 9140 GOSUB 1100: IF C>0 THEN EC=0: GOSUB 10000: STOP 9150 REM LDA #1; STA A$; LDA N.LSB; LDY #1; STA A$,Y 9160 N=13: C(1)=169: C(2)=1: C(3)=141: C(4)=D0: C(5)=D1: C(6)=173 9170 C(7)=A0: C(8)=A1: C(9)=160: C(10)=1: C(11)=153: C(12)=D0 9180 C(13)=D1: GOSUB 1500: RETURN 9200 REM << A$=" LITERAL " >> 9205 NC=0 :REM STORE # OF CHARS 9210 GOSUB 1100: IF C=34 THEN 9250 9220 NC=NC+1: IF NC=256 THEN PRINT"STRING TOO LONG": STOP 9230 S(NC)=C 9240 GOTO 9210 9250 GOSUB 1100: IF C<>0 THEN EC=0: GOSUB 10000: STOP 9260 REM LDA # NC: STA A$: LDY #1 9265 REM ..FOR K=1 TO NC: LDA # S(K): STA A$,Y: INY: NEXT K.. 9270 N=7: C(1)=169: C(2)=NC: C(3)=141: C(4)=D0: C(5)=D1: C(6)=160: C(7)=1 9280 GOSUB 1500 9290 N=6: FOR K=1 TO NC: C(1)=169: C(2)=S(K): C(3)=153: C(4)=D0: C(5)=D1 9295 C(6)=200: GOSUB 1500: NEXT K : RETURN 9400 REM << A$=B$ ... >> 9410 GOSUB 1600: S0=NL: S1=NH :REM B$ ADDR 9420 GOSUB 1100: IF C=170 THEN 9500 :REM '+ 9430 IF C>0 THEN EC=0: GOSUB 10000: STOP 9440 REM LDX B$: LDY #0; LOOP: LDA B$,Y; STA A$,Y; INY; BPL LOOP 9450 N=15: C(1)=174: C(2)=S0: C(3)=S1: C(4)=160: C(5)=0: C(6)=185: C(7)=S0 9460 C(8)=S1: C(9)=153: C(10)=D0: C(11)=D1: C(12)=200: C(13)=202 9470 C(14)=16: C(15)=246: GOSUB 1500: RETURN 9500 REM << A$=B$ + C$ >> 9510 GOSUB 1100: GOSUB 1300: IF VT<>2 THEN EC=65: GOSUB 10000: STOP 9520 GOSUB 1600: S2=NL: S3=NH :REM C$ ADDR 9530 GOSUB 1100: IF C>0 THEN EC=0: GOSUB 10000: STOP 9535 GOSUB 9450: REM A$=B$ 9540 N=53: C(1)=169: C(2)=D0: C(3)=133: C(4)=253: C(5)=169: C(6)=D1 9545 C(7)=133: C(8)=254: C(9)=173: C(10)=S0: C(11)=S1: C(12)=24: C(13)=101 9550 C(14)=253: C(15)=133: C(16)=253: C(17)=169: C(18)=0: C(19)=101 9555 C(20)=254: C(21)=133: C(22)=254: C(23)=174: C(24)=S2: C(25)=S3 9560 C(26)=160: C(27)=1: C(28)=185: C(29)=S2: C(30)=S3: C(31)=145 9565 C(32)=253: C(33)=200: C(34)=170: C(35)=208: C(36)=247: C(37)=173 9570 C(38)=S0: C(39)=S1: C(40)=24: C(41)=109: C(42)=S2: C(43)=S3 9575 C(44)=144: C(45)=5: C(46)=162: C(47)=23: C(48)=108: C(49)=0 9580 C(50)=3: C(51)=141: C(52)=D0: C(53)=D1 9590 GOSUB 1500: RETURN 9700 REM << PRINT A$ >> 9710 GOSUB 1600: S0=NL: S1=NH 9720 REM LDX LEN(A$); LDY #1; LOOP: LDA A$,Y; JSR $FFD2; INY; DEX; BNE LOOP 9730 N=15: C(1)=174: C(2)=S0: C(3)=S1: C(4)=160: C(5)=1: C(6)=185 9740 C(7)=S0: C(8)=S1: C(9)=32: C(10)=210: C(11)=255: C(12)=200 9750 C(13)=202: C(14)=208: C(15)=246: GOSUB 1500 9760 GOSUB 1100: IF C=0 THEN PC=13: GOSUB 6200: RETURN 9770 IF C<>59 THEN EC=59: EC$=";": GOSUB 10000: STOP 9780 GOSUB 1100: IF C>0 THEN EC=0: GOSUB 10000: STOP 9790 RETURN 10000 PRINT:PRINT"SYNTAX ERROR IN LINE[146]";LN 10010 IF EC=0 THEN PRINT"EXPECTED END-OF-LINE NOT FOUND":RETURN 10020 IF EC=1 THEN PRINT"INVALID LINE NUMBER":RETURN 10030 IF EC=48 THEN PRINT"NUMERIC VALUE 0-9 EXPECTED": RETURN 10040 IF EC=65 THEN PRINT"VARIABLE A-Z EXPECTED": RETURN 10050 IF EC>127 THEN PRINT"EXPECTED BASIC KEYWORD ";EC$: RETURN 10060 PRINT"EXPECTED CHARACTER ";CHR$(EC);" WITH ASCII VALUE"EC :RETURN 11000 REM -- PUT M.L. PRINT ROUTINE INTO MEMORY -- 11010 M=49376 :REM $C0E0 11020 CS=3319 :REM CHECKSUM 11030 READ B: IF B<0 THEN 11060 11040 POKE M,B: M=M+1: CK=CK+B 11050 GOTO 11030 11060 IF CK<>CS THEN PRINT"ERROR IN DATA STATEMENTS STARTING AT 11120":STOP 11070 RETURN 11080 DATA 169, 32, 200, 136, 16, 2 11090 DATA 169, 45, 32, 210, 255, 152, 16, 12 11100 DATA 138, 73, 255, 24, 105, 1, 170, 152 11110 DATA 73, 255, 105, 0, 32, 205, 189, 96 11120 DATA -1