M3PL.MOD 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. MODULE M3PL; (*NW 6.3.83 / 20.5.85 / 2.8.86*)
  2. (*One-pass Modula-2 Compiler for Lilith. Copyright N.Wirth*)
  3. FROM Terminal IMPORT Read, Write, WriteString, WriteLn;
  4. FROM FileSystem IMPORT Lookup, Response, GetPos, Close, Delete;
  5. FROM Clock IMPORT Time, GetTime;
  6. FROM M3DL IMPORT
  7. WordSize, MaxCodeLength,
  8. cardtyp, inttyp, realtyp, chartyp, bitstyp, dbltyp, notyp, stringtyp,
  9. addrtyp, undftyp, mainmod, sysmod,
  10. ObjPtr, StrPtr, ParPtr, ConstValue, StrForm, ObjClass;
  11. FROM M2S IMPORT
  12. Symbol, sym, id, numtyp, intval, dblval, realval, source, IdBuf, scanerr,
  13. InitScanner, GetSym, Diff, KeepId, Mark, CloseScanner;
  14. FROM M3TL IMPORT
  15. topScope, Scope, NewObj, NewStr, NewPar, NewImp,
  16. NewScope, CloseScope, Find, FindImport, FindInScope, CheckUDP,
  17. MarkHeap, ReleaseHeap, InitTableHandler;
  18. FROM M3RL IMPORT
  19. ModNo, ModList, RefFile,
  20. InitRef, InRef, OpenRef, OutPos, OutUnit, CloseRef;
  21. FROM M3GL IMPORT
  22. LabelRange, ItemMode, Item, curLev, curPrio, pc, rngchk,
  23. load, loadAdr, fixup, fixupC, FixupEnter, CheckStack, AllocString,
  24. GenNeg, GenNot, GenAnd, GenOr, GenOp, GenIn, GenSet, GenSingSet,
  25. GenItem, GenIndex, GenField, GenWith, GenDeRef,
  26. PrepAss, GenAssign, GenFJ, GenCFJ, GenBJ, GenCBJ,
  27. PrepCall, GenParam, GenCall, GenEnter, GenEnterMod, GenResult, GenReturn,
  28. GenCase1, GenCase2, GenCase3, GenTrap, GenFor1, GenFor2, GenFor3, GenFor4,
  29. GenStParam, GenStFct, GenEndDecl, InitGenerator, OutCodeFile;
  30. CONST NL = 27; (*max name length*)
  31. NofCases = 128;
  32. NofExits = 16;
  33. LoopLevels = 4;
  34. MaxInt = 32767;
  35. EnumTypSize = 1;
  36. SetTypSize = 1;
  37. PointerTypSize = 1;
  38. ProcTypSize = 1;
  39. DynArrDesSize = 2;
  40. StartAddress = 4;
  41. VAR ch: CHAR;
  42. pno, pnoI: CARDINAL;
  43. isdef, isimp, constFlag: BOOLEAN;
  44. FileName: ARRAY [0..NL] OF CHAR;
  45. TM: Time;
  46. PROCEDURE Type(VAR typ: StrPtr); FORWARD;
  47. PROCEDURE Expression(VAR x: Item); FORWARD;
  48. PROCEDURE Block(ancestor: ObjPtr; qual: BOOLEAN;
  49. VAR adr: INTEGER; VAR L0: CARDINAL); FORWARD;
  50. PROCEDURE err(n: CARDINAL);
  51. BEGIN Mark(n)
  52. END err;
  53. PROCEDURE CheckSym(s: Symbol; n: CARDINAL);
  54. BEGIN
  55. IF sym = s THEN GetSym ELSE Mark(n) END
  56. END CheckSym;
  57. PROCEDURE RefPoint;
  58. VAR p0, p1: CARDINAL;
  59. BEGIN GetPos(source, p0, p1); OutPos(p1, pc)
  60. END RefPoint;
  61. PROCEDURE qualident(VAR obj: ObjPtr);
  62. BEGIN (*sym = ident*)
  63. obj := Find(id); GetSym;
  64. WHILE (sym = period) & (obj # NIL) & (obj^.class = Module) DO
  65. GetSym;
  66. IF sym = ident THEN
  67. obj := FindInScope(id, obj^.root); GetSym;
  68. IF (obj # NIL) & NOT obj^.exported THEN obj := NIL END
  69. ELSE err(10)
  70. END
  71. END
  72. END qualident;
  73. PROCEDURE ConstExpression(VAR x: Item);
  74. BEGIN constFlag := TRUE; Expression(x);
  75. IF x.mode # conMd THEN
  76. err(44); x.mode := conMd; x.val.C := 1
  77. END ;
  78. constFlag := FALSE
  79. END ConstExpression;
  80. PROCEDURE CheckComp(t0, t1: StrPtr);
  81. BEGIN
  82. IF (t0 # t1) & ((t0 # inttyp) OR (t1 # cardtyp)) THEN err(61) END
  83. END CheckComp;
  84. PROCEDURE CaseLabelList(Ltyp: StrPtr;
  85. VAR n: CARDINAL; VAR tab: ARRAY OF LabelRange);
  86. VAR x,y: Item; i,j: CARDINAL; f: StrForm;
  87. BEGIN f := Ltyp^.form;
  88. IF f = Range THEN Ltyp := Ltyp^.RBaseTyp
  89. ELSIF (f > Int) & (f # Enum) THEN err(83)
  90. END ;
  91. LOOP ConstExpression(x); CheckComp(Ltyp, x.typ);
  92. IF sym = ellipsis THEN
  93. GetSym; ConstExpression(y); CheckComp(Ltyp, y.typ);
  94. IF y.val.I < x.val.I THEN err(63); y := x END
  95. ELSE y := x
  96. END ;
  97. (*enter label range into ordered table*) i := n;
  98. IF i < NofCases THEN
  99. LOOP
  100. IF i = 0 THEN EXIT END ;
  101. IF tab[i-1].low <= y.val.I THEN
  102. IF tab[i-1].high >= x.val.I THEN err(62) END ;
  103. EXIT
  104. END ;
  105. tab[i] := tab[i-1]; i := i-1
  106. END ;
  107. WITH tab[i] DO
  108. low := x.val.I; high := y.val.I; label := pc
  109. END ;
  110. n := n+1
  111. ELSE err(92)
  112. END ;
  113. IF sym = comma THEN GetSym
  114. ELSIF (sym = number) OR (sym = ident) THEN err(11)
  115. ELSE EXIT
  116. END
  117. END
  118. END CaseLabelList;
  119. PROCEDURE Subrange(VAR typ: StrPtr);
  120. VAR x, y: Item; f: StrForm;
  121. BEGIN typ := NewStr(Range); ConstExpression(x); f := x.typ^.form;
  122. IF (f <= Int) OR (f = Enum) THEN typ^.min := x.val.I ELSE err(82) END ;
  123. CheckSym(ellipsis, 21); ConstExpression(y); CheckComp(x.typ, y.typ);
  124. IF (y.typ = cardtyp) & (y.val.C > MaxInt) THEN err(95) END ;
  125. WITH typ^ DO max := y.val.I;
  126. IF min > max THEN err(63); min := max END ;
  127. RBaseTyp := x.typ; size := x.typ^.size
  128. END
  129. END Subrange;
  130. PROCEDURE SimpleType(VAR typ: StrPtr);
  131. VAR obj, last: ObjPtr; typ0: StrPtr; n: CARDINAL;
  132. BEGIN typ := undftyp;
  133. IF sym = ident THEN
  134. qualident(obj);
  135. IF (obj # NIL) & (obj^.class = Typ) THEN typ := obj^.typ
  136. ELSE err(52)
  137. END ;
  138. IF sym = lbrak THEN
  139. GetSym; typ0 := typ; Subrange(typ);
  140. IF typ^.RBaseTyp # typ0 THEN
  141. IF (typ0 = inttyp) & (typ^.RBaseTyp = cardtyp) THEN
  142. typ^.RBaseTyp := inttyp
  143. ELSE err(61)
  144. END
  145. END ;
  146. IF sym = rbrak THEN GetSym ELSE err(16);
  147. IF sym = rparen THEN GetSym END
  148. END
  149. END
  150. ELSIF sym = lparen THEN
  151. GetSym; typ := NewStr(Enum); last := NIL; n := 0;
  152. LOOP
  153. IF sym = ident THEN
  154. obj := NewObj(id, Const); KeepId;
  155. obj^.conval.C := n; obj^.conval.prev := last;
  156. obj^.typ := typ; last := obj; n := n+1; GetSym
  157. ELSE err(10)
  158. END ;
  159. IF sym = comma THEN GetSym
  160. ELSIF sym = ident THEN err(11)
  161. ELSE EXIT
  162. END
  163. END ;
  164. WITH typ^ DO
  165. ConstLink := last; NofConst := n; size := EnumTypSize
  166. END ;
  167. CheckSym(rparen, 15)
  168. ELSIF sym = lbrak THEN
  169. GetSym; Subrange(typ);
  170. IF sym = rbrak THEN GetSym ELSE err(16);
  171. IF sym = rparen THEN GetSym END
  172. END
  173. ELSE err(32)
  174. END
  175. END SimpleType;
  176. PROCEDURE FieldListSequence(VAR maxadr: INTEGER; adr: INTEGER);
  177. VAR fld1, last, tagfldtyp: ObjPtr; typ: StrPtr; size: INTEGER;
  178. PROCEDURE VariantPart;
  179. (*variables of Fieldlist used: maxadr, adr*)
  180. VAR lastadr: INTEGER; N: CARDINAL;
  181. tab: ARRAY [0..NofCases-1] OF LabelRange;
  182. BEGIN maxadr := adr; N := 0;
  183. LOOP
  184. IF sym < bar THEN CaseLabelList(typ, N, tab);
  185. CheckSym(colon, 13); FieldListSequence(lastadr, adr);
  186. IF lastadr > maxadr THEN maxadr := lastadr END
  187. END ;
  188. IF sym = bar THEN GetSym ELSE EXIT END
  189. END ;
  190. IF sym = else THEN
  191. GetSym; FieldListSequence(lastadr, adr);
  192. IF lastadr > maxadr THEN maxadr := lastadr END
  193. END
  194. END VariantPart;
  195. BEGIN typ := undftyp;
  196. IF (sym = ident) OR (sym = case) THEN
  197. LOOP
  198. IF sym = ident THEN last := topScope^.last;
  199. LOOP
  200. IF sym = ident THEN
  201. fld1 := NewObj(id, Field); KeepId; GetSym
  202. ELSE err(10)
  203. END ;
  204. IF sym = comma THEN GetSym
  205. ELSIF sym = ident THEN err(11)
  206. ELSE EXIT
  207. END
  208. END ;
  209. CheckSym(colon, 13); Type(typ); size := typ^.size;
  210. fld1 := last^.next;
  211. WHILE fld1 # NIL DO
  212. fld1^.typ := typ; fld1^.offset := adr;
  213. adr := adr + size; fld1 := fld1^.next
  214. END
  215. ELSIF sym = case THEN
  216. GetSym; fld1 := NIL; tagfldtyp := NIL;
  217. IF sym = ident THEN
  218. fld1 := NewObj(id, Field); KeepId; GetSym
  219. END ;
  220. CheckSym(colon, 13);
  221. IF sym = ident THEN qualident(tagfldtyp) ELSE err(10) END ;
  222. IF (tagfldtyp # NIL) & (tagfldtyp^.class = Typ) THEN
  223. typ := tagfldtyp^.typ
  224. ELSE err(52)
  225. END ;
  226. IF fld1 # NIL THEN
  227. fld1^.offset := adr; fld1^.typ := typ;
  228. adr := adr + typ^.size
  229. END ;
  230. CheckSym(of, 23); VariantPart; adr := maxadr;
  231. CheckSym(end, 20)
  232. END ;
  233. IF sym = semicolon THEN GetSym
  234. ELSIF sym = ident THEN err(12)
  235. ELSE EXIT
  236. END
  237. END
  238. END ;
  239. maxadr := adr
  240. END FieldListSequence;
  241. PROCEDURE FormalType(VAR typ: StrPtr);
  242. VAR objtyp: ObjPtr;
  243. BEGIN typ := undftyp;
  244. IF sym = array THEN
  245. GetSym; typ := NewStr(Array);
  246. WITH typ^ DO
  247. strobj := NIL; size := DynArrDesSize; dyn := TRUE
  248. END ;
  249. CheckSym(of, 23);
  250. IF sym = ident THEN
  251. qualident(objtyp);
  252. IF (objtyp # NIL) & (objtyp^.class = Typ) THEN
  253. typ^.ElemTyp := objtyp^.typ
  254. ELSE err(52)
  255. END
  256. ELSE err(10)
  257. END
  258. ELSIF sym = ident THEN
  259. qualident(objtyp);
  260. IF (objtyp # NIL) & (objtyp^.class = Typ) THEN
  261. typ := objtyp^.typ
  262. ELSE err(52)
  263. END
  264. ELSE err(10)
  265. END
  266. END FormalType;
  267. PROCEDURE FormalTypeList(proctyp: StrPtr);
  268. VAR obj: ObjPtr; par, par0, par1: ParPtr; isvar: BOOLEAN;
  269. BEGIN par := NIL;
  270. IF (sym = ident) OR (sym = var) OR (sym = array) THEN
  271. LOOP
  272. IF sym = var THEN GetSym; isvar := TRUE ELSE isvar := FALSE END ;
  273. par := NewPar(0, isvar, par); FormalType(par^.typ);
  274. IF sym = comma THEN GetSym
  275. ELSIF sym = ident THEN err(11)
  276. ELSE EXIT
  277. END
  278. END
  279. END ;
  280. CheckSym(rparen, 15);
  281. par1 := NIL; (*reverse list*)
  282. WHILE par # NIL DO
  283. par0 := par; par := par0^.next; par0^.next := par1; par1 := par0
  284. END ;
  285. proctyp^.firstPar := par1;
  286. IF sym = colon THEN
  287. GetSym; proctyp^.resTyp := undftyp;
  288. IF sym = ident THEN qualident(obj);
  289. IF (obj # NIL) & (obj^.class = Typ) THEN proctyp^.resTyp := obj^.typ
  290. ELSE err(52)
  291. END
  292. ELSE err(10)
  293. END
  294. ELSE proctyp^.resTyp := notyp
  295. END
  296. END FormalTypeList;
  297. PROCEDURE ArrayType(VAR typ: StrPtr);
  298. VAR a,b: INTEGER;
  299. BEGIN typ := NewStr(Array); typ^.dyn := FALSE; a := 0;
  300. SimpleType(typ^.IndexTyp);
  301. WITH typ^.IndexTyp^ DO
  302. IF form # Range THEN
  303. err(94); form := Range; RBaseTyp := cardtyp; min := 0; max := 0
  304. END ;
  305. a := min; b := max
  306. END ;
  307. IF sym = of THEN
  308. GetSym; Type(typ^.ElemTyp)
  309. ELSIF sym = comma THEN
  310. GetSym; ArrayType(typ^.ElemTyp)
  311. ELSE err(23)
  312. END ;
  313. IF b >= 0 THEN
  314. IF b - MaxInt >= a THEN err(210); a := b END
  315. ELSIF a < 0 THEN
  316. IF b >= a + MaxInt THEN err(210); a := b END
  317. END ;
  318. a := b-a+1; b := typ^.ElemTyp^.size;
  319. IF typ^.ElemTyp^.form = Char THEN a := (a+1) DIV 2
  320. ELSIF MaxInt DIV b >= a THEN a := a*b
  321. ELSE err(210); a := 1
  322. END ;
  323. typ^.size := a
  324. END ArrayType;
  325. PROCEDURE Type(VAR typ: StrPtr);
  326. VAR obj: ObjPtr; btyp: StrPtr;
  327. BEGIN
  328. IF sym < lparen THEN err(33);
  329. REPEAT GetSym UNTIL sym >= lparen
  330. END ;
  331. IF sym = array THEN
  332. GetSym; ArrayType(typ)
  333. ELSIF sym = record THEN
  334. GetSym; typ := NewStr(Record); NewScope(Typ);
  335. FieldListSequence(typ^.size, 0); typ^.firstFld := topScope^.next;
  336. CheckSym(end, 20); CloseScope
  337. ELSIF sym = set THEN
  338. GetSym; CheckSym(of, 23);
  339. typ := NewStr(Set); SimpleType(typ^.SBaseTyp);
  340. btyp := typ^.SBaseTyp;
  341. IF btyp^.form = Enum THEN
  342. IF btyp^.NofConst > WordSize THEN err(209) END
  343. ELSIF btyp^.form = Range THEN
  344. IF (btyp^.min < 0) OR (btyp^.max >= WordSize) THEN err(209) END
  345. ELSE err(60)
  346. END ;
  347. typ^.size := SetTypSize
  348. ELSIF sym = pointer THEN
  349. GetSym; typ := NewStr(Pointer);
  350. typ^.BaseId := 0; typ^.size := PointerTypSize; CheckSym(to, 24);
  351. IF sym = ident THEN qualident(obj);
  352. IF obj = NIL THEN typ^.BaseId := id; KeepId (*forward ref*)
  353. ELSIF obj^.class = Typ THEN typ^.PBaseTyp := obj^.typ
  354. ELSE err(52)
  355. END
  356. ELSE Type(typ^.PBaseTyp)
  357. END
  358. ELSIF sym = procedure THEN
  359. GetSym; typ := NewStr(ProcTyp); typ^.size := ProcTypSize;
  360. IF sym = lparen THEN
  361. GetSym; FormalTypeList(typ)
  362. ELSE typ^.resTyp := notyp
  363. END
  364. ELSE
  365. SimpleType(typ)
  366. END ;
  367. IF (sym < semicolon) OR (else < sym) THEN err(34);
  368. WHILE (sym < ident) OR (else < sym) & (sym < begin) DO
  369. GetSym
  370. END
  371. END
  372. END Type;
  373. PROCEDURE selector(VAR x: Item; obj: ObjPtr);
  374. VAR y: Item;
  375. BEGIN GenItem(x, obj, Scope);
  376. LOOP
  377. IF sym = lbrak THEN GetSym;
  378. LOOP loadAdr(x); Expression(y); GenIndex(x, y);
  379. IF sym = comma THEN GetSym ELSE EXIT END
  380. END ;
  381. CheckSym(rbrak, 16)
  382. ELSIF sym = period THEN
  383. GetSym;
  384. IF sym = ident THEN
  385. IF (x.typ # NIL) & (x.typ^.form = Record) THEN
  386. obj := FindInScope(id, x.typ^.firstFld); GenField(x, obj)
  387. ELSE err(57)
  388. END ;
  389. GetSym
  390. ELSE err(10)
  391. END
  392. ELSIF sym = arrow THEN
  393. GetSym; GenDeRef(x)
  394. ELSE EXIT
  395. END
  396. END
  397. END selector;
  398. PROCEDURE ActualParameters(VAR x: Item; fpar: ParPtr);
  399. VAR apar: Item;
  400. BEGIN
  401. IF sym # rparen THEN
  402. LOOP Expression(apar);
  403. IF fpar # NIL THEN
  404. GenParam(apar, fpar); fpar := fpar^.next
  405. ELSE err(64)
  406. END ;
  407. IF sym = comma THEN GetSym
  408. ELSIF (lparen <= sym) & (sym <= ident) THEN GetSym; err(11)
  409. ELSE EXIT
  410. END
  411. END
  412. END ;
  413. IF fpar # NIL THEN err(65) END
  414. END ActualParameters;
  415. PROCEDURE StandProcCall(VAR p: Item);
  416. VAR x: Item; m, n: CARDINAL;
  417. BEGIN m := p.cod^.cnum; n := 0;
  418. IF m = 1 THEN GenTrap(10); p.typ := notyp ELSE
  419. CheckSym(lparen, 22);
  420. LOOP Expression(x); GenStParam(p, x, m, n); n := n+1;
  421. IF sym = comma THEN GetSym ELSIF sym # ident THEN EXIT END
  422. END ;
  423. CheckSym(rparen, 15); GenStFct(p, m, n)
  424. END
  425. END StandProcCall;
  426. PROCEDURE Element(VAR x: Item);
  427. VAR e1, e2: Item;
  428. BEGIN Expression(e1);
  429. IF sym = ellipsis THEN GetSym;
  430. IF e1.mode = conMd THEN Expression(e2);
  431. IF e2.mode # conMd THEN err(90) END
  432. ELSE load(e1); Expression(e2)
  433. END ;
  434. GenSet(x, e1, e2)
  435. ELSE GenSingSet(x, e1)
  436. END ;
  437. END Element;
  438. PROCEDURE Sets(VAR x: Item; styp: StrPtr);
  439. VAR y: Item;
  440. BEGIN x.typ := styp; y.typ := styp;
  441. IF sym # rbrace THEN
  442. Element(x);
  443. LOOP
  444. IF sym = comma THEN GetSym
  445. ELSIF (lparen <= sym) & (sym <= ident) THEN err(11)
  446. ELSE EXIT
  447. END ;
  448. Element(y); GenOp(ORD(plus), x, y)
  449. END
  450. ELSE x.mode := conMd; x.val.S := {}
  451. END ;
  452. CheckSym(rbrace, 17)
  453. END Sets;
  454. PROCEDURE Factor(VAR x: Item);
  455. VAR obj: ObjPtr; xt: StrPtr; fpar: ParPtr;
  456. BEGIN
  457. IF sym < lparen THEN err(31);
  458. REPEAT GetSym UNTIL sym >= lparen
  459. END ;
  460. IF sym = ident THEN
  461. qualident(obj);
  462. IF sym = lbrace THEN
  463. GetSym;
  464. IF (obj # NIL) & (obj^.class = Typ) &
  465. (obj^.typ^.form = Set) THEN Sets(x, obj^.typ)
  466. ELSE err(52); Sets(x, bitstyp)
  467. END
  468. ELSE
  469. selector(x, obj);
  470. IF (x.mode = codMd) & (x.cod^.cnum > 0) THEN StandProcCall(x)
  471. ELSIF sym = lparen THEN GetSym;
  472. IF x.mode = typMd THEN (*type transfer function*)
  473. xt := x.typ; Expression(x); load(x); (*may be chartyp!*)
  474. IF xt^.size # x.typ^.size THEN err(81) END ;
  475. x.typ := xt
  476. ELSE PrepCall(x, fpar); ActualParameters(x, fpar); GenCall(x)
  477. END ;
  478. CheckSym(rparen, 15)
  479. END
  480. END
  481. ELSIF sym = number THEN
  482. GetSym; x.mode := conMd;
  483. CASE numtyp OF
  484. 1: x.typ := cardtyp; x.val.C := intval |
  485. 2: x.typ := dbltyp; x.val.D := dblval |
  486. 3: x.typ := chartyp; x.val.C := intval |
  487. 4: x.typ := realtyp; x.val.R := realval
  488. END
  489. ELSIF sym = string THEN
  490. x.typ := stringtyp; x.mode := conMd;
  491. AllocString(id, x.val.D0, x.val.D1); GetSym
  492. ELSIF sym = lparen THEN
  493. GetSym; Expression(x); CheckSym(rparen, 15)
  494. ELSIF sym = lbrace THEN GetSym; Sets(x, bitstyp)
  495. ELSIF sym = not THEN
  496. GetSym; Factor(x); GenNot(x)
  497. ELSE err(31); x.typ := undftyp; x.mode := expMd
  498. END
  499. END Factor;
  500. PROCEDURE Term(VAR x: Item);
  501. VAR y: Item; mulop: Symbol;
  502. BEGIN Factor(x);
  503. IF sym = and THEN
  504. GetSym; GenAnd(x); Term(y); GenOp(ORD(and), x, y)
  505. ELSE
  506. WHILE (times <= sym) & (sym < and) DO
  507. mulop := sym; GetSym;
  508. IF ~constFlag & ((x.mode # conMd) OR (mulop # times)) THEN load(x) END ;
  509. Factor(y); GenOp(ORD(mulop), x, y)
  510. END
  511. END
  512. END Term;
  513. PROCEDURE SimpleExpression(VAR x: Item);
  514. VAR y: Item; addop: Symbol;
  515. BEGIN
  516. IF sym = minus THEN
  517. GetSym; Term(x); GenNeg(x)
  518. ELSE
  519. IF sym = plus THEN GetSym END ;
  520. Term(x)
  521. END ;
  522. IF sym = or THEN
  523. GetSym; GenOr(x); SimpleExpression(y); GenOp(ORD(or), x, y)
  524. ELSE
  525. WHILE (plus <= sym) & (sym < or) DO
  526. addop := sym; GetSym;
  527. IF ~constFlag & ((x.mode # conMd) OR (addop = minus)) THEN load(x) END ;
  528. Term(y); GenOp(ORD(addop), x, y)
  529. END
  530. END
  531. END SimpleExpression;
  532. PROCEDURE Expression(VAR x: Item);
  533. VAR y: Item; relation: Symbol;
  534. BEGIN SimpleExpression(x);
  535. IF (eql <= sym) & (sym <= geq) THEN
  536. relation := sym; GetSym;
  537. IF ~constFlag THEN load(x) END ;
  538. SimpleExpression(y); GenOp(ORD(relation), x, y)
  539. ELSIF sym = in THEN GetSym;
  540. IF ~constFlag THEN load(x) END ;
  541. SimpleExpression(y); GenIn(x, y)
  542. END
  543. END Expression;
  544. PROCEDURE Priority;
  545. VAR x: Item;
  546. BEGIN
  547. IF sym = lbrak THEN
  548. GetSym; ConstExpression(x);
  549. IF (x.typ = cardtyp) & (x.val.C < 16) THEN curPrio := x.val.C + 1
  550. ELSE err(147)
  551. END ;
  552. CheckSym(rbrak, 16)
  553. END
  554. END Priority;
  555. PROCEDURE ImportList(impmod: ObjPtr);
  556. VAR obj: ObjPtr;
  557. BEGIN
  558. IF (impmod # NIL) & (impmod^.class # Module) THEN
  559. impmod := NIL; err(55)
  560. END ;
  561. LOOP
  562. IF sym = ident THEN
  563. IF impmod = NIL THEN obj := FindImport(id)
  564. ELSE obj := FindInScope(id, impmod^.root);
  565. IF (obj # NIL) & NOT obj^.exported THEN obj := NIL END
  566. END ;
  567. IF obj # NIL THEN NewImp(topScope, obj) ELSE err(50) END ;
  568. GetSym
  569. ELSE err(10)
  570. END ;
  571. IF sym = comma THEN GetSym
  572. ELSIF sym = ident THEN err(11)
  573. ELSE EXIT
  574. END
  575. END ;
  576. CheckSym(semicolon, 12)
  577. END ImportList;
  578. PROCEDURE ExportList;
  579. VAR obj: ObjPtr;
  580. BEGIN
  581. LOOP
  582. IF sym = ident THEN
  583. obj := NewObj(id, Temp); KeepId; GetSym
  584. ELSE err(10)
  585. END ;
  586. IF sym = comma THEN GetSym
  587. ELSIF sym = ident THEN err(11)
  588. ELSE EXIT
  589. END
  590. END ;
  591. CheckSym(semicolon, 12)
  592. END ExportList;
  593. PROCEDURE FormalParameters(proc: ObjPtr);
  594. VAR isvar: BOOLEAN;
  595. par, par0, par1: ParPtr; typ0: StrPtr;
  596. BEGIN par := NIL;
  597. IF (sym = ident) OR (sym = var) THEN
  598. LOOP par1 := par; isvar := FALSE;
  599. IF sym = var THEN GetSym; isvar := TRUE END ;
  600. LOOP
  601. IF sym = ident THEN
  602. par := NewPar(id, isvar, par); KeepId; GetSym
  603. ELSE err(10)
  604. END ;
  605. IF sym = comma THEN GetSym
  606. ELSIF sym = ident THEN err(11)
  607. ELSIF sym = var THEN err(11); GetSym
  608. ELSE EXIT
  609. END
  610. END ;
  611. CheckSym(colon, 13); FormalType(typ0); par0 := par;
  612. WHILE par0 # par1 DO
  613. par0^.typ := typ0; par0 := par0^.next
  614. END ;
  615. IF sym = semicolon THEN GetSym
  616. ELSIF sym = ident THEN err(12)
  617. ELSE EXIT
  618. END
  619. END
  620. END ;
  621. par1 := NIL; (*reverse list*)
  622. WHILE par # NIL DO
  623. par0 := par; par := par0^.next; par0^.next := par1; par1 := par0
  624. END ;
  625. proc^.firstParam := par1;
  626. CheckSym(rparen, 15)
  627. END FormalParameters;
  628. PROCEDURE CheckParameters(proc: ObjPtr);
  629. VAR isvar: BOOLEAN;
  630. par, par0, par1: ParPtr; typ0: StrPtr;
  631. BEGIN par0 := proc^.firstParam;
  632. IF (sym = ident) OR (sym = var) THEN
  633. LOOP par1 := par0; isvar := FALSE;
  634. IF sym = var THEN GetSym; isvar := TRUE END ;
  635. LOOP
  636. IF sym = ident THEN
  637. IF par0 # NIL THEN par0^.name := id; par0 := par0^.next
  638. ELSE err(66)
  639. END ;
  640. KeepId; GetSym
  641. ELSE err(10)
  642. END ;
  643. IF sym = comma THEN GetSym
  644. ELSIF sym = ident THEN err(11)
  645. ELSIF sym = var THEN err(11); GetSym
  646. ELSE EXIT
  647. END
  648. END ;
  649. CheckSym(colon, 13); FormalType(typ0); par := par1;
  650. WHILE par # par0 DO
  651. IF (par^.typ # typ0) &
  652. ((par^.typ^.form # Array) OR (typ0^.form # Array) OR
  653. (par^.typ^.ElemTyp # typ0^.ElemTyp)) THEN err(69)
  654. END ;
  655. IF par^.varpar # isvar THEN err(68) END ;
  656. par := par^.next
  657. END ;
  658. IF sym = semicolon THEN GetSym
  659. ELSIF sym = ident THEN err(12)
  660. ELSE EXIT
  661. END
  662. END
  663. END ;
  664. IF par0 # NIL THEN err(70) END ;
  665. CheckSym(rparen, 15)
  666. END CheckParameters;
  667. PROCEDURE MakeParameterObjects(proc: ObjPtr; VAR adr: INTEGER);
  668. VAR par: ParPtr; obj: ObjPtr; typ0: StrPtr; addr: INTEGER;
  669. BEGIN par := proc^.firstParam; addr := StartAddress;
  670. WHILE par # NIL DO
  671. obj := NewObj(par^.name, Var); par^.name := addr;
  672. (*address used when unstacking parameters*)
  673. WITH obj^ DO
  674. typ := par^.typ; vmod := 0; vlev := curLev; vadr := addr;
  675. IF par^.varpar THEN param := {1} ELSE param := {0} END
  676. END ;
  677. IF addr > 255 THEN err(99); addr := 0 END ;
  678. typ0 := par^.typ;
  679. IF (typ0^.form = Array) & typ0^.dyn THEN
  680. addr := addr + DynArrDesSize
  681. ELSIF par^.varpar THEN addr := addr + PointerTypSize
  682. ELSIF typ0^.size <= 2 THEN addr := addr + typ0^.size
  683. ELSE addr := addr+1
  684. END ;
  685. par := par^.next
  686. END ;
  687. adr := addr
  688. END MakeParameterObjects;
  689. PROCEDURE ProcedureDeclaration(VAR proc: ObjPtr);
  690. VAR i, L0: CARDINAL; adr: INTEGER; res: ObjPtr;
  691. BEGIN
  692. IF curLev = 0 THEN proc := Find(id) ELSE proc := NIL END ;
  693. IF (proc # NIL) & (proc^.class = Proc) &
  694. (proc^.pmod = 0) & (proc^.pd^.adr = 0) THEN
  695. (*procedure heading in definition module or forward declaration*)
  696. CheckSym(ident, 10);
  697. IF sym = lparen THEN
  698. GetSym; CheckParameters(proc);
  699. IF sym = colon THEN GetSym;
  700. IF sym = ident THEN qualident(res);
  701. IF (res = NIL) OR (res^.class # Typ) OR (res^.typ # proc^.typ) THEN
  702. err(71)
  703. END
  704. ELSE err(10)
  705. END
  706. ELSIF proc^.typ # notyp THEN err(72)
  707. END
  708. ELSIF proc^.firstParam # NIL THEN err(73)
  709. END
  710. ELSE
  711. proc := NewObj(id, Proc); KeepId; pno := pno + 1;
  712. WITH proc^ DO
  713. pmod := 0; typ := notyp; firstParam := NIL;
  714. pd^.num := pno; pd^.lev := curLev; pd^.adr := 0
  715. END ;
  716. CheckSym(ident, 10);
  717. IF sym = lparen THEN
  718. GetSym; FormalParameters(proc);
  719. IF sym = colon THEN
  720. GetSym; proc^.typ := undftyp;
  721. IF sym = ident THEN qualident(res);
  722. IF (res # NIL) & (res^.class = Typ) THEN proc^.typ := res^.typ
  723. ELSE err(52)
  724. END
  725. ELSE err(10)
  726. END
  727. END
  728. END
  729. END ;
  730. IF NOT isdef THEN
  731. CheckSym(semicolon, 12); MarkHeap;
  732. NewScope(Proc); curLev := curLev + 1;
  733. MakeParameterObjects(proc, adr);
  734. IF sym = code THEN GetSym;
  735. IF proc^.pd^.num > pnoI THEN pno := pno - 1;
  736. ELSE (*this procedure declared in definition module*) err(74)
  737. END ;
  738. i := 0;
  739. LOOP
  740. IF sym = number THEN GetSym;
  741. IF (i < MaxCodeLength) & (numtyp = 1) & (intval < 400B) THEN
  742. proc^.cd^.cod[i] := CHAR(intval); i := i+1
  743. ELSE err(91)
  744. END
  745. END ;
  746. IF sym = semicolon THEN GetSym
  747. ELSIF sym = number THEN err(12)
  748. ELSE EXIT
  749. END
  750. END ;
  751. WITH proc^ DO
  752. class := Code; (*!!!*) cnum := 0; length := i
  753. END ;
  754. CheckSym(end, 20);
  755. IF sym = ident THEN
  756. IF Diff(id, proc^.name) # 0 THEN err(77) END ;
  757. GetSym
  758. ELSE err(10)
  759. END
  760. ELSIF sym = forward THEN GetSym
  761. ELSE proc^.pd^.adr := pc;
  762. Block(proc, FALSE, adr, L0);
  763. IF proc^.typ = notyp THEN GenReturn ELSE GenTrap(9) END ;
  764. FixupEnter(L0, adr)
  765. END ;
  766. CloseScope; curLev := curLev - 1; ReleaseHeap
  767. ELSE proc^.pd^.size := adr; proc^.pd^.adr := 0
  768. END
  769. END ProcedureDeclaration;
  770. PROCEDURE ModuleDeclaration(VAR mod: ObjPtr; VAR adr: INTEGER);
  771. VAR L0, prio: CARDINAL; qual: BOOLEAN; impmod: ObjPtr;
  772. BEGIN qual := FALSE; CheckSym(ident, 10);
  773. mod := NewObj(id, Module); KeepId;
  774. pno := pno + 1; mod^.modno := pno; prio := curPrio; Priority;
  775. CheckSym(semicolon, 12); NewScope(Module);
  776. WHILE (sym = from) OR (sym = import) DO impmod := NIL;
  777. IF sym = from THEN GetSym;
  778. IF sym = ident THEN
  779. impmod := FindImport(id); GetSym
  780. ELSE err(10)
  781. END ;
  782. CheckSym(import, 30)
  783. ELSE GetSym
  784. END ;
  785. ImportList(impmod)
  786. END ;
  787. IF sym = export THEN GetSym;
  788. IF sym = qualified THEN GetSym; qual := TRUE END ;
  789. ExportList
  790. END ;
  791. Block(mod, qual, adr, L0); GenReturn;
  792. CloseScope; curPrio := prio; curLev := curLev - 1
  793. END ModuleDeclaration;
  794. MODULE Loops;
  795. IMPORT fixup, err, LoopLevels, NofExits;
  796. EXPORT EnterLoop, RecordExit, ExitLoop;
  797. VAR h,k: CARDINAL;
  798. index: ARRAY [0..LoopLevels-1] OF CARDINAL;
  799. label: ARRAY [0..NofExits-1] OF CARDINAL;
  800. PROCEDURE EnterLoop;
  801. BEGIN index[h] := k; h := h+1
  802. END EnterLoop;
  803. PROCEDURE RecordExit(L: CARDINAL);
  804. BEGIN
  805. IF h = 0 THEN err(39)
  806. ELSIF k < NofExits THEN label[k] := L; k := k+1
  807. ELSE err(93)
  808. END
  809. END RecordExit;
  810. PROCEDURE ExitLoop;
  811. BEGIN h := h-1;
  812. WHILE k > index[h] DO k := k-1; fixup(label[k]) END
  813. END ExitLoop;
  814. BEGIN h := 0; k := 0
  815. END Loops;
  816. PROCEDURE Block(ancestor: ObjPtr; qual: BOOLEAN;
  817. VAR adr: INTEGER; VAR L0: CARDINAL);
  818. VAR obj, last: ObjPtr; newtypdef: BOOLEAN;
  819. id0: CARDINAL; x: Item; typ: StrPtr;
  820. PROCEDURE StatSeq;
  821. VAR obj: ObjPtr; fpar: ParPtr; x, y: Item; L0, L1: CARDINAL;
  822. PROCEDURE ElsePart;
  823. VAR L0, L1: CARDINAL;
  824. BEGIN
  825. IF (sym = elsif) OR (sym = bar) THEN
  826. GetSym; Expression(x); GenCFJ(x, L0);
  827. CheckSym(then, 27); StatSeq;
  828. IF sym = end THEN fixup(L0)
  829. ELSE GenFJ(L1); fixup(L0); ElsePart; fixup(L1)
  830. END
  831. ELSIF sym = else THEN
  832. GetSym; StatSeq
  833. END
  834. END ElsePart;
  835. PROCEDURE CasePart;
  836. VAR x: Item; n, L0, L1: CARDINAL;
  837. tab: ARRAY [0..NofCases-1] OF LabelRange;
  838. BEGIN n := 0;
  839. Expression(x); GenCase1(x, L0); CheckSym(of, 23);
  840. LOOP
  841. IF sym < bar THEN
  842. CaseLabelList(x.typ, n, tab);
  843. CheckSym(colon, 13); StatSeq; GenCase2
  844. END ;
  845. IF sym = bar THEN GetSym ELSE EXIT END
  846. END ;
  847. L1 := pc;
  848. IF sym = else THEN
  849. GetSym; StatSeq; GenCase2
  850. ELSE GenTrap(4)
  851. END ;
  852. RefPoint; GenCase3(L0, L1, n, tab)
  853. END CasePart;
  854. PROCEDURE ForPart;
  855. VAR obj: ObjPtr;
  856. v, e1, e2, e3: Item;
  857. L0, L1: CARDINAL;
  858. BEGIN obj := NIL;
  859. IF sym = ident THEN
  860. obj := Find(id);
  861. IF obj # NIL THEN
  862. IF (obj^.class # Var) OR (obj^.param # {}) OR
  863. (obj^.vmod > 0) THEN err(75) END
  864. ELSE err(50)
  865. END ;
  866. GetSym
  867. ELSE err(10)
  868. END ;
  869. GenItem(v, obj, Scope); loadAdr(v);
  870. IF sym = becomes THEN GetSym ELSE err(19);
  871. IF sym = eql THEN GetSym END
  872. END ;
  873. Expression(e1); GenFor1(v,e1);
  874. CheckSym(to, 24); Expression(e2); GenFor2(v,e2);
  875. IF sym = by THEN
  876. GetSym; ConstExpression(e3)
  877. ELSE e3.typ := inttyp; e3.mode := conMd; e3.val.I := 1
  878. END ;
  879. GenFor3(e3, L0, L1);
  880. CheckSym(do, 25); StatSeq; GenFor4(e3, L0, L1)
  881. END ForPart;
  882. BEGIN
  883. LOOP
  884. IF sym < ident THEN err(35);
  885. REPEAT GetSym UNTIL sym >= ident
  886. END ;
  887. IF sym = ident THEN
  888. RefPoint; qualident(obj); selector(x, obj);
  889. IF sym = becomes THEN
  890. GetSym; PrepAss(x); Expression(y); GenAssign(x, y)
  891. ELSIF sym = eql THEN
  892. err(19); GetSym; PrepAss(x); Expression(y); GenAssign(x, y)
  893. ELSIF (x.mode = codMd) & (x.cod^.cnum > 0) THEN
  894. StandProcCall(x);
  895. IF x.typ # notyp THEN err(76) END
  896. ELSE PrepCall(x, fpar);
  897. IF sym = lparen THEN
  898. GetSym; ActualParameters(x, fpar); CheckSym(rparen, 15)
  899. ELSIF fpar # NIL THEN err(65)
  900. END ;
  901. GenCall(x);
  902. IF x.typ # notyp THEN err(76) END
  903. END
  904. ELSIF sym = if THEN
  905. GetSym; RefPoint; Expression(x); GenCFJ(x, L0);
  906. CheckSym(then, 27); StatSeq;
  907. IF sym = end THEN fixup(L0)
  908. ELSE GenFJ(L1); fixup(L0); ElsePart; fixup(L1)
  909. END ;
  910. CheckSym(end, 20)
  911. ELSIF sym = case THEN
  912. GetSym; RefPoint; CasePart; CheckSym(end, 20)
  913. ELSIF sym = while THEN
  914. GetSym; L1 := pc; RefPoint; Expression(x); GenCFJ(x, L0);
  915. CheckSym(do, 25); StatSeq; GenBJ(L1); fixup(L0);
  916. WHILE sym = bar DO
  917. GetSym; RefPoint; Expression(x); GenCFJ(x, L0);
  918. CheckSym(do, 25); StatSeq; GenBJ(L1); fixup(L0)
  919. END ;
  920. CheckSym(end, 20)
  921. ELSIF sym = repeat THEN
  922. GetSym; L0 := pc; StatSeq;
  923. IF sym = until THEN
  924. GetSym; RefPoint; Expression(x); GenCBJ(x, L0)
  925. ELSE err(26)
  926. END
  927. ELSIF sym = loop THEN
  928. GetSym; EnterLoop; L0 := pc; StatSeq; GenBJ(L0); ExitLoop;
  929. CheckSym(end, 20)
  930. ELSIF sym = for THEN
  931. GetSym; RefPoint; ForPart; CheckSym(end, 20)
  932. ELSIF sym = with THEN
  933. GetSym; x.typ := NIL;
  934. IF sym = ident THEN
  935. qualident(obj); selector(x, obj);
  936. IF (x.typ # NIL) & (x.typ^.form = Record) THEN
  937. NewScope(Typ); GenWith(x, adr);
  938. topScope^.withadr := adr; topScope^.right := x.typ^.firstFld;
  939. IF adr > 255 THEN err(99); adr := 0 END ;
  940. adr := adr + 1 (*allocate anonymous variable for address*)
  941. ELSE err(57); x.typ := NIL
  942. END
  943. ELSE err(10)
  944. END ;
  945. CheckSym(do, 25); StatSeq; CheckSym(end, 20);
  946. IF x.typ # NIL THEN CloseScope END
  947. ELSIF sym = exit THEN
  948. GetSym; GenFJ(L0); RecordExit(L0)
  949. ELSIF sym = return THEN GetSym;
  950. IF sym < semicolon THEN
  951. Expression(x); GenResult(x, ancestor)
  952. ELSIF ancestor^.typ # notyp THEN err(139)
  953. END ;
  954. GenReturn
  955. END ;
  956. CheckStack;
  957. IF sym = semicolon THEN GetSym
  958. ELSIF (sym <= ident) OR (if <= sym) & (sym <= for) THEN err(12)
  959. ELSE EXIT
  960. END
  961. END
  962. END StatSeq;
  963. PROCEDURE CheckExports(obj: ObjPtr);
  964. BEGIN
  965. IF obj # NIL THEN
  966. IF obj^.class = Temp THEN err(80)
  967. ELSIF ~qual & obj^.exported THEN (*import in outer scope*)
  968. NewImp(topScope^.left, obj)
  969. END ;
  970. CheckExports(obj^.left); CheckExports(obj^.right)
  971. END
  972. END CheckExports;
  973. BEGIN (*Block*)
  974. LOOP
  975. IF sym = const THEN
  976. GetSym;
  977. WHILE sym = ident DO
  978. id0 := id; KeepId; GetSym;
  979. IF sym = eql THEN
  980. GetSym; ConstExpression(x)
  981. ELSIF sym = becomes THEN
  982. err(18); GetSym; ConstExpression(x)
  983. ELSE err(18)
  984. END ;
  985. obj := NewObj(id0, Const); obj^.typ := x.typ; obj^.conval := x.val;
  986. IF x.typ = stringtyp THEN obj^.conval.D2 := id; KeepId END ;
  987. CheckSym(semicolon, 12)
  988. END
  989. ELSIF sym = type THEN
  990. GetSym;
  991. WHILE sym = ident DO
  992. typ := undftyp; obj := NIL; newtypdef := TRUE;
  993. IF isimp & (curLev = 0) THEN
  994. obj := Find(id);
  995. IF (obj # NIL) & (obj^.class = Typ) & (obj^.typ^.form = Opaque) THEN
  996. newtypdef := FALSE
  997. END
  998. END ;
  999. IF newtypdef THEN id0 := id; KeepId END ;
  1000. GetSym;
  1001. IF sym = eql THEN
  1002. GetSym; Type(typ)
  1003. ELSIF (sym = becomes) OR (sym = colon) THEN
  1004. err(18); GetSym; Type(typ)
  1005. ELSIF NOT isdef THEN err(18)
  1006. ELSE typ := NewStr(Opaque); typ^.size := PointerTypSize
  1007. END ;
  1008. IF newtypdef THEN
  1009. obj := NewObj(id0, Typ); obj^.typ := typ; obj^.mod := mainmod;
  1010. IF typ^.strobj = NIL THEN typ^.strobj := obj END ;
  1011. ELSIF typ^.size = PointerTypSize THEN obj^.typ^ := typ^
  1012. ELSE err(87)
  1013. END ;
  1014. CheckUDP(obj, topScope^.right); (*check for undefined pointer types*)
  1015. CheckSym(semicolon, 12)
  1016. END
  1017. ELSIF sym = var THEN
  1018. GetSym;
  1019. WHILE sym = ident DO last := topScope^.last; obj := last;
  1020. LOOP
  1021. IF sym = ident THEN
  1022. obj := NewObj(id, Var); KeepId; GetSym
  1023. ELSE err(10)
  1024. END ;
  1025. IF sym = comma THEN GetSym
  1026. ELSIF sym = ident THEN err(11)
  1027. ELSE EXIT
  1028. END
  1029. END ;
  1030. CheckSym(colon, 13); Type(typ);
  1031. WHILE last # obj DO
  1032. last := last^.next; last^.typ := typ;
  1033. WITH last^ DO
  1034. param := {}; vmod := 0; vlev := curLev; vadr := adr
  1035. END ;
  1036. IF typ^.size <= 2 THEN adr := adr + typ^.size
  1037. ELSE adr := adr + 1
  1038. END ;
  1039. IF adr > 255 THEN err(99); adr := 0 END
  1040. END ;
  1041. CheckSym(semicolon, 12)
  1042. END
  1043. ELSIF sym = procedure THEN
  1044. GetSym; ProcedureDeclaration(obj); CheckSym(semicolon, 12)
  1045. ELSIF sym = module THEN
  1046. GetSym; ModuleDeclaration(obj, adr); CheckSym(semicolon, 12)
  1047. ELSE
  1048. IF (sym # begin) & (sym # end) THEN err(36);
  1049. REPEAT GetSym UNTIL (sym >= begin) OR (sym = end)
  1050. END ;
  1051. IF (sym <= begin) OR (sym = eof) THEN EXIT END
  1052. END
  1053. END ;
  1054. IF ancestor^.class = Module THEN
  1055. ancestor^.firstObj := topScope^.next; ancestor^.root := topScope^.right;
  1056. IF ancestor = mainmod THEN
  1057. fixupC(L0); GenEndDecl(ancestor, ModNo)
  1058. ELSE CheckExports(topScope^.right);
  1059. curLev := curLev + 1; GenEnterMod(ancestor)
  1060. END
  1061. ELSE (*procedure*) ancestor^.firstLocal := topScope^.next;
  1062. GenEnter(L0, ancestor); GenEndDecl(ancestor, 0)
  1063. END ;
  1064. IF sym = begin THEN
  1065. IF isdef THEN err(37) END ;
  1066. GetSym; StatSeq; RefPoint
  1067. END ;
  1068. CheckSym(end, 20); OutUnit(ancestor);
  1069. IF sym = ident THEN
  1070. IF Diff(id, ancestor^.name) # 0 THEN err(77) END ;
  1071. GetSym
  1072. ELSE err(10)
  1073. END
  1074. END Block;
  1075. PROCEDURE CompilationUnit;
  1076. VAR id0, L0: CARDINAL; adr: INTEGER;
  1077. hdr, importMod: ObjPtr; impok: BOOLEAN;
  1078. FName: ARRAY [0..NL] OF CHAR;
  1079. PROCEDURE GetFileName(j: CARDINAL;
  1080. VAR FName: ARRAY OF CHAR; ext: ARRAY OF CHAR);
  1081. VAR i,L: CARDINAL;
  1082. BEGIN i := 3; L := CARDINAL(IdBuf[j]) + j-1;
  1083. WHILE j < L DO
  1084. j := j+1; FName[i] := IdBuf[j]; i := i+1
  1085. END ;
  1086. j := 0; L := HIGH(ext);
  1087. WHILE j <= L DO
  1088. FName[i] := ext[j]; i := i+1; j := j+1
  1089. END ;
  1090. FName[i] := 0C
  1091. END GetFileName;
  1092. PROCEDURE ImportModule;
  1093. VAR adr: INTEGER; pno: CARDINAL;
  1094. BEGIN
  1095. IF sym = ident THEN
  1096. IF Diff(id, sysmod^.name) = 0 THEN importMod := sysmod
  1097. ELSE GetFileName(id, FileName, ".SBL"); WriteLn;
  1098. WriteString(" - "); WriteString(FileName);
  1099. InRef(FileName, hdr, adr, pno);
  1100. IF hdr # NIL THEN importMod := hdr^.right
  1101. ELSE impok := FALSE;
  1102. importMod := NIL; WriteString(" not found (or bad)")
  1103. END
  1104. END ;
  1105. GetSym
  1106. ELSE err(10)
  1107. END ;
  1108. END ImportModule;
  1109. PROCEDURE Out(n: CARDINAL);
  1110. VAR k: CARDINAL; d: ARRAY [0..5] OF CARDINAL;
  1111. BEGIN k := 0; Write(" ");
  1112. REPEAT d[k] := n MOD 10; n := n DIV 10; k := k+1 UNTIL n = 0;
  1113. REPEAT k := k-1; Write(CHAR(d[k]+60B)) UNTIL k = 0
  1114. END Out;
  1115. PROCEDURE CheckUDProc(obj: ObjPtr);
  1116. BEGIN (*check for undefined procedure bodies*)
  1117. WHILE obj # NIL DO
  1118. IF (obj^.class = Proc) & (obj^.pmod = 0) &
  1119. (obj^.pd^.adr = 0) THEN err(89)
  1120. END ;
  1121. obj := obj^.next
  1122. END
  1123. END CheckUDProc;
  1124. BEGIN isdef := FALSE; isimp := FALSE; impok := TRUE;
  1125. curLev := 0; curPrio := 0; constFlag := FALSE;
  1126. FName := "DK."; GetSym;
  1127. IF sym = definition THEN GetSym; isdef := TRUE
  1128. ELSIF sym = implementation THEN GetSym; isimp := TRUE
  1129. END ;
  1130. IF sym = module THEN
  1131. GetSym;
  1132. IF sym = ident THEN
  1133. id0 := id; mainmod^.name := id0; KeepId; GetSym;
  1134. IF NOT isdef THEN Priority END ;
  1135. CheckSym(semicolon, 12); MarkHeap; NewScope(Module);
  1136. IF isimp THEN
  1137. GetFileName(id0, FName, ".SBL"); WriteLn;
  1138. WriteString(" - "); WriteString(FName);
  1139. InRef(FName, hdr, adr, pno);
  1140. IF hdr # NIL THEN importMod := hdr^.right;
  1141. topScope^.right := importMod^.root; (*mainmod*)
  1142. topScope^.next := hdr^.next; topScope^.last := hdr^.last
  1143. ELSE importMod := NIL;
  1144. WriteString(" not found (or bad)"); impok := FALSE
  1145. END
  1146. ELSE adr := 3; pno := 0; mainmod^.key := sysmod^.key
  1147. END ;
  1148. WHILE (sym = from) OR (sym = import) DO
  1149. IF sym = from THEN
  1150. GetSym; ImportModule; CheckSym(import, 30);
  1151. ImportList(importMod)
  1152. ELSE (*sym = import*) GetSym;
  1153. LOOP ImportModule;
  1154. IF importMod # NIL THEN NewImp(topScope, importMod) END ;
  1155. IF sym = comma THEN GetSym
  1156. ELSIF sym # ident THEN EXIT
  1157. END
  1158. END ;
  1159. CheckSym(semicolon, 12)
  1160. END
  1161. END ;
  1162. IF sym = export THEN
  1163. GetSym; err(38);
  1164. WHILE sym # semicolon DO GetSym END ;
  1165. GetSym
  1166. END ;
  1167. IF impok THEN
  1168. pnoI := pno;
  1169. IF isdef THEN GetFileName(id0, FName, ".SBL")
  1170. ELSE GetFileName(id0, FName, ".RFC")
  1171. END ;
  1172. WriteLn; WriteString(" + "); WriteString(FName);
  1173. Lookup(RefFile, FName, TRUE);
  1174. IF RefFile.res # done THEN err(222) END ;
  1175. OpenRef; GenFJ(L0); Block(mainmod, TRUE, adr, L0);
  1176. IF sym # period THEN err(14) END ;
  1177. IF NOT isdef THEN CheckUDProc(mainmod^.firstObj) END ;
  1178. IF NOT scanerr THEN
  1179. IF NOT isdef THEN
  1180. GetFileName(id0, FName, ".OBJ"); WriteLn;
  1181. WriteString(" + "); WriteString(FName); Out(pc);
  1182. OutCodeFile(FName, mainmod^.key, adr, pno+1, id0, ModNo, ModList)
  1183. END ;
  1184. CloseRef(adr, pno); Close(RefFile)
  1185. ELSE Delete(RefFile)
  1186. END
  1187. END ;
  1188. CloseScope; ReleaseHeap
  1189. ELSE err(10)
  1190. END ;
  1191. ELSE err(28)
  1192. END ;
  1193. IF scanerr THEN WriteString(" errors detected") END
  1194. END CompilationUnit;
  1195. PROCEDURE ReadName;
  1196. CONST DEL = 177C;
  1197. VAR i: CARDINAL;
  1198. BEGIN
  1199. REPEAT Read(ch) UNTIL (ch >= "A") OR (ch = 33C);
  1200. FileName := "DK."; i := 3;
  1201. WHILE (CAP(ch) >= "A") & (CAP(ch) <= "Z")
  1202. OR (ch >= "0") & (ch <= "9")
  1203. OR (ch = ".") OR (ch = DEL) DO
  1204. IF ch = DEL THEN
  1205. IF i > 3 THEN Write(DEL); i := i-1 END
  1206. ELSIF i < NL THEN
  1207. Write(ch); FileName[i] := ch; i := i+1
  1208. END ;
  1209. Read(ch)
  1210. END ;
  1211. IF (3 < i) & (i < NL) & (FileName[i-1] = ".") THEN
  1212. FileName[i] := "M"; i := i+1;
  1213. FileName[i] := "O"; i := i+1;
  1214. FileName[i] := "D"; i := i+1; WriteString("MOD");
  1215. END ;
  1216. FileName[i] := 0C
  1217. END ReadName;
  1218. BEGIN WriteString("ETHZ M3L NW 2.8.86"); WriteLn;
  1219. LOOP WriteString("in> "); rngchk := TRUE; ReadName;
  1220. IF (ch = 33C) OR (FileName[3] < "A") THEN EXIT END ;
  1221. IF ch = "/" THEN
  1222. Write("/"); Read(ch);
  1223. IF ch = "r" THEN Write("r"); rngchk := FALSE END
  1224. END ;
  1225. Lookup(source, FileName, FALSE);
  1226. IF source.res = done THEN GetTime(TM);
  1227. WITH sysmod^.key^ DO
  1228. k0 := TM.day; k1 := TM.minute; k2 := TM.millisecond
  1229. END ;
  1230. InitScanner(FileName); InitTableHandler; InitRef; InitGenerator;
  1231. CompilationUnit; Close(source);
  1232. ELSE WriteString(" not found")
  1233. END ;
  1234. WriteLn
  1235. END ;
  1236. CloseScanner; WriteLn
  1237. END M3PL.