PCP.Mod 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924
  1. (* Paco, Copyright 2000 - 2002, Patrik Reali, ETH Zurich *)
  2. MODULE PCP; (** AUTHOR "prk"; PURPOSE "Parallel Compiler: parser"; *)
  3. IMPORT
  4. Machine, Modules, Objects, Kernel, Strings,
  5. StringPool,
  6. PCM, PCS, PCT, PCB, PCC, SYSTEM, PCArrays;
  7. CONST
  8. (* The Tokens
  9. ProgTools.Enum PCS
  10. null
  11. times slash div mod and
  12. plus minus or eql neq lss leq gtr geq in is
  13. arrow period comma
  14. colon upto rparen rbrak rbrace
  15. of then do to by
  16. lparen lbrak lbrace
  17. not
  18. becomes
  19. number nil true false string
  20. ident semicolon bar end else
  21. elsif until if case while
  22. repeat for loop with exit passivate return
  23. refines implements
  24. array definition object record pointer begin code
  25. const type var procedure import
  26. module eof
  27. ~
  28. *)
  29. null = PCS.null; times = PCS.times; slash = PCS.slash; div = PCS.div;
  30. mod = PCS.mod; and = PCS.and; plus = PCS.plus; minus = PCS.minus;
  31. or = PCS.or; eql = PCS.eql; neq = PCS.neq; lss = PCS.lss; leq = PCS.leq;
  32. gtr = PCS.gtr; geq = PCS.geq; in = PCS.in; is = PCS.is; arrow = PCS.arrow;
  33. period = PCS.period; comma = PCS.comma; colon = PCS.colon; upto = PCS.upto;
  34. rparen = PCS.rparen; rbrak = PCS.rbrak; rbrace = PCS.rbrace; of = PCS.of;
  35. then = PCS.then; do = PCS.do; to = PCS.to; by = PCS.by; lparen = PCS.lparen;
  36. lbrak = PCS.lbrak; lbrace = PCS.lbrace; not = PCS.not; becomes = PCS.becomes;
  37. number = PCS.number; nil = PCS.nil; true = PCS.true; false = PCS.false;
  38. string = PCS.string; ident = PCS.ident; semicolon = PCS.semicolon;
  39. bar = PCS.bar; end = PCS.end; else = PCS.else; elsif = PCS.elsif;
  40. until = PCS.until; if = PCS.if; case = PCS.case; while = PCS.while;
  41. repeat = PCS.repeat; for = PCS.for; loop = PCS.loop; with = PCS.with;
  42. exit = PCS.exit; passivate = PCS.passivate; return = PCS.return;
  43. refines = PCS.refines; implements = PCS.implements; array = PCS.array;
  44. definition = PCS.definition; object = PCS.object; record = PCS.record;
  45. pointer = PCS.pointer; begin = PCS.begin; codeToken = PCS.code; const = PCS.const;
  46. type = PCS.type; var = PCS.var; procedure = PCS.procedure; import = PCS.import;
  47. module = PCS.module; eof = PCS.eof; finally = PCS.finally;
  48. (** fof >> *)
  49. filler = PCS.qmark; backslash = PCS.backslash;
  50. scalarproduct = PCS.scalarproduct;
  51. elementproduct = PCS.elementproduct;
  52. elementquotient = PCS.elementquotient;
  53. transpose = PCS.transpose; dtimes = PCS.dtimes;
  54. eeql = PCS.eeql; eneq = PCS.eneq; elss = PCS.elss;
  55. eleq = PCS.eleq; egtr = PCS.egtr; egeq = PCS.egeq;
  56. AllowOverloadedModule = FALSE;
  57. (* fof removed the mechanism allowing to choose an operator from a module.
  58. Example: "a :=[myModule1] b;" chooses assignment operator for "a" from module "myModule1".
  59. My proposal is to generally prohibit multiple occurence of operators by restriction of its definition to the object's defining module.
  60. For now we do it with this switch.
  61. Note: if AllowOverloadedModule = TRUE then constant arrays do not work in code. Example A :=[1,2,3] or [1,2,3]+[4,5,6] do then not work.
  62. *)
  63. (** << fof *)
  64. (*local constants, implementations restrictions*)
  65. MaxIdentDef = 128; (*maximal number of IdentDef in a VarDecl*)
  66. TYPE
  67. IdentDefDesc = RECORD name: PCS.Name; vis: SET END; (*
  68. name = (parsed name) OR ("")
  69. vis = (parsed vis) OR (PCT.Internal)
  70. *)
  71. VAR
  72. (** Assembler Plugin *)
  73. Assemble*: PROCEDURE (scanner: PCS.Scanner; scope: PCT.Scope; exported, inlined: BOOLEAN): PCM.Attribute;
  74. (* cached string constants used by the parser*)
  75. noname, self, untraced, delegate, overloading,
  76. exclusive, active, safe, priority, realtime, winapi (* ejz *), clang (*fof for linux *) ,notag (* sz *),
  77. deltype, hiddenptr, procfld, ptrfld: StringPool.Index;
  78. NModules, NObjects, NDefinitions, NArrays, NRecords, NPointers, NDelegates, NProcedureTypes,
  79. NExclusive, NExclusiveMain, NActive,
  80. NSyncsCount: LONGINT; (* statistical counters *)
  81. (* ============================================================== *)
  82. (* ------------- The Parser Object ---------------------------------- *)
  83. TYPE
  84. (* Synchronize a thread with its child processes, await till all left the monitor or timeout *)
  85. Barrier = OBJECT (Kernel.Timer)
  86. VAR
  87. timeout: LONGINT;
  88. started, ended: LONGINT;
  89. PROCEDURE & SInit*(timeout: LONGINT);
  90. BEGIN started := 0; ended := 0; SELF.timeout := timeout*1000; Init;
  91. END SInit;
  92. PROCEDURE Enter;
  93. BEGIN
  94. Machine.AtomicInc(started);
  95. Machine.AtomicInc(NSyncsCount);
  96. END Enter;
  97. PROCEDURE Exit;
  98. BEGIN
  99. Machine.AtomicInc(ended);
  100. IF started = ended THEN Wakeup END
  101. END Exit;
  102. PROCEDURE Await;
  103. BEGIN Sleep(timeout)
  104. END Await;
  105. PROCEDURE Stats(VAR started, inside: LONGINT);
  106. BEGIN started := SELF.started; inside := SELF.started - SELF.ended
  107. END Stats;
  108. END Barrier;
  109. Parser* = OBJECT
  110. VAR
  111. sync: Barrier;
  112. sym, savedsym: PCS.Token;
  113. scanner, savedscanner: PCS.Scanner;
  114. scope, codescope: PCT.Scope; (*codescope is the scope where the code is defined, where a WITH is used*)
  115. looplevel, scopelevel: SHORTINT; (*copy of scope(ProcScope).level or 0 (rec/mod)*)
  116. forexitcount, forretcount, retcount, fincount: LONGINT; (*nested for-loops inside a LOOP-statement, used to remove the temp for-counters*)
  117. curloop: PCB.LoopInfo;
  118. code: PCC.Code;
  119. inline: BOOLEAN;
  120. locked: BOOLEAN; (*parser inside a locked statement block, set by StatementBlock*)
  121. unlockOnExit: BOOLEAN; (* EXCLUSIVE block nested in a LOOP, must unlock when exit is called *)
  122. die: BOOLEAN; (*kill the parser*)
  123. notifyScope: BOOLEAN; (*notify the parent of current scope that the body mode is available*)
  124. isRecord: BOOLEAN; (*cached: scope IS PCT.RecScope*)
  125. inspect: BOOLEAN; (* TRUE if body is parsed to find hidden local variables, i.e. procedure calls that return pointers *)
  126. forwardPtr: ARRAY 128 OF RECORD ptr: PCT.Pointer; name: PCS.Name END;
  127. nofForwardPtr: LONGINT;
  128. (* --------------------------------------------------------- *)
  129. (* Parser utilities *)
  130. PROCEDURE Error(n: WORD; pos: LONGINT);
  131. BEGIN PCM.Error(n, pos, "")
  132. END Error;
  133. PROCEDURE Check(x: PCS.Token);
  134. BEGIN
  135. IF sym = x THEN scanner.Get(sym) ELSE PCM.Error(x, scanner.errpos, "") END;
  136. END Check;
  137. (* Test whether the current symbol is a semicolon. Report an error if not. In case of multiple semicolons
  138. the follow each other, report a warning for each occurence *)
  139. PROCEDURE CheckSemicolons;
  140. BEGIN
  141. IF (sym = semicolon) THEN
  142. scanner.Get(sym);
  143. IF (sym = semicolon) THEN
  144. REPEAT
  145. PCM.Warning(315, scanner.errpos, "");
  146. scanner.Get(sym);
  147. UNTIL sym # semicolon;
  148. END;
  149. ELSE
  150. PCM.Error(semicolon, scanner.errpos, "");
  151. END;
  152. END CheckSemicolons;
  153. (* Report an error if the pseudo module SYSTEM is not imported by the specified module *)
  154. PROCEDURE CheckSysImported(module : PCT.Module);
  155. BEGIN
  156. IF ~module.sysImported THEN
  157. Error(135, scanner.errpos);
  158. ELSE
  159. INCL(PCT.System.flags, PCT.used);
  160. END;
  161. END CheckSysImported;
  162. (* --------------------------------------------------------- *)
  163. (* Active Oberon Language Productions *)
  164. (* Declaration Section *)
  165. PROCEDURE TypeModifier(VAR flags: SET; default, allowed: SET);
  166. BEGIN
  167. flags := default;
  168. IF (sym = lbrace) THEN
  169. REPEAT
  170. scanner.Get(sym);
  171. IF sym # ident THEN
  172. Error(ident, scanner.errpos)
  173. ELSIF scanner.name = untraced THEN
  174. INCL (flags, PCM.Untraced);
  175. ELSIF scanner.name = delegate THEN
  176. EXCL (flags, PCT.StaticMethodsOnly);
  177. ELSIF scanner.name = realtime THEN
  178. INCL (flags, PCT.RealtimeProcType);
  179. ELSIF scanner.name = overloading THEN
  180. INCL (flags, PCT.Overloading);
  181. ELSIF scanner.name = winapi THEN (* ejz *)
  182. CheckSysImported(scope.module);
  183. INCL (flags, PCT.WinAPIParam);
  184. ELSIF scanner.name = clang THEN (* fof for Linux *)
  185. CheckSysImported(scope.module);
  186. INCL (flags, PCT.CParam);
  187. ELSE
  188. Error(0, scanner.errpos); scanner.Get(sym)
  189. END;
  190. scanner.Get( sym )
  191. UNTIL sym # comma;
  192. IF (flags - allowed # {}) THEN flags := default; Error(200, scanner.errpos) END;
  193. Check(rbrace)
  194. END;
  195. IF (flags = {PCM.Untraced}) THEN
  196. CheckSysImported(scope.module);
  197. END;
  198. END TypeModifier;
  199. PROCEDURE IdentDef (VAR i: IdentDefDesc; allowRO: BOOLEAN); (* IdentDef = ident ["*"|"-"]. *)
  200. BEGIN
  201. i.vis := PCT.Internal;
  202. IF sym = ident THEN
  203. i.name := scanner.name; scanner.Get(sym)
  204. ELSE
  205. i.name := PCT.Anonymous;
  206. Error(ident, scanner.errpos)
  207. END;
  208. IF sym = times THEN
  209. i.vis := PCT.Public; scanner.Get(sym)
  210. ELSIF sym = minus THEN
  211. IF allowRO THEN
  212. i.vis := PCT.Internal + {PCT.PublicR}
  213. ELSE
  214. i.vis := PCT.Public; Error(47, scanner.errpos)
  215. END;
  216. scanner.Get(sym)
  217. END;
  218. END IdentDef;
  219. PROCEDURE OperatorDef(VAR i: IdentDefDesc; allowRO: BOOLEAN);
  220. VAR opName: PCS.Name;
  221. BEGIN
  222. i.vis:= PCT.Internal;
  223. opName := StringPool.GetIndex1(scanner.str);
  224. i.name := opName;
  225. IF ~scanner.IsOperatorValid() THEN
  226. PCM.Error(142, scanner.errpos, "");
  227. END;
  228. scanner.Get(sym);
  229. IF sym = times THEN
  230. i.vis := PCT.Public;
  231. scanner.Get(sym)
  232. ELSIF sym = minus THEN
  233. IF allowRO THEN
  234. i.vis := PCT.Internal + {PCT.PublicR}
  235. ELSE
  236. i.vis := PCT.Public; Error(47, scanner.errpos)
  237. END;
  238. scanner.Get(sym)
  239. END;
  240. END OperatorDef;
  241. PROCEDURE FPSection(scope: PCT.ProcScope; pflags: SET); (* ejz *)
  242. VAR name: ARRAY 32 OF PCS.Name; i, n: LONGINT; res: WORD; VarPar: BOOLEAN;
  243. pos: ARRAY 32 OF LONGINT; t: PCT.Struct;
  244. (** fof >> *)
  245. ConstPar: BOOLEAN;
  246. (** << fof *)
  247. BEGIN
  248. VarPar := sym = var;
  249. (** fof 070731 >> *)
  250. ConstPar := (sym = const);
  251. IF ConstPar THEN INCL( pflags, PCM.ReadOnly ); END;
  252. (** << fof *)
  253. IF VarPar OR ConstPar (* fof 070731 *) THEN scanner.Get(sym) END;
  254. n := 0;
  255. LOOP
  256. pos[n] := scanner.errpos;
  257. name[n] := scanner.name;
  258. (** fof >> *)
  259. (*! temporary range as parameters, remove !*)
  260. Check( ident );
  261. IF sym = upto THEN (* a..b BY c *) (* range type fof *)
  262. IF VarPar THEN PCM.Error( 122, scanner.errpos, "" ) END;
  263. (*flags[n] := pflags + {rangeflag};*) INC( n );
  264. scanner.Get( sym ); pos[n] := scanner.errpos;
  265. name[n] := scanner.name;
  266. (* flags[n] := pflags + {rangeflag};*) INC( n );
  267. Check( ident ); Check( by );
  268. pos[n] := scanner.errpos;
  269. name[n] := scanner.name; Check( ident );
  270. (*flags[n] := pflags + {rangeflag};*)
  271. ELSE (*flags[n] := pflags; *)
  272. END;
  273. (** << fof *)
  274. INC(n);
  275. (*Check(ident);*) (* fof *)
  276. IF sym # comma THEN EXIT END;
  277. scanner.Get(sym)
  278. END;
  279. Check(colon); Type(t, noname);
  280. i := 0;
  281. (* fof 070731 *)
  282. IF ConstPar & ((t IS PCT.Array) OR (t IS PCT.Record)) THEN VarPar := TRUE;
  283. END;
  284. WHILE i < n DO
  285. scope.CreatePar(PCT.Internal, VarPar, name[i], pflags, t, pos[i], (* fof *) res); (* ejz *)
  286. IF res # PCT.Ok THEN PCM.ErrorN(res, pos[i], name[i]) END;
  287. INC(i)
  288. END
  289. END FPSection;
  290. PROCEDURE FormalPars(scope: PCT.ProcScope; VAR rtype: PCT.Struct; pflags: SET); (* ejz *)
  291. VAR o: PCT.Symbol; res: WORD;
  292. BEGIN
  293. rtype := PCT.NoType;
  294. IF sym = lparen THEN
  295. scanner.Get(sym);
  296. IF sym # rparen THEN
  297. FPSection(scope, pflags); (* ejz *)
  298. WHILE sym = semicolon DO
  299. scanner.Get(sym); FPSection(scope, pflags) (* ejz *)
  300. END;
  301. END;
  302. Check(rparen);
  303. IF sym = colon THEN
  304. scanner.Get(sym);
  305. IF sym = object THEN
  306. rtype := PCT.Ptr;
  307. scanner.Get(sym)
  308. ELSIF sym = array THEN
  309. scanner.Get(sym);
  310. ArrayType(rtype, FALSE (* fof *));
  311. ELSE
  312. Qualident(o);
  313. IF (o IS PCT.Type) THEN
  314. rtype := o.type
  315. ELSE
  316. Error(52, scanner.errpos);
  317. rtype := PCT.UndefType
  318. END
  319. END;
  320. IF (rtype IS PCT.Array) & (rtype(PCT.Array).mode = PCT.open) THEN Error(91, scanner.errpos) END;
  321. (* ug *) IF (rtype # PCT.UndefType) & PCT.ContainsPointer(rtype) THEN
  322. scope.CreatePar(PCT.Internal, TRUE, PCT.PtrReturnType, pflags, rtype, 0 (* fof *), res);
  323. END
  324. ELSIF scope.formalParCount = 0 THEN (* fn *)
  325. PCM.Warning (916, scanner.errpos, "");
  326. END
  327. END;
  328. IF {PCT.CParam, PCT.WinAPIParam} * pflags # {} (* fof for Linux *) THEN scope.ReversePars() END (* ejz *)
  329. END FormalPars;
  330. PROCEDURE CheckOperator(scope: PCT.ProcScope; VAR name: PCS.Name; rtype: PCT.Struct; pos: LONGINT);
  331. VAR
  332. opStr: ARRAY PCS.MaxStrLen OF CHAR;
  333. p: PCT.Parameter;
  334. recScope: PCT.RecScope;
  335. PROCEDURE CheckCardinality(nofparam: LONGINT): BOOLEAN;
  336. BEGIN
  337. CASE opStr[0] OF
  338. | "+", "-": RETURN (nofparam = 1) OR (nofparam = 2)
  339. | "~": RETURN (opStr[1] = 0X) & (nofparam = 1)
  340. | "[": RETURN nofparam > 0
  341. ELSE RETURN nofparam = 2
  342. END;
  343. END CheckCardinality;
  344. BEGIN
  345. StringPool.GetString(name, opStr);
  346. IF ~CheckCardinality(scope.formalParCount) THEN
  347. Error(143, pos); (* invalid number of formal parameters *)
  348. END;
  349. IF opStr = ":=" THEN
  350. IF rtype # PCT.NoType THEN
  351. Error(147, pos); (* operator ":=" has no return value *)
  352. END;
  353. IF ~scope.firstPar.ref THEN
  354. Error(148, pos); (* first parameter of ":=" must be VAR *)
  355. END;
  356. IF (scope.firstPar.nextPar # NIL) & (scope.firstPar.type = scope.firstPar.nextPar.type) THEN
  357. PCM.Warning(PCM.InvalidCode, pos, "Warning: both parameters of identical type");
  358. END
  359. ELSIF opStr = "[]" THEN
  360. IF (scope = NIL) OR (scope.parent = NIL) OR ~(scope.parent IS PCT.RecScope) THEN
  361. Error(990, pos) (* operator "[]" only allowed in record scope *)
  362. ELSE
  363. recScope := scope.parent(PCT.RecScope);
  364. IF rtype = PCT.NoType THEN
  365. name := StringPool.GetIndex1(PCT.AssignIndexer);
  366. ELSE
  367. name := StringPool.GetIndex1(PCT.ReadIndexer);
  368. END
  369. END
  370. ELSE
  371. IF rtype = PCT.NoType THEN
  372. Error(141, pos); (* all other operators must have a return value *)
  373. END
  374. END;
  375. p := scope.firstPar;
  376. WHILE (p # NIL) & PCT.IsBasic(p.type) DO
  377. p := p.nextPar;
  378. END;
  379. (* Ignore "[]" because SELF is an implicit parameter *)
  380. IF (opStr # "[]") & (p = NIL) THEN
  381. Error(146, pos); (* at least one parameter must not be a basic type *)
  382. END;
  383. END CheckOperator;
  384. PROCEDURE RecordType(VAR t: PCT.Struct; pointed: BOOLEAN);
  385. VAR recstruct: PCT.Record; ptr: PCT.Pointer; recscope: PCT.RecScope; recparser: RecordParser; bpos: LONGINT; res: WORD;
  386. intf: ARRAY 32 OF PCT.Interface;
  387. BEGIN
  388. t := PCT.NoType;
  389. (* fof removed NOTAG, doesn't have any effect
  390. IF sym = lbrak THEN
  391. scanner.Get(sym);
  392. IF sym = ident THEN
  393. IF scanner.name # notag THEN Error(scanner.name, scanner.errpos) END
  394. ELSE Error(scanner.name, scanner.errpos) END;
  395. scanner.Get(sym); Check(rbrak)
  396. END;
  397. *)
  398. IF sym = lparen THEN scanner.Get(sym); bpos := scanner.errpos; Type(t, noname); Check(rparen) END;
  399. NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
  400. IF pointed THEN
  401. ptr := PCT.NewClass(t, intf, recscope, FALSE, res);
  402. IF res # PCT.Ok THEN Error(res, bpos) END;
  403. recstruct := ptr.baseR;
  404. t := ptr
  405. ELSE
  406. recstruct := PCT.NewRecord(t, recscope, {}, FALSE, res);
  407. IF res # PCT.Ok THEN Error(res, bpos) END;
  408. t := recstruct
  409. END;
  410. PCT.AddRecord(scope, recstruct);
  411. NEW(recparser, sync, recscope, scanner, sym); (* let the record parser take care of this *)
  412. SkipScope;
  413. END RecordType;
  414. PROCEDURE Interface(): PCT.Interface;
  415. VAR o: PCT.Symbol; p: PCT.Pointer;
  416. BEGIN
  417. Qualident(o);
  418. IF (o # NIL) & (o IS PCT.Type) & (o.type IS PCT.Pointer) THEN
  419. p := o.type(PCT.Pointer);
  420. IF (p.baseR # NIL) & (PCT.interface IN p.baseR.mode) THEN
  421. RETURN p
  422. END
  423. END;
  424. PCM.Error(200, scanner.errpos, "not a definition");
  425. RETURN NIL
  426. END Interface;
  427. PROCEDURE ObjectType(VAR t: PCT.Struct; name: StringPool.Index);
  428. VAR recstruct: PCT.Record; ptr: PCT.Pointer; recscope: PCT.RecScope; parser: ObjectParser; bpos, i: LONGINT; res: WORD;
  429. intf: ARRAY 32 OF PCT.Interface;
  430. BEGIN
  431. t := PCT.NoType;
  432. IF sym = lparen THEN scanner.Get(sym); bpos := scanner.errpos; Type(t, noname); Check(rparen) END;
  433. IF sym = implements THEN
  434. INCL(PCM.codeOptions, PCM.UseDefinitions); (* type declaration -> interface registration *)
  435. INCL(PCM.codeOptions, PCM.ExportDefinitions);
  436. scanner.Get(sym);
  437. i := 1;
  438. intf[0] := Interface();
  439. WHILE sym = comma DO
  440. scanner.Get(sym); intf[i] := Interface(); INC(i)
  441. END
  442. END;
  443. NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
  444. ptr := PCT.NewClass(t, intf, recscope, FALSE, res);
  445. IF res # PCT.Ok THEN Error(res, bpos) END;
  446. recstruct := ptr.baseR;
  447. t := ptr;
  448. PCT.AddRecord(scope, recstruct);
  449. NEW(parser, sync, recscope, scanner, sym); (* let the record parser take care of this *)
  450. SkipScope;
  451. IF name # noname THEN
  452. IF sym # ident THEN
  453. PCM.ErrorN(ident, scanner.errpos, name)
  454. ELSIF name # scanner.name THEN
  455. PCM.ErrorN(4, scanner.errpos, name); scanner.Get(sym)
  456. ELSE
  457. scanner.Get(sym)
  458. END
  459. END
  460. END ObjectType;
  461. PROCEDURE DefinitionType(pos: LONGINT; VAR t: PCT.Struct; name: StringPool.Index);
  462. VAR intf: ARRAY 1 OF PCT.Interface; parser: InterfaceParser; recscope: PCT.RecScope; int: PCT.Interface; res: WORD;
  463. BEGIN
  464. INCL(PCM.codeOptions, PCM.ExportDefinitions);
  465. IF sym = refines THEN
  466. scanner.Get(sym);
  467. intf[0] := Interface()
  468. END;
  469. Check(semicolon);
  470. NEW(recscope); PCT.SetOwner(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
  471. int := PCT.NewInterface(intf, recscope, FALSE, res);
  472. IF res # PCT.Ok THEN Error(res, pos) END;
  473. t := int;
  474. PCT.AddRecord(scope, int.baseR);
  475. NEW(parser, sync, recscope, scanner, sym);
  476. WHILE sym # end DO scanner.Get(sym) END;
  477. scanner.Get(sym);
  478. IF name # noname THEN
  479. IF sym # ident THEN
  480. PCM.ErrorN(ident, scanner.errpos, name)
  481. ELSIF name # scanner.name THEN
  482. PCM.ErrorN(4, scanner.errpos, name); scanner.Get(sym)
  483. ELSE
  484. scanner.Get(sym)
  485. END
  486. END
  487. END DefinitionType;
  488. (** fof >> *)
  489. PROCEDURE TensorType( VAR t: PCT.Struct );
  490. VAR aarray: PCT.Tensor; base: PCT.Struct; res: WORD;
  491. BEGIN
  492. Type( base, noname ); NEW( aarray ); t := aarray; PCT.InitTensor( aarray, base, res );
  493. IF res # PCT.Ok THEN Error( res, scanner.errpos ) END;
  494. t := aarray;
  495. END TensorType;
  496. (** << fof *)
  497. PROCEDURE ArrayType (VAR t: PCT.Struct; enhArray: BOOLEAN (* fof *));
  498. VAR index: PCB.Expression; array: PCT.Array; pos0, pos: LONGINT; res: WORD; base: PCT.Struct;
  499. (** fof >> *)
  500. earray: PCT.EnhArray; first: BOOLEAN; aarray: PCT.Tensor;
  501. (** << fof *)
  502. BEGIN
  503. pos0 := scanner.errpos;
  504. (* fof removed NOTAG, doesn't have any effect
  505. IF sym = lbrak THEN
  506. scanner.Get(sym);
  507. IF sym = ident THEN
  508. IF scanner.name # notag THEN Error(scanner.name, scanner.errpos) END
  509. ELSE Error(scanner.name, scanner.errpos) END;
  510. scanner.Get(sym); Check(rbrak)
  511. END;
  512. *)
  513. (** fof >> *)
  514. IF (~enhArray) & (sym = lbrak) THEN enhArray := TRUE; scanner.Get( sym ); first := TRUE ELSE first := FALSE END;
  515. IF first & (sym = PCS.qmark) THEN
  516. scanner.Get( sym ); Check( rbrak ); Check( of ); TensorType( t );
  517. ELSIF enhArray THEN
  518. IF sym = times THEN scanner.Get( sym ); index := NIL; ELSE SimpleExpr( index ); END;
  519. IF sym = rbrak THEN
  520. scanner.Get( sym ); Check( of ); pos := scanner.errpos; Type( base, noname );
  521. ELSIF sym = comma THEN scanner.Get( sym ); pos := scanner.errpos; ArrayType( base, TRUE )
  522. ELSE Error( rbrak, scanner.errpos ); t := PCT.UndefType; RETURN
  523. END;
  524. IF index = NIL THEN (* open enh array *)
  525. NEW( earray ); t := earray; PCT.InitOpenEnhArray( earray, base, {PCT.open}, res );
  526. IF res # PCT.Ok THEN Error( res, pos ) END;
  527. ELSIF ~PCT.IsCardinalType( index.type ) THEN (* invalid type *)
  528. Error( 51, pos ); t := PCT.UndefType
  529. ELSIF index IS PCB.Const THEN (* static enh array *)
  530. NEW( earray ); t := earray; PCT.InitStaticEnhArray( earray, index( PCB.Const ).con.int, base, {PCT.static}, res );
  531. ELSE (* dynamic sized enh array *)
  532. (* t := PCB.NewDynSizedEnhArray( index, base, res ); *)
  533. Error( 200, scanner.errpos ); t := PCT.UndefType; RETURN
  534. END;
  535. IF res # PCT.Ok THEN Error( res, pos ) END
  536. (** << fof *)
  537. ELSIF sym = of THEN
  538. scanner.Get(sym); pos := scanner.errpos; Type(base, noname);
  539. NEW(array); t := array;
  540. PCT.InitOpenArray(array, base, res);
  541. IF res # PCT.Ok THEN Error(res, pos) END
  542. ELSE
  543. SimpleExpr(index);
  544. IF sym = of THEN
  545. scanner.Get(sym); pos := scanner.errpos; Type(base, noname)
  546. ELSIF sym = comma THEN
  547. scanner.Get(sym); pos := scanner.errpos; ArrayType(base, FALSE (* fof *))
  548. ELSE
  549. Error(of, scanner.errpos); t := PCT.UndefType;
  550. RETURN
  551. END;
  552. IF ~PCT.IsCardinalType(index.type) THEN
  553. Error(51, pos); t := PCT.UndefType
  554. ELSIF index IS PCB.Const THEN
  555. NEW(array); t := array;
  556. PCT.InitStaticArray(array, index(PCB.Const).con.int, base, res)
  557. ELSE
  558. (*fof disabled semi-dynamic array functionality *)
  559. PCM.Error(50, pos, "");
  560. t := PCB.NewDynSizedArray(index, base, res)
  561. END;
  562. IF res # PCT.Ok THEN Error(res, pos) END
  563. END
  564. END ArrayType;
  565. PROCEDURE PointerType(VAR t: PCT.Struct; name: StringPool.Index);
  566. VAR pos, pos1: LONGINT; res: WORD; id: PCS.Name; o: PCT.Symbol; ptr: PCT.Pointer;
  567. BEGIN
  568. IF sym = record THEN
  569. scanner.Get(sym); RecordType(t, TRUE)
  570. ELSIF sym # ident THEN
  571. pos1:=scanner.errpos;
  572. Type(t, noname);
  573. NEW(ptr); PCT.InitPointer(ptr, t, res); t := ptr;
  574. IF res # PCT.Ok THEN Error(res, pos1) END
  575. ELSE (* ident own handling, because of forwards *)
  576. id := scanner.name;
  577. scanner.Get(sym);
  578. IF sym = period THEN (* Mod.Type *)
  579. o := PCT.Find(scope, scope, id, PCT.structdeclared, TRUE);
  580. IF o = NIL THEN
  581. Error(0, scanner.errpos);
  582. o := PCB.unknownObj
  583. ELSIF o IS PCT.Module THEN
  584. scanner.Get(sym);
  585. IF sym = ident THEN
  586. o := PCT.Find(scope, o(PCT.Module).scope, scanner.name, PCT.complete, TRUE);
  587. scanner.Get(sym);
  588. IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END
  589. ELSE
  590. Error(ident, scanner.errpos);
  591. o := PCB.unknownObj
  592. END
  593. END
  594. ELSE (* Type *)
  595. o := PCT.Find(scope, scope, id, PCT.local, TRUE);
  596. END;
  597. IF o = NIL THEN
  598. NEW(ptr);
  599. forwardPtr[nofForwardPtr].ptr := ptr;
  600. forwardPtr[nofForwardPtr].name := id;
  601. INC(nofForwardPtr);
  602. t := ptr
  603. ELSIF o IS PCT.Type THEN
  604. NEW(ptr); PCT.InitPointer(ptr, o.type, res); t := ptr;
  605. IF res # PCT.Ok THEN Error(res, pos) END
  606. ELSE
  607. Error(52, scanner.errpos); t := PCT.UndefType
  608. END
  609. END
  610. END PointerType;
  611. PROCEDURE Type (VAR t: PCT.Struct; name: StringPool.Index);
  612. VAR o: PCT.Symbol; procscope: PCT.ProcScope; pos: LONGINT; res: WORD;
  613. proc: PCT.Delegate; sf: SET;
  614. BEGIN
  615. pos := scanner.errpos;
  616. IF sym = array THEN
  617. Machine.AtomicInc(NArrays);
  618. scanner.Get(sym); ArrayType(t, FALSE (* fof *));
  619. ELSIF sym = record THEN
  620. Machine.AtomicInc(NRecords);
  621. scanner.Get(sym); RecordType(t, FALSE);
  622. ELSIF sym = pointer THEN
  623. Machine.AtomicInc(NPointers);
  624. scanner.Get(sym); Check(to); PointerType(t, noname);
  625. ELSIF sym = object THEN
  626. scanner.Get(sym);
  627. IF (sym = semicolon) OR (sym = rparen) THEN
  628. t := PCT.Ptr (* generic OBJECT *)
  629. ELSE
  630. Machine.AtomicInc(NObjects);
  631. ObjectType(t, name)
  632. END
  633. ELSIF sym = definition THEN
  634. Machine.AtomicInc(NDefinitions);
  635. scanner.Get(sym);
  636. DefinitionType(pos, t, name)
  637. ELSIF sym = procedure THEN
  638. Machine.AtomicInc(NProcedureTypes);
  639. scanner.Get(sym);
  640. TypeModifier(sf, {PCT.StaticMethodsOnly}, {PCT.StaticMethodsOnly, PCT.RealtimeProcType (* ug *), PCT.WinAPIParam, PCT.CParam} (* fof for Linux *) ); (* ejz *)
  641. IF (sf = {}) OR (sf = {PCT.RealtimeProc}) THEN Machine.AtomicInc(NDelegates) END;
  642. NEW(procscope); PCT.InitScope(procscope, scope, {}, FALSE); PCT.SetOwner(procscope);
  643. IF {PCT.CParam, PCT.WinAPIParam} * sf # {} (* fof for Linux *) THEN (* ejz *)
  644. IF scope IS PCT.ProcScope THEN
  645. PCM.Error(200, scanner.errpos, "invalid WINAPI proc")
  646. ELSIF PCT.CParam IN sf THEN (* fof for Linux *)
  647. procscope.SetCC( PCT.CLangCC )
  648. ELSE
  649. procscope.SetCC(PCT.WinAPICC)
  650. END
  651. END;
  652. FormalPars (procscope, t, sf - {PCT.StaticMethodsOnly}); (* ejz *)
  653. NEW(proc); PCT.InitDelegate(proc, t, procscope, sf, res);
  654. IF res # PCT.Ok THEN Error(res, pos) END;
  655. t := proc
  656. ELSE
  657. Qualident(o);
  658. IF (o IS PCT.Type) THEN
  659. t := o.type
  660. ELSE
  661. Error(52, scanner.errpos); t := PCT.UndefType
  662. END
  663. END
  664. END Type;
  665. PROCEDURE VarDecl;
  666. VAR id: ARRAY MaxIdentDef OF IdentDefDesc; pos: ARRAY MaxIdentDef OF LONGINT; (** fof *) c, n: LONGINT; res: WORD; t: PCT.Struct; flag: ARRAY MaxIdentDef OF SET;
  667. BEGIN n := 1;
  668. pos[0] := scanner.errpos; (* fof *)
  669. IdentDef (id[0], TRUE);
  670. TypeModifier(flag[0], {}, {PCM.Untraced});
  671. WHILE sym = comma DO
  672. scanner.Get(sym);
  673. pos[n] := scanner.errpos; (* fof *)
  674. IdentDef (id[n], TRUE);
  675. TypeModifier(flag[n], {}, {PCM.Untraced});
  676. INC(n)
  677. END;
  678. Check(colon); Type(t, noname);
  679. c := 0;
  680. WHILE c < n DO
  681. scope.CreateVar(id[c].name, id[c].vis, flag[c], t, pos[c], (* fof *) NIL, res); INC(c);
  682. IF res # PCT.Ok THEN PCM.ErrorN(res, scanner.errpos, id[c-1].name) END
  683. END;
  684. END VarDecl;
  685. PROCEDURE TypeDecl;
  686. VAR i: IdentDefDesc; pos: LONGINT; res: WORD; t: PCT.Struct;
  687. BEGIN
  688. pos := scanner.errpos;
  689. IdentDef(i, FALSE); Check(eql); Type(t, i.name);
  690. scope.CreateType(i.name, i.vis, t, pos, (*fof*) res);
  691. IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END;
  692. END TypeDecl;
  693. PROCEDURE ConstDecl;
  694. VAR i: IdentDefDesc; x: PCB.Const; pos: LONGINT; res: WORD; long: HUGEINT;
  695. BEGIN
  696. pos := scanner.errpos;
  697. IdentDef(i, FALSE); Check(eql); ConstExpr(x);
  698. scope.CreateValue(i.name, i.vis, x.con, pos, (*fof*) res);
  699. IF x.con.type = PCT.Int64 THEN
  700. long := x.con.long;
  701. IF long DIV 2 <= LONG(MAX(LONGINT)) THEN
  702. (*!fof: replace this with a warning once everything is converted *)
  703. PCM.Error(-1,pos,"unsigned longint is a hugeint -> use SHORT");
  704. END;
  705. END;
  706. IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END
  707. END ConstDecl;
  708. PROCEDURE FixForwards;
  709. VAR obj: PCT.Symbol; state: SHORTINT; res: WORD;
  710. BEGIN
  711. state := PCT.structallocated;
  712. IF isRecord THEN state := PCT.structdeclared END;
  713. WHILE nofForwardPtr > 0 DO
  714. DEC(nofForwardPtr);
  715. obj := PCT.Find(scope, scope, forwardPtr[nofForwardPtr].name, state, TRUE);
  716. IF obj = NIL THEN
  717. PCM.ErrorN(128, scanner.errpos, forwardPtr[nofForwardPtr].name); obj := PCB.unknownObj
  718. END;
  719. PCT.InitPointer(forwardPtr[nofForwardPtr].ptr, obj.type, res);
  720. IF res # PCT.Ok THEN Error(res, scanner.errpos) END
  721. END
  722. END FixForwards;
  723. PROCEDURE ListOf(parse: PROCEDURE);
  724. BEGIN
  725. scanner.Get(sym);
  726. WHILE sym = ident DO
  727. parse;
  728. CheckSemicolons;
  729. END
  730. END ListOf;
  731. PROCEDURE DeclSeq;
  732. VAR t: PCT.Struct; name: PCS.Name; pos: LONGINT; res: WORD;
  733. BEGIN
  734. WHILE sym = definition DO
  735. pos := scanner.errpos;
  736. scanner.Get(sym);
  737. name := scanner.name;
  738. Check(ident);
  739. DefinitionType(pos, t, name);
  740. Check(semicolon);
  741. scope.CreateType(name, PCT.Public, t, pos(*fof*), res);
  742. IF res # PCT.Ok THEN PCM.ErrorN(res, pos, name) END
  743. END;
  744. LOOP
  745. IF sym = const THEN
  746. scanner.Get(sym);
  747. WHILE sym = ident DO
  748. ConstDecl;
  749. CheckSemicolons;
  750. END
  751. ELSIF sym = type THEN
  752. scanner.Get(sym);
  753. WHILE sym = ident DO
  754. TypeDecl;
  755. CheckSemicolons;
  756. END
  757. ELSIF sym = var THEN
  758. scanner.Get(sym);
  759. WHILE sym = ident DO
  760. VarDecl;
  761. CheckSemicolons;
  762. END
  763. ELSE
  764. EXIT
  765. END
  766. END;
  767. FixForwards;
  768. PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
  769. PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
  770. WHILE sym = procedure DO
  771. scanner.Get(sym); ProcDecl;
  772. IF sym # end THEN Check(semicolon) END
  773. END;
  774. PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos);
  775. savedsym := sym;
  776. savedscanner := scanner;
  777. scanner := PCS.ForkScanner(scanner);
  778. inspect := TRUE;
  779. Body(TRUE); (* suppress = TRUE *)
  780. scanner := savedscanner;
  781. sym := savedsym;
  782. inspect := FALSE;
  783. PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos);
  784. END DeclSeq;
  785. (* --------------------------------------------------------- *)
  786. (* Active Oberon Language Productions *)
  787. (* Implementation Section *)
  788. PROCEDURE Qualident (VAR o: PCT.Symbol); (*Qualident = [ident "."] ident*)
  789. (* returns the object or unknownObj *)
  790. VAR pos: LONGINT;
  791. BEGIN
  792. IF sym = ident THEN
  793. IF scanner.name = self THEN
  794. o := PCT.Find(scope, scope, PCT.SelfName, PCT.procdeclared, TRUE)
  795. ELSIF scope.state >= PCT.procdeclared THEN (*parsing code*)
  796. o := PCT.Find(scope, scope, scanner.name, PCT.procdeclared, TRUE)
  797. ELSIF isRecord THEN
  798. o := PCT.Find(scope, scope, scanner.name, PCT.structdeclared, TRUE) (*break scope <-> recordscope cycle*)
  799. ELSE
  800. o := PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE)
  801. END;
  802. pos := scanner.errpos; scanner.Get(sym);
  803. IF o = NIL THEN
  804. Error(0, pos); o := PCB.unknownObj
  805. ELSIF (sym = period) & (o IS PCT.Module) THEN (*semantic check needed because of language design*)
  806. scanner.Get(sym);
  807. IF sym = ident THEN
  808. o := PCT.Find(scope, o(PCT.Module).scope, scanner.name, PCT.procdeclared(*PCT.complete*), TRUE);
  809. scanner.Get(sym);
  810. IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
  811. ELSE Error(ident, scanner.errpos);
  812. END
  813. END
  814. ELSE o := PCB.unknownObj; Error(ident, scanner.errpos);
  815. END;
  816. END Qualident;
  817. PROCEDURE GetModule(VAR o: PCT.Symbol);
  818. BEGIN
  819. IF sym = ident THEN
  820. o := PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE);
  821. ELSE
  822. o := PCB.unknownObj; Error(ident, scanner.errpos);
  823. END;
  824. END GetModule;
  825. (** fof >> *)
  826. PROCEDURE Range( VAR exp, texp, bexp: PCB.Expression ): BOOLEAN;
  827. VAR isRange: BOOLEAN;
  828. BEGIN
  829. exp := NIL; texp := NIL; bexp := NIL;
  830. IF sym = times THEN isRange := TRUE; scanner.Get( sym );
  831. ELSIF sym = upto THEN (* ".." without first argument *)
  832. ELSE Expr( exp ); isRange := FALSE;
  833. END;
  834. IF (sym = upto) THEN
  835. isRange := TRUE; scanner.Get( sym );
  836. IF (sym = ident) & (scanner.name = StringPool.GetIndex1( "MAX" )) THEN
  837. scanner.Get( sym );
  838. IF sym = by THEN
  839. (* Error( 200, scanner.errpos ); *)
  840. scanner.Get( sym ); Expr( bexp );
  841. END;
  842. ELSIF sym = by THEN (* ".." without second argument *)
  843. scanner.Get( sym ); Expr( bexp );
  844. ELSIF (sym = comma) OR (sym = rbrak) OR (sym = rparen) THEN RETURN TRUE;
  845. ELSE
  846. Expr( texp );
  847. IF sym = by THEN
  848. (* Error( 200, scanner.errpos ); *)
  849. scanner.Get( sym ); Expr( bexp );
  850. END;
  851. END;
  852. END;
  853. RETURN isRange;
  854. END Range;
  855. (** << fof *)
  856. PROCEDURE ExprList(VAR x: PCB.ExprList);
  857. VAR y: PCB.Expression;
  858. texp, bexp: PCB.Expression; z: PCB.Const; range: BOOLEAN; (* fof *)
  859. BEGIN
  860. (** fof >> *)
  861. LOOP
  862. IF Range( y, texp, bexp ) THEN
  863. IF y = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( 0, PCT.Int32 ) ); y := z; END;
  864. IF texp = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( MAX( LONGINT ), PCT.Int32 ) ); texp := z END;
  865. IF bexp = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( 1, PCT.Int32 ) ); bexp := z END;
  866. x.Append( y ); x.Append( texp ); x.Append( bexp );
  867. ELSE x.Append( y );
  868. END;
  869. IF sym = comma THEN scanner.Get( sym ); ELSE EXIT END;
  870. END; (* loop *)
  871. (** << fof *)
  872. (*
  873. Expr(y); x.Append(y);
  874. WHILE sym = comma DO
  875. scanner.Get(sym); Expr(y); x.Append(y)
  876. END
  877. *)
  878. END ExprList;
  879. PROCEDURE GetGuard(search: PCT.Scope; symbol: PCT.Symbol): PCT.Symbol;
  880. BEGIN
  881. WHILE search # NIL DO
  882. IF search IS PCT.WithScope THEN
  883. IF search(PCT.WithScope).withSym = symbol THEN
  884. RETURN search(PCT.WithScope).withGuard;
  885. END;
  886. END;
  887. search := search.parent;
  888. END;
  889. RETURN NIL;
  890. END GetGuard;
  891. PROCEDURE Designator(VAR x: PCB.Designator);
  892. VAR o: PCT.Symbol; exp: PCB.Expression; y: PCB.Designator;
  893. guard: PCT.Symbol;
  894. ovlarray: BOOLEAN; m: PCT.Method;
  895. (** fof >> *)
  896. texp, bexp: PCB.Expression; (* from .. to BY by *)
  897. range: BOOLEAN; atype: PCT.Struct; idx: PCB.EnhIndex; aidx: PCB.AnyIndex;
  898. (** << fof *)
  899. BEGIN
  900. LOOP
  901. IF x IS PCB.Var THEN
  902. guard := GetGuard(scope, x(PCB.Var).obj);
  903. IF guard # NIL THEN
  904. x := PCB.NewGuard(scanner.errpos, x, guard, FALSE);
  905. END;
  906. ELSIF x IS PCB.Field THEN
  907. guard := GetGuard(scope, x(PCB.Field).field);
  908. IF guard # NIL THEN
  909. x := PCB.NewGuard(scanner.errpos, x, guard, FALSE);
  910. END
  911. END;
  912. IF sym = period THEN
  913. scanner.Get(sym);
  914. IF sym = ident THEN
  915. x := PCB.NewField(codescope, x, scanner.name, scanner.errpos); scanner.Get(sym)
  916. ELSE
  917. Error(ident, scanner.errpos)
  918. END
  919. ELSIF sym = lbrak THEN
  920. ovlarray := FALSE;
  921. IF x.type IS PCT.Pointer THEN
  922. IF (x.type(PCT.Pointer).base IS PCT.Record) THEN
  923. m := PCT.FindIndexer(x.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.ReadIndexer));
  924. IF m = NIL THEN
  925. m := PCT.FindIndexer(x.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.AssignIndexer))
  926. END;
  927. ovlarray := m # NIL;
  928. END;
  929. END;
  930. IF ovlarray THEN
  931. RETURN
  932. (** fof >> *)
  933. ELSIF x.type IS PCT.EnhArray THEN (* enhanced array treatment *)
  934. idx := PCB.NewEnhIndex( scanner.errpos, x ); x := idx;
  935. (* NEW( idx, scanner.errpos, x ); x := idx; *)
  936. scanner.Get( sym );
  937. LOOP
  938. IF Range( exp, texp, bexp ) THEN (* ranged expression of the form [exp] .. [texp] [BY bexp] *)
  939. idx.AppendRange( scanner.errpos, exp, texp, bexp );
  940. ELSE (* exp is already parsed *)
  941. idx.AppendIndex( scanner.errpos, exp );
  942. END;
  943. IF sym # comma THEN EXIT END;
  944. scanner.Get( sym )
  945. END;
  946. Check( rbrak ); idx.Finish;
  947. ELSIF x.type IS PCT.Tensor THEN (* any array treatment *)
  948. NEW( aidx, scanner.errpos, x ); x := aidx; scanner.Get( sym );
  949. LOOP
  950. IF sym = filler THEN scanner.Get( sym ); aidx.AppendFiller( scanner.errpos );
  951. ELSIF Range( exp, texp, bexp ) THEN (* ranged expression of the form [exp] .. [texp] [BY bexp] *)
  952. (* idx.AppendRange( scanner.errpos, exp, texp, bexp ); *)
  953. aidx.AppendRange( scanner.errpos, exp, texp, bexp );
  954. ELSE (* exp is already parsed *)
  955. aidx.AppendIndex( scanner.errpos, exp );
  956. END;
  957. IF sym # comma THEN EXIT END;
  958. scanner.Get( sym )
  959. END;
  960. Check( rbrak ); aidx.Finish;
  961. (** << fof *)
  962. ELSE
  963. (** fof >> *)
  964. range := FALSE; atype := x.type;
  965. (*IF x IS PCB.Range THEN PCM.Error( -1, scanner.errpos, "ranges cannot be indexed directly" ); END; *)
  966. (** << fof *)
  967. scanner.Get(sym);
  968. LOOP
  969. Expr(exp); x := PCB.NewIndex(scanner.errpos, x, exp);
  970. IF sym # comma THEN EXIT END;
  971. scanner.Get(sym)
  972. END;
  973. Check(rbrak)
  974. END
  975. ELSIF sym = arrow THEN
  976. x := PCB.NewDeref(scanner.errpos, x);
  977. scanner.Get(sym)
  978. ELSIF (sym = lparen) & PCB.IsInterface(x) THEN
  979. INCL(PCM.codeOptions, PCM.UseDefinitions); (* use lookup and call *)
  980. scanner.Get(sym);
  981. Qualident(o);
  982. y := PCB.MakeNode(scanner.errpos, codescope, o);
  983. Designator(y);
  984. Check(rparen);
  985. x := PCB.Interface(x, y)
  986. (*ELSIF (sym=lparen) & (x IS PCB.Type) THEN
  987. scanner.Get(sym); Expr(y); Check(rparen);
  988. x := PCB.NewConversion(scanner.errpos,y,x.type);
  989. *)
  990. ELSIF (sym = lparen) & ~x.IsCallable() & (scope.state >= PCT.procdeclared) THEN (*needs semantic check because of ambiguous language design*)
  991. (*in declaration phase only expressions make sense!*)
  992. scanner.Get(sym); Qualident (o); Check(rparen);
  993. x:=PCB.NewGuard(scanner.errpos, x, o, FALSE)
  994. ELSE
  995. EXIT (* -> ENDLOOP *)
  996. END;
  997. END (* LOOP *)
  998. END Designator;
  999. PROCEDURE Element(VAR x: PCB.Expression);
  1000. VAR y: PCB.Expression; pos: LONGINT;
  1001. BEGIN
  1002. Expr(x);
  1003. IF sym = upto THEN
  1004. pos:=scanner.errpos;
  1005. scanner.Get(sym); Expr(y); x:=PCB.NewDOp(pos, PCC.setfn, x, y) (*this operator cannot be overwritten*)
  1006. ELSE
  1007. x := PCB.NewMOp(scanner.errpos, NIL, PCC.setfn, x); (*this operator cannot be overwritten*)
  1008. END
  1009. END Element;
  1010. PROCEDURE Set(VAR x: PCB.Expression);
  1011. VAR y: PCB.Expression; pos: LONGINT;
  1012. BEGIN
  1013. scanner.Get(sym);
  1014. IF sym # rbrace THEN
  1015. Element(x);
  1016. WHILE sym = comma DO
  1017. pos:=scanner.errpos;
  1018. scanner.Get(sym); Element(y); x := PCB.NewDOp(pos, plus, x, y);
  1019. END
  1020. ELSE
  1021. x := PCB.NewSetValue(scanner.errpos, {})
  1022. END;
  1023. Check(rbrace)
  1024. END Set;
  1025. (** fof >> *)
  1026. PROCEDURE MathArray( VAR x: PCB.Expression );
  1027. (* temporary patch to make array expressions work. This will be improved in the new compiler *)
  1028. VAR array: PCB.ArrayExpression;
  1029. len: ARRAY 32 OF LONGINT;
  1030. dim: LONGINT; type: PCT.Struct;
  1031. name: ARRAY 256 OF CHAR;
  1032. error: BOOLEAN;
  1033. bytes: POINTER TO ARRAY OF SYSTEM.BYTE;
  1034. pos: LONGINT; size: LONGINT;
  1035. PROCEDURE Parse( a: PCB.ArrayExpression );
  1036. VAR array: PCB.ArrayExpression; first,aq: PCB.ArrayQ;
  1037. BEGIN
  1038. NEW(aq); first := aq; a.pos := scanner.errpos;
  1039. scanner.Get( sym );
  1040. IF sym = lbrak THEN
  1041. LOOP
  1042. NEW( array ); Parse( array ); aq.e := array; aq.pos := scanner.errpos;
  1043. IF sym = comma THEN
  1044. scanner.Get( sym );
  1045. IF sym # lbrak THEN PCM.Error( lbrak, scanner.errpos, "[ expected" ); EXIT; END;
  1046. NEW( aq.next ); aq := aq.next;
  1047. ELSE EXIT
  1048. END;
  1049. END;
  1050. ELSE
  1051. LOOP
  1052. aq.pos := scanner.errpos; Expr( aq.e );
  1053. IF sym = comma THEN scanner.Get( sym ); ELSE EXIT END;
  1054. NEW( aq.next ); aq := aq.next;
  1055. END;
  1056. END;
  1057. Check( rbrak );
  1058. a.SetArray(first);
  1059. END Parse;
  1060. PROCEDURE CheckLens( a: PCB.ArrayQ; d: LONGINT );
  1061. VAR l, pos: LONGINT;
  1062. BEGIN
  1063. IF d > dim THEN dim := d END;
  1064. l := 0;
  1065. WHILE (a # NIL ) DO
  1066. pos := a.pos;
  1067. IF a.e IS PCB.ArrayExpression THEN CheckLens( a.e(PCB.ArrayExpression).array, d + 1 ) END;
  1068. a := a.next; INC( l );
  1069. END;
  1070. IF len[d] = 0 THEN
  1071. (* KernelLog.String("len["); KernelLog.Int(d,0); KernelLog.String("] = "); KernelLog.Int(l,0); KernelLog.Ln; *)
  1072. len[d] := l
  1073. ELSIF len[d] # l THEN PCM.Error( 999, pos, "array dimensions must be of equal size" );
  1074. ELSE (* KernelLog.String("(len["); KernelLog.Int(d,0); KernelLog.String("] ok)"); KernelLog.Ln; *)
  1075. END;
  1076. END CheckLens;
  1077. PROCEDURE GetType( a: PCB.ArrayQ );
  1078. VAR name: ARRAY 64 OF CHAR;
  1079. BEGIN
  1080. WHILE (a # NIL ) DO
  1081. IF a.e IS PCB.ArrayExpression THEN GetType( a.e(PCB.ArrayExpression).array )
  1082. ELSE
  1083. PCT.GetTypeName( a.e.type, name );
  1084. (* KernelLog.String("Type: "); KernelLog.String(name); KernelLog.Ln; *)
  1085. IF type = NIL THEN type := a.e.type
  1086. ELSIF a.e.type = type THEN (* ok *)
  1087. ELSIF PCT.IsBasic( a.e.type ) & PCT.IsBasic( type ) THEN
  1088. IF (PCT.TypeDistance( type, a.e.type ) > 0) THEN type := a.e.type END;
  1089. ELSE error := TRUE; PCM.Error( 999, a.pos, "invalid type" );
  1090. END;
  1091. END;
  1092. a := a.next;
  1093. END;
  1094. END GetType;
  1095. PROCEDURE Convert( a: PCB.ArrayQ );
  1096. VAR e: PCB.Expression;
  1097. BEGIN
  1098. WHILE (a # NIL ) DO
  1099. IF a.e IS PCB.ArrayExpression THEN Convert( a.e(PCB.ArrayExpression).array ) ELSE e := PCB.NewConversion( a.pos, a.e, type ); a.e := e; INC( pos ); END;
  1100. a := a.next;
  1101. END;
  1102. END Convert;
  1103. PROCEDURE FillConst( a: PCB.ArrayQ );
  1104. VAR s: SHORTINT; i: INTEGER; l: LONGINT; r: REAL; x: LONGREAL; con: PCT.Const;
  1105. BEGIN
  1106. WHILE (a # NIL ) DO
  1107. IF a.e IS PCB.ArrayExpression THEN FillConst( a.e(PCB.ArrayExpression).array )
  1108. ELSE
  1109. IF a.e IS PCB.Const THEN
  1110. con := a.e( PCB.Const ).con;
  1111. IF type = PCT.Int8 THEN s := SHORT( SHORT( con.int ) ); SYSTEM.MOVE( ADDRESSOF( s ), ADDRESSOF( bytes[pos] ), size );
  1112. ELSIF type = PCT.Int16 THEN i := SHORT( con.int ); SYSTEM.MOVE( ADDRESSOF( i ), ADDRESSOF( bytes[pos] ), size );
  1113. ELSIF type = PCT.Int32 THEN l := con.int; SYSTEM.MOVE( ADDRESSOF( l ), ADDRESSOF( bytes[pos] ), size );
  1114. ELSIF type = PCT.Float32 THEN r := SHORT( con.real ); SYSTEM.MOVE( ADDRESSOF( r ), ADDRESSOF( bytes[pos] ), size );
  1115. ELSIF type = PCT.Float64 THEN x := con.real; SYSTEM.MOVE( ADDRESSOF( x ), ADDRESSOF( bytes[pos] ), size );
  1116. ELSE PCM.Error( 200, a.pos, "basic types only" );
  1117. END;
  1118. ELSE
  1119. IF type = PCT.Int8 THEN s := -1; SYSTEM.MOVE( ADDRESSOF( s ), ADDRESSOF( bytes[pos] ), size );
  1120. ELSIF type = PCT.Int16 THEN i := -1; SYSTEM.MOVE( ADDRESSOF( i ), ADDRESSOF( bytes[pos] ), size );
  1121. ELSIF type = PCT.Int32 THEN l := -1; SYSTEM.MOVE( ADDRESSOF( l ), ADDRESSOF( bytes[pos] ), size );
  1122. ELSIF type = PCT.Float32 THEN r := -1; SYSTEM.MOVE( ADDRESSOF( r ), ADDRESSOF( bytes[pos] ), size );
  1123. ELSIF type = PCT.Float64 THEN x := -1; SYSTEM.MOVE( ADDRESSOF( x ), ADDRESSOF( bytes[pos] ), size );
  1124. ELSE PCM.Error( 200, a.pos, "basic types only" );
  1125. END;
  1126. END;
  1127. INC( pos, size );
  1128. END;
  1129. a := a.next;
  1130. END;
  1131. END FillConst;
  1132. PROCEDURE IsConst(a: PCB.ArrayQ): BOOLEAN;
  1133. VAR result: BOOLEAN;
  1134. BEGIN
  1135. result := TRUE;
  1136. WHILE (a # NIL) & result DO
  1137. IF a.e IS PCB.ArrayExpression THEN
  1138. result := IsConst(a.e(PCB.ArrayExpression).array)
  1139. ELSE
  1140. result := a.e IS PCB.Const;
  1141. END;
  1142. a := a.next;
  1143. END;
  1144. RETURN result
  1145. END IsConst;
  1146. BEGIN
  1147. error := FALSE;
  1148. NEW( array); Parse( array ); dim := -1; CheckLens( array.array, 0 );
  1149. (*KernelLog.String("dim="); KernelLog.Int(dim+1,0); KernelLog.Ln; *)
  1150. type := NIL; GetType( array.array );
  1151. IF error THEN RETURN END;
  1152. PCT.GetTypeName( type, name );
  1153. (* KernelLog.String("Common type: "); KernelLog.String(name); KernelLog.Ln; *)
  1154. IF ~error THEN
  1155. Convert( array.array );
  1156. (* KernelLog.String("is const");*)
  1157. IF type = PCT.Int8 THEN size := 1
  1158. ELSIF type = PCT.Int16 THEN size := 2
  1159. ELSIF type = PCT.Int32 THEN size := 4
  1160. ELSIF type = PCT.Float32 THEN size := 4
  1161. ELSIF type = PCT.Float64 THEN size := 8
  1162. END;
  1163. IF IsConst(array.array) THEN
  1164. NEW( bytes, size * pos ); pos := 0;
  1165. FillConst( array.array );
  1166. x := PCB.NewArrayValue( scanner.errpos, bytes^, len, dim + 1, type );
  1167. ELSE
  1168. array.SetType(PCT.MakeArrayType(len,dim+1,type,size));
  1169. x := array;
  1170. END;
  1171. END;
  1172. ASSERT(x#NIL);
  1173. END MathArray;
  1174. (** << fof *)
  1175. PROCEDURE Factor(VAR x: PCB.Expression);
  1176. VAR el: PCB.ExprList; d, dh: PCB.Designator; o: PCT.Symbol; h: PCT.Variable; hiddenVarName : StringPool.Index;
  1177. rtype: PCT.Struct; pos: LONGINT; mod: PCT.Symbol; ap: PCB.AnyProc; res : WORD;
  1178. m: PCT.Proc;
  1179. pars: ARRAY 1 OF PCB.Expression; (* ug *)
  1180. (** fof >> *)
  1181. c: PCB.ConstDesignator; y: PCB.Expression; wasNot: BOOLEAN;
  1182. (** << fof *)
  1183. BEGIN
  1184. pos := scanner.errpos;
  1185. wasNot := FALSE; (* fof *)
  1186. IF sym = number THEN
  1187. CASE scanner.numtyp OF
  1188. | PCS.char: x := PCB.NewIntValue(scanner.errpos, scanner.intval, PCT.GetCharType(scanner.intval))
  1189. | PCS.integer: x := PCB.NewIntValue(scanner.errpos, scanner.intval, PCT.GetIntType(scanner.intval))
  1190. | PCS.longinteger: x := PCB.NewLongIntValue(scanner.errpos, scanner.longintval)
  1191. | PCS.real: x := PCB.NewFloatValue(scanner.errpos, scanner.realval, PCT.Float32)
  1192. | PCS.longreal: x := PCB.NewFloatValue(scanner.errpos, scanner.lrlval, PCT.Float64)
  1193. END;
  1194. scanner.Get(sym)
  1195. ELSIF sym = string THEN
  1196. x := PCB.NewStrValue(scanner.errpos, scanner.str); scanner.Get(sym)
  1197. ELSIF sym = nil THEN
  1198. x:=PCB.NewNILValue(scanner.errpos); scanner.Get(sym)
  1199. ELSIF sym = true THEN
  1200. x := PCB.NewBoolValue(scanner.errpos, TRUE); scanner.Get(sym)
  1201. ELSIF sym = false THEN
  1202. x := PCB.NewBoolValue(scanner.errpos, FALSE); scanner.Get(sym)
  1203. ELSIF sym = lbrace THEN (*Set*)
  1204. Set(x)
  1205. (** fof >> *)
  1206. ELSIF sym = lbrak THEN (* constant array *)
  1207. MathArray( x );
  1208. IF x IS PCB.ArrayExpression THEN
  1209. scope.CreateHiddenVarName(hiddenVarName);
  1210. scope.CreateVar(hiddenVarName, PCT.Hidden, {}, x.type, pos, o, res);
  1211. h := scope.FindHiddenVar(pos, o);
  1212. dh := PCB.MakeNode(scanner.errpos, codescope, h);
  1213. x(PCB.ArrayExpression).d := dh
  1214. END;
  1215. (** << fof *)
  1216. ELSIF sym = lparen THEN (*Subexpression*)
  1217. scanner.Get(sym); Expr(x) ; Check(rparen)
  1218. ELSIF (sym=not) THEN
  1219. wasNot := TRUE; (* fof *)
  1220. scanner.Get(sym);
  1221. IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~(PCM.NoOpOverloading IN PCM.parserOptions) THEN
  1222. scanner.Get(sym);
  1223. GetModule(mod);
  1224. scanner.Get(sym);
  1225. Check(rbrak);
  1226. END;
  1227. Factor(y (* fof *));
  1228. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic((* fof *) y.type) THEN
  1229. x := PCB.NewMOp(scanner.errpos, scope, not, y (* fof *))
  1230. ELSE
  1231. pars[0] := y (* fof *);
  1232. x := CallOperator(not, mod, pars, pos);
  1233. END;
  1234. ELSIF (sym = ident) THEN
  1235. Qualident(o);
  1236. IF o IS PCT.Value THEN
  1237. (** fof >> *)
  1238. IF (o( PCT.Value ).const # NIL ) &
  1239. (o( PCT.Value ).const.type IS PCT.EnhArray) THEN (* may be used as designator *)
  1240. d := PCB.MakeNode( scanner.errpos, codescope, o ); Designator( d ); x := d;
  1241. ELSE
  1242. (** << fof *)
  1243. x := PCB.NewValue(scanner.errpos, o)
  1244. END; (** fof *)
  1245. ELSE
  1246. IF (sym = lparen) & (o IS PCT.Type) THEN
  1247. scanner.Get(sym);
  1248. Expr(x); Check(rparen);
  1249. x := PCB.NewConversion(scanner.errpos,x,o.type);
  1250. ELSE
  1251. d := PCB.MakeNode(scanner.errpos, codescope, o); Designator(d);
  1252. IF PCB.IsProcReturningPointer(d, rtype) & inspect THEN
  1253. scope.CreateHiddenVarName(hiddenVarName);
  1254. scope.CreateVar(hiddenVarName, PCT.Hidden, {}, rtype, pos, o, res);
  1255. END;
  1256. IF (sym = lparen) THEN
  1257. el := PCB.NewExprList(scanner.errpos, d);
  1258. scanner.Get(sym);
  1259. IF sym # rparen THEN ExprList(el) END;
  1260. IF PCB.IsProcReturningPointer(d, rtype) THEN
  1261. h := scope.FindHiddenVar(pos, o);
  1262. ASSERT(h # NIL);
  1263. dh := PCB.MakeNode(scanner.errpos, codescope, h);
  1264. el.Append(dh)
  1265. END;
  1266. Check(rparen);
  1267. IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
  1268. x := PCB.NewFuncCall(scanner.errpos, d, el, scopelevel);
  1269. ELSIF (sym = lbrak) THEN
  1270. (* Find PCT.ReadIndexer method in scope of the type. *)
  1271. m := PCT.FindIndexer(d.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.ReadIndexer));
  1272. IF m # NIL THEN
  1273. NEW(ap, scanner.errpos, scope, m, d (* SELF *));
  1274. d := ap;
  1275. el:=PCB.NewExprList(scanner.errpos, d);
  1276. scanner.Get(sym);
  1277. IF sym # rbrak THEN ExprList(el) END;
  1278. Check(rbrak);
  1279. x := PCB.NewFuncCall(scanner.errpos, d, el, scopelevel);
  1280. END
  1281. ELSE x := d
  1282. END
  1283. END
  1284. END;
  1285. ELSE
  1286. Error(13, scanner.errpos); x:=PCB.InvalidExpr; scanner.Get(sym)
  1287. END;
  1288. (** fof >> *)
  1289. (* suffix *)
  1290. IF sym = PCS.transpose THEN
  1291. IF wasNot THEN (* transpose operator has higher precedence than not, reevaluate expression: *)
  1292. x := PCB.NewMOp( scanner.errpos, scope, transpose, y ); x := PCB.NewMOp( scanner.errpos, scope, not, x );
  1293. ELSE x := PCB.NewMOp( scanner.errpos, scope, transpose, x );
  1294. END;
  1295. scanner.Get( sym );
  1296. END;
  1297. (** << fof *)
  1298. END Factor;
  1299. PROCEDURE Term(VAR x: PCB.Expression);
  1300. VAR
  1301. y : PCB.Expression; op: PCS.Token; pos: LONGINT;
  1302. mod: PCT.Symbol;
  1303. pars: ARRAY 2 OF PCB.Expression; (* ug *)
  1304. BEGIN
  1305. Factor(x);
  1306. WHILE (sym >= times) & (sym <= and) OR (sym >= backslash) & (sym <= egeq) (* fof *) DO
  1307. pos:=scanner.errpos; op := sym; scanner.Get(sym);
  1308. mod := NIL;
  1309. IF AllowOverloadedModule & (* fof *) (sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
  1310. scanner.Get(sym);
  1311. GetModule(mod);
  1312. scanner.Get(sym);
  1313. Check(rbrak);
  1314. END;
  1315. Factor(y);
  1316. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
  1317. x := PCB.NewDOp(pos, op, x, y)
  1318. ELSE
  1319. pars[0] := x; pars[1] := y; (* ug *)
  1320. x := CallOperator(op, mod, pars, pos);
  1321. END
  1322. END
  1323. END Term;
  1324. PROCEDURE CallAssignmentOp(op: PCS.Token; mod: PCT.Symbol; p1: PCB.Designator; p2: PCB.Expression; pos: LONGINT; suppress: BOOLEAN);
  1325. VAR
  1326. pars: ARRAY 2 OF PCT.Struct;
  1327. name: PCS.Name; o: PCT.Symbol; d: PCB.Designator; el: PCB.ExprList;
  1328. parents: BOOLEAN;
  1329. searchScope: PCT.Scope;
  1330. BEGIN
  1331. PCS.GetOpName(op, name);
  1332. IF (mod # NIL) & (mod IS PCT.Module) THEN
  1333. searchScope := mod(PCT.Module).scope;
  1334. parents := FALSE;
  1335. ELSE
  1336. searchScope := scope;
  1337. parents := TRUE;
  1338. END;
  1339. (* o := GetOperator(name, pars^, pos); *)
  1340. pars[0] := p1.type; pars[1] := p2.type;
  1341. o := PCT.FindOperator(scope, searchScope, parents, name, pars, LEN(pars), pos);
  1342. IF o = NIL THEN
  1343. (* Error(137, pos); (* operator not defined *) *)
  1344. PCB.Assign(code, suppress, p1, p2, FALSE (*fof*));
  1345. ELSE
  1346. d := PCB.MakeNode(pos, codescope, o);
  1347. Designator(d);
  1348. el := PCB.NewExprList(pos, d);
  1349. el.Append(p1);
  1350. el.Append(p2);
  1351. (* RETURN PCB.NewFuncCall(pos, d, el, scopelevel); *)
  1352. PCB.CallProc(code, suppress, d, el,scopelevel);
  1353. END;
  1354. END CallAssignmentOp;
  1355. PROCEDURE CallOperator(op: PCS.Token; mod: PCT.Symbol; pars: ARRAY OF PCB.Expression; pos: LONGINT): PCB.Expression;
  1356. VAR
  1357. name: PCS.Name; o: PCT.Symbol; d: PCB.Designator; el: PCB.ExprList;
  1358. parents: BOOLEAN;
  1359. searchScope: PCT.Scope;
  1360. args: ARRAY 2 OF PCT.Struct;
  1361. dh: PCB.Designator; h: PCT.Variable; hiddenVarName : StringPool.Index;
  1362. rtype: PCT.Struct; res: WORD; i : LONGINT;
  1363. BEGIN
  1364. PCS.GetOpName(op, name);
  1365. IF (mod # NIL) & (mod IS PCT.Module) THEN
  1366. searchScope := mod(PCT.Module).scope;
  1367. parents := FALSE;
  1368. ELSE
  1369. searchScope := scope;
  1370. parents := TRUE;
  1371. END;
  1372. FOR i := 0 TO LEN(pars)-1 DO
  1373. args[i] := pars[i].type
  1374. END;
  1375. o := PCT.FindOperator(scope, searchScope, parents, name, args, LEN(pars), pos);
  1376. IF o = NIL THEN
  1377. (* Error(137, pos); (* operator not defined *) *)
  1378. IF LEN(pars) = 1 THEN
  1379. RETURN PCB.NewMOp(pos, scope, op, pars[0])
  1380. ELSE
  1381. RETURN PCB.NewDOp(pos, op, pars[0], pars[1])
  1382. END
  1383. END;
  1384. d := PCB.MakeNode(pos, codescope, o); Designator(d);
  1385. IF PCB.IsProcReturningPointer(d, rtype) & inspect THEN
  1386. scope.CreateHiddenVarName(hiddenVarName);
  1387. scope.CreateVar(hiddenVarName, PCT.Hidden, {}, rtype, pos, o, res);
  1388. END;
  1389. el := PCB.NewExprList(pos, d);
  1390. FOR i := 0 TO LEN(pars)-1 DO
  1391. el.Append(pars[i])
  1392. END;
  1393. IF PCB.IsProcReturningPointer(d, rtype) THEN
  1394. h := scope.FindHiddenVar(pos, o);
  1395. ASSERT(h # NIL);
  1396. dh := PCB.MakeNode(pos, codescope, h);
  1397. el.Append(dh)
  1398. END;
  1399. IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
  1400. RETURN PCB.NewFuncCall(pos, d, el, scopelevel);
  1401. END CallOperator;
  1402. PROCEDURE SimpleExpr(VAR x: PCB.Expression);
  1403. VAR y: PCB.Expression; op: PCS.Token; pos: LONGINT;
  1404. mod: PCT.Symbol;
  1405. pars1: ARRAY 1 OF PCB.Expression; pars2: ARRAY 2 OF PCB.Expression; (* ug *)
  1406. BEGIN
  1407. IF (sym = plus) OR (sym = minus) THEN
  1408. pos := scanner.errpos;
  1409. op := sym; scanner.Get(sym);
  1410. IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~(PCM.NoOpOverloading IN PCM.parserOptions) THEN
  1411. scanner.Get(sym);
  1412. GetModule(mod);
  1413. scanner.Get(sym);
  1414. Check(rbrak);
  1415. END;
  1416. Term(x);
  1417. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type) THEN
  1418. x := PCB.NewMOp(pos, scope, op, x)
  1419. ELSE
  1420. pars1[0] := x;
  1421. x := CallOperator(op, mod, pars1, pos);
  1422. END
  1423. ELSE
  1424. Term(x)
  1425. END;
  1426. WHILE (sym >= plus) & (sym <= or) DO
  1427. pos:=scanner.errpos;
  1428. op := sym; scanner.Get(sym);
  1429. mod := NIL;
  1430. IF AllowOverloadedModule & (* fof *) (sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
  1431. scanner.Get(sym);
  1432. GetModule(mod);
  1433. scanner.Get(sym);
  1434. Check(rbrak);
  1435. END;
  1436. Term(y);
  1437. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
  1438. x := PCB.NewDOp(pos, op, x, y)
  1439. ELSE
  1440. pars2[0] := x; pars2[1] := y; (* ug *)
  1441. x := CallOperator(op, mod, pars2, pos);
  1442. END
  1443. END
  1444. END SimpleExpr;
  1445. PROCEDURE Expr(VAR x: PCB.Expression);
  1446. VAR y: PCB.Expression; op: PCS.Token; pos: LONGINT;
  1447. mod: PCT.Symbol;
  1448. pars : ARRAY 2 OF PCB.Expression; (* ug *)
  1449. BEGIN
  1450. SimpleExpr(x);
  1451. IF (sym >= eql) & (sym <= is) THEN
  1452. pos:=scanner.errpos;
  1453. op := sym; scanner.Get(sym);
  1454. IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
  1455. scanner.Get(sym);
  1456. GetModule(mod);
  1457. scanner.Get(sym);
  1458. Check(rbrak);
  1459. END;
  1460. SimpleExpr(y);
  1461. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
  1462. x := PCB.NewDOp(pos, op, x, y)
  1463. ELSE
  1464. pars[0] := x; pars[1] := y; (* ug *)
  1465. x := CallOperator(op, mod, pars, pos);
  1466. END
  1467. END
  1468. END Expr;
  1469. PROCEDURE ConstExpr(VAR x: PCB.Const);
  1470. VAR pos: LONGINT; y: PCB.Expression;
  1471. BEGIN
  1472. pos := scanner.errpos;
  1473. Expr(y);
  1474. x := PCB.ConstExpression(pos, y)
  1475. END ConstExpr;
  1476. PROCEDURE Case(body, suppress: BOOLEAN; VAR awaitCount: LONGINT; VAR caseinfo: PCB.CaseInfo);
  1477. VAR x, y: PCB.Const; firstline: BOOLEAN;
  1478. BEGIN
  1479. firstline := TRUE;
  1480. LOOP
  1481. ConstExpr(x); y := x;
  1482. IF sym = upto THEN
  1483. scanner.Get(sym); ConstExpr(y);
  1484. END;
  1485. PCB.CaseLine(code, suppress, caseinfo, x, y, firstline);
  1486. firstline := FALSE;
  1487. IF sym # comma THEN EXIT END;
  1488. scanner.Get(sym)
  1489. END;
  1490. Check(colon);
  1491. StatementSeq(body, suppress, awaitCount)
  1492. END Case;
  1493. PROCEDURE If(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
  1494. VAR cond: PCB.Expression; info: PCB.LoopInfo; ifsuppress, elsifclause: BOOLEAN;
  1495. BEGIN
  1496. (* if/elsif already checked *)
  1497. elsifclause := FALSE;
  1498. LOOP
  1499. Expr(cond); Check(then);
  1500. ifsuppress := PCB.If(code, suppress, info, cond, elsifclause);
  1501. StatementSeq(body, suppress OR ifsuppress, awaitCount);
  1502. IF sym # elsif THEN EXIT END;
  1503. elsifclause := TRUE;
  1504. scanner.Get(sym);
  1505. END;
  1506. IF sym = else THEN
  1507. scanner.Get(sym);
  1508. ifsuppress := PCB.Else(code, suppress, info);
  1509. StatementSeq(body, suppress OR ifsuppress, awaitCount)
  1510. END;
  1511. PCB.EndIf(code, suppress, info);
  1512. Check(end)
  1513. END If;
  1514. PROCEDURE BlockModifier(allowBody, suppress: BOOLEAN; VAR locked: BOOLEAN);
  1515. VAR x: PCB.Const; c: LONGINT; res: WORD;
  1516. BEGIN
  1517. IF sym = lbrace THEN
  1518. locked := FALSE;
  1519. IF ~suppress THEN
  1520. scanner.Get(sym);
  1521. LOOP
  1522. IF sym = ident THEN
  1523. IF scanner.name = exclusive THEN
  1524. Machine.AtomicInc(NExclusive);
  1525. IF allowBody THEN Machine.AtomicInc(NExclusiveMain) END;
  1526. PCT.SetMode(scope, PCT.exclusive, res);
  1527. scanner.Get(sym);
  1528. locked := TRUE
  1529. ELSIF allowBody & (scanner.name = active) THEN
  1530. Machine.AtomicInc(NActive);
  1531. PCT.SetMode(scope, PCT.active, res);
  1532. scanner.Get(sym)
  1533. ELSIF allowBody & (scanner.name = realtime) THEN
  1534. PCT.SetProcFlag(scope, PCT.RealtimeProc, res);
  1535. scanner.Get(sym)
  1536. ELSIF allowBody & (scanner.name = safe) THEN
  1537. PCT.SetMode(scope, PCT.safe, res);
  1538. scanner.Get(sym)
  1539. ELSIF allowBody & (scanner.name = priority) THEN
  1540. scanner.Get(sym);
  1541. IF sym = lparen THEN
  1542. scanner.Get(sym); ConstExpr(x); Check(rparen);
  1543. IF ~PCT.IsCardinalType(x.type) THEN
  1544. c:=0; Error(51, scanner.errpos)
  1545. ELSIF x.type # PCT.Int8 THEN
  1546. c := 0; Error(220, scanner.errpos)
  1547. ELSE
  1548. c := x.con.int
  1549. END
  1550. ELSE
  1551. c:=0
  1552. END;
  1553. IF isRecord THEN
  1554. scope.parent(PCT.RecScope).owner.prio := c;
  1555. ELSE
  1556. PCM.Error(200, scanner.errpos, "priority only for records")
  1557. END
  1558. ELSE Error(0, scanner.errpos); scanner.Get(sym) (*skip the ident, probably a typo*)
  1559. END;
  1560. IF res # PCT.Ok THEN Error(res, scanner.errpos); res := 0 END
  1561. ELSE
  1562. Check (ident);
  1563. END;
  1564. IF sym # comma THEN EXIT END;
  1565. scanner.Get(sym)
  1566. END;
  1567. IF PCT.IsRealtimeScope(scope) THEN
  1568. IF isRecord THEN
  1569. scope.parent(PCT.RecScope).owner.prio := Objects.Realtime (* ug: realtime scope enforces priority realtime of active object *)
  1570. END
  1571. END;
  1572. IF locked THEN
  1573. IF PCT.IsRealtimeScope(scope) THEN Error(162, scanner.errpos) END;
  1574. END;
  1575. ELSE
  1576. REPEAT scanner.Get(sym) UNTIL (sym = rbrace) OR (sym = eof);
  1577. END;
  1578. Check(rbrace)
  1579. END
  1580. END BlockModifier;
  1581. PROCEDURE StatementBlock(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
  1582. VAR lock: BOOLEAN;
  1583. BEGIN
  1584. (*sym = begin*)
  1585. scanner.Get(sym);
  1586. BlockModifier(body, suppress, lock);
  1587. IF ~inspect & body & notifyScope THEN PCT.ChangeState(scope.parent, PCT.modeavailable, scanner.errpos) END; (*NEW waits for it*)
  1588. IF ~suppress & lock THEN
  1589. IF locked THEN Error(246, scanner.errpos) END;
  1590. locked := TRUE;
  1591. unlockOnExit := looplevel > 0;
  1592. PCB.Lock(code, scope, scanner.errpos, TRUE);
  1593. StatementSeq(body, suppress, awaitCount);
  1594. PCB.Lock(code, scope, scanner.errpos, FALSE);
  1595. unlockOnExit := FALSE;
  1596. locked := FALSE
  1597. ELSE
  1598. StatementSeq(body, suppress, awaitCount)
  1599. END;
  1600. Check(end)
  1601. END StatementBlock;
  1602. PROCEDURE CallNewOnObject (code: PCC.Code; suppress: BOOLEAN; proc: PCB.Designator; params: PCB.ExprList; curlevel: SHORTINT);
  1603. VAR varName: StringPool.Index; symbol: PCT.Variable; res: WORD; parameters: PCB.ExprList; item: PCB.Expression; tempVar: PCB.Designator;
  1604. BEGIN
  1605. symbol := codescope.FindHiddenVar (-PCB.newfn, codescope);
  1606. ASSERT (suppress OR (symbol # NIL));
  1607. IF symbol = NIL THEN
  1608. codescope.CreateHiddenVarName(varName);
  1609. codescope.CreateVar(varName, PCT.Hidden, {}, PCT.Ptr, -PCB.newfn, codescope, res);
  1610. symbol := codescope.lastHiddenVar;
  1611. END;
  1612. symbol.type := params.first.type;
  1613. parameters := PCB.NewExprList (params.pos, proc);
  1614. tempVar := PCB.MakeNode (params.first.pos, codescope, symbol);
  1615. parameters.Append (tempVar); item := params.first.link; WHILE item # NIL DO parameters.Append (item); item := item.link END;
  1616. PCB.CallProc(code, suppress, proc, parameters, scopelevel);
  1617. PCB.Assign (code, suppress, params.first(PCB.Designator), tempVar, FALSE);
  1618. END CallNewOnObject;
  1619. PROCEDURE StatementSeq(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
  1620. VAR d, d1: PCB.Designator; x, y: PCB.Expression; c: PCB.Const; o, o1: PCT.Symbol;
  1621. param: PCB.ExprList; pos, stack: LONGINT; res: WORD;
  1622. oldscope: PCT.Scope; s: PCT.WithScope; procscope: PCT.ProcScope;
  1623. awaitparser: AwaitParser;
  1624. loopinfo: PCB.LoopInfo; caseinfo: PCB.CaseInfo;
  1625. first, ifsuppress, oldUnlockOnExit: BOOLEAN;
  1626. oldforcount, i: LONGINT;
  1627. mod: PCT.Symbol;
  1628. name: StringPool.Index;
  1629. proc: PCT.Proc; procScope: PCT.ProcScope;
  1630. module: PCT.Module; modScope: PCT.ModScope;
  1631. returnPos, temp: POINTER TO ARRAY OF LONGINT;
  1632. ap: PCB.AnyProc; m: PCT.Method; indexer: BOOLEAN;
  1633. sproc: PCB.SProc;
  1634. ae: PCB.ArrayExpression;
  1635. be: PCB.BuiltInEl;
  1636. arrayType: PCT.EnhArray;
  1637. aindex: POINTER TO ARRAY OF LONGINT;
  1638. PROCEDURE AssignIndices(ae: PCB.ArrayExpression; dim: LONGINT);
  1639. VAR a: PCB.ArrayQ; index: PCB.EnhIndex; i,j: LONGINT;
  1640. BEGIN
  1641. a := ae.array;
  1642. i := 0;
  1643. WHILE a # NIL DO
  1644. aindex[dim] := i;
  1645. IF a.e IS PCB.ArrayExpression THEN
  1646. AssignIndices(a.e(PCB.ArrayExpression),dim+1);
  1647. ELSE
  1648. index := PCB.NewEnhIndex(d.pos,d);
  1649. FOR j := 0 TO LEN(aindex)-1 DO
  1650. index.AppendIndex(a.e.pos,PCB.NewIntValue(0,aindex[j],PCT.Int32));
  1651. END;
  1652. PCB.Assign(code,suppress, index, a.e, FALSE);
  1653. END;
  1654. INC(i); a := a.next;
  1655. END;
  1656. END AssignIndices;
  1657. BEGIN
  1658. LOOP
  1659. IF (sym < ident) THEN
  1660. Error(ident, scanner.errpos);
  1661. REPEAT scanner.Get(sym) UNTIL sym >= ident
  1662. ELSIF (sym = semicolon) THEN
  1663. PCM.Warning(315, scanner.errpos, "");
  1664. END;
  1665. pos:=scanner.errpos;
  1666. IF ~suppress THEN PCC.NewInstr(code, pos) END;
  1667. CASE sym OF
  1668. | ident:
  1669. Qualident(o);
  1670. d := PCB.MakeNode(scanner.errpos, codescope, o); Designator(d);
  1671. (* If the leftside of the assignment uses an indexer *)
  1672. indexer := FALSE;
  1673. IF sym = lbrak THEN
  1674. m := PCT.FindIndexer(d.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.AssignIndexer));
  1675. IF m # NIL THEN
  1676. NEW(ap, scanner.errpos, scope, m, d (* SELF *));
  1677. d := ap;
  1678. param:=PCB.NewExprList(scanner.errpos, d);
  1679. scanner.Get(sym);
  1680. IF sym # rbrak THEN ExprList(param) END;
  1681. Check(rbrak);
  1682. indexer := TRUE;
  1683. END
  1684. END;
  1685. IF sym = becomes THEN
  1686. scanner.Get(sym);
  1687. mod := NIL;
  1688. IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(d.type)) THEN
  1689. scanner.Get(sym);
  1690. GetModule(mod);
  1691. scanner.Get(sym);
  1692. Check(rbrak);
  1693. END;
  1694. Expr(y);
  1695. IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(d.type) & PCT.IsBasic(y.type)) THEN
  1696. PCB.Assign(code, suppress, d, y, FALSE (* fof *));
  1697. ELSIF indexer THEN
  1698. param.Append(y);
  1699. IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
  1700. PCB.CallProc(code, suppress, d, param, scopelevel)
  1701. ELSE
  1702. CallAssignmentOp(becomes, mod, d, y, scanner.errpos, suppress)
  1703. END
  1704. ELSIF ~indexer THEN
  1705. param:=PCB.NewExprList(scanner.errpos, d);
  1706. IF sym = lparen THEN
  1707. scanner.Get(sym);
  1708. IF sym # rparen THEN ExprList(param) END;
  1709. Check(rparen)
  1710. END;
  1711. IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
  1712. IF (d IS PCB.SProc) & (d(PCB.SProc).nr = PCB.newfn) & (param.first # NIL) & (param.first.type IS PCT.Pointer) & (param.first.type(PCT.Pointer).baseR # NIL) THEN
  1713. CallNewOnObject (code, suppress, d, param, scopelevel);
  1714. ELSE
  1715. PCB.CallProc(code, suppress, d, param, scopelevel);
  1716. END;
  1717. ELSE
  1718. HALT(MAX(INTEGER));
  1719. END (* if -> proccall *);
  1720. indexer := FALSE;
  1721. | if:
  1722. scanner.Get(sym); If(FALSE, suppress, awaitCount)
  1723. | with:
  1724. first := TRUE;
  1725. REPEAT
  1726. IF (sym = bar) & first THEN
  1727. PCM.Error(end, scanner.errpos, "Oberon-2 WITH not supported");
  1728. first := FALSE
  1729. END;
  1730. scanner.Get(sym); (*skip with or bar *)
  1731. IF sym = ident THEN
  1732. Qualident(o);
  1733. IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
  1734. d:=PCB.MakeNode(scanner.errpos, codescope, o);
  1735. ELSE
  1736. Error(ident, scanner.errpos); d:=PCB.InvalidDesig
  1737. END;
  1738. Check(colon); Qualident(o1); d1:=PCB.MakeNode(scanner.errpos, codescope, o1);
  1739. NEW(s); PCT.InitScope(s, scope, {}, FALSE); PCT.SetOwner(s);
  1740. IF (o # NIL) & (o IS PCT.Variable) THEN
  1741. s.withSym := o;
  1742. s.withGuard := o1;
  1743. ELSE
  1744. Error(130, pos);
  1745. END;
  1746. oldscope := scope; scope := s;
  1747. PCT.ChangeState(s, PCT.complete, scanner.errpos);
  1748. Check(do);
  1749. ifsuppress := PCB.If(code, suppress, loopinfo, PCB.NewMOp(scanner.errpos, NIL, not, PCB.NewDOp(scanner.errpos, is, d, d1)), FALSE);
  1750. PCB.Trap(code, suppress OR ifsuppress, PCM.WithTrap);
  1751. ifsuppress := PCB.Else(code, suppress, loopinfo);
  1752. StatementSeq(FALSE, suppress OR ifsuppress, awaitCount);
  1753. PCB.EndIf(code, suppress, loopinfo);
  1754. scope := oldscope;
  1755. UNTIL sym # bar;
  1756. IF sym = else THEN
  1757. IF first THEN PCM.Error(end, scanner.errpos, "Oberon-2 WITH not supported") END;
  1758. scanner.Get(sym);
  1759. StatementSeq(FALSE, TRUE, awaitCount)
  1760. END;
  1761. Check(end)
  1762. | case:
  1763. scanner.Get(sym); Expr(x); Check(of);
  1764. PCB.Case(code, suppress, caseinfo, x);
  1765. LOOP
  1766. IF sym < bar THEN Case(FALSE, suppress, awaitCount, caseinfo) END;
  1767. IF sym = bar THEN scanner.Get(sym) ELSE EXIT END
  1768. END;
  1769. PCB.CaseElse(code, suppress, caseinfo);
  1770. IF sym = else THEN
  1771. scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount)
  1772. ELSE
  1773. PCB.Trap(code, suppress, PCM.CaseTrap)
  1774. END;
  1775. PCB.CaseEnd(code, suppress, caseinfo);
  1776. Check(end);
  1777. | while:
  1778. scanner.Get(sym); Expr(x); pos := scanner.errpos; Check(do);
  1779. PCB.While(code, suppress, loopinfo, x);
  1780. StatementSeq(FALSE, suppress, awaitCount); Check(end);
  1781. PCB.EndLoop(code, suppress, loopinfo);
  1782. | repeat:
  1783. PCB.BeginLoop(code, suppress, loopinfo);
  1784. scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount); Check(until); Expr(x);
  1785. PCB.Repeat(code, suppress, loopinfo, x);
  1786. | for:
  1787. scanner.Get(sym);
  1788. IF sym = ident THEN
  1789. o:=PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE);
  1790. IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
  1791. d:=PCB.MakeNode(scanner.errpos, codescope, o); scanner.Get(sym)
  1792. ELSE
  1793. Error(ident, scanner.errpos); d:=PCB.InvalidDesig
  1794. END;
  1795. Check(becomes); Expr(x);
  1796. Check(to); Expr(y);
  1797. IF sym = by THEN scanner.Get(sym); ConstExpr(c) ELSE c:=PCB.NewIntValue(scanner.errpos, 1, PCT.Int8)(*PCB.One*) END;
  1798. PCB.BeginFor(code, suppress, pos, d, x, y, c, loopinfo);
  1799. stack := PCC.GetStaticSize(d.type);
  1800. INC(stack, (-stack) MOD 4); (*align*)
  1801. stack := stack DIV 4;
  1802. INC(forexitcount, stack); INC(forretcount, stack);
  1803. Check(do); StatementSeq(FALSE, suppress, awaitCount); Check(end);
  1804. DEC(forexitcount, stack); DEC(forretcount, stack);
  1805. PCB.EndFor(code, suppress, pos, d, c, loopinfo)
  1806. | loop:
  1807. oldforcount := forexitcount; forexitcount := 0;
  1808. loopinfo := curloop; INC(looplevel);
  1809. oldUnlockOnExit := unlockOnExit; unlockOnExit := FALSE;
  1810. PCB.BeginLoop(code, suppress, curloop);
  1811. scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount); Check(end);
  1812. PCB.EndLoop(code, suppress, curloop);
  1813. unlockOnExit := oldUnlockOnExit;
  1814. curloop := loopinfo; DEC(looplevel);
  1815. forexitcount := oldforcount
  1816. | exit:
  1817. pos:=scanner.errpos; scanner.Get(sym);
  1818. IF looplevel = 0 THEN
  1819. Error(exit, scanner.errpos)
  1820. ELSE
  1821. IF unlockOnExit THEN
  1822. PCB.Lock(code, scope, scanner.errpos, FALSE);
  1823. END;
  1824. PCB.Exit(code, suppress, curloop, forexitcount);
  1825. suppress := TRUE
  1826. END
  1827. | return:
  1828. IF returnPos = NIL THEN (* retcount = 0 *)
  1829. NEW(returnPos,128);
  1830. returnPos[0] := scanner.errpos;
  1831. ELSE
  1832. ASSERT(retcount # 0);
  1833. IF retcount >= LEN(returnPos) THEN
  1834. NEW(temp, LEN(returnPos) * 2);
  1835. FOR i := 0 TO LEN(returnPos) - 1 DO
  1836. temp[i] := returnPos[i];
  1837. END;
  1838. returnPos := temp
  1839. END;
  1840. returnPos[retcount] := scanner.errpos
  1841. END;
  1842. scanner.Get(sym);
  1843. IF sym < semicolon THEN Expr(x); ELSE x := NIL END;
  1844. PCB.Return(code, suppress, codescope, pos, x, locked, forretcount); (*use the declaration scope!*)
  1845. INC(retcount); suppress := TRUE;
  1846. | passivate:
  1847. IF (~locked) & (~suppress) THEN
  1848. PCM.Warning(314, scanner.errpos, "");
  1849. END;
  1850. scanner.Get(sym);
  1851. Check(lparen);
  1852. scope.CreateAwaitProcName(name, awaitCount); INC(awaitCount);
  1853. IF inspect THEN
  1854. NEW(procscope); PCT.InitScope(procscope, scope, {}, FALSE);
  1855. PCT.SetOwner(procscope);
  1856. scope.CreateProc(name, PCT.Internal, {}, procscope, PCT.Bool, pos, res);
  1857. NEW(awaitparser, sync, procscope, scanner, sym);
  1858. END;
  1859. Expr(x); (* ug: instead of not existing SkipExpr() *)
  1860. PCB.Await(code, suppress, scope, pos, name);
  1861. Check(rparen);
  1862. IF PCT.IsRealtimeScope(scope) THEN Error(162, scanner.errpos) END;
  1863. | begin:
  1864. StatementBlock(FALSE, suppress, awaitCount)
  1865. | finally:
  1866. IF ~suppress THEN
  1867. IF body THEN
  1868. IF fincount > 0 THEN
  1869. Error(162, scanner.errpos);
  1870. ELSE
  1871. IF retcount > 0 THEN
  1872. IF returnPos = NIL THEN
  1873. Error(161, scanner.errpos);
  1874. ELSE
  1875. FOR i:= 0 TO LEN(returnPos) - 1 DO
  1876. Error(161, returnPos[i]);
  1877. END;
  1878. END;
  1879. END;
  1880. END;
  1881. IF (fincount = 0) & (retcount = 0) THEN
  1882. IF (scope # NIL) & (scope IS PCT.ProcScope) THEN
  1883. procScope := scope(PCT.ProcScope);
  1884. proc := procScope.ownerO;
  1885. PCB.Finally(pos, code, proc);
  1886. ELSIF (scope # NIL) & (scope IS PCT.ModScope) THEN
  1887. modScope := scope(PCT.ModScope);
  1888. module := modScope.owner;
  1889. PCB.Finally(pos, code, module);
  1890. END;
  1891. END;
  1892. ELSE
  1893. Error(160, scanner.errpos);
  1894. END;
  1895. INC(fincount)
  1896. END;
  1897. scanner.Get(sym); StatementSeq(body, suppress, awaitCount); (* Parse the rest recursive*)
  1898. ELSE
  1899. (* Error(end) *)
  1900. END;
  1901. IF sym = semicolon THEN scanner.Get(sym)
  1902. ELSIF (sym <= ident) OR (if <= sym) & (sym <= return) THEN Error(semicolon, scanner.errpos)
  1903. ELSIF sym = finally THEN
  1904. ELSE EXIT
  1905. END
  1906. END (*loop*)
  1907. END StatementSeq;
  1908. PROCEDURE Body(suppress : BOOLEAN);
  1909. VAR
  1910. owner: PCT.Proc;
  1911. name: ARRAY 32 OF CHAR;
  1912. export: BOOLEAN;
  1913. awaitCount: LONGINT; (* parsing a body starts with awaitCount = 0 *)
  1914. BEGIN
  1915. IF sym = begin THEN
  1916. IF suppress THEN
  1917. StatementBlock(TRUE, suppress, awaitCount)
  1918. ELSE
  1919. retcount := 0;
  1920. fincount := 0;
  1921. PCT.GetScopeName(scope, name);
  1922. IF inline THEN Error(200, scanner.errpos) END;
  1923. code := PCB.Enter(scope);
  1924. StatementBlock(TRUE, suppress, awaitCount);
  1925. IF (scope # NIL) & (scope IS PCT.ProcScope) THEN
  1926. owner := scope(PCT.ProcScope).ownerO;
  1927. IF (owner.type # PCT.NoType) & (retcount = 0) THEN
  1928. PCM.Warning(313, scanner.errpos, "")
  1929. END
  1930. END;
  1931. PCB.Leave(code, scope, FALSE)
  1932. END
  1933. ELSIF sym = codeToken THEN
  1934. IF ~suppress THEN
  1935. INCL(PCT.System.flags, PCT.used);
  1936. export := (scope IS PCT.ModScope) OR
  1937. ((scope IS PCT.ProcScope) & (PCT.Public * scope(PCT.ProcScope).ownerO.vis # {}));
  1938. IF Assemble = NIL THEN (*no assembler installed*)
  1939. PCM.Error(0, scanner.errpos, "no assembler available")
  1940. ELSIF inline THEN
  1941. scope.code := Assemble(scanner, scope, export, TRUE)
  1942. ELSE
  1943. code := PCB.Enter(scope);
  1944. PCB.Inline(code, Assemble(scanner, scope, export, FALSE));
  1945. PCB.Leave(code, scope, TRUE)
  1946. END
  1947. END;
  1948. scanner.SkipUntilNextEnd (sym);
  1949. Check(end)
  1950. ELSE
  1951. IF ~suppress THEN
  1952. code := PCB.Enter(scope);
  1953. PCB.Leave(code, scope, FALSE);
  1954. END;
  1955. IF (sym = var) OR (sym = const) OR (sym = type) THEN
  1956. PCM.Error(43, scanner.errpos, "data decl after proc decl")
  1957. ELSIF (sym # end) THEN
  1958. Error(43, scanner.errpos)
  1959. ELSE
  1960. scanner.Get(sym)
  1961. END
  1962. END
  1963. END Body;
  1964. PROCEDURE ProcDecl;
  1965. VAR
  1966. procparser: ProcedureParser; procscope: PCT.ProcScope; pos: LONGINT; res: WORD;
  1967. i: IdentDefDesc; flags: SET; rtype: PCT.Struct; forward, suppress : BOOLEAN;
  1968. opName: PCS.Name; pflags: SET; right: SHORTINT; (* ejz *)
  1969. opStr: ARRAY PCS.MaxStrLen OF CHAR;
  1970. BEGIN
  1971. flags := {}; forward := FALSE; pflags := {}; (* ejz *)
  1972. CASE sym OF
  1973. | minus:
  1974. INCL(flags, PCT.Inline); scanner.Get(sym)
  1975. | and:
  1976. INCL(flags, PCT.Constructor); scanner.Get(sym)
  1977. | times:
  1978. (*compatibility with Ceres, ignore*)
  1979. scanner.Get(sym);
  1980. PCM.Error(237, scanner.errpos, "")
  1981. | arrow:
  1982. forward := TRUE; scanner.Get(sym);
  1983. PCM.Warning(238, scanner.errpos, "")
  1984. | lbrak, lbrace: (* ejz *)
  1985. IF sym = lbrak THEN right := rbrak ELSE right := rbrace END;
  1986. REPEAT
  1987. scanner.Get(sym);
  1988. IF (sym = ident) & (scanner.name = winapi) THEN
  1989. (* scope proc is winapi *)
  1990. CheckSysImported(scope.module);
  1991. INCL(pflags, PCT.WinAPIParam);
  1992. ELSIF (sym = ident) & (scanner.name = clang) THEN (* fof for Linux *)
  1993. (* scope proc is c *)
  1994. CheckSysImported(scope.module);
  1995. INCL( pflags, PCT.CParam );
  1996. ELSIF (sym = ident) & (scanner.name = realtime) THEN
  1997. INCL(flags, PCT.RealtimeProc);
  1998. ELSE
  1999. PCM.Error(200, scanner.errpos, "unknown calling convention")
  2000. END;
  2001. scanner.Get(sym);
  2002. UNTIL sym # comma;
  2003. Check(right);
  2004. IF (PCT.RealtimeProc IN flags) & (sym = minus) THEN
  2005. INCL(flags, PCT.Inline); scanner.Get(sym)
  2006. END
  2007. ELSE
  2008. END;
  2009. pos:=scanner.errpos;
  2010. IF PCM.NoOpOverloading IN PCM.parserOptions THEN
  2011. IF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
  2012. suppress := TRUE;
  2013. PCM.Error(200, scanner.errpos, "operators not supported")
  2014. END;
  2015. IdentDef(i, FALSE);
  2016. ELSE
  2017. IF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
  2018. OperatorDef(i, FALSE);
  2019. INCL(flags, PCT.Operator);
  2020. StringPool.GetString(i.name, opStr);
  2021. IF (opStr # "[]") & (scope IS PCT.RecScope) THEN
  2022. PCM.Error(140, scanner.errpos, "");
  2023. ELSIF opStr = "[]" THEN
  2024. INCL(flags, PCT.Indexer)
  2025. END;
  2026. ELSE
  2027. IdentDef(i, FALSE);
  2028. END;
  2029. END;
  2030. NEW(procscope); PCT.InitScope(procscope, scope, {PCT.AutodeclareSelf}, FALSE);
  2031. IF {PCT.CParam, PCT.WinAPIParam} * pflags # {} (* fof for Linux *) THEN (* ejz *)
  2032. IF scope IS PCT.ProcScope THEN (* ejz *)
  2033. PCM.Error(200, scanner.errpos, "invalid WINAPI proc")
  2034. ELSIF PCT.CParam IN pflags THEN (* fof for Linux *)
  2035. procscope.SetCC( PCT.CLangCC )
  2036. ELSE
  2037. procscope.SetCC(PCT.WinAPICC)
  2038. END
  2039. END;
  2040. PCT.SetOwner(procscope);
  2041. FormalPars(procscope, rtype, pflags); (* ejz *)
  2042. IF PCT.Operator IN flags THEN CheckOperator(procscope, i.name, rtype, pos) END;
  2043. IF forward THEN RETURN END; (*don't register this procedure, just ignore it*)
  2044. Check(semicolon);
  2045. scope.CreateProc(i.name, i.vis, flags, procscope, rtype, pos(*fof*), res);
  2046. IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END;
  2047. NEW(procparser, sync, procscope, PCT.Inline IN flags, scanner, sym); (*parse the rest of scope*)
  2048. SkipScope; (* skip the record scope, the other parser is parsing it *)
  2049. IF suppress THEN
  2050. scanner.Get(sym)
  2051. ELSIF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
  2052. opName := StringPool.GetIndex1(scanner.str);
  2053. IF (opName # i.name) & ~(PCT.Indexer IN flags) THEN
  2054. PCM.ErrorN(4, scanner.errpos, i.name)
  2055. ELSIF (PCT.Indexer IN flags) & (scanner.str # "[]") THEN
  2056. PCM.ErrorN(4, scanner.errpos, i.name)
  2057. END;
  2058. scanner.Get(sym);
  2059. ELSIF sym = ident THEN
  2060. IF scanner.name # i.name THEN PCM.ErrorN(4, scanner.errpos, i.name) END; (*[S8;1;2]*)
  2061. scanner.Get(sym)
  2062. ELSE PCM.ErrorN(ident, scanner.errpos, i.name)
  2063. END
  2064. END ProcDecl;
  2065. PROCEDURE SkipScope;
  2066. VAR cnt: LONGINT;
  2067. BEGIN
  2068. (*skip decl section*)
  2069. WHILE (sym # eof) & (sym # begin) & (sym # end) & (sym # codeToken) DO
  2070. IF (sym = record) THEN
  2071. scanner.Get(sym); SkipScope
  2072. ELSIF (sym = object) THEN
  2073. scanner.Get(sym);
  2074. IF (sym # semicolon) & (sym # rparen) THEN SkipScope END
  2075. ELSIF sym = procedure THEN
  2076. scanner.Get(sym);
  2077. IF sym = lbrace THEN (* allow REALTIME and/or DELEGATE modifier *)
  2078. WHILE sym # rbrace DO scanner.Get(sym) END;
  2079. scanner.Get(sym);
  2080. END;
  2081. IF (sym = and) OR (sym = minus) THEN scanner.Get(sym) END;
  2082. IF (sym = ident) OR (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN SkipScope END;
  2083. ELSE
  2084. scanner.Get(sym)
  2085. END
  2086. END;
  2087. (*skip statseq *)
  2088. IF sym = begin THEN
  2089. scanner.Get(sym); cnt := 1;
  2090. WHILE cnt > 0 DO
  2091. IF (sym = if) OR (sym = case) OR (sym = while) OR (sym = for) OR (sym = loop) OR (sym = with) OR (sym = begin) THEN
  2092. INC(cnt)
  2093. ELSIF sym = end THEN
  2094. DEC(cnt)
  2095. ELSIF sym = eof THEN
  2096. cnt := 0
  2097. END;
  2098. scanner.Get(sym)
  2099. END
  2100. ELSIF sym = codeToken THEN
  2101. scanner.SkipUntilNextEnd (sym);
  2102. scanner.Get(sym)
  2103. ELSIF sym = end THEN
  2104. scanner.Get(sym);
  2105. END;
  2106. END SkipScope;
  2107. (** fof >> *)
  2108. PROCEDURE Epilog;
  2109. END Epilog;
  2110. (** << fof *)
  2111. BEGIN {ACTIVE}
  2112. IF die THEN sync.Exit; RETURN END;
  2113. PCT.SetOwner(scope);
  2114. DeclSeq;
  2115. Body(FALSE); (* suppress = FALSE *)
  2116. Epilog; (* fof *)
  2117. PCT.ChangeState(scope, PCT.complete, scanner.errpos);
  2118. sync.Exit
  2119. END Parser;
  2120. (** fof >> *)
  2121. CustomArrayParser = OBJECT (Parser)
  2122. VAR
  2123. bodyscope: PCT.ProcScope; old: PCT.Scope;
  2124. PROCEDURE Body(suppress: BOOLEAN); (*override Parser.Body*)
  2125. BEGIN
  2126. IF sym = begin THEN
  2127. scope := bodyscope; codescope := scope;
  2128. notifyScope := ~suppress;
  2129. Body^(suppress);
  2130. IF inspect THEN (* body was inspected for hidden variables *)
  2131. PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
  2132. ELSE (* normal code generation *)
  2133. PCT.ChangeState(scope, PCT.complete, scanner.errpos)
  2134. END;
  2135. scope := old; codescope := scope
  2136. ELSE
  2137. IF (sym = var) OR (sym = const) OR (sym = type) THEN
  2138. PCM.Error(43, scanner.errpos, "data decl after proc decl")
  2139. ELSIF (sym # end) THEN
  2140. Error(43, scanner.errpos)
  2141. ELSE
  2142. scanner.Get(sym)
  2143. END
  2144. END
  2145. END Body;
  2146. PROCEDURE DeclSeq; (* vars and procs are allowed, no const and types *)
  2147. VAR res: WORD;
  2148. BEGIN
  2149. LOOP
  2150. (* allow ident w/o var, to minimize the misleading err 83 in the rest of the module *)
  2151. IF (sym = var) OR (sym = ident) THEN
  2152. IF sym = var THEN scanner.Get(sym) ELSE PCM.Error(end, scanner.errpos, "or maybe VAR") END;
  2153. WHILE sym = ident DO
  2154. VarDecl;
  2155. IF sym # end THEN
  2156. CheckSemicolons;
  2157. END;
  2158. END
  2159. ELSIF sym = semicolon THEN
  2160. CheckSemicolons; (* advances to next symbol *)
  2161. ELSE EXIT
  2162. END
  2163. END;
  2164. FixForwards;
  2165. PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
  2166. PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
  2167. WHILE sym = procedure DO
  2168. scanner.Get(sym); ProcDecl;
  2169. IF sym # end THEN Check(semicolon) END
  2170. END;
  2171. IF sym = begin THEN
  2172. old := scope;
  2173. NEW(bodyscope); PCT.InitScope(bodyscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(bodyscope);
  2174. scope.CreateProc(PCT.BodyName, PCT.Public, {}, bodyscope, PCT.NoType, scanner.errpos(*fof*), res); ASSERT(res = PCT.Ok);
  2175. PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos); (* ug: must be done explicitly here in order to allow cross method calls of objects *)
  2176. PCT.ChangeState(bodyscope, PCT.procdeclared, scanner.errpos);
  2177. savedsym := sym;
  2178. savedscanner := scanner;
  2179. scanner := PCS.ForkScanner(scanner);
  2180. inspect := TRUE;
  2181. Body(TRUE); (* suppress = TRUE *)
  2182. scanner := savedscanner;
  2183. sym := savedsym;
  2184. inspect := FALSE
  2185. END
  2186. END DeclSeq;
  2187. PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.CustomArrayScope; s: PCS.Scanner; sym: PCS.Token);
  2188. BEGIN
  2189. sync.Enter; SELF.sync := sync;
  2190. isRecord := TRUE;
  2191. scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
  2192. scanner := PCS.ForkScanner(s);
  2193. END InitRec;
  2194. END CustomArrayParser;
  2195. (** << fof *)
  2196. ObjectParser = OBJECT (Parser)
  2197. VAR
  2198. bodyscope: PCT.ProcScope; old: PCT.Scope;
  2199. PROCEDURE Body(suppress: BOOLEAN); (*override Parser.Body*)
  2200. BEGIN
  2201. IF sym = begin THEN
  2202. scope := bodyscope; codescope := scope;
  2203. notifyScope := ~suppress;
  2204. Body^(suppress);
  2205. IF inspect THEN (* body was inspected for hidden variables *)
  2206. PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
  2207. ELSE (* normal code generation *)
  2208. PCT.ChangeState(scope, PCT.complete, scanner.errpos)
  2209. END;
  2210. scope := old; codescope := scope
  2211. ELSE
  2212. IF (sym = var) OR (sym = const) OR (sym = type) THEN
  2213. PCM.Error(43, scanner.errpos, "data decl after proc decl")
  2214. ELSIF (sym # end) THEN
  2215. Error(43, scanner.errpos)
  2216. ELSE
  2217. scanner.Get(sym)
  2218. END
  2219. END
  2220. END Body;
  2221. PROCEDURE DeclSeq; (* vars and procs are allowed, no const and types *)
  2222. VAR res: WORD;
  2223. BEGIN
  2224. LOOP
  2225. (* allow ident w/o var, to minimize the misleading err 83 in the rest of the module *)
  2226. IF (sym = var) OR (sym = ident) THEN
  2227. IF sym = var THEN scanner.Get(sym) ELSE PCM.Error(end, scanner.errpos, "or maybe VAR") END;
  2228. WHILE sym = ident DO
  2229. VarDecl;
  2230. IF sym # end THEN
  2231. CheckSemicolons;
  2232. END;
  2233. END
  2234. ELSIF sym = semicolon THEN
  2235. CheckSemicolons; (* advances to next symbol *)
  2236. ELSE EXIT
  2237. END
  2238. END;
  2239. FixForwards;
  2240. PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
  2241. PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
  2242. WHILE sym = procedure DO
  2243. scanner.Get(sym); ProcDecl;
  2244. IF sym # end THEN Check(semicolon) END
  2245. END;
  2246. IF sym = begin THEN
  2247. old := scope;
  2248. NEW(bodyscope); PCT.InitScope(bodyscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(bodyscope);
  2249. scope.CreateProc(PCT.BodyName, PCT.Public, {}, bodyscope, PCT.NoType, scanner.errpos(*fof*), res); ASSERT(res = PCT.Ok);
  2250. PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos); (* ug: must be done explicitly here in order to allow cross method calls of objects *)
  2251. PCT.ChangeState(bodyscope, PCT.procdeclared, scanner.errpos);
  2252. savedsym := sym;
  2253. savedscanner := scanner;
  2254. scanner := PCS.ForkScanner(scanner);
  2255. inspect := TRUE;
  2256. Body(TRUE); (* suppress = TRUE *)
  2257. scanner := savedscanner;
  2258. sym := savedsym;
  2259. inspect := FALSE
  2260. END
  2261. END DeclSeq;
  2262. PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
  2263. BEGIN
  2264. sync.Enter; SELF.sync := sync;
  2265. isRecord := TRUE;
  2266. scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
  2267. scanner := PCS.ForkScanner(s);
  2268. END InitRec;
  2269. END ObjectParser;
  2270. RecordParser = OBJECT (Parser)
  2271. PROCEDURE Body(suppress: BOOLEAN);
  2272. BEGIN
  2273. Check(end)
  2274. END Body;
  2275. PROCEDURE DeclSeq; (* the DeclSeq of a record is a simplified DeclSeq, but nevertheless different *)
  2276. BEGIN
  2277. LOOP
  2278. IF sym = semicolon THEN
  2279. CheckSemicolons; (* advances to next symbol *)
  2280. ELSIF sym = ident THEN VarDecl;
  2281. ELSE EXIT
  2282. END
  2283. END;
  2284. FixForwards; (*anonymous declaration possible!*)
  2285. PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos);
  2286. PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
  2287. END DeclSeq;
  2288. PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
  2289. BEGIN
  2290. sync.Enter; SELF.sync := sync;
  2291. isRecord := TRUE;
  2292. scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
  2293. scanner := PCS.ForkScanner(s);
  2294. END InitRec;
  2295. END RecordParser;
  2296. InterfaceParser = OBJECT (Parser)
  2297. PROCEDURE Body(suppress: BOOLEAN);
  2298. BEGIN
  2299. Check(end)
  2300. END Body;
  2301. PROCEDURE DeclSeq;
  2302. VAR name: PCS.Name; procscope: PCT.ProcScope; t: PCT.Struct; pos: LONGINT; res: WORD;
  2303. BEGIN
  2304. WHILE sym = procedure DO
  2305. pos := scanner.errpos;
  2306. scanner.Get(sym);
  2307. name := scanner.name;
  2308. Check(ident);
  2309. NEW(procscope); PCT.InitScope(procscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(procscope);
  2310. FormalPars (procscope, t, {});
  2311. scope.CreateProc(name, PCT.Public, {}, procscope, t, pos(*fof*), res);
  2312. IF res # PCT.Ok THEN PCM.ErrorN(res, pos, name) END;
  2313. Check(semicolon);
  2314. PCT.ChangeState(procscope, PCT.structdeclared, scanner.errpos)
  2315. END;
  2316. PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos)
  2317. END DeclSeq;
  2318. PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
  2319. BEGIN
  2320. sync.Enter; SELF.sync := sync;
  2321. isRecord := TRUE;
  2322. scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
  2323. scanner := PCS.ForkScanner(s);
  2324. END InitRec;
  2325. END InterfaceParser;
  2326. (* Parse a procedure, beginning from the parameters to the END. This only fills the scope,
  2327. the symbol has to be inserted by the caller *)
  2328. ProcedureParser = OBJECT (Parser)
  2329. PROCEDURE & InitProc*(sync: Barrier; procscope: PCT.ProcScope; inline: BOOLEAN; VAR s: PCS.Scanner; sym: PCS.Token);
  2330. BEGIN
  2331. sync.Enter; SELF.sync := sync;
  2332. SELF.inline := inline;
  2333. scope := procscope; codescope := procscope; scanner := s; SELF.sym := sym;
  2334. scopelevel := procscope.ownerO.level; looplevel := 0;
  2335. scanner := PCS.ForkScanner(s)
  2336. END InitProc;
  2337. END ProcedureParser;
  2338. (* Parse the condition in an AWAIT statement as a separate procedure *)
  2339. AwaitParser = OBJECT(Parser)
  2340. PROCEDURE DeclSeq;
  2341. BEGIN
  2342. PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
  2343. END DeclSeq;
  2344. PROCEDURE Body(suppress: BOOLEAN);
  2345. VAR x: PCB.Expression;
  2346. BEGIN
  2347. code := PCB.Enter(scope);
  2348. Expr(x);
  2349. PCB.Return(code, suppress, codescope, scanner.errpos, x, FALSE, 0); (*use the declaration scope!*)
  2350. PCB.Leave(code, scope, FALSE);
  2351. END Body;
  2352. PROCEDURE &Init*(sync: Barrier; procscope: PCT.ProcScope; VAR s: PCS.Scanner; sym: PCS.Token);
  2353. BEGIN
  2354. sync.Enter; SELF.sync := sync;
  2355. scope := procscope; codescope := procscope; scanner := s; SELF.sym := sym;
  2356. scopelevel := procscope.ownerO.level; looplevel := 0;
  2357. scanner := PCS.ForkScanner(s)
  2358. END Init;
  2359. END AwaitParser;
  2360. ModuleParser = OBJECT (Parser)
  2361. VAR modscope: PCT.ModScope; (*cached value*)
  2362. PROCEDURE ImportList;
  2363. VAR alias, name: StringPool.Index; new: PCT.Module; res: WORD;
  2364. BEGIN
  2365. LOOP
  2366. IF sym # ident THEN Error(ident, scanner.errpos); EXIT END;
  2367. alias := scanner.name;
  2368. scanner.Get(sym);
  2369. IF sym = becomes THEN
  2370. scanner.Get(sym);
  2371. IF sym = ident THEN
  2372. name := scanner.name;
  2373. ELSIF sym = string THEN
  2374. name := StringPool.GetIndex1(scanner.str) (*scanner.str is read-only and GetIndex has a VAR....*)
  2375. ELSE
  2376. Error(ident, scanner.errpos); EXIT
  2377. END;
  2378. scanner.Get(sym)
  2379. ELSE
  2380. name := alias;
  2381. END;
  2382. IF name # PCT.System.name THEN
  2383. IF sym = in THEN
  2384. scanner.Get(sym);
  2385. CreateContext (name, scanner.name);
  2386. Check (ident);
  2387. ELSE
  2388. CreateContext (name, modscope.owner.context);
  2389. END;
  2390. END;
  2391. PCT.Import(modscope.owner, new, name);
  2392. IF new = NIL THEN
  2393. PCM.ErrorN(152, scanner.errpos, name)
  2394. ELSE
  2395. IF new # PCT.System THEN
  2396. modscope.owner.AddDirectImp(new);
  2397. END;
  2398. modscope.AddModule(alias, new, scanner.errpos, (* fof *) res); (*must create copy, otherwise list fields get overwritten*)
  2399. IF res # PCT.Ok THEN PCM.ErrorN(res, scanner.errpos, alias) END
  2400. END;
  2401. IF sym = comma THEN scanner.Get(sym)
  2402. ELSE EXIT
  2403. END
  2404. END;
  2405. Check(semicolon)
  2406. END ImportList;
  2407. PROCEDURE ParseInterface;
  2408. VAR mod: PCT.Module; sf, flags: SET; name, label, context: PCS.Name;
  2409. BEGIN
  2410. IF sym = module THEN scanner.Get(sym);
  2411. IF sym = ident THEN
  2412. name := scanner.name; label := name;
  2413. scanner.Get(sym);
  2414. IF sym = in THEN
  2415. scanner.Get(sym);
  2416. context := scanner.name;
  2417. IF (scanner.str # "Oberon") & (scanner.str # "A2") THEN
  2418. PCM.Error (133, scanner.errpos, scanner.str)
  2419. END;
  2420. Check (ident);
  2421. ELSE
  2422. StringPool.GetIndex (Modules.DefaultContext, context);
  2423. END;
  2424. CreateContext (name, context);
  2425. TypeModifier(sf, {}, {PCT.Overloading});
  2426. PCT.InitScope(scope, NIL, sf, FALSE);
  2427. mod := PCT.NewModule(name, FALSE, flags, modscope);
  2428. mod.context := context; mod.label := label;
  2429. Check(semicolon);
  2430. IF sym = import THEN scanner.Get(sym); ImportList END
  2431. ELSE Error(ident, scanner.errpos)
  2432. END
  2433. ELSE Error(16, scanner.errpos)
  2434. END;
  2435. die := PCM.error
  2436. END ParseInterface;
  2437. PROCEDURE Await*;
  2438. VAR count, inside: LONGINT;
  2439. BEGIN
  2440. sync.Await;
  2441. sync.Stats(count, inside);
  2442. IF inside > 0 THEN
  2443. PCM.LogWStr(" ("); PCM.LogWNum(inside); PCM.LogW("/"); PCM.LogWNum(count); PCM.LogWStr(")")
  2444. END;
  2445. PCM.error := PCM.error OR (inside > 0)
  2446. END Await;
  2447. PROCEDURE & InitModule*(modscope: PCT.ModScope; s: PCS.Scanner);
  2448. VAR recscope: PCT.RecScope; rec: PCT.Record; res: WORD;i, j: LONGINT; (** fof *)
  2449. BEGIN
  2450. Machine.AtomicInc(NModules);
  2451. NEW(sync, 10(*timeout*)); sync.Enter;
  2452. scope := modscope; codescope := modscope; scanner := s; s.Get(sym); scopelevel := 0; looplevel := 0;
  2453. PCT.SetOwner(scope);
  2454. SELF.modscope := modscope;
  2455. PCArrays.InitScope( modscope ); (* fof *)
  2456. (*predefined variables*)
  2457. scope.CreateVar(PCT.SelfName, PCT.Internal, {PCM.Untraced}, PCT.Ptr, 0, (*fof*) NIL, res); (*module self, used for module locking*)
  2458. ASSERT(res = PCT.Ok);
  2459. ParseInterface;
  2460. IF ~die THEN
  2461. (*predefined types*)
  2462. NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
  2463. rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
  2464. scope.CreateType(deltype, PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
  2465. recscope.CreateVar(procfld, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2466. recscope.CreateVar(self, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2467. PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
  2468. PCC.delegate := rec;
  2469. NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
  2470. rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
  2471. scope.CreateType(hiddenptr, PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
  2472. recscope.CreateVar(ptrfld, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2473. PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
  2474. PCC.hdptr := rec;
  2475. (** fof >> *)
  2476. (* keyword "RANGE" support
  2477. NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
  2478. rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
  2479. scope.CreateType(StringPool.GetIndex1("RANGE"), PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
  2480. recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2481. recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2482. recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2483. recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Set, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
  2484. PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
  2485. PCC.range := rec;
  2486. *)
  2487. FOR i := 0 TO LEN( PCC.anyarr ) - 1 DO
  2488. NEW( recscope ); PCT.InitScope( recscope, scope, {PCT.SuperclassAvailable}, FALSE ); PCT.SetOwner( recscope ); rec := PCT.NewRecord( PCT.NoType, recscope, {PCT.SystemType}, FALSE , res );
  2489. ASSERT( res = PCT.Ok );
  2490. (*scope.CreateType(hiddenptr, PCT.Internal, rec, 0 (*fof*) ,res); ASSERT(res = PCT.Ok);*)
  2491. recscope.CreateVar( ptrfld, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res );
  2492. FOR j := 1 TO 3 + 2 * i DO recscope.CreateVar( PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res ); ASSERT( res = PCT.Ok ); END;
  2493. PCT.ChangeState( recscope, PCT.complete, scanner.errpos ); PCC.anyarr[i] := rec;
  2494. END;
  2495. (** << fof *)
  2496. PCC.topscope := modscope;
  2497. END
  2498. END InitModule;
  2499. (** fof >> *)
  2500. PROCEDURE Epilog;
  2501. VAR res: WORD; sym: PCT.Symbol; var: PCT.Variable;
  2502. BEGIN
  2503. (* check if the array module has been used in PCArrays. If so then put it into the scope to protect from unloading *)
  2504. IF PCArrays.ArrayModule # NIL THEN (* must be done here by this process *)
  2505. IF modscope.owner.name = PCArrays.ArrayModuleIdx THEN HALT( 100 ) END;
  2506. modscope.AddModule( PCArrays.ArrayModuleIdx, PCArrays.ArrayModule, 0, res );
  2507. modscope.owner.AddDirectImp( PCArrays.ArrayModule ); (* makes the use of ArrayBase visible, may be omitted *)
  2508. END;
  2509. Epilog^;
  2510. END Epilog;
  2511. (** << fof *)
  2512. END ModuleParser;
  2513. (** fof 070731 >> *)
  2514. PROCEDURE InitializationWarning( s: PCT.Symbol );
  2515. VAR par: PCT.Parameter; name: ARRAY 256 OF CHAR;
  2516. BEGIN
  2517. (*
  2518. IF s # NIL THEN
  2519. StringPool.GetString( s.name, name );
  2520. PCM.LogWStr(name); PCM.LogWLn;
  2521. END;
  2522. *)
  2523. IF (s = NIL) OR (s.pos = 0) THEN RETURN
  2524. ELSIF s IS PCT.Parameter THEN
  2525. par := s( PCT.Parameter );
  2526. IF ~(PCT.written IN par.flags) THEN
  2527. IF ((par.type IS PCT.Array)
  2528. (*
  2529. OR
  2530. (par.type IS PCT.Record)
  2531. *)
  2532. ) &
  2533. ~(PCM.ReadOnly IN par.flags) THEN
  2534. StringPool.GetString( s.name, name );
  2535. PCM.Warning( 917, par.pos, name );
  2536. PCT.RemoveWarning( par );
  2537. (*
  2538. ELSIF ~(PCM.ReadOnly IN par.flags) & par.ref THEN PCM.Warning( 901, par.pos, "VAR parameter not initialized" );
  2539. too verbose
  2540. *)
  2541. END;
  2542. END;
  2543. ELSIF s IS PCT.LocalVar THEN
  2544. IF ~(PCT.written IN s.flags) & ({PCT.PublicW} * s.vis = {}) THEN
  2545. StringPool.GetString( s.name, name );
  2546. PCM.Warning( 901, s.pos, name );
  2547. PCT.RemoveWarning(s);
  2548. END;
  2549. ELSIF s IS PCT.GlobalVar THEN
  2550. IF ~(PCT.written IN s.flags) & ({PCT.PublicW} * s.vis = {}) THEN
  2551. StringPool.GetString( s.name, name );
  2552. PCM.Warning(901,s.pos,name);
  2553. PCT.RemoveWarning(s);
  2554. END;
  2555. END;
  2556. END InitializationWarning;
  2557. PROCEDURE UsageWarning( s: PCT.Symbol );
  2558. VAR name: ARRAY 256 OF CHAR;
  2559. BEGIN
  2560. IF (s = NIL) OR (s.pos = 0) OR (s IS PCT.Parameter) (* too verbose *) THEN RETURN END;
  2561. IF ~(PCT.used IN s.flags) &
  2562. (PCT.Public * s.vis = {}) THEN
  2563. StringPool.GetString( s.name, name );
  2564. PCM.Warning( 900, s.pos, name );
  2565. PCT.RemoveWarning( s );
  2566. END;
  2567. END UsageWarning;
  2568. (* Generates a warning if a field has the same name as an inherited field *)
  2569. PROCEDURE SameNameWarning(s : PCT.Symbol);
  2570. VAR
  2571. record : PCT.Record; warned : BOOLEAN;
  2572. name : ARRAY 128 OF CHAR;
  2573. PROCEDURE HasVar(scope : PCT.Scope; var : PCT.Variable) : BOOLEAN;
  2574. VAR v : PCT.Variable;
  2575. BEGIN
  2576. ASSERT((scope # NIL) & (var # NIL));
  2577. v := scope.firstVar;
  2578. LOOP
  2579. IF (v = NIL) OR (v.name = var.name) THEN EXIT; END;
  2580. v := v.nextVar;
  2581. END;
  2582. RETURN v # NIL;
  2583. END HasVar;
  2584. BEGIN
  2585. IF (s = NIL) OR (s.pos = 0) THEN RETURN END;
  2586. IF (s IS PCT.Variable) & (s.inScope # NIL) & (s.inScope IS PCT.RecScope) & (s.inScope(PCT.RecScope).owner # NIL) THEN
  2587. warned := FALSE;
  2588. record := s.inScope(PCT.RecScope).owner.brec;
  2589. WHILE (record # NIL) & (record.scope # NIL) & (~warned) DO
  2590. IF HasVar(record.scope, s(PCT.Variable)) THEN
  2591. warned := TRUE;
  2592. StringPool.GetString(s.name, name);
  2593. PCM.Warning(914, s.pos, name);
  2594. PCT.RemoveWarning( s );
  2595. END;
  2596. record := record.brec;
  2597. END;
  2598. END;
  2599. END SameNameWarning;
  2600. (* Generates a warning if a symbol is exported but the scope containing it is not *)
  2601. PROCEDURE UselessExportWarning(s : PCT.Symbol);
  2602. VAR recScope : PCT.RecScope; name : ARRAY 128 OF CHAR;
  2603. BEGIN
  2604. IF (s = NIL) OR (s.pos = 0) OR (s.vis * PCT.Public = {}) THEN RETURN; END;
  2605. IF (s.inScope # NIL) THEN
  2606. IF (s.inScope IS PCT.RecScope) THEN
  2607. recScope := s.inScope (PCT.RecScope);
  2608. IF recScope.owner # NIL THEN
  2609. IF ((recScope.owner.owner # NIL) & (recScope.owner.owner.vis * PCT.Public = {})) (* RECORD *)
  2610. OR
  2611. ((recScope.owner.ptr # NIL) & (recScope.owner.ptr.owner # NIL) &
  2612. (recScope.owner.ptr.owner.vis * PCT.Public = {})) (* POINTER TO RECORD or OBJECT *)
  2613. THEN
  2614. IF (s IS PCT.Method) &
  2615. ((s(PCT.Method).boundTo.scope(PCT.RecScope).initproc = s) OR
  2616. ((s(PCT.Method).boundTo.scope(PCT.RecScope).body = s))) THEN
  2617. (* Constructors and bodies are always public *)
  2618. RETURN;
  2619. END;
  2620. IF (s IS PCT.Method) &
  2621. ((s(PCT.Method).super = NIL) OR (s(PCT.Method).super.vis * PCT.Public = {})) THEN
  2622. (* not autoexported *)
  2623. StringPool.GetString(s.name, name);
  2624. PCM.Warning(915, s.pos, name);
  2625. PCT.RemoveWarning(s);
  2626. END;
  2627. END;
  2628. END;
  2629. ELSIF (s IS PCT.Proc) & (s.inScope IS PCT.ProcScope) THEN
  2630. StringPool.GetString(s.name, name);
  2631. PCM.Warning(915, s.pos, name);
  2632. PCT.RemoveWarning(s);
  2633. END;
  2634. END;
  2635. END UselessExportWarning;
  2636. PROCEDURE ScopeWarnings(scope: PCT.Scope);
  2637. VAR s: PCT.Symbol;
  2638. BEGIN
  2639. s := scope.sorted;
  2640. WHILE (s # NIL ) DO
  2641. UsageWarning( s ); InitializationWarning( s );
  2642. SameNameWarning( s ); (* sven stauber *)
  2643. UselessExportWarning( s );
  2644. s := s.sorted;
  2645. END;
  2646. END ScopeWarnings;
  2647. PROCEDURE ImportListWarnings( mod: PCT.Module );
  2648. VAR i: LONGINT;
  2649. BEGIN
  2650. IF mod.sysImported & (PCT.System.flags * {PCT.used} = {}) THEN
  2651. PCM.Warning( 900, PCT.System.pos, "SYSTEM");
  2652. END;
  2653. IF mod.directImps = NIL THEN RETURN END;
  2654. FOR i := 0 TO LEN( mod.directImps ) - 1 DO
  2655. UsageWarning( mod.directImps[i] );
  2656. END;
  2657. END ImportListWarnings;
  2658. (** << fof *)
  2659. PROCEDURE ParseModule*(scope: PCT.ModScope; s: PCS.Scanner);
  2660. VAR parser: ModuleParser; name: StringPool.Index; sym: PCS.Token;
  2661. BEGIN
  2662. (* There's one global symbol representing the SYSTEM pseudo module. Clear the used flag before parsing the module
  2663. so we can detect whether SYSTEM is used after parsing *)
  2664. EXCL(PCT.System.flags, PCT.used);
  2665. (* note: can use s directly instead of parser.scanner, because the module parser uses the same scanner *)
  2666. NEW(parser, scope, s);
  2667. parser.Await;
  2668. IF ~parser.die THEN
  2669. IF (PCM.Warnings IN PCM.parserOptions) THEN
  2670. PCT.TraverseScopes(parser.modscope,ScopeWarnings); (*fof*)
  2671. ImportListWarnings( parser.modscope.module ); (*fof*)
  2672. END;
  2673. name := scope.owner(PCT.Module).label;
  2674. IF parser.sym = ident THEN
  2675. IF s.name # name THEN PCM.ErrorN(4, s.errpos, s.name) END;
  2676. s.Get(sym);
  2677. IF sym = period THEN (* s.Get(sym) *) ELSE PCM.Error(period, s.errpos, "") END;
  2678. ELSE PCM.ErrorN(ident, s.errpos, name)
  2679. END
  2680. END
  2681. END ParseModule;
  2682. PROCEDURE CreateString(VAR idx: StringPool.Index; str: ARRAY OF CHAR); (*to insert string constants*)
  2683. BEGIN StringPool.GetIndex(str, idx)
  2684. END CreateString;
  2685. PROCEDURE CreateContext (VAR name: StringPool.Index; context: StringPool.Index);
  2686. VAR string, temp: ARRAY 64 OF CHAR;
  2687. BEGIN
  2688. StringPool.GetString (context, string);
  2689. IF string # Modules.DefaultContext THEN
  2690. Strings.Append (string, "-");
  2691. StringPool.GetString (name, temp);
  2692. Strings.Append (string, temp);
  2693. StringPool.GetIndex (string, name);
  2694. END;
  2695. END CreateContext;
  2696. BEGIN
  2697. CreateString(untraced, "UNTRACED");
  2698. CreateString(delegate, "DELEGATE");
  2699. CreateString(overloading, "OVERLOADING");
  2700. CreateString(self, "SELF");
  2701. CreateString(exclusive, "EXCLUSIVE");
  2702. CreateString(active, "ACTIVE");
  2703. CreateString(safe, "SAFE");
  2704. CreateString(priority, "PRIORITY");
  2705. CreateString(realtime, "REALTIME");
  2706. CreateString(deltype, "@Delegate");
  2707. CreateString(hiddenptr, "@HdPtrDesc");
  2708. CreateString(procfld, "proc");
  2709. CreateString(ptrfld, "ptr");
  2710. CreateString(winapi, "WINAPI"); (* ejz *)
  2711. CreateString( clang, "C" ); (* fof for Linux Version *)
  2712. CreateString(notag, "NOTAG"); (* sz *)
  2713. noname := -1
  2714. END PCP.
  2715. (*
  2716. 08.08.07 sst Added SameNameWarning, UselessExportWarning & AWAIT not in exclusive block warning
  2717. 24.06.03 prk Check that name after END is the same as declared after MODULE
  2718. 21.07.02 prk EXIT in an exclusive block must release lock
  2719. 05.02.02 prk PCT.Find cleanup
  2720. 11.12.01 prk problem parsing invalid WITH syntax fixed
  2721. 22.11.01 prk improved flag handling
  2722. 19.11.01 prk definitions
  2723. 17.11.01 prk more flexible type handling of integer constants
  2724. 16.11.01 prk constant folding of reals done with maximal precision
  2725. 16.11.01 prk improved error message when operators and Oberon-2 WITH found
  2726. 01.11.01 prk improved error handling for OBJECT without VAR
  2727. 14.09.01 prk PRIORITY modifier, error messages improved
  2728. 29.08.01 prk PCT functions: return "res" instead of taking "pos"
  2729. 27.08.01 prk PCT.Insert removed, use Create procedures instead
  2730. 27.08.01 prk scope.unsorted list removed; use var, proc, const and type lists instead
  2731. 17.08.01 prk overloading
  2732. 09.08.01 prk Symbol Table Loader Plugin
  2733. 11.07.01 prk support for fields and methods with same name in scope
  2734. 06.07.01 prk mark object explicitly
  2735. 05.07.01 prk import interface redesigned
  2736. 04.07.01 prk SkipScope, seek for END in CODE bodies, ignore other keywords
  2737. 04.07.01 prk scope flags added, remove imported
  2738. 02.07.01 prk access flags, new design
  2739. 27.06.01 prk StringPool cleaned up
  2740. 27.06.01 prk ProcScope.CreatePar added
  2741. 21.06.01 prk using stringpool index instead of array of char
  2742. 15.06.01 prk support for duplicate scope entries
  2743. 14.06.01 prk type descs for dynamic arrays of ptrs generated by the compiler
  2744. 12.06.01 prk Interfaces
  2745. 30.05.01 prk destination (\d) compiler-option to install the back-end
  2746. 17.05.01 prk Delegates
  2747. 10.05.01 prk remove temporary for-counter when EXIT inside a for-loop
  2748. 08.05.01 prk PCT interface cleanup. Use InitX instead of New*, allows type extension
  2749. 26.04.01 prk separation of RECORD and OBJECT in the parser
  2750. 29.03.01 prk Java imports
  2751. *)