home *** CD-ROM | disk | FTP | other *** search
- 1 rem==================================
- 2 rem mini-comp
- 3 rem rupert report #58
- 4 rem a minimal compiler for the c-64
- 5 rem==================================
- 6 rem run 2000 to compile
- 7 rem==================================
- 8 rem
- 9 rem lines 1 through 999 are examples of all statements allowed by mini-comp
- 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);
- 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 vf=true: if c<65 or c>90 then vf=false: return
- 1310 ad=(c-65)*2 + vm
- 1320 nx=ad: gosub 1400: a0=nl: a1=nh : rem var lsb
- 1330 nx=ad+1: gosub 1400: a2=nl: a3=nh : rem var msb
- 1340 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
- 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(50) :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
- 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 vf then gosub 3000 : goto 2290: rem '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 ec=178: ec$=" = ": gosub 10000: stop :rem '=
- 3040 gosub 1100 :rem '-, nn, or b
- 3050 gosub 1300: if vf then 3400 :rem 'b
- 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 not vf 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 not vf 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 not vf 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 not vf 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 not vf 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
- 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
-