CPP.txt 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649
  1. MODULE LindevCPP;
  2. (* THIS IS TEXT COPY OF CPP.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT
  5. DevCPM := LindevCPM, DevCPT := LindevCPT, DevCPB := LindevCPB, DevCPS := LindevCPS;
  6. CONST
  7. anchorVarPar = TRUE;
  8. (* numtyp values *)
  9. char = 1; integer = 2; real = 4; int64 = 5; real32 = 6; real64 = 7;
  10. (*symbol values*)
  11. null = 0; times = 1; slash = 2; div = 3; mod = 4;
  12. and = 5; plus = 6; minus = 7; or = 8; eql = 9;
  13. neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
  14. in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
  15. comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
  16. rbrace = 25; of = 26; then = 27; do = 28; to = 29;
  17. by = 30; not = 33;
  18. lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
  19. number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
  20. bar = 50; end = 51; else = 52; elsif = 53; until = 54;
  21. if = 55; case = 56; while = 57; repeat = 58; for = 59;
  22. loop = 60; with = 61; exit = 62; return = 63; array = 64;
  23. record = 65; pointer = 66; begin = 67; const = 68; type = 69;
  24. var = 70; out = 71; procedure = 72; close = 73; import = 74;
  25. module = 75; eof = 76;
  26. (* object modes *)
  27. Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7;
  28. SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13; Attr = 20;
  29. (* Structure forms *)
  30. Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6;
  31. Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12;
  32. Pointer = 13; ProcTyp = 14; Comp = 15;
  33. Char16 = 16; String16 = 17; Int64 = 18;
  34. intSet = {Int8..Int32, Int64}; charSet = {Char8, Char16};
  35. (* composite structure forms *)
  36. Basic = 1; Array = 2; DynArr = 3; Record = 4;
  37. (*function number*)
  38. haltfn = 0; newfn = 1; incfn = 13; sysnewfn = 30;
  39. (* nodes classes *)
  40. Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
  41. Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
  42. Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
  43. Nifelse = 20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
  44. Nreturn = 26; Nwith = 27; Ntrap = 28; Ncomp = 30;
  45. (* node subclasses *)
  46. super = 1;
  47. (* module visibility of objects *)
  48. internal = 0; external = 1; externalR = 2; inPar = 3; outPar = 4;
  49. (* procedure flags (conval.setval) *)
  50. hasBody = 1; isRedef = 2; slNeeded = 3; imVar = 4;
  51. (* attribute flags (attr.adr, struct.attribute, proc.conval.setval)*)
  52. newAttr = 16; absAttr = 17; limAttr = 18; empAttr = 19; extAttr = 20;
  53. (* case statement flags (conval.setval) *)
  54. useTable = 1; useTree = 2;
  55. (* sysflags *)
  56. nilBit = 1; inBit = 2; outBit = 4; newBit = 8; iidBit = 16; interface = 10; som = 20; jstr = -13;
  57. TYPE
  58. Elem = POINTER TO RECORD
  59. next: Elem;
  60. struct: DevCPT.Struct;
  61. obj, base: DevCPT.Object;
  62. pos: INTEGER;
  63. name: DevCPT.String
  64. END;
  65. VAR
  66. sym, level: BYTE;
  67. LoopLevel: SHORTINT;
  68. TDinit, lastTDinit: DevCPT.Node;
  69. userList: Elem;
  70. recList: Elem;
  71. hasReturn: BOOLEAN;
  72. numUsafeVarPar, numFuncVarPar: INTEGER;
  73. PROCEDURE^ Type(VAR typ: DevCPT.Struct; VAR name: DevCPT.String);
  74. PROCEDURE^ Expression(VAR x: DevCPT.Node);
  75. PROCEDURE^ Block(VAR procdec, statseq: DevCPT.Node);
  76. (* forward type handling *)
  77. PROCEDURE IncompleteType (typ: DevCPT.Struct): BOOLEAN;
  78. BEGIN
  79. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  80. RETURN (typ = DevCPT.undftyp) OR (typ.comp = Record) & (typ.BaseTyp = DevCPT.undftyp)
  81. END IncompleteType;
  82. PROCEDURE SetType (struct: DevCPT.Struct; obj: DevCPT.Object; typ: DevCPT.Struct; name: DevCPT.String);
  83. VAR u: Elem;
  84. BEGIN
  85. IF obj # NIL THEN obj.typ := typ ELSE struct.BaseTyp := typ END;
  86. IF name # NIL THEN
  87. NEW(u); u.struct := struct; u.obj := obj; u.pos := DevCPM.errpos; u.name := name;
  88. u.next := userList; userList := u
  89. END
  90. END SetType;
  91. PROCEDURE CheckAlloc (VAR typ: DevCPT.Struct; dynAllowed: BOOLEAN; pos: INTEGER);
  92. BEGIN
  93. typ.pvused := TRUE;
  94. IF typ.comp = DynArr THEN
  95. IF ~dynAllowed THEN DevCPM.Mark(88, pos); typ := DevCPT.undftyp END
  96. ELSIF typ.comp = Record THEN
  97. IF (typ.attribute = absAttr) OR (typ.attribute = limAttr) & (typ.mno # 0) THEN
  98. DevCPM.Mark(193, pos); typ := DevCPT.undftyp
  99. END
  100. END
  101. END CheckAlloc;
  102. PROCEDURE CheckRecursiveType (outer, inner: DevCPT.Struct; pos: INTEGER);
  103. VAR fld: DevCPT.Object;
  104. BEGIN
  105. IF outer = inner THEN DevCPM.Mark(58, pos)
  106. ELSIF inner.comp IN {Array, DynArr} THEN CheckRecursiveType(outer, inner.BaseTyp, pos)
  107. ELSIF inner.comp = Record THEN
  108. fld := inner.link;
  109. WHILE (fld # NIL) & (fld.mode = Fld) DO
  110. CheckRecursiveType(outer, fld.typ, pos);
  111. fld := fld.link
  112. END;
  113. IF inner.BaseTyp # NIL THEN CheckRecursiveType(outer, inner.BaseTyp, pos) END
  114. END
  115. END CheckRecursiveType;
  116. PROCEDURE FixType (struct: DevCPT.Struct; obj: DevCPT.Object; typ: DevCPT.Struct; pos: INTEGER);
  117. (* fix forward reference *)
  118. VAR t: DevCPT.Struct; f, bf: DevCPT.Object; i: SHORTINT;
  119. BEGIN
  120. IF obj # NIL THEN
  121. IF obj.mode = Var THEN (* variable type *)
  122. IF struct # NIL THEN (* receiver type *)
  123. IF (typ.form # Pointer) OR (typ.BaseTyp # struct) THEN DevCPM.Mark(180, pos) END;
  124. ELSE CheckAlloc(typ, obj.mnolev > level, pos) (* TRUE for parameters *)
  125. END
  126. ELSIF obj.mode = VarPar THEN (* varpar type *)
  127. IF struct # NIL THEN (* varpar receiver type *)
  128. IF typ # struct THEN DevCPM.Mark(180, pos) END
  129. END
  130. ELSIF obj.mode = Fld THEN (* field type *)
  131. CheckAlloc(typ, FALSE, pos);
  132. CheckRecursiveType(struct, typ, pos)
  133. ELSIF obj.mode = TProc THEN (* proc return type *)
  134. IF typ.form = Comp THEN typ := DevCPT.undftyp; DevCPM.Mark(54, pos) END
  135. ELSIF obj.mode = Typ THEN (* alias type *)
  136. IF typ.form IN {Byte..Set, Char16, Int64} THEN (* make alias structure *)
  137. t := DevCPT.NewStr(typ.form, Basic); i := t.ref;
  138. t^ := typ^; t.ref := i; t.strobj := obj; t.mno := 0;
  139. t.BaseTyp := typ; typ := t
  140. END;
  141. IF obj.vis # internal THEN
  142. IF typ.comp = Record THEN typ.exp := TRUE
  143. ELSIF typ.form = Pointer THEN typ.BaseTyp.exp := TRUE
  144. END
  145. END
  146. ELSE HALT(100)
  147. END;
  148. obj.typ := typ
  149. ELSE
  150. IF struct.form = Pointer THEN (* pointer base type *)
  151. IF typ.comp = Record THEN DevCPM.PropagateRecPtrSysFlag(typ.sysflag, struct.sysflag)
  152. ELSIF typ.comp IN {Array, DynArr} THEN DevCPM.PropagateArrPtrSysFlag(typ.sysflag, struct.sysflag)
  153. ELSE typ := DevCPT.undftyp; DevCPM.Mark(57, pos)
  154. END;
  155. struct.untagged := struct.sysflag > 0;
  156. IF (struct.strobj # NIL) & (struct.strobj.vis # internal) THEN typ.exp := TRUE END;
  157. ELSIF struct.comp = Array THEN (* array base type *)
  158. CheckAlloc(typ, FALSE, pos);
  159. CheckRecursiveType(struct, typ, pos)
  160. ELSIF struct.comp = DynArr THEN (* array base type *)
  161. CheckAlloc(typ, TRUE, pos);
  162. CheckRecursiveType(struct, typ, pos)
  163. ELSIF struct.comp = Record THEN (* record base type *)
  164. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  165. typ.pvused := TRUE; struct.extlev := SHORT(SHORT(typ.extlev + 1));
  166. DevCPM.PropagateRecordSysFlag(typ.sysflag, struct.sysflag);
  167. IF (typ.attribute = 0) OR (typ.attribute = limAttr) & (typ.mno # 0) THEN DevCPM.Mark(181, pos)
  168. ELSIF (struct.attribute = absAttr) & (typ.attribute # absAttr) THEN DevCPM.Mark(191, pos)
  169. ELSIF (typ.attribute = limAttr) & (struct.attribute # limAttr) THEN DevCPM.Mark(197, pos)
  170. END;
  171. f := struct.link;
  172. WHILE f # NIL DO (* check for field name conflicts *)
  173. DevCPT.FindField(f.name, typ, bf);
  174. IF bf # NIL THEN DevCPM.Mark(1, pos) END;
  175. f := f.link
  176. END;
  177. CheckRecursiveType(struct, typ, pos);
  178. struct.untagged := struct.sysflag > 0;
  179. ELSIF struct.form = ProcTyp THEN (* proc type return type *)
  180. IF typ.form = Comp THEN typ := DevCPT.undftyp; DevCPM.Mark(54, pos) END;
  181. ELSE HALT(100)
  182. END;
  183. struct.BaseTyp := typ
  184. END
  185. END FixType;
  186. PROCEDURE CheckForwardTypes;
  187. VAR u, next: Elem; progress: BOOLEAN;
  188. BEGIN
  189. u := userList; userList := NIL;
  190. WHILE u # NIL DO
  191. next := u.next; DevCPS.name := u.name^$; DevCPT.Find(DevCPS.name, u.base);
  192. IF u.base = NIL THEN DevCPM.Mark(0, u.pos)
  193. ELSIF u.base.mode # Typ THEN DevCPM.Mark(72, u.pos)
  194. ELSE u.next := userList; userList := u (* reinsert *)
  195. END;
  196. u := next
  197. END;
  198. REPEAT (* iteration for multy level alias *)
  199. u := userList; userList := NIL; progress := FALSE;
  200. WHILE u # NIL DO
  201. next := u.next;
  202. IF IncompleteType(u.base.typ) THEN
  203. u.next := userList; userList := u (* reinsert *)
  204. ELSE
  205. progress := TRUE;
  206. FixType(u.struct, u.obj, u.base.typ, u.pos)
  207. END;
  208. u := next
  209. END
  210. UNTIL (userList = NIL) OR ~progress;
  211. u := userList; (* remaining type relations are cyclic *)
  212. WHILE u # NIL DO
  213. IF (u.obj = NIL) OR (u.obj.mode = Typ) THEN DevCPM.Mark(58, u.pos) END;
  214. u := u.next
  215. END;
  216. END CheckForwardTypes;
  217. PROCEDURE CheckUnimpl (m: DevCPT.Object; typ: DevCPT.Struct; pos: INTEGER);
  218. VAR obj: DevCPT.Object;
  219. BEGIN
  220. IF m # NIL THEN
  221. IF (m.mode = TProc) & (absAttr IN m.conval.setval) THEN
  222. DevCPT.FindField(m.name^, typ, obj);
  223. IF (obj = NIL) OR (obj.mode # TProc) OR (absAttr IN obj.conval.setval) THEN
  224. DevCPM.Mark(192, pos);
  225. DevCPM.errorMes := DevCPM.errorMes + " " + m.name^ + " not implemented";
  226. IF typ.strobj # NIL THEN
  227. DevCPM.errorMes := DevCPM.errorMes+ " in " + typ.strobj.name^
  228. END
  229. END
  230. END;
  231. CheckUnimpl(m.left, typ, pos);
  232. CheckUnimpl(m.right, typ, pos)
  233. END
  234. END CheckUnimpl;
  235. PROCEDURE CheckRecords (rec: Elem);
  236. VAR b: DevCPT.Struct;
  237. BEGIN
  238. WHILE rec # NIL DO (* check for unimplemented methods in base type *)
  239. b := rec.struct.BaseTyp;
  240. WHILE (b # NIL) & (b # DevCPT.undftyp) DO
  241. CheckUnimpl(b.link, rec.struct, rec.pos);
  242. b := b.BaseTyp
  243. END;
  244. rec := rec.next
  245. END
  246. END CheckRecords;
  247. PROCEDURE err(n: SHORTINT);
  248. BEGIN DevCPM.err(n)
  249. END err;
  250. PROCEDURE CheckSym(s: SHORTINT);
  251. BEGIN
  252. IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
  253. END CheckSym;
  254. PROCEDURE qualident(VAR id: DevCPT.Object);
  255. VAR obj: DevCPT.Object; lev: BYTE;
  256. BEGIN (*sym = ident*)
  257. DevCPT.Find(DevCPS.name, obj); DevCPS.Get(sym);
  258. IF (sym = period) & (obj # NIL) & (obj.mode = Mod) THEN
  259. DevCPS.Get(sym);
  260. IF sym = ident THEN
  261. DevCPT.FindImport(DevCPS.name, obj, obj); DevCPS.Get(sym)
  262. ELSE err(ident); obj := NIL
  263. END
  264. END ;
  265. IF obj = NIL THEN err(0);
  266. obj := DevCPT.NewObj(); obj.mode := Var; obj.typ := DevCPT.undftyp; obj.adr := 0
  267. ELSE lev := obj.mnolev;
  268. IF (obj.mode IN {Var, VarPar}) & (lev # level) THEN
  269. obj.leaf := FALSE;
  270. IF lev > 0 THEN DevCPB.StaticLink(SHORT(SHORT(level-lev)), TRUE) END (* !!! *)
  271. END
  272. END ;
  273. id := obj
  274. END qualident;
  275. PROCEDURE ConstExpression(VAR x: DevCPT.Node);
  276. BEGIN Expression(x);
  277. IF x.class # Nconst THEN
  278. err(50); x := DevCPB.NewIntConst(1)
  279. END
  280. END ConstExpression;
  281. PROCEDURE CheckMark(obj: DevCPT.Object); (* !!! *)
  282. VAR n: INTEGER; mod: ARRAY 256 OF DevCPT.String;
  283. BEGIN DevCPS.Get(sym);
  284. IF (sym = times) OR (sym = minus) THEN
  285. IF (level > 0) OR ~(obj.mode IN {Var, Fld, TProc}) & (sym = minus) THEN err(41) END ;
  286. IF sym = times THEN obj.vis := external ELSE obj.vis := externalR END ;
  287. DevCPS.Get(sym)
  288. ELSE obj.vis := internal
  289. END;
  290. IF (obj.mode IN {TProc, LProc, XProc, CProc, Var, Typ, Con, Fld}) & (sym = lbrak) THEN
  291. DevCPS.Get(sym);
  292. IF (sym = number) & (DevCPS.numtyp = char) THEN
  293. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  294. END;
  295. IF sym = string THEN
  296. IF DevCPS.str^ # "" THEN obj.entry := DevCPS.str END;
  297. DevCPS.Get(sym); n := 0;
  298. IF (sym = comma) & (obj.mode IN {LProc, XProc, CProc, Var, Con}) THEN
  299. DevCPS.Get(sym);
  300. IF (sym = number) & (DevCPS.numtyp = char) THEN
  301. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  302. END;
  303. IF sym = string THEN
  304. obj.library := obj.entry; obj.entry := NIL;
  305. IF DevCPS.str^ # "" THEN obj.entry := DevCPS.str END;
  306. DevCPS.Get(sym);
  307. ELSE err(string)
  308. END
  309. END;
  310. WHILE sym = comma DO
  311. DevCPS.Get(sym);
  312. IF (sym = number) & (DevCPS.numtyp = char) THEN
  313. NEW(DevCPS.str, 2); DevCPS.str[0] := SHORT(CHR(DevCPS.intval)); DevCPS.str[1] := 0X; sym := string
  314. END;
  315. IF sym = string THEN
  316. IF n < LEN(mod) THEN mod[n] := DevCPS.str; INC(n)
  317. ELSE err(235)
  318. END;
  319. DevCPS.Get(sym)
  320. ELSE err(string)
  321. END
  322. END;
  323. IF n > 0 THEN
  324. NEW(obj.modifiers, n);
  325. WHILE n > 0 DO DEC(n); obj.modifiers[n] := mod[n] END
  326. END
  327. ELSE err(string)
  328. END;
  329. CheckSym(rbrak);
  330. IF DevCPM.options * {DevCPM.interface, DevCPM.java} = {} THEN err(225) END
  331. END
  332. END CheckMark;
  333. PROCEDURE CheckSysFlag (VAR sysflag: SHORTINT;
  334. GetSF: PROCEDURE(id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT));
  335. VAR x: DevCPT.Object; i: SHORTINT;
  336. BEGIN
  337. sysflag := 0;
  338. IF sym = lbrak THEN
  339. DevCPS.Get(sym);
  340. WHILE (sym = number) OR (sym = ident) OR (sym = string) DO
  341. IF sym = number THEN
  342. IF DevCPS.numtyp = integer THEN
  343. i := SHORT(DevCPS.intval); GetSF("", i, sysflag)
  344. ELSE err(225)
  345. END
  346. ELSIF sym = ident THEN
  347. DevCPT.Find(DevCPS.name, x);
  348. IF (x # NIL) & (x.mode = Con) & (x.typ.form IN {Int8, Int16, Int32}) THEN
  349. i := SHORT(x.conval.intval); GetSF("", i, sysflag)
  350. ELSE
  351. GetSF(DevCPS.name, 0, sysflag)
  352. END
  353. ELSE
  354. GetSF(DevCPS.str^, 0, sysflag)
  355. END;
  356. DevCPS.Get(sym);
  357. IF (sym = comma) OR (sym = plus) THEN DevCPS.Get(sym) END
  358. END;
  359. CheckSym(rbrak)
  360. END
  361. END CheckSysFlag;
  362. PROCEDURE Receiver(VAR mode, vis: BYTE; VAR name: DevCPT.Name; VAR typ, rec: DevCPT.Struct);
  363. VAR obj: DevCPT.Object; tname: DevCPT.String;
  364. BEGIN typ := DevCPT.undftyp; rec := NIL; vis := 0;
  365. IF sym = var THEN DevCPS.Get(sym); mode := VarPar;
  366. ELSIF sym = in THEN DevCPS.Get(sym); mode := VarPar; vis := inPar (* ??? *)
  367. ELSE mode := Var
  368. END ;
  369. name := DevCPS.name; CheckSym(ident); CheckSym(colon);
  370. IF sym # ident THEN err(ident) END;
  371. Type(typ, tname);
  372. IF tname = NIL THEN
  373. IF typ.form = Pointer THEN rec := typ.BaseTyp ELSE rec := typ END;
  374. IF ~((mode = Var) & (typ.form = Pointer) & (rec.comp = Record) OR
  375. (mode = VarPar) & (typ.comp = Record)) THEN err(70); rec := NIL END;
  376. IF (rec # NIL) & (rec.mno # level) THEN err(72); rec := NIL END
  377. ELSE err(0)
  378. END;
  379. CheckSym(rparen);
  380. IF rec = NIL THEN rec := DevCPT.NewStr(Comp, Record); rec.BaseTyp := NIL END
  381. END Receiver;
  382. PROCEDURE FormalParameters(
  383. VAR firstPar: DevCPT.Object; VAR resTyp: DevCPT.Struct; VAR name: DevCPT.String
  384. );
  385. VAR mode, vis: BYTE; sys: SHORTINT;
  386. par, first, last, res, newPar, iidPar: DevCPT.Object; typ: DevCPT.Struct;
  387. BEGIN
  388. first := NIL; last := firstPar;
  389. newPar := NIL; iidPar := NIL;
  390. IF (sym = ident) OR (sym = var) OR (sym = in) OR (sym = out) THEN
  391. LOOP
  392. sys := 0; vis := 0;
  393. IF sym = var THEN DevCPS.Get(sym); mode := VarPar
  394. ELSIF sym = in THEN DevCPS.Get(sym); mode := VarPar; vis := inPar
  395. ELSIF sym = out THEN DevCPS.Get(sym); mode := VarPar; vis := outPar
  396. ELSE mode := Var
  397. END ;
  398. IF mode = VarPar THEN CheckSysFlag(sys, DevCPM.GetVarParSysFlag) END;
  399. IF ODD(sys DIV inBit) THEN vis := inPar
  400. ELSIF ODD(sys DIV outBit) THEN vis := outPar
  401. END;
  402. IF ODD(sys DIV newBit) & (vis # outPar) THEN err(225)
  403. ELSIF ODD(sys DIV iidBit) & (vis # inPar) THEN err(225)
  404. END;
  405. LOOP
  406. IF sym = ident THEN
  407. DevCPT.Insert(DevCPS.name, par); DevCPS.Get(sym);
  408. par.mode := mode; par.link := NIL; par.vis := vis; par.sysflag := SHORT(sys);
  409. IF first = NIL THEN first := par END ;
  410. IF firstPar = NIL THEN firstPar := par ELSE last.link := par END ;
  411. last := par
  412. ELSE err(ident)
  413. END;
  414. IF sym = comma THEN DevCPS.Get(sym)
  415. ELSIF sym = ident THEN err(comma)
  416. ELSIF sym = var THEN err(comma); DevCPS.Get(sym)
  417. ELSE EXIT
  418. END
  419. END ;
  420. CheckSym(colon); Type(typ, name);
  421. IF mode # VarPar THEN CheckAlloc(typ, TRUE, DevCPM.errpos) END;
  422. IF (mode = VarPar) & (vis = inPar) & (typ.form # Undef) & (typ.form # Comp) & (typ.sysflag = 0) THEN err(177)
  423. END;
  424. (* typ.pbused is set when parameter type name is parsed *)
  425. WHILE first # NIL DO
  426. SetType (NIL, first, typ, name);
  427. IF DevCPM.com IN DevCPM.options THEN
  428. IF ODD(sys DIV newBit) THEN
  429. IF (newPar # NIL) OR (typ.form # Pointer) OR (typ.sysflag # interface) THEN err(168) END;
  430. newPar := first
  431. ELSIF ODD(sys DIV iidBit) THEN
  432. IF (iidPar # NIL) OR (typ # DevCPT.guidtyp) THEN err(168) END;
  433. iidPar := first
  434. END
  435. END;
  436. first := first.link
  437. END;
  438. IF sym = semicolon THEN DevCPS.Get(sym)
  439. ELSIF sym = ident THEN err(semicolon)
  440. ELSE EXIT
  441. END
  442. END
  443. END;
  444. CheckSym(rparen);
  445. IF (newPar = NIL) # (iidPar = NIL) THEN err(168) END;
  446. name := NIL;
  447. IF sym = colon THEN
  448. DevCPS.Get(sym);
  449. Type(resTyp, name);
  450. IF resTyp.form = Comp THEN resTyp := DevCPT.undftyp; err(54) END
  451. ELSE resTyp := DevCPT.notyp
  452. END
  453. END FormalParameters;
  454. PROCEDURE CheckOverwrite (proc, base: DevCPT.Object; rec: DevCPT.Struct);
  455. VAR o, bo: DevCPT.Object;
  456. BEGIN
  457. IF base # NIL THEN
  458. IF base.conval.setval * {absAttr, empAttr, extAttr} = {} THEN err(182) END;
  459. IF (proc.link.mode # base.link.mode) OR (proc.link.vis # base.link.vis)
  460. OR ~DevCPT.Extends(proc.link.typ, base.link.typ) THEN err(115) END;
  461. o := proc.link; bo := base.link;
  462. WHILE (o # NIL) & (bo # NIL) DO
  463. IF (bo.sysflag # 0) & (o.sysflag = 0) THEN (* propagate sysflags *)
  464. o.sysflag := bo.sysflag
  465. END;
  466. o := o.link; bo := bo.link
  467. END;
  468. DevCPB.CheckParameters(proc.link.link, base.link.link, FALSE);
  469. IF ~DevCPT.Extends(proc.typ, base.typ) THEN err(117) END;
  470. IF (base.vis # proc.vis) & ((proc.vis # internal) OR rec.exp) THEN err(183) END;
  471. INCL(proc.conval.setval, isRedef)
  472. END;
  473. END CheckOverwrite;
  474. PROCEDURE GetAttributes (proc, base: DevCPT.Object; owner: DevCPT.Struct); (* read method attributes *)
  475. VAR attr, battr: SET; o: DevCPT.Object;
  476. BEGIN
  477. attr := {};
  478. IF sym = comma THEN (* read attributes *)
  479. DevCPS.Get(sym);
  480. IF sym = ident THEN
  481. DevCPT.Find(DevCPS.name, o);
  482. IF (o # NIL) & (o.mode = SProc) & (o.adr = newfn) THEN
  483. IF ~(DevCPM.oberon IN DevCPM.options) THEN INCL(attr, newAttr) ELSE err(178) END;
  484. DevCPS.Get(sym);
  485. IF sym = comma THEN
  486. DevCPS.Get(sym);
  487. IF sym = ident THEN DevCPT.Find(DevCPS.name, o) ELSE o := NIL; err(ident) END
  488. ELSE o := NIL
  489. END
  490. END;
  491. IF o # NIL THEN
  492. IF (o.mode # Attr) OR (o.adr = limAttr) OR (DevCPM.oberon IN DevCPM.options) THEN err(178)
  493. ELSE INCL(attr, o.adr)
  494. END;
  495. DevCPS.Get(sym)
  496. END
  497. ELSE err(ident)
  498. END
  499. END;
  500. IF (base = NIL) & ~(newAttr IN attr) THEN err(185); INCL(attr, newAttr)
  501. ELSIF (base # NIL) & (newAttr IN attr) THEN err(186)
  502. END;
  503. IF absAttr IN attr THEN
  504. IF owner.attribute # absAttr THEN err(190) END;
  505. IF (proc.vis = internal) & owner.exp THEN err(179) END
  506. END;
  507. IF (owner.attribute = 0) OR (owner.attribute = limAttr) THEN
  508. IF (empAttr IN attr) & (newAttr IN attr) THEN err(187)
  509. (*
  510. ELSIF extAttr IN attr THEN err(188)
  511. *)
  512. END
  513. END;
  514. IF base # NIL THEN
  515. battr := base.conval.setval;
  516. IF empAttr IN battr THEN
  517. IF absAttr IN attr THEN err(189) END
  518. ELSIF ~(absAttr IN battr) THEN
  519. IF (absAttr IN attr) OR (empAttr IN attr) THEN err(189) END
  520. END
  521. END;
  522. IF empAttr IN attr THEN
  523. IF proc.typ # DevCPT.notyp THEN err(195)
  524. ELSE
  525. o := proc.link; WHILE (o # NIL) & (o.vis # outPar) DO o := o.link END;
  526. IF o # NIL THEN err(195) END
  527. END
  528. END;
  529. IF (owner.sysflag = interface) & ~(absAttr IN attr) THEN err(162) END;
  530. proc.conval.setval := attr
  531. END GetAttributes;
  532. PROCEDURE RecordType(VAR typ: DevCPT.Struct; attr: DevCPT.Object);
  533. VAR fld, first, last, base: DevCPT.Object; r: Elem; ftyp: DevCPT.Struct; name: DevCPT.String;
  534. BEGIN typ := DevCPT.NewStr(Comp, Record); typ.BaseTyp := NIL;
  535. CheckSysFlag(typ.sysflag, DevCPM.GetRecordSysFlag);
  536. IF attr # NIL THEN
  537. IF ~(DevCPM.oberon IN DevCPM.options) & (attr.adr # empAttr) THEN typ.attribute := SHORT(SHORT(attr.adr))
  538. ELSE err(178)
  539. END
  540. END;
  541. IF typ.sysflag = interface THEN
  542. IF (DevCPS.str # NIL) & (DevCPS.str[0] = "{") THEN typ.ext := DevCPS.str END;
  543. IF typ.attribute # absAttr THEN err(163) END;
  544. IF sym # lparen THEN err(160) END
  545. END;
  546. IF sym = lparen THEN
  547. DevCPS.Get(sym); (*record extension*)
  548. IF sym = ident THEN
  549. Type(ftyp, name);
  550. IF ftyp.form = Pointer THEN ftyp := ftyp.BaseTyp END;
  551. SetType(typ, NIL, ftyp, name);
  552. IF (ftyp.comp = Record) & (ftyp # DevCPT.anytyp) THEN
  553. ftyp.pvused := TRUE; typ.extlev := SHORT(SHORT(ftyp.extlev + 1));
  554. DevCPM.PropagateRecordSysFlag(ftyp.sysflag, typ.sysflag);
  555. IF (ftyp.attribute = 0) OR (ftyp.attribute = limAttr) & (ftyp.mno # 0) THEN err(181)
  556. ELSIF (typ.attribute = absAttr) & (ftyp.attribute # absAttr) & ~(DevCPM.java IN DevCPM.options) THEN err(191)
  557. ELSIF (ftyp.attribute = limAttr) & (typ.attribute # limAttr) THEN err(197)
  558. END
  559. ELSIF ftyp # DevCPT.undftyp THEN err(53)
  560. END
  561. ELSE err(ident)
  562. END ;
  563. IF typ.attribute # absAttr THEN (* save typ for unimplemented method check *)
  564. NEW(r); r.struct := typ; r.pos := DevCPM.errpos; r.next := recList; recList := r
  565. END;
  566. CheckSym(rparen)
  567. END;
  568. (*
  569. DevCPT.OpenScope(0, NIL);
  570. *)
  571. first := NIL; last := NIL;
  572. LOOP
  573. IF sym = ident THEN
  574. LOOP
  575. IF sym = ident THEN
  576. IF (typ.BaseTyp # NIL) & (typ.BaseTyp # DevCPT.undftyp) THEN
  577. DevCPT.FindBaseField(DevCPS.name, typ, fld);
  578. IF fld # NIL THEN err(1) END
  579. END ;
  580. DevCPT.InsertField(DevCPS.name, typ, fld);
  581. fld.mode := Fld; fld.link := NIL; fld.typ := DevCPT.undftyp;
  582. CheckMark(fld);
  583. IF first = NIL THEN first := fld END ;
  584. IF last = NIL THEN typ.link := fld ELSE last.link := fld END ;
  585. last := fld
  586. ELSE err(ident)
  587. END ;
  588. IF sym = comma THEN DevCPS.Get(sym)
  589. ELSIF sym = ident THEN err(comma)
  590. ELSE EXIT
  591. END
  592. END ;
  593. CheckSym(colon); Type(ftyp, name);
  594. CheckAlloc(ftyp, FALSE, DevCPM.errpos);
  595. WHILE first # NIL DO
  596. SetType(typ, first, ftyp, name); first := first.link
  597. END;
  598. IF typ.sysflag = interface THEN err(161) END
  599. END;
  600. IF sym = semicolon THEN DevCPS.Get(sym)
  601. ELSIF sym = ident THEN err(semicolon)
  602. ELSE EXIT
  603. END
  604. END;
  605. (*
  606. IF typ.link # NIL THEN ASSERT(typ.link = DevCPT.topScope.right) END;
  607. typ.link := DevCPT.topScope.right; DevCPT.CloseScope;
  608. *)
  609. typ.untagged := typ.sysflag > 0;
  610. DevCPB.Inittd(TDinit, lastTDinit, typ); CheckSym(end)
  611. END RecordType;
  612. PROCEDURE ArrayType(VAR typ: DevCPT.Struct);
  613. VAR x: DevCPT.Node; n: INTEGER; sysflag: SHORTINT; name: DevCPT.String;
  614. BEGIN CheckSysFlag(sysflag, DevCPM.GetArraySysFlag);
  615. IF sym = of THEN (*dynamic array*)
  616. typ := DevCPT.NewStr(Comp, DynArr); typ.mno := 0; typ.sysflag := sysflag;
  617. DevCPS.Get(sym); Type(typ.BaseTyp, name); SetType(typ, NIL, typ.BaseTyp, name);
  618. CheckAlloc(typ.BaseTyp, TRUE, DevCPM.errpos);
  619. IF typ.BaseTyp.comp = DynArr THEN typ.n := typ.BaseTyp.n + 1 ELSE typ.n := 0 END
  620. ELSE
  621. typ := DevCPT.NewStr(Comp, Array); typ.sysflag := sysflag; ConstExpression(x);
  622. IF x.typ.form IN {Int8, Int16, Int32} THEN n := x.conval.intval;
  623. IF (n <= 0) OR (n > DevCPM.MaxIndex) THEN err(63); n := 1 END
  624. ELSE err(42); n := 1
  625. END ;
  626. typ.n := n;
  627. IF sym = of THEN
  628. DevCPS.Get(sym); Type(typ.BaseTyp, name); SetType(typ, NIL, typ.BaseTyp, name);
  629. CheckAlloc(typ.BaseTyp, FALSE, DevCPM.errpos)
  630. ELSIF sym = comma THEN
  631. DevCPS.Get(sym);
  632. IF sym # of THEN ArrayType(typ.BaseTyp) END
  633. ELSE err(35)
  634. END
  635. END;
  636. typ.untagged := typ.sysflag > 0
  637. END ArrayType;
  638. PROCEDURE PointerType(VAR typ: DevCPT.Struct);
  639. VAR id: DevCPT.Object; name: DevCPT.String;
  640. BEGIN typ := DevCPT.NewStr(Pointer, Basic); CheckSysFlag(typ.sysflag, DevCPM.GetPointerSysFlag);
  641. CheckSym(to);
  642. Type(typ.BaseTyp, name);
  643. SetType(typ, NIL, typ.BaseTyp, name);
  644. IF (typ.BaseTyp # DevCPT.undftyp) & (typ.BaseTyp.comp = Basic) THEN
  645. typ.BaseTyp := DevCPT.undftyp; err(57)
  646. END;
  647. IF typ.BaseTyp.comp = Record THEN DevCPM.PropagateRecPtrSysFlag(typ.BaseTyp.sysflag, typ.sysflag)
  648. ELSIF typ.BaseTyp.comp IN {Array, DynArr} THEN DevCPM.PropagateArrPtrSysFlag(typ.BaseTyp.sysflag, typ.sysflag)
  649. END;
  650. typ.untagged := typ.sysflag > 0
  651. END PointerType;
  652. PROCEDURE Type (VAR typ: DevCPT.Struct; VAR name: DevCPT.String); (* name # NIL => forward reference *)
  653. VAR id: DevCPT.Object; tname: DevCPT.String;
  654. BEGIN
  655. typ := DevCPT.undftyp; name := NIL;
  656. IF sym < lparen THEN err(12);
  657. REPEAT DevCPS.Get(sym) UNTIL sym >= lparen
  658. END ;
  659. IF sym = ident THEN
  660. DevCPT.Find(DevCPS.name, id);
  661. IF (id = NIL) OR (id.mode = -1) OR (id.mode = Typ) & IncompleteType(id.typ) THEN (* forward type definition *)
  662. name := DevCPT.NewName(DevCPS.name); DevCPS.Get(sym);
  663. IF (id = NIL) & (sym = period) THEN (* missing module *)
  664. err(0); DevCPS.Get(sym); name := NIL;
  665. IF sym = ident THEN DevCPS.Get(sym) END
  666. ELSIF sym = record THEN (* wrong attribute *)
  667. err(178); DevCPS.Get(sym); name := NIL; RecordType(typ, NIL)
  668. END
  669. ELSE
  670. qualident(id);
  671. IF id.mode = Typ THEN
  672. IF ~(DevCPM.oberon IN DevCPM.options)
  673. & ((id.typ = DevCPT.lreal64typ) OR (id.typ = DevCPT.lint64typ) OR (id.typ = DevCPT.lchar16typ)) THEN
  674. err(198)
  675. END;
  676. typ := id.typ
  677. ELSIF id.mode = Attr THEN
  678. IF sym = record THEN
  679. DevCPS.Get(sym); RecordType(typ, id)
  680. ELSE err(12)
  681. END
  682. ELSE err(52)
  683. END
  684. END
  685. ELSIF sym = array THEN
  686. DevCPS.Get(sym); ArrayType(typ)
  687. ELSIF sym = record THEN
  688. DevCPS.Get(sym); RecordType(typ, NIL)
  689. ELSIF sym = pointer THEN
  690. DevCPS.Get(sym); PointerType(typ)
  691. ELSIF sym = procedure THEN
  692. DevCPS.Get(sym); typ := DevCPT.NewStr(ProcTyp, Basic);
  693. CheckSysFlag(typ.sysflag, DevCPM.GetProcTypSysFlag);
  694. typ.untagged := typ.sysflag > 0;
  695. IF sym = lparen THEN
  696. DevCPS.Get(sym); DevCPT.OpenScope(level, NIL);
  697. FormalParameters(typ.link, typ.BaseTyp, tname); SetType(typ, NIL, typ.BaseTyp, tname); DevCPT.CloseScope
  698. ELSE typ.BaseTyp := DevCPT.notyp; typ.link := NIL
  699. END
  700. ELSE err(12)
  701. END ;
  702. LOOP
  703. IF (sym >= semicolon) & (sym <= else) OR (sym = rparen) OR (sym = eof)
  704. OR (sym = number) OR (sym = comma) OR (sym = string) THEN EXIT END;
  705. err(15); IF sym = ident THEN EXIT END;
  706. DevCPS.Get(sym)
  707. END
  708. END Type;
  709. PROCEDURE ActualParameters(VAR aparlist: DevCPT.Node; fpar: DevCPT.Object; VAR pre, lastp: DevCPT.Node);
  710. VAR apar, last, newPar, iidPar, n: DevCPT.Node;
  711. BEGIN
  712. aparlist := NIL; last := NIL;
  713. IF sym # rparen THEN
  714. newPar := NIL; iidPar := NIL;
  715. LOOP Expression(apar);
  716. IF fpar # NIL THEN
  717. IF (apar.typ.form = Pointer) & (fpar.typ.form = Comp) THEN DevCPB.DeRef(apar) END;
  718. DevCPB.Param(apar, fpar);
  719. IF (fpar.mode = Var) OR (fpar.vis = inPar) THEN DevCPB.CheckBuffering(apar, NIL, fpar, pre, lastp) END;
  720. DevCPB.Link(aparlist, last, apar);
  721. IF ODD(fpar.sysflag DIV newBit) THEN newPar := apar
  722. ELSIF ODD(fpar.sysflag DIV iidBit) THEN iidPar := apar
  723. END;
  724. IF (newPar # NIL) & (iidPar # NIL) THEN DevCPB.CheckNewParamPair(newPar, iidPar) END;
  725. IF anchorVarPar & (fpar.mode = VarPar) & ~(DevCPM.java IN DevCPM.options)
  726. OR (DevCPM.allSysVal IN DevCPM.options) (* source output: avoid double evaluation *)
  727. & ((fpar.mode = VarPar) & (fpar.typ.comp = Record) & ~fpar.typ.untagged
  728. OR (fpar.typ.comp = DynArr) & ~fpar.typ.untagged) THEN
  729. n := apar;
  730. WHILE n.class IN {Nfield, Nindex, Nguard} DO n := n.left END;
  731. IF (n.class = Nderef) & (n.subcl = 0) THEN
  732. IF n.left.class = Nguard THEN n := n.left END;
  733. DevCPB.CheckVarParBuffering(n.left, pre, lastp)
  734. END
  735. END;
  736. fpar := fpar.link
  737. ELSE err(64)
  738. END;
  739. IF sym = comma THEN DevCPS.Get(sym)
  740. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  741. ELSE EXIT
  742. END
  743. END
  744. END;
  745. IF fpar # NIL THEN err(65) END
  746. END ActualParameters;
  747. PROCEDURE selector(VAR x: DevCPT.Node);
  748. VAR obj, proc, p, fpar: DevCPT.Object; y, apar, pre, lastp: DevCPT.Node; typ: DevCPT.Struct; name: DevCPT.Name;
  749. BEGIN
  750. LOOP
  751. IF sym = lbrak THEN DevCPS.Get(sym);
  752. LOOP
  753. IF (x.typ # NIL) & (x.typ.form = Pointer) THEN DevCPB.DeRef(x) END ;
  754. Expression(y); DevCPB.Index(x, y);
  755. IF sym = comma THEN DevCPS.Get(sym) ELSE EXIT END
  756. END ;
  757. CheckSym(rbrak)
  758. ELSIF sym = period THEN DevCPS.Get(sym);
  759. IF sym = ident THEN name := DevCPS.name; DevCPS.Get(sym);
  760. IF x.typ # NIL THEN
  761. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END ;
  762. IF x.typ.comp = Record THEN
  763. typ := x.typ; DevCPT.FindField(name, typ, obj); DevCPB.Field(x, obj);
  764. IF (obj # NIL) & (obj.mode = TProc) THEN
  765. IF sym = arrow THEN (* super call *) DevCPS.Get(sym);
  766. y := x.left;
  767. IF y.class = Nderef THEN y := y.left END ; (* y = record variable *)
  768. IF y.obj # NIL THEN
  769. proc := DevCPT.topScope; (* find innermost scope which owner is a TProc *)
  770. WHILE (proc.link # NIL) & (proc.link.mode # TProc) DO proc := proc.left END ;
  771. IF (proc.link = NIL) OR (proc.link.link # y.obj) (* OR (proc.link.name^ # name) *) THEN err(75)
  772. END ;
  773. typ := y.obj.typ;
  774. IF typ.form = Pointer THEN typ := typ.BaseTyp END ;
  775. DevCPT.FindBaseField(x.obj.name^, typ, p);
  776. IF p # NIL THEN
  777. x.subcl := super; x.typ := p.typ; (* correct result type *)
  778. IF p.conval.setval * {absAttr, empAttr} # {} THEN err(194) END;
  779. IF (p.vis = externalR) & (p.mnolev < 0) & (proc.link.name^ # name) THEN err(196) END;
  780. ELSE err(74)
  781. END
  782. ELSE err(75)
  783. END
  784. ELSE
  785. proc := obj;
  786. WHILE (proc.mnolev >= 0) & ~(newAttr IN proc.conval.setval) & (typ.BaseTyp # NIL) DO
  787. (* find base method *)
  788. typ := typ.BaseTyp; DevCPT.FindField(name, typ, proc);
  789. END;
  790. IF (proc.vis = externalR) & (proc.mnolev < 0) THEN err(196) END;
  791. END ;
  792. IF (obj.typ # DevCPT.notyp) & (sym # lparen) THEN err(lparen) END
  793. END
  794. ELSE err(53)
  795. END
  796. ELSE err(52)
  797. END
  798. ELSE err(ident)
  799. END
  800. ELSIF sym = arrow THEN DevCPS.Get(sym); DevCPB.DeRef(x)
  801. ELSIF sym = dollar THEN
  802. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END;
  803. DevCPS.Get(sym); DevCPB.StrDeref(x)
  804. ELSIF sym = lparen THEN
  805. IF (x.obj # NIL) & (x.obj.mode IN {XProc, LProc, CProc, TProc}) THEN typ := x.obj.typ
  806. ELSIF x.typ.form = ProcTyp THEN typ := x.typ.BaseTyp
  807. ELSIF x.class = Nproc THEN EXIT (* standard procedure *)
  808. ELSE typ := NIL
  809. END;
  810. IF typ # DevCPT.notyp THEN
  811. DevCPS.Get(sym);
  812. IF typ = NIL THEN (* type guard *)
  813. IF sym = ident THEN
  814. qualident(obj);
  815. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, TRUE)
  816. ELSE err(52)
  817. END
  818. ELSE err(ident)
  819. END
  820. ELSE (* function call *)
  821. pre := NIL; lastp := NIL;
  822. DevCPB.PrepCall(x, fpar);
  823. IF (x.obj # NIL) & (x.obj.mode = TProc) THEN DevCPB.CheckBuffering(x.left, NIL, x.obj.link, pre, lastp)
  824. END;
  825. ActualParameters(apar, fpar, pre, lastp);
  826. DevCPB.Call(x, apar, fpar);
  827. IF pre # NIL THEN DevCPB.Construct(Ncomp, pre, x); pre.typ := x.typ; x := pre END;
  828. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  829. END;
  830. CheckSym(rparen)
  831. ELSE EXIT
  832. END
  833. (*
  834. ELSIF (sym = lparen) & (x.class # Nproc) & (x.typ.form # ProcTyp) &
  835. ((x.obj = NIL) OR (x.obj.mode # TProc)) THEN
  836. DevCPS.Get(sym);
  837. IF sym = ident THEN
  838. qualident(obj);
  839. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, TRUE)
  840. ELSE err(52)
  841. END
  842. ELSE err(ident)
  843. END ;
  844. CheckSym(rparen)
  845. *)
  846. ELSE EXIT
  847. END
  848. END
  849. END selector;
  850. PROCEDURE StandProcCall(VAR x: DevCPT.Node);
  851. VAR y: DevCPT.Node; m: BYTE; n: SHORTINT;
  852. BEGIN m := SHORT(SHORT(x.obj.adr)); n := 0;
  853. IF sym = lparen THEN DevCPS.Get(sym);
  854. IF sym # rparen THEN
  855. LOOP
  856. IF n = 0 THEN Expression(x); DevCPB.StPar0(x, m); n := 1
  857. ELSIF n = 1 THEN Expression(y); DevCPB.StPar1(x, y, m); n := 2
  858. ELSE Expression(y); DevCPB.StParN(x, y, m, n); INC(n)
  859. END ;
  860. IF sym = comma THEN DevCPS.Get(sym)
  861. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  862. ELSE EXIT
  863. END
  864. END ;
  865. CheckSym(rparen)
  866. ELSE DevCPS.Get(sym)
  867. END ;
  868. DevCPB.StFct(x, m, n)
  869. ELSE err(lparen)
  870. END ;
  871. IF (level > 0) & ((m = newfn) OR (m = sysnewfn)) THEN DevCPT.topScope.link.leaf := FALSE END
  872. END StandProcCall;
  873. PROCEDURE Element(VAR x: DevCPT.Node);
  874. VAR y: DevCPT.Node;
  875. BEGIN Expression(x);
  876. IF sym = upto THEN
  877. DevCPS.Get(sym); Expression(y); DevCPB.SetRange(x, y)
  878. ELSE DevCPB.SetElem(x)
  879. END
  880. END Element;
  881. PROCEDURE Sets(VAR x: DevCPT.Node);
  882. VAR y: DevCPT.Node;
  883. BEGIN
  884. IF sym # rbrace THEN
  885. Element(x);
  886. LOOP
  887. IF sym = comma THEN DevCPS.Get(sym)
  888. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  889. ELSE EXIT
  890. END ;
  891. Element(y); DevCPB.Op(plus, x, y)
  892. END
  893. ELSE x := DevCPB.EmptySet()
  894. END ;
  895. CheckSym(rbrace)
  896. END Sets;
  897. PROCEDURE Factor(VAR x: DevCPT.Node);
  898. VAR fpar, id: DevCPT.Object; apar: DevCPT.Node;
  899. BEGIN
  900. IF sym < not THEN err(13);
  901. REPEAT DevCPS.Get(sym) UNTIL sym >= lparen
  902. END ;
  903. IF sym = ident THEN
  904. qualident(id); x := DevCPB.NewLeaf(id); selector(x);
  905. IF (x.class = Nproc) & (x.obj.mode = SProc) THEN StandProcCall(x) (* x may be NIL *)
  906. (*
  907. ELSIF sym = lparen THEN
  908. DevCPS.Get(sym); DevCPB.PrepCall(x, fpar);
  909. ActualParameters(apar, fpar);
  910. DevCPB.Call(x, apar, fpar);
  911. CheckSym(rparen);
  912. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  913. *)
  914. END
  915. ELSIF sym = number THEN
  916. CASE DevCPS.numtyp OF
  917. char:
  918. x := DevCPB.NewIntConst(DevCPS.intval); x.typ := DevCPT.char8typ;
  919. IF DevCPS.intval > 255 THEN x.typ := DevCPT.char16typ END
  920. | integer: x := DevCPB.NewIntConst(DevCPS.intval)
  921. | int64: x := DevCPB.NewLargeIntConst(DevCPS.intval, DevCPS.realval)
  922. | real: x := DevCPB.NewRealConst(DevCPS.realval, NIL)
  923. | real32: x := DevCPB.NewRealConst(DevCPS.realval, DevCPT.real32typ)
  924. | real64: x := DevCPB.NewRealConst(DevCPS.realval, DevCPT.real64typ)
  925. END ;
  926. DevCPS.Get(sym)
  927. ELSIF sym = string THEN
  928. x := DevCPB.NewString(DevCPS.str, DevCPS.lstr, DevCPS.intval);
  929. DevCPS.Get(sym)
  930. ELSIF sym = nil THEN
  931. x := DevCPB.Nil(); DevCPS.Get(sym)
  932. ELSIF sym = lparen THEN
  933. DevCPS.Get(sym); Expression(x); CheckSym(rparen)
  934. ELSIF sym = lbrak THEN
  935. DevCPS.Get(sym); err(lparen); Expression(x); CheckSym(rparen)
  936. ELSIF sym = lbrace THEN DevCPS.Get(sym); Sets(x)
  937. ELSIF sym = not THEN
  938. DevCPS.Get(sym); Factor(x); DevCPB.MOp(not, x)
  939. ELSE err(13); DevCPS.Get(sym); x := NIL
  940. END ;
  941. IF x = NIL THEN x := DevCPB.NewIntConst(1); x.typ := DevCPT.undftyp END
  942. END Factor;
  943. PROCEDURE Term(VAR x: DevCPT.Node);
  944. VAR y: DevCPT.Node; mulop: BYTE;
  945. BEGIN Factor(x);
  946. WHILE (times <= sym) & (sym <= and) DO
  947. mulop := sym; DevCPS.Get(sym);
  948. Factor(y); DevCPB.Op(mulop, x, y)
  949. END
  950. END Term;
  951. PROCEDURE SimpleExpression(VAR x: DevCPT.Node);
  952. VAR y: DevCPT.Node; addop: BYTE;
  953. BEGIN
  954. IF sym = minus THEN DevCPS.Get(sym); Term(x); DevCPB.MOp(minus, x)
  955. ELSIF sym = plus THEN DevCPS.Get(sym); Term(x); DevCPB.MOp(plus, x)
  956. ELSE Term(x)
  957. END ;
  958. WHILE (plus <= sym) & (sym <= or) DO
  959. addop := sym; DevCPS.Get(sym); Term(y);
  960. IF x.typ.form = Pointer THEN DevCPB.DeRef(x) END;
  961. IF (x.typ.comp IN {Array, DynArr}) & (x.typ.BaseTyp.form IN charSet) (* OR (x.typ.sysflag = jstr) *) THEN
  962. DevCPB.StrDeref(x)
  963. END;
  964. IF y.typ.form = Pointer THEN DevCPB.DeRef(y) END;
  965. IF (y.typ.comp IN {Array, DynArr}) & (y.typ.BaseTyp.form IN charSet) (* OR (y.typ.sysflag = jstr) *) THEN
  966. DevCPB.StrDeref(y)
  967. END;
  968. DevCPB.Op(addop, x, y)
  969. END
  970. END SimpleExpression;
  971. PROCEDURE Expression(VAR x: DevCPT.Node);
  972. VAR y, pre, last: DevCPT.Node; obj: DevCPT.Object; relation: BYTE;
  973. BEGIN SimpleExpression(x);
  974. IF (eql <= sym) & (sym <= geq) THEN
  975. relation := sym; DevCPS.Get(sym); SimpleExpression(y);
  976. pre := NIL; last := NIL;
  977. IF (x.typ.comp IN {Array, DynArr}) & (x.typ.BaseTyp.form IN charSet) THEN
  978. DevCPB.StrDeref(x)
  979. END;
  980. IF (y.typ.comp IN {Array, DynArr}) & (y.typ.BaseTyp.form IN charSet) THEN
  981. DevCPB.StrDeref(y)
  982. END;
  983. DevCPB.CheckBuffering(x, NIL, NIL, pre, last);
  984. DevCPB.CheckBuffering(y, NIL, NIL, pre, last);
  985. DevCPB.Op(relation, x, y);
  986. IF pre # NIL THEN DevCPB.Construct(Ncomp, pre, x); pre.typ := x.typ; x := pre END
  987. ELSIF sym = in THEN
  988. DevCPS.Get(sym); SimpleExpression(y); DevCPB.In(x, y)
  989. ELSIF sym = is THEN
  990. DevCPS.Get(sym);
  991. IF sym = ident THEN
  992. qualident(obj);
  993. IF obj.mode = Typ THEN DevCPB.TypTest(x, obj, FALSE)
  994. ELSE err(52)
  995. END
  996. ELSE err(ident)
  997. END
  998. END
  999. END Expression;
  1000. PROCEDURE ProcedureDeclaration(VAR x: DevCPT.Node);
  1001. VAR proc, fwd: DevCPT.Object;
  1002. name: DevCPT.Name;
  1003. mode: BYTE;
  1004. forward: BOOLEAN;
  1005. sys: SHORTINT;
  1006. PROCEDURE GetCode;
  1007. VAR ext: DevCPT.ConstExt; i, n, c: INTEGER; s: ARRAY 256 OF SHORTCHAR;
  1008. BEGIN
  1009. n := 0;
  1010. IF sym = string THEN
  1011. NEW(ext, DevCPS.intval);
  1012. WHILE DevCPS.str[n] # 0X DO ext[n+1] := DevCPS.str[n]; INC(n) END ;
  1013. ext^[0] := SHORT(CHR(n)); DevCPS.Get(sym);
  1014. ELSE
  1015. LOOP
  1016. IF sym = number THEN c := DevCPS.intval; INC(n);
  1017. IF (c < 0) OR (c > 255) OR (n = 255) THEN
  1018. err(64); c := 1; n := 1
  1019. END ;
  1020. DevCPS.Get(sym); s[n] := SHORT(CHR(c))
  1021. END ;
  1022. IF sym = comma THEN DevCPS.Get(sym)
  1023. ELSIF sym = number THEN err(comma)
  1024. ELSE s[0] := SHORT(CHR(n)); EXIT
  1025. END
  1026. END;
  1027. NEW(ext, n + 1); i := 0;
  1028. WHILE i <= n DO ext[i] := s[i]; INC(i) END;
  1029. END;
  1030. proc.conval.ext := ext;
  1031. INCL(proc.conval.setval, hasBody)
  1032. END GetCode;
  1033. PROCEDURE GetParams;
  1034. VAR name: DevCPT.String;
  1035. BEGIN
  1036. proc.mode := mode; proc.typ := DevCPT.notyp;
  1037. proc.sysflag := SHORT(sys);
  1038. proc.conval.setval := {};
  1039. IF sym = lparen THEN
  1040. DevCPS.Get(sym); FormalParameters(proc.link, proc.typ, name);
  1041. IF name # NIL THEN err(0) END
  1042. END;
  1043. CheckForwardTypes; userList := NIL;
  1044. IF fwd # NIL THEN
  1045. DevCPB.CheckParameters(proc.link, fwd.link, TRUE);
  1046. IF ~DevCPT.EqualType(proc.typ, fwd.typ) THEN err(117) END ;
  1047. proc := fwd; DevCPT.topScope := proc.scope;
  1048. IF mode = IProc THEN proc.mode := IProc END
  1049. END
  1050. END GetParams;
  1051. PROCEDURE Body;
  1052. VAR procdec, statseq: DevCPT.Node; c: INTEGER;
  1053. BEGIN
  1054. c := DevCPM.errpos;
  1055. INCL(proc.conval.setval, hasBody);
  1056. CheckSym(semicolon); Block(procdec, statseq);
  1057. DevCPB.Enter(procdec, statseq, proc); x := procdec;
  1058. x.conval := DevCPT.NewConst(); x.conval.intval := c; x.conval.intval2 := DevCPM.startpos;
  1059. CheckSym(end);
  1060. IF sym = ident THEN
  1061. IF DevCPS.name # proc.name^ THEN err(4) END ;
  1062. DevCPS.Get(sym)
  1063. ELSE err(ident)
  1064. END
  1065. END Body;
  1066. PROCEDURE TProcDecl;
  1067. VAR baseProc, o, bo: DevCPT.Object;
  1068. objTyp, recTyp: DevCPT.Struct;
  1069. objMode, objVis: BYTE;
  1070. objName: DevCPT.Name;
  1071. pnode: DevCPT.Node;
  1072. fwdAttr: SET;
  1073. BEGIN
  1074. DevCPS.Get(sym); mode := TProc;
  1075. IF level > 0 THEN err(73) END;
  1076. Receiver(objMode, objVis, objName, objTyp, recTyp);
  1077. IF sym = ident THEN
  1078. name := DevCPS.name;
  1079. DevCPT.FindField(name, recTyp, fwd);
  1080. DevCPT.FindBaseField(name, recTyp, baseProc);
  1081. IF (baseProc # NIL) & (baseProc.mode # TProc) THEN baseProc := NIL; err(1) END ;
  1082. IF fwd = baseProc THEN fwd := NIL END ;
  1083. IF (fwd # NIL) & (fwd.mnolev # level) THEN fwd := NIL END ;
  1084. IF (fwd # NIL) & (fwd.mode = TProc) & (fwd.conval.setval * {hasBody, absAttr, empAttr} = {}) THEN
  1085. (* there exists a corresponding forward declaration *)
  1086. proc := DevCPT.NewObj(); proc.leaf := TRUE;
  1087. proc.mode := TProc; proc.conval := DevCPT.NewConst();
  1088. CheckMark(proc);
  1089. IF fwd.vis # proc.vis THEN err(118) END;
  1090. fwdAttr := fwd.conval.setval
  1091. ELSE
  1092. IF fwd # NIL THEN err(1); fwd := NIL END ;
  1093. DevCPT.InsertField(name, recTyp, proc);
  1094. proc.mode := TProc; proc.conval := DevCPT.NewConst();
  1095. CheckMark(proc);
  1096. IF recTyp.strobj # NIL THEN (* preserve declaration order *)
  1097. o := recTyp.strobj.link;
  1098. IF o = NIL THEN recTyp.strobj.link := proc
  1099. ELSE
  1100. WHILE o.nlink # NIL DO o := o.nlink END;
  1101. o.nlink := proc
  1102. END
  1103. END
  1104. END;
  1105. INC(level); DevCPT.OpenScope(level, proc);
  1106. DevCPT.Insert(objName, proc.link); proc.link.mode := objMode; proc.link.vis := objVis; proc.link.typ := objTyp;
  1107. ASSERT(DevCPT.topScope # NIL);
  1108. GetParams; (* may change proc := fwd !!! *)
  1109. ASSERT(DevCPT.topScope # NIL);
  1110. GetAttributes(proc, baseProc, recTyp);
  1111. IF (fwd # NIL) & (fwdAttr / proc.conval.setval * {absAttr, empAttr, extAttr} # {}) THEN err(184) END;
  1112. CheckOverwrite(proc, baseProc, recTyp);
  1113. IF ~forward THEN
  1114. IF empAttr IN proc.conval.setval THEN (* insert empty procedure *)
  1115. pnode := NIL; DevCPB.Enter(pnode, NIL, proc);
  1116. pnode.conval := DevCPT.NewConst();
  1117. pnode.conval.intval := DevCPM.errpos;
  1118. pnode.conval.intval2 := DevCPM.errpos;
  1119. x := pnode;
  1120. ELSIF DevCPM.noCode IN DevCPM.options THEN INCL(proc.conval.setval, hasBody)
  1121. ELSIF ~(absAttr IN proc.conval.setval) THEN Body
  1122. END;
  1123. proc.adr := 0
  1124. ELSE
  1125. proc.adr := DevCPM.errpos;
  1126. IF proc.conval.setval * {empAttr, absAttr} # {} THEN err(184) END
  1127. END;
  1128. DEC(level); DevCPT.CloseScope;
  1129. ELSE err(ident)
  1130. END;
  1131. END TProcDecl;
  1132. BEGIN proc := NIL; forward := FALSE; x := NIL; mode := LProc; sys := 0;
  1133. IF (sym # ident) & (sym # lparen) THEN
  1134. CheckSysFlag(sys, DevCPM.GetProcSysFlag);
  1135. IF sys # 0 THEN
  1136. IF ODD(sys DIV DevCPM.CProcFlag) THEN mode := CProc END
  1137. ELSE
  1138. IF sym = times THEN (* mode set later in DevCPB.CheckAssign *)
  1139. ELSIF sym = arrow THEN forward := TRUE
  1140. ELSE err(ident)
  1141. END;
  1142. DevCPS.Get(sym)
  1143. END
  1144. END ;
  1145. IF sym = lparen THEN TProcDecl
  1146. ELSIF sym = ident THEN DevCPT.Find(DevCPS.name, fwd);
  1147. name := DevCPS.name;
  1148. IF (fwd # NIL) & ((fwd.mnolev # level) OR (fwd.mode = SProc)) THEN fwd := NIL END ;
  1149. IF (fwd # NIL) & (fwd.mode IN {LProc, XProc}) & ~(hasBody IN fwd.conval.setval) THEN
  1150. (* there exists a corresponding forward declaration *)
  1151. proc := DevCPT.NewObj(); proc.leaf := TRUE;
  1152. proc.mode := mode; proc.conval := DevCPT.NewConst();
  1153. CheckMark(proc);
  1154. IF fwd.vis # proc.vis THEN err(118) END
  1155. ELSE
  1156. IF fwd # NIL THEN err(1); fwd := NIL END ;
  1157. DevCPT.Insert(name, proc);
  1158. proc.mode := mode; proc.conval := DevCPT.NewConst();
  1159. CheckMark(proc);
  1160. END ;
  1161. IF (proc.vis # internal) & (mode = LProc) THEN mode := XProc END ;
  1162. IF (mode # LProc) & (level > 0) THEN err(73) END ;
  1163. INC(level); DevCPT.OpenScope(level, proc);
  1164. proc.link := NIL; GetParams; (* may change proc := fwd !!! *)
  1165. IF mode = CProc THEN GetCode
  1166. ELSIF DevCPM.noCode IN DevCPM.options THEN INCL(proc.conval.setval, hasBody)
  1167. ELSIF ~forward THEN Body; proc.adr := 0
  1168. ELSE proc.adr := DevCPM.errpos
  1169. END ;
  1170. DEC(level); DevCPT.CloseScope
  1171. ELSE err(ident)
  1172. END
  1173. END ProcedureDeclaration;
  1174. PROCEDURE CaseLabelList(VAR lab, root: DevCPT.Node; LabelForm: SHORTINT; VAR min, max: INTEGER);
  1175. VAR x, y, lastlab: DevCPT.Node; i, f: SHORTINT; xval, yval: INTEGER;
  1176. PROCEDURE Insert(VAR n: DevCPT.Node); (* build binary tree of label ranges *) (* !!! *)
  1177. BEGIN
  1178. IF n = NIL THEN
  1179. IF x.hint # 1 THEN n := x END
  1180. ELSIF yval < n.conval.intval THEN Insert(n.left)
  1181. ELSIF xval > n.conval.intval2 THEN Insert(n.right)
  1182. ELSE err(63)
  1183. END
  1184. END Insert;
  1185. BEGIN lab := NIL; lastlab := NIL;
  1186. LOOP ConstExpression(x); f := x.typ.form;
  1187. IF f IN {Int8..Int32} + charSet THEN xval := x.conval.intval
  1188. ELSE err(61); xval := 1
  1189. END ;
  1190. IF (f IN {Int8..Int32}) # (LabelForm IN {Int8..Int32}) THEN err(60) END;
  1191. IF sym = upto THEN
  1192. DevCPS.Get(sym); ConstExpression(y); yval := y.conval.intval;
  1193. IF (y.typ.form IN {Int8..Int32}) # (LabelForm IN {Int8..Int32}) THEN err(60) END;
  1194. IF yval < xval THEN err(63); yval := xval END
  1195. ELSE yval := xval
  1196. END ;
  1197. x.conval.intval2 := yval;
  1198. IF xval < min THEN min := xval END;
  1199. IF yval > max THEN max := yval END;
  1200. IF lab = NIL THEN lab := x; Insert(root)
  1201. ELSIF yval < lab.conval.intval - 1 THEN x.link := lab; lab := x; Insert(root)
  1202. ELSIF yval = lab.conval.intval - 1 THEN x.hint := 1; Insert(root); lab.conval.intval := xval
  1203. ELSIF xval = lab.conval.intval2 + 1 THEN x.hint := 1; Insert(root); lab.conval.intval2 := yval
  1204. ELSE
  1205. y := lab;
  1206. WHILE (y.link # NIL) & (xval > y.link.conval.intval2 + 1) DO y := y.link END;
  1207. IF y.link = NIL THEN y.link := x; Insert(root)
  1208. ELSIF yval < y.link.conval.intval - 1 THEN x.link := y.link; y.link := x; Insert(root)
  1209. ELSIF yval = y.link.conval.intval - 1 THEN x.hint := 1; Insert(root); y.link.conval.intval := xval
  1210. ELSIF xval = y.link.conval.intval2 + 1 THEN x.hint := 1; Insert(root); y.link.conval.intval2 := yval
  1211. END
  1212. END;
  1213. IF sym = comma THEN DevCPS.Get(sym)
  1214. ELSIF (sym = number) OR (sym = ident) THEN err(comma)
  1215. ELSE EXIT
  1216. END
  1217. END
  1218. END CaseLabelList;
  1219. PROCEDURE StatSeq(VAR stat: DevCPT.Node);
  1220. VAR fpar, id, t, obj: DevCPT.Object; idtyp: DevCPT.Struct; e: BOOLEAN;
  1221. s, x, y, z, apar, last, lastif, pre, lastp: DevCPT.Node; pos, p: INTEGER; name: DevCPT.Name;
  1222. PROCEDURE CasePart(VAR x: DevCPT.Node);
  1223. VAR low, high: INTEGER; e: BOOLEAN; cases, lab, y, lastcase, root: DevCPT.Node;
  1224. BEGIN
  1225. Expression(x);
  1226. IF (x.class = Ntype) OR (x.class = Nproc) THEN err(126)
  1227. ELSIF x.typ.form = Int64 THEN err(260)
  1228. ELSIF ~(x.typ.form IN {Int8..Int32} + charSet) THEN err(125)
  1229. END ;
  1230. CheckSym(of); cases := NIL; lastcase := NIL; root := NIL;
  1231. low := MAX(INTEGER); high := MIN(INTEGER);
  1232. LOOP
  1233. IF sym < bar THEN
  1234. CaseLabelList(lab, root, x.typ.form, low, high);
  1235. CheckSym(colon); StatSeq(y);
  1236. DevCPB.Construct(Ncasedo, lab, y); DevCPB.Link(cases, lastcase, lab)
  1237. END ;
  1238. IF sym = bar THEN DevCPS.Get(sym) ELSE EXIT END
  1239. END;
  1240. e := sym = else;
  1241. IF e THEN DevCPS.Get(sym); StatSeq(y) ELSE y := NIL END ;
  1242. DevCPB.Construct(Ncaselse, cases, y); DevCPB.Construct(Ncase, x, cases);
  1243. cases.conval := DevCPT.NewConst();
  1244. cases.conval.intval := low; cases.conval.intval2 := high;
  1245. IF e THEN cases.conval.setval := {1} ELSE cases.conval.setval := {} END;
  1246. DevCPB.OptimizeCase(root); cases.link := root (* !!! *)
  1247. END CasePart;
  1248. PROCEDURE SetPos(x: DevCPT.Node);
  1249. BEGIN
  1250. x.conval := DevCPT.NewConst(); x.conval.intval := pos
  1251. END SetPos;
  1252. PROCEDURE CheckBool(VAR x: DevCPT.Node);
  1253. BEGIN
  1254. IF (x.class = Ntype) OR (x.class = Nproc) THEN err(126); x := DevCPB.NewBoolConst(FALSE)
  1255. ELSIF x.typ.form # Bool THEN err(120); x := DevCPB.NewBoolConst(FALSE)
  1256. END
  1257. END CheckBool;
  1258. BEGIN stat := NIL; last := NIL;
  1259. LOOP x := NIL;
  1260. IF sym < ident THEN err(14);
  1261. REPEAT DevCPS.Get(sym) UNTIL sym >= ident
  1262. END ;
  1263. pos := DevCPM.startpos;
  1264. IF sym = ident THEN
  1265. qualident(id); x := DevCPB.NewLeaf(id); selector(x);
  1266. IF sym = becomes THEN
  1267. DevCPS.Get(sym); Expression(y);
  1268. IF (y.typ.form = Pointer) & (x.typ.form = Comp) THEN DevCPB.DeRef(y) END;
  1269. pre := NIL; lastp := NIL;
  1270. DevCPB.CheckBuffering(y, x, NIL, pre, lastp);
  1271. DevCPB.Assign(x, y);
  1272. IF pre # NIL THEN SetPos(x); DevCPB.Construct(Ncomp, pre, x); x := pre END;
  1273. ELSIF sym = eql THEN
  1274. err(becomes); DevCPS.Get(sym); Expression(y); DevCPB.Assign(x, y)
  1275. ELSIF (x.class = Nproc) & (x.obj.mode = SProc) THEN
  1276. StandProcCall(x);
  1277. IF (x # NIL) & (x.typ # DevCPT.notyp) THEN err(55) END;
  1278. IF (x # NIL) & (x.class = Nifelse) THEN (* error pos for ASSERT *)
  1279. SetPos(x.left); SetPos(x.left.right)
  1280. END
  1281. ELSIF x.class = Ncall THEN err(55)
  1282. ELSE
  1283. pre := NIL; lastp := NIL;
  1284. DevCPB.PrepCall(x, fpar);
  1285. IF (x.obj # NIL) & (x.obj.mode = TProc) THEN DevCPB.CheckBuffering(x.left, NIL, x.obj.link, pre, lastp) END;
  1286. IF sym = lparen THEN
  1287. DevCPS.Get(sym); ActualParameters(apar, fpar, pre, lastp); CheckSym(rparen)
  1288. ELSE apar := NIL;
  1289. IF fpar # NIL THEN err(65) END
  1290. END ;
  1291. DevCPB.Call(x, apar, fpar);
  1292. IF x.typ # DevCPT.notyp THEN err(55) END;
  1293. IF pre # NIL THEN SetPos(x); DevCPB.Construct(Ncomp, pre, x); x := pre END;
  1294. IF level > 0 THEN DevCPT.topScope.link.leaf := FALSE END
  1295. END
  1296. ELSIF sym = if THEN
  1297. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(x); CheckBool(x); CheckSym(then); StatSeq(y);
  1298. DevCPB.Construct(Nif, x, y); SetPos(x); lastif := x;
  1299. WHILE sym = elsif DO
  1300. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(y); CheckBool(y); CheckSym(then); StatSeq(z);
  1301. DevCPB.Construct(Nif, y, z); SetPos(y); DevCPB.Link(x, lastif, y)
  1302. END ;
  1303. pos := DevCPM.startpos;
  1304. IF sym = else THEN DevCPS.Get(sym); StatSeq(y) ELSE y := NIL END ;
  1305. DevCPB.Construct(Nifelse, x, y); CheckSym(end); DevCPB.OptIf(x);
  1306. ELSIF sym = case THEN
  1307. DevCPS.Get(sym); pos := DevCPM.startpos; CasePart(x); CheckSym(end)
  1308. ELSIF sym = while THEN
  1309. DevCPS.Get(sym); pos := DevCPM.startpos; Expression(x); CheckBool(x); CheckSym(do); StatSeq(y);
  1310. DevCPB.Construct(Nwhile, x, y); CheckSym(end)
  1311. ELSIF sym = repeat THEN
  1312. DevCPS.Get(sym); StatSeq(x);
  1313. IF sym = until THEN DevCPS.Get(sym); pos := DevCPM.startpos; Expression(y); CheckBool(y)
  1314. ELSE err(43)
  1315. END ;
  1316. DevCPB.Construct(Nrepeat, x, y)
  1317. ELSIF sym = for THEN
  1318. DevCPS.Get(sym); pos := DevCPM.startpos;
  1319. IF sym = ident THEN qualident(id);
  1320. IF ~(id.typ.form IN intSet) THEN err(68) END ;
  1321. CheckSym(becomes); Expression(y);
  1322. x := DevCPB.NewLeaf(id); DevCPB.Assign(x, y); SetPos(x);
  1323. CheckSym(to); pos := DevCPM.startpos; Expression(y);
  1324. IF y.class # Nconst THEN
  1325. DevCPB.GetTempVar("@for", x.left.typ, t);
  1326. z := DevCPB.NewLeaf(t); DevCPB.Assign(z, y); SetPos(z); DevCPB.Link(stat, last, z);
  1327. y := DevCPB.NewLeaf(t)
  1328. ELSE
  1329. DevCPB.CheckAssign(x.left.typ, y)
  1330. END ;
  1331. DevCPB.Link(stat, last, x);
  1332. p := DevCPM.startpos;
  1333. IF sym = by THEN DevCPS.Get(sym); ConstExpression(z) ELSE z := DevCPB.NewIntConst(1) END ;
  1334. x := DevCPB.NewLeaf(id);
  1335. IF z.conval.intval > 0 THEN DevCPB.Op(leq, x, y)
  1336. ELSIF z.conval.intval < 0 THEN DevCPB.Op(geq, x, y)
  1337. ELSE err(63); DevCPB.Op(geq, x, y)
  1338. END ;
  1339. CheckSym(do); StatSeq(s);
  1340. y := DevCPB.NewLeaf(id); DevCPB.StPar1(y, z, incfn); pos := DevCPM.startpos; SetPos(y);
  1341. IF s = NIL THEN s := y
  1342. ELSE z := s;
  1343. WHILE z.link # NIL DO z := z.link END ;
  1344. z.link := y
  1345. END ;
  1346. CheckSym(end); DevCPB.Construct(Nwhile, x, s); pos := p
  1347. ELSE err(ident)
  1348. END
  1349. ELSIF sym = loop THEN
  1350. DevCPS.Get(sym); INC(LoopLevel); StatSeq(x); DEC(LoopLevel);
  1351. DevCPB.Construct(Nloop, x, NIL); CheckSym(end)
  1352. ELSIF sym = with THEN
  1353. DevCPS.Get(sym); idtyp := NIL; x := NIL;
  1354. LOOP
  1355. IF sym < bar THEN
  1356. pos := DevCPM.startpos;
  1357. IF sym = ident THEN
  1358. qualident(id); y := DevCPB.NewLeaf(id);
  1359. IF (id # NIL) & (id.typ.form = Pointer) & ((id.mode = VarPar) OR ~id.leaf) THEN
  1360. err(-302) (* warning 302 *)
  1361. END ;
  1362. CheckSym(colon);
  1363. IF sym = ident THEN qualident(t);
  1364. IF t.mode = Typ THEN
  1365. IF id # NIL THEN
  1366. idtyp := id.typ; DevCPB.TypTest(y, t, FALSE); id.typ := t.typ;
  1367. IF id.ptyp = NIL THEN id.ptyp := idtyp END
  1368. ELSE err(130)
  1369. END
  1370. ELSE err(52)
  1371. END
  1372. ELSE err(ident)
  1373. END
  1374. ELSE err(ident)
  1375. END ;
  1376. CheckSym(do); StatSeq(s); DevCPB.Construct(Nif, y, s); SetPos(y);
  1377. IF idtyp # NIL THEN
  1378. IF id.ptyp = idtyp THEN id.ptyp := NIL END;
  1379. id.typ := idtyp; idtyp := NIL
  1380. END ;
  1381. IF x = NIL THEN x := y; lastif := x ELSE DevCPB.Link(x, lastif, y) END
  1382. END;
  1383. IF sym = bar THEN DevCPS.Get(sym) ELSE EXIT END
  1384. END;
  1385. e := sym = else; pos := DevCPM.startpos;
  1386. IF e THEN DevCPS.Get(sym); StatSeq(s) ELSE s := NIL END ;
  1387. DevCPB.Construct(Nwith, x, s); CheckSym(end);
  1388. IF e THEN x.subcl := 1 END
  1389. ELSIF sym = exit THEN
  1390. DevCPS.Get(sym);
  1391. IF LoopLevel = 0 THEN err(46) END ;
  1392. DevCPB.Construct(Nexit, x, NIL)
  1393. ELSIF sym = return THEN DevCPS.Get(sym);
  1394. IF sym < semicolon THEN Expression(x) END ;
  1395. IF level > 0 THEN DevCPB.Return(x, DevCPT.topScope.link)
  1396. ELSE (* not standard Oberon *) DevCPB.Return(x, NIL)
  1397. END;
  1398. hasReturn := TRUE
  1399. END ;
  1400. IF x # NIL THEN SetPos(x); DevCPB.Link(stat, last, x) END ;
  1401. IF sym = semicolon THEN DevCPS.Get(sym)
  1402. ELSIF (sym <= ident) OR (if <= sym) & (sym <= return) THEN err(semicolon)
  1403. ELSE EXIT
  1404. END
  1405. END
  1406. END StatSeq;
  1407. PROCEDURE Block(VAR procdec, statseq: DevCPT.Node);
  1408. VAR typ: DevCPT.Struct;
  1409. obj, first, last, o: DevCPT.Object;
  1410. x, lastdec: DevCPT.Node;
  1411. i: SHORTINT;
  1412. rname: DevCPT.Name;
  1413. name: DevCPT.String;
  1414. rec: Elem;
  1415. BEGIN
  1416. IF ((sym < begin) OR (sym > var)) & (sym # procedure) & (sym # end) & (sym # close) THEN err(36) END;
  1417. first := NIL; last := NIL; userList := NIL; recList := NIL;
  1418. LOOP
  1419. IF sym = const THEN
  1420. DevCPS.Get(sym);
  1421. WHILE sym = ident DO
  1422. DevCPT.Insert(DevCPS.name, obj);
  1423. obj.mode := Con; CheckMark(obj);
  1424. obj.typ := DevCPT.int8typ; obj.mode := Var; (* Var to avoid recursive definition *)
  1425. IF sym = eql THEN
  1426. DevCPS.Get(sym); ConstExpression(x)
  1427. ELSIF sym = becomes THEN
  1428. err(eql); DevCPS.Get(sym); ConstExpression(x)
  1429. ELSE err(eql); x := DevCPB.NewIntConst(1)
  1430. END ;
  1431. obj.mode := Con; obj.typ := x.typ; obj.conval := x.conval; (* ConstDesc ist not copied *)
  1432. CheckSym(semicolon)
  1433. END
  1434. END ;
  1435. IF sym = type THEN
  1436. DevCPS.Get(sym);
  1437. WHILE sym = ident DO
  1438. DevCPT.Insert(DevCPS.name, obj); obj.mode := Typ; obj.typ := DevCPT.undftyp;
  1439. CheckMark(obj); obj.mode := -1;
  1440. IF sym # eql THEN err(eql) END;
  1441. IF (sym = eql) OR (sym = becomes) OR (sym = colon) THEN
  1442. DevCPS.Get(sym); Type(obj.typ, name); SetType(NIL, obj, obj.typ, name);
  1443. END;
  1444. obj.mode := Typ;
  1445. IF obj.typ.form IN {Byte..Set, Char16, Int64} THEN (* make alias structure *)
  1446. typ := DevCPT.NewStr(obj.typ.form, Basic); i := typ.ref;
  1447. typ^ := obj.typ^; typ.ref := i; typ.strobj := NIL; typ.mno := 0; typ.txtpos := DevCPM.errpos;
  1448. typ.BaseTyp := obj.typ; obj.typ := typ;
  1449. END;
  1450. IF obj.typ.strobj = NIL THEN obj.typ.strobj := obj END ;
  1451. IF obj.typ.form = Pointer THEN (* !!! *)
  1452. typ := obj.typ.BaseTyp;
  1453. IF (typ # NIL) & (typ.comp = Record) & (typ.strobj = NIL) THEN
  1454. (* pointer to unnamed record: name record as "pointerName^" *)
  1455. rname := obj.name^$; i := 0;
  1456. WHILE rname[i] # 0X DO INC(i) END;
  1457. rname[i] := "^"; rname[i+1] := 0X;
  1458. DevCPT.Insert(rname, o); o.mode := Typ; o.typ := typ; typ.strobj := o
  1459. END
  1460. END;
  1461. IF obj.vis # internal THEN
  1462. typ := obj.typ;
  1463. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  1464. IF typ.comp = Record THEN typ.exp := TRUE END
  1465. END;
  1466. CheckSym(semicolon)
  1467. END
  1468. END ;
  1469. IF sym = var THEN
  1470. DevCPS.Get(sym);
  1471. WHILE sym = ident DO
  1472. LOOP
  1473. IF sym = ident THEN
  1474. DevCPT.Insert(DevCPS.name, obj);
  1475. obj.mode := Var; obj.link := NIL; obj.leaf := obj.vis = internal; obj.typ := DevCPT.undftyp;
  1476. CheckMark(obj);
  1477. IF first = NIL THEN first := obj END ;
  1478. IF last = NIL THEN DevCPT.topScope.scope := obj ELSE last.link := obj END ;
  1479. last := obj
  1480. ELSE err(ident)
  1481. END ;
  1482. IF sym = comma THEN DevCPS.Get(sym)
  1483. ELSIF sym = ident THEN err(comma)
  1484. ELSE EXIT
  1485. END
  1486. END ;
  1487. CheckSym(colon); Type(typ, name);
  1488. CheckAlloc(typ, FALSE, DevCPM.errpos);
  1489. WHILE first # NIL DO SetType(NIL, first, typ, name); first := first.link END ;
  1490. CheckSym(semicolon)
  1491. END
  1492. END ;
  1493. IF (sym < const) OR (sym > var) THEN EXIT END ;
  1494. END ;
  1495. CheckForwardTypes;
  1496. userList := NIL; rec := recList; recList := NIL;
  1497. DevCPT.topScope.adr := DevCPM.errpos;
  1498. procdec := NIL; lastdec := NIL;
  1499. IF (sym # procedure) & (sym # begin) & (sym # end) & (sym # close) THEN err(37) END;
  1500. WHILE sym = procedure DO
  1501. DevCPS.Get(sym); ProcedureDeclaration(x);
  1502. IF x # NIL THEN
  1503. IF lastdec = NIL THEN procdec := x ELSE lastdec.link := x END ;
  1504. lastdec := x
  1505. END ;
  1506. CheckSym(semicolon)
  1507. END ;
  1508. IF DevCPM.noerr & ~(DevCPM.oberon IN DevCPM.options) THEN CheckRecords(rec) END;
  1509. hasReturn := FALSE;
  1510. IF (sym # begin) & (sym # end) & (sym # close) THEN err(38) END;
  1511. IF sym = begin THEN DevCPS.Get(sym); StatSeq(statseq)
  1512. ELSE statseq := NIL
  1513. END ;
  1514. IF (DevCPT.topScope.link # NIL) & (DevCPT.topScope.link.typ # DevCPT.notyp)
  1515. & ~hasReturn & (DevCPT.topScope.link.sysflag = 0) THEN err(133) END;
  1516. IF (level = 0) & (TDinit # NIL) THEN
  1517. lastTDinit.link := statseq; statseq := TDinit
  1518. END
  1519. END Block;
  1520. PROCEDURE Module*(VAR prog: DevCPT.Node);
  1521. VAR impName, aliasName: DevCPT.Name;
  1522. procdec, statseq: DevCPT.Node;
  1523. c, sf: INTEGER; done: BOOLEAN;
  1524. BEGIN
  1525. DevCPS.Init; LoopLevel := 0; level := 0; DevCPS.Get(sym);
  1526. IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END ;
  1527. IF sym = ident THEN
  1528. DevCPT.Open(DevCPS.name); DevCPS.Get(sym);
  1529. DevCPT.libName := "";
  1530. IF sym = lbrak THEN
  1531. INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
  1532. IF sym = eql THEN DevCPS.Get(sym)
  1533. ELSE INCL(DevCPM.options, DevCPM.noCode)
  1534. END;
  1535. IF sym = string THEN DevCPT.libName := DevCPS.str^$; DevCPS.Get(sym)
  1536. ELSE err(string)
  1537. END;
  1538. CheckSym(rbrak)
  1539. END;
  1540. CheckSym(semicolon);
  1541. IF sym = import THEN DevCPS.Get(sym);
  1542. LOOP
  1543. IF sym = ident THEN
  1544. aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
  1545. IF sym = becomes THEN DevCPS.Get(sym);
  1546. IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
  1547. END ;
  1548. DevCPT.Import(aliasName, impName, done)
  1549. ELSE err(ident)
  1550. END ;
  1551. IF sym = comma THEN DevCPS.Get(sym)
  1552. ELSIF sym = ident THEN err(comma)
  1553. ELSE EXIT
  1554. END
  1555. END ;
  1556. CheckSym(semicolon)
  1557. END ;
  1558. IF DevCPM.noerr THEN TDinit := NIL; lastTDinit := NIL; c := DevCPM.errpos;
  1559. Block(procdec, statseq); DevCPB.Enter(procdec, statseq, NIL); prog := procdec;
  1560. prog.conval := DevCPT.NewConst(); prog.conval.intval := c; prog.conval.intval2 := DevCPM.startpos;
  1561. IF sym = close THEN DevCPS.Get(sym); StatSeq(prog.link) END;
  1562. prog.conval.realval := DevCPM.startpos;
  1563. CheckSym(end);
  1564. IF sym = ident THEN
  1565. IF DevCPS.name # DevCPT.SelfName THEN err(4) END ;
  1566. DevCPS.Get(sym)
  1567. ELSE err(ident)
  1568. END;
  1569. IF sym # period THEN err(period) END
  1570. END
  1571. ELSE err(ident)
  1572. END ;
  1573. TDinit := NIL; lastTDinit := NIL;
  1574. DevCPS.str := NIL
  1575. END Module;
  1576. END LindevCPP.