home *** CD-ROM | disk | FTP | other *** search
/ Ahoy 1988 October / Ahoy_Magazine_88-10_1988_Double_L.d64 / Mini-comp (.txt) < prev    next >
Commodore BASIC  |  2022-10-26  |  8KB  |  249 lines

  1. 1 rem==================================
  2. 2 rem        mini-comp
  3. 3 rem     rupert report #58
  4. 4 rem a minimal compiler for the c-64
  5. 5 rem==================================
  6. 6 rem     run 2000 to compile
  7. 7 rem==================================
  8. 8 rem
  9. 9 rem   lines 1 through 999 are examples of all statements allowed by mini-comp
  10. 10 a=50
  11. 20 b=-10
  12. 30 c=a
  13. 40 d=a+b
  14. 50 if a=b then 60
  15. 60 goto 70
  16. 70 print
  17. 80 print a
  18. 90 print b;
  19. 100 print chr$(c)
  20. 110 print chr$(d);
  21. 999 end
  22. 1000 rem --- common routines ---
  23. 1100 c=peek(m): m=m+1: print c,: if c=32 then 1100: rem ignore spaces
  24. 1110 if c=0 then print
  25. 1120 return
  26. 1300 vf=true: if c<65 or c>90 then vf=false: return
  27. 1310 ad=(c-65)*2 + vm
  28. 1320 nx=ad: gosub 1400: a0=nl: a1=nh   : rem var lsb
  29. 1330 nx=ad+1: gosub 1400: a2=nl: a3=nh : rem var msb
  30. 1340 return
  31. 1400 nh=int(nx/256)
  32. 1410 nl=nx-256*nh
  33. 1420 return
  34. 1500 for kk=1 to n
  35. 1510 if cm>em then print"out of memory - compiled prgm too large": end
  36. 1520 poke cm,c(kk)
  37. 1530 print cm;":";c(kk)
  38. 1540 cm=cm+1: next
  39. 1550 return
  40. 2000 rem ====== initialization =========
  41. 2010 dim ll(50,2)      :rem ll(n,1)=line # of nth line
  42. 2015 :rem  ll(n,2)=compiled mem location of this line
  43. 2020 dim c(50)   :rem stores object code bytes
  44. 2030 false=0: true=not false
  45. 2040 def fnptr(m)=peek(m)+256*peek(m+1)
  46. 2050 vm=49152  :rem $c000 start of variable mem
  47. 2060 pm=49408  :rem $c100 start of object memory
  48. 2070 em=53247  :rem $cfff end of object memory
  49. 2080 bt=2049   :rem $0800 start of basic text
  50. 2085 gosub 11000   :rem put print rtn in mem
  51. 2090 m=bt        :rem next source memory to peek
  52. 2100 sn=1      :rem current source statement number
  53. 2110 cm=pm       :rem next object memory to poke
  54. 2120 for n=vm to vm+51: poke n,0: next : rem clr var's
  55. 2125 rem ============= main ============
  56. 2130 ptr=fnptr(m): m=m+2   :rem next line ptr
  57. 2140 ln=fnptr(m): m=m+2     :rem current line #
  58. 2150 if ln>999 then print "=== end of pass 1 ===": goto 2400
  59. 2160 print "     current line # ="; ln
  60. 2170 ll(sn,1)=ln     :rem current line #
  61. 2180 ll(sn,2)=cm          :rem start obj mem loc
  62. 2190 sn=sn+1    :rem # source statements
  63. 2200 rem --- get byte ---
  64. 2210 gosub 1100    :rem fetch next byte
  65. 2220 gosub 1300: if vf then gosub 3000 : goto 2290: rem 'variable
  66. 2230 if c=139 then gosub 4000: goto 2290: rem 'if
  67. 2240 if c=137 then gosub 5000: goto 2290: rem 'goto
  68. 2250 if c=153 then gosub 6000: goto 2290: rem 'print
  69. 2260 if c=128 then gosub 7000: goto 2290: rem 'end
  70. 2270 if c=143 then gosub 8000: goto 2290: rem 'rem
  71. 2280 print "unknown command code";c;"in line";ll(sn,1):stop
  72. 2290 if c>0 then ec=0: gosub 10000: stop :rem 'eol
  73. 2300 get k$:if k$="" then 2130 :rem back for more
  74. 2310 get k$:if k$="" then 2310
  75. 2320 goto 2130
  76. 2400 rem  - pass 2 - fix jump addresses
  77. 2410 if ji=0 then 2570 :rem no jumps
  78. 2420 for n=1 to ji   :rem check items in jump table
  79. 2430 :mm=jt(n,1) :rem referenced line #
  80. 2440 :for j=1 to sn    :rem check actual line #s
  81. 2445 :rem   - get obj mem target address and jmp address:
  82. 2450 :if mm=ll(j,1) then taddr=jt(n,2):  jaddr=ll(j,2): goto 2490
  83. 2460 :next j
  84. 2470 :rem no match found
  85. 2480 :ec=1: ln=jt(n,0): gosub 10000:stop
  86. 2490 :nx=jaddr :rem addr of line # mm
  87. 2530 :gosub 1400 :rem convert line #
  88. 2540 :poke taddr,nl     :rem use addr in jump table
  89. 2550 :poke taddr+1,nh
  90. 2560 next n    :rem next jump table item
  91. 2570 print"=== end of pass 2 ==="
  92. 2580 print"to execute the compiled program, enter"
  93. 2590 print" sys"; pm
  94. 2595 print"object code resides from";pm;"to";cm-1
  95. 2600 end
  96. 3000 rem <<<  a=(-)nn, a=b, a=b+c >>>
  97. 3010 d0=a0: d1=a1 :rem addr of a's lsb
  98. 3020 d2=a2: d3=a3 :rem a's msb
  99. 3030 gosub 1100: if c<>178 then ec=178: ec$=" = ": gosub 10000: stop   :rem '=
  100. 3040 gosub 1100   :rem '-, nn, or b
  101. 3050 gosub 1300: if vf then 3400 :rem 'b
  102. 3055 rem <<< a=(-)nn >>>
  103. 3060 if c=171 then c$="-" :rem '-
  104. 3065 if c<>171 then c$=" "+chr$(c) :rem '0-9
  105. 3070 gosub 1100  :rem get digits of nn
  106. 3080 if c=0 then 3120
  107. 3085 if chr$(c)<"0" or chr$(c)>"9" then ec=48: gosub 10000: stop
  108. 3090 c$=c$+chr$(c)
  109. 3100 goto 3070
  110. 3120 nn=val(c$)
  111. 3130 nn%=nn   :rem error check
  112. 3140 if nn<0 then nn=nn+65536       :rem convert (-32768,32767) to (0,65535)
  113. 3150 nx=nn: gosub 1400
  114. 3170 msb=nh: lsb=nl
  115. 3175 :rem lda #nn(lsb), sta a(lsb), lda  #nn(msb), sta a(msb)
  116. 3180 n=10: c(1)=169: c(2)=lsb: c(3)=141: c(4)=d0: c(5)=d1
  117. 3190 c(6)=169: c(7)=msb: c(8)=141: c(9)=d2: c(10)=d3
  118. 3200 gosub 1500    :rem poke values into object memory
  119. 3210 return
  120. 3400 rem <<< a=b or a=b+c >>>
  121. 3410 s0=a0: s1=a1   :rem b's lsb addr
  122. 3420 s2=a2: s3=a3   :rem b's msb
  123. 3430 gosub 1100
  124. 3440 if c=0 then 3600   :rem a=b
  125. 3450 rem <<< a=b+c >>>
  126. 3460 if c<>170 then ec=170:  ec$=" + ": gosub 10000: stop :rem test '+
  127. 3470 gosub 1100: gosub 1300: if not vf then ec=65: gosub 10000: stop: rem 'c
  128. 3480 gosub 1100: if c>0 then ec=0: gosub 10000: stop :rem 'eol
  129. 3490 s4=a0: s5=a1   :rem addr c's lsb
  130. 3500 s6=a2: s7=a3   :rem c's msb
  131. 3530 rem clc, lda b(lsb), adc c(lsb),sta a(lsb)
  132. 3535 rem lda b(msb), adc c(msb), sta a(msb)
  133. 3540 n=19: c(1)=24: c(2)=173: c(3)=s0: c(4)=s1
  134. 3550 c(5)=109: c(6)=s4: c(7)=s5: c(8)=141: c(9)=d0: c(10)=d1
  135. 3560 c(11)=173: c(12)=s2: c(13)=s3: c(14)=109: c(15)=s6: c(16)=s7
  136. 3570 c(17)=141: c(18)=d2: c(19)=d3
  137. 3580 gosub 1500
  138. 3590 return
  139. 3600 rem <<< a=b >>>
  140. 3610 rem lda b(lsb), sta a(lsb), lda b(msb), sta a(msb)
  141. 3620 n=12: c(1)=173: c(2)=s0: c(3)=s1: c(4)=141: c(5)=d0: c(6)=d1
  142. 3630 c(7)=173: c(8)=s2: c(9)=s3: c(10)=141: c(11)=d2: c(12)=d3
  143. 3640 gosub 1500
  144. 3650 return
  145. 4000 rem <<<  if a=b then mm  >>>
  146. 4010 gosub 1100  :rem 'a
  147. 4020 gosub 1300: if not vf then ec=65:   gosub 10000: stop
  148. 4030 s0=a0: s1=a1: s2=a2: s3=a3
  149. 4040 gosub 1100: if c<>178 then ec=178:  gosub 10000: stop   :rem '=
  150. 4050 gosub 1100      :rem 'b
  151. 4060 gosub 1300: if not vf then ec=65:   gosub 10000: stop
  152. 4070 gosub 1100      :rem 'then
  153. 4080 if c<>167 then ec=167: gosub 10000: stop
  154. 4090 c$=""
  155. 4100 gosub 1100: if c=0 then 4120   :rem get mm
  156. 4110 c$=c$+chr$(c): goto 4100
  157. 4120 mm=val(c$)
  158. 4130 if mm<0 or mm>999 then ec=1:  gosub 10000: stop
  159. 4140 ji=ji+1       :rem jump table index
  160. 4150 jt(ji,0)=ln   :rem current line #
  161. 4160 jt(ji,1)=mm   :rem target line #
  162. 4170 jt(ji,2)=cm+17   :rem mem loc after 'jmp
  163. 4180 rem  lda a(msb), cmp b(msb), bne exit,
  164. 4185 rem  lda a(lsb), cmp b(lsb), bne exit, jmp mm
  165. 4190 n=19: c(1)=173: c(2)=s2: c(3)=s3
  166. 4200 c(4)=205: c(5)=a2: c(6)=a3
  167. 4210 c(7)=208: c(8)=11: c(9)=173: c(10)=s0: c(11)=s1
  168. 4220 c(12)=205: c(13)=a0: c(14)=a1
  169. 4230 c(15)=208: c(16)=3: c(17)=76: c(18)=0: c(19)=0
  170. 4240 gosub 1500
  171. 4250 return
  172. 5000 rem <<< goto mm >>>
  173. 5010 c$=""
  174. 5020 gosub 1100: rem get digits of mm
  175. 5030 if c=0 then 5060
  176. 5040 c$=c$+chr$(c)
  177. 5050 goto 5020
  178. 5060 mm=val(c$)
  179. 5070 if mm<0 or mm>999 then ec=1:  gosub 10000: stop
  180. 5080 ji=ji+1      :rem jump table index
  181. 5085 jt(ji,0)=ln  :rem source line#
  182. 5090 jt(ji,1)=mm  :rem target line#
  183. 5100 jt(ji,2)=cm+1 :rem obj mem location after 'jmp'
  184. 5110 rem  jmp mm
  185. 5120 n=3: c(1)=76: c(2)=0: c(3)=0
  186. 5130 gosub 1500
  187. 5140 return
  188. 6000 rem <<< print, print a[;], or print chr$(a)[;] >>>
  189. 6010 gosub 1100: if c=199 then 6300 :rem 'chr$
  190. 6020 if c=0 then pc=13: gosub 6200: return:  rem 'print
  191. 6030 gosub 1300: if not vf then ec=65:   gosub 10000: stop
  192. 6040 rem <<< print a >>>
  193. 6050 rem   ldx $a(msb), ldy $a(lsb), jsr $c0e0
  194. 6060 print: n=9: c(1)=174: c(2)=a0: c(3)=a1
  195. 6070 c(4)=172: c(5)=a2: c(6)=a3
  196. 6080 c(7)=32: c(8)=224: c(9)=192
  197. 6090 gosub 1500
  198. 6095 pc=32: gosub 6200    :rem add space after  digits
  199. 6100 gosub 1100: if c=0 then pc=13: gosub 6200: return   :rem print cr
  200. 6110 if c<>59 then ec=59: gosub 10000:   stop  :rem  ' ;
  201. 6120 gosub 1100: if c>0 then ec=0: gosub 10000: stop
  202. 6130 return
  203. 6200 rem --- print character pc ---
  204. 6210 rem lda #pc, jsr $ffd2
  205. 6220 print:n=5: c(1)=169: c(2)=pc: c(3)=32
  206. 6230 c(4)=210: c(5)=255: gosub 1500
  207. 6240 return
  208. 6300 rem <<< print chr$(a) [;] >>>
  209. 6310 gosub 1100: if c<>40 then ec=40: gosub 10000: stop :rem  '(
  210. 6320 gosub 1100: gosub 1300: if not vf then ec=65: gosub 10000: stop
  211. 6330 rem    lda a(lsb), jsr $ffd2
  212. 6340 print: n=6: c(1)=173: c(2)=a0: c(3)=a1
  213. 6350 c(4)=32: c(5)=210: c(6)=255
  214. 6360 gosub 1500
  215. 6370 gosub 1100: if c<>41 then ec=41: gosub 10000: stop  : rem ')
  216. 6380 gosub 1100: if c>0 then 6400
  217. 6390 print: pc=13: gosub 6200: return
  218. 6400 if c<>59 then ec=59: gosub 10000:   stop  :rem ';
  219. 6410 gosub 1100: if c<>0 then ec=0:gosub 10000: stop
  220. 6420 return
  221. 7000 rem <<< end >>>
  222. 7005 rem    rts
  223. 7010 n=1: c(1)=96: gosub 1500
  224. 7020 gosub 1100: if c<>0 then ec=0:gosub 10000: stop
  225. 7030 return
  226. 8000 rem <<< rem >>>
  227. 8010 gosub 1100: if c>0 then 8010
  228. 8020 return
  229. 10000 print:print"syntax error in line[146]";ln
  230. 10010 if ec=0 then print"expected end-of-line not found":return
  231. 10020 if ec=1 then print"invalid line number":return
  232. 10030 if ec=48 then print"numeric value 0-9 expected": return
  233. 10040 if ec=65 then print"variable a-z expected": return
  234. 10050 if ec>127 then print"expected basic keyword ";ec$: return
  235. 10060 print"expected character   ";chr$(ec);"   with ascii value"ec :return
  236. 11000 rem -- put m.l. print routine into memory --
  237. 11010 m=49376  :rem $c0e0
  238. 11020 cs=3319 :rem checksum
  239. 11030 read b: if b<0 then 11060
  240. 11040 poke m,b: m=m+1: ck=ck+b
  241. 11050 goto 11030
  242. 11060 if ck<>cs then print"error in data statements starting at 11120":stop
  243. 11070 return
  244. 11080 data 169, 32, 200, 136, 16, 2
  245. 11090 data 169, 45, 32, 210, 255, 152, 16, 12
  246. 11100 data 138, 73, 255, 24, 105, 1, 170, 152
  247. 11110 data 73, 255, 105, 0, 32, 205, 189, 96
  248. 11120 data -1
  249.