12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924 |
- (* Paco, Copyright 2000 - 2002, Patrik Reali, ETH Zurich *)
- MODULE PCP; (** AUTHOR "prk"; PURPOSE "Parallel Compiler: parser"; *)
- IMPORT
- Machine, Modules, Objects, Kernel, Strings,
- StringPool,
- PCM, PCS, PCT, PCB, PCC, SYSTEM, PCArrays;
- CONST
- (* The Tokens
- ProgTools.Enum PCS
- null
- times slash div mod and
- plus minus or eql neq lss leq gtr geq in is
- arrow period comma
- colon upto rparen rbrak rbrace
- of then do to by
- lparen lbrak lbrace
- not
- becomes
- number nil true false string
- ident semicolon bar end else
- elsif until if case while
- repeat for loop with exit passivate return
- refines implements
- array definition object record pointer begin code
- const type var procedure import
- module eof
- ~
- *)
- null = PCS.null; times = PCS.times; slash = PCS.slash; div = PCS.div;
- mod = PCS.mod; and = PCS.and; plus = PCS.plus; minus = PCS.minus;
- or = PCS.or; eql = PCS.eql; neq = PCS.neq; lss = PCS.lss; leq = PCS.leq;
- gtr = PCS.gtr; geq = PCS.geq; in = PCS.in; is = PCS.is; arrow = PCS.arrow;
- period = PCS.period; comma = PCS.comma; colon = PCS.colon; upto = PCS.upto;
- rparen = PCS.rparen; rbrak = PCS.rbrak; rbrace = PCS.rbrace; of = PCS.of;
- then = PCS.then; do = PCS.do; to = PCS.to; by = PCS.by; lparen = PCS.lparen;
- lbrak = PCS.lbrak; lbrace = PCS.lbrace; not = PCS.not; becomes = PCS.becomes;
- number = PCS.number; nil = PCS.nil; true = PCS.true; false = PCS.false;
- string = PCS.string; ident = PCS.ident; semicolon = PCS.semicolon;
- bar = PCS.bar; end = PCS.end; else = PCS.else; elsif = PCS.elsif;
- until = PCS.until; if = PCS.if; case = PCS.case; while = PCS.while;
- repeat = PCS.repeat; for = PCS.for; loop = PCS.loop; with = PCS.with;
- exit = PCS.exit; passivate = PCS.passivate; return = PCS.return;
- refines = PCS.refines; implements = PCS.implements; array = PCS.array;
- definition = PCS.definition; object = PCS.object; record = PCS.record;
- pointer = PCS.pointer; begin = PCS.begin; codeToken = PCS.code; const = PCS.const;
- type = PCS.type; var = PCS.var; procedure = PCS.procedure; import = PCS.import;
- module = PCS.module; eof = PCS.eof; finally = PCS.finally;
- (** fof >> *)
- filler = PCS.qmark; backslash = PCS.backslash;
- scalarproduct = PCS.scalarproduct;
- elementproduct = PCS.elementproduct;
- elementquotient = PCS.elementquotient;
- transpose = PCS.transpose; dtimes = PCS.dtimes;
- eeql = PCS.eeql; eneq = PCS.eneq; elss = PCS.elss;
- eleq = PCS.eleq; egtr = PCS.egtr; egeq = PCS.egeq;
- AllowOverloadedModule = FALSE;
- (* fof removed the mechanism allowing to choose an operator from a module.
- Example: "a :=[myModule1] b;" chooses assignment operator for "a" from module "myModule1".
- My proposal is to generally prohibit multiple occurence of operators by restriction of its definition to the object's defining module.
- For now we do it with this switch.
- 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.
- *)
- (** << fof *)
- (*local constants, implementations restrictions*)
- MaxIdentDef = 128; (*maximal number of IdentDef in a VarDecl*)
- TYPE
- IdentDefDesc = RECORD name: PCS.Name; vis: SET END; (*
- name = (parsed name) OR ("")
- vis = (parsed vis) OR (PCT.Internal)
- *)
- VAR
- (** Assembler Plugin *)
- Assemble*: PROCEDURE (scanner: PCS.Scanner; scope: PCT.Scope; exported, inlined: BOOLEAN): PCM.Attribute;
- (* cached string constants used by the parser*)
- noname, self, untraced, delegate, overloading,
- exclusive, active, safe, priority, realtime, winapi (* ejz *), clang (*fof for linux *) ,notag (* sz *),
- deltype, hiddenptr, procfld, ptrfld: StringPool.Index;
- NModules, NObjects, NDefinitions, NArrays, NRecords, NPointers, NDelegates, NProcedureTypes,
- NExclusive, NExclusiveMain, NActive,
- NSyncsCount: LONGINT; (* statistical counters *)
- (* ============================================================== *)
- (* ------------- The Parser Object ---------------------------------- *)
- TYPE
- (* Synchronize a thread with its child processes, await till all left the monitor or timeout *)
- Barrier = OBJECT (Kernel.Timer)
- VAR
- timeout: LONGINT;
- started, ended: LONGINT;
- PROCEDURE & SInit*(timeout: LONGINT);
- BEGIN started := 0; ended := 0; SELF.timeout := timeout*1000; Init;
- END SInit;
- PROCEDURE Enter;
- BEGIN
- Machine.AtomicInc(started);
- Machine.AtomicInc(NSyncsCount);
- END Enter;
- PROCEDURE Exit;
- BEGIN
- Machine.AtomicInc(ended);
- IF started = ended THEN Wakeup END
- END Exit;
- PROCEDURE Await;
- BEGIN Sleep(timeout)
- END Await;
- PROCEDURE Stats(VAR started, inside: LONGINT);
- BEGIN started := SELF.started; inside := SELF.started - SELF.ended
- END Stats;
- END Barrier;
- Parser* = OBJECT
- VAR
- sync: Barrier;
- sym, savedsym: PCS.Token;
- scanner, savedscanner: PCS.Scanner;
- scope, codescope: PCT.Scope; (*codescope is the scope where the code is defined, where a WITH is used*)
- looplevel, scopelevel: SHORTINT; (*copy of scope(ProcScope).level or 0 (rec/mod)*)
- forexitcount, forretcount, retcount, fincount: LONGINT; (*nested for-loops inside a LOOP-statement, used to remove the temp for-counters*)
- curloop: PCB.LoopInfo;
- code: PCC.Code;
- inline: BOOLEAN;
- locked: BOOLEAN; (*parser inside a locked statement block, set by StatementBlock*)
- unlockOnExit: BOOLEAN; (* EXCLUSIVE block nested in a LOOP, must unlock when exit is called *)
- die: BOOLEAN; (*kill the parser*)
- notifyScope: BOOLEAN; (*notify the parent of current scope that the body mode is available*)
- isRecord: BOOLEAN; (*cached: scope IS PCT.RecScope*)
- inspect: BOOLEAN; (* TRUE if body is parsed to find hidden local variables, i.e. procedure calls that return pointers *)
- forwardPtr: ARRAY 128 OF RECORD ptr: PCT.Pointer; name: PCS.Name END;
- nofForwardPtr: LONGINT;
- (* --------------------------------------------------------- *)
- (* Parser utilities *)
- PROCEDURE Error(n: WORD; pos: LONGINT);
- BEGIN PCM.Error(n, pos, "")
- END Error;
- PROCEDURE Check(x: PCS.Token);
- BEGIN
- IF sym = x THEN scanner.Get(sym) ELSE PCM.Error(x, scanner.errpos, "") END;
- END Check;
- (* Test whether the current symbol is a semicolon. Report an error if not. In case of multiple semicolons
- the follow each other, report a warning for each occurence *)
- PROCEDURE CheckSemicolons;
- BEGIN
- IF (sym = semicolon) THEN
- scanner.Get(sym);
- IF (sym = semicolon) THEN
- REPEAT
- PCM.Warning(315, scanner.errpos, "");
- scanner.Get(sym);
- UNTIL sym # semicolon;
- END;
- ELSE
- PCM.Error(semicolon, scanner.errpos, "");
- END;
- END CheckSemicolons;
- (* Report an error if the pseudo module SYSTEM is not imported by the specified module *)
- PROCEDURE CheckSysImported(module : PCT.Module);
- BEGIN
- IF ~module.sysImported THEN
- Error(135, scanner.errpos);
- ELSE
- INCL(PCT.System.flags, PCT.used);
- END;
- END CheckSysImported;
- (* --------------------------------------------------------- *)
- (* Active Oberon Language Productions *)
- (* Declaration Section *)
- PROCEDURE TypeModifier(VAR flags: SET; default, allowed: SET);
- BEGIN
- flags := default;
- IF (sym = lbrace) THEN
- REPEAT
- scanner.Get(sym);
- IF sym # ident THEN
- Error(ident, scanner.errpos)
- ELSIF scanner.name = untraced THEN
- INCL (flags, PCM.Untraced);
- ELSIF scanner.name = delegate THEN
- EXCL (flags, PCT.StaticMethodsOnly);
- ELSIF scanner.name = realtime THEN
- INCL (flags, PCT.RealtimeProcType);
- ELSIF scanner.name = overloading THEN
- INCL (flags, PCT.Overloading);
- ELSIF scanner.name = winapi THEN (* ejz *)
- CheckSysImported(scope.module);
- INCL (flags, PCT.WinAPIParam);
- ELSIF scanner.name = clang THEN (* fof for Linux *)
- CheckSysImported(scope.module);
- INCL (flags, PCT.CParam);
- ELSE
- Error(0, scanner.errpos); scanner.Get(sym)
- END;
- scanner.Get( sym )
- UNTIL sym # comma;
- IF (flags - allowed # {}) THEN flags := default; Error(200, scanner.errpos) END;
- Check(rbrace)
- END;
- IF (flags = {PCM.Untraced}) THEN
- CheckSysImported(scope.module);
- END;
- END TypeModifier;
- PROCEDURE IdentDef (VAR i: IdentDefDesc; allowRO: BOOLEAN); (* IdentDef = ident ["*"|"-"]. *)
- BEGIN
- i.vis := PCT.Internal;
- IF sym = ident THEN
- i.name := scanner.name; scanner.Get(sym)
- ELSE
- i.name := PCT.Anonymous;
- Error(ident, scanner.errpos)
- END;
- IF sym = times THEN
- i.vis := PCT.Public; scanner.Get(sym)
- ELSIF sym = minus THEN
- IF allowRO THEN
- i.vis := PCT.Internal + {PCT.PublicR}
- ELSE
- i.vis := PCT.Public; Error(47, scanner.errpos)
- END;
- scanner.Get(sym)
- END;
- END IdentDef;
- PROCEDURE OperatorDef(VAR i: IdentDefDesc; allowRO: BOOLEAN);
- VAR opName: PCS.Name;
- BEGIN
- i.vis:= PCT.Internal;
- opName := StringPool.GetIndex1(scanner.str);
- i.name := opName;
- IF ~scanner.IsOperatorValid() THEN
- PCM.Error(142, scanner.errpos, "");
- END;
- scanner.Get(sym);
- IF sym = times THEN
- i.vis := PCT.Public;
- scanner.Get(sym)
- ELSIF sym = minus THEN
- IF allowRO THEN
- i.vis := PCT.Internal + {PCT.PublicR}
- ELSE
- i.vis := PCT.Public; Error(47, scanner.errpos)
- END;
- scanner.Get(sym)
- END;
- END OperatorDef;
- PROCEDURE FPSection(scope: PCT.ProcScope; pflags: SET); (* ejz *)
- VAR name: ARRAY 32 OF PCS.Name; i, n: LONGINT; res: WORD; VarPar: BOOLEAN;
- pos: ARRAY 32 OF LONGINT; t: PCT.Struct;
- (** fof >> *)
- ConstPar: BOOLEAN;
- (** << fof *)
- BEGIN
- VarPar := sym = var;
- (** fof 070731 >> *)
- ConstPar := (sym = const);
- IF ConstPar THEN INCL( pflags, PCM.ReadOnly ); END;
- (** << fof *)
- IF VarPar OR ConstPar (* fof 070731 *) THEN scanner.Get(sym) END;
- n := 0;
- LOOP
- pos[n] := scanner.errpos;
- name[n] := scanner.name;
- (** fof >> *)
- (*! temporary range as parameters, remove !*)
- Check( ident );
- IF sym = upto THEN (* a..b BY c *) (* range type fof *)
- IF VarPar THEN PCM.Error( 122, scanner.errpos, "" ) END;
- (*flags[n] := pflags + {rangeflag};*) INC( n );
- scanner.Get( sym ); pos[n] := scanner.errpos;
- name[n] := scanner.name;
- (* flags[n] := pflags + {rangeflag};*) INC( n );
- Check( ident ); Check( by );
- pos[n] := scanner.errpos;
- name[n] := scanner.name; Check( ident );
- (*flags[n] := pflags + {rangeflag};*)
- ELSE (*flags[n] := pflags; *)
- END;
- (** << fof *)
- INC(n);
- (*Check(ident);*) (* fof *)
- IF sym # comma THEN EXIT END;
- scanner.Get(sym)
- END;
- Check(colon); Type(t, noname);
- i := 0;
- (* fof 070731 *)
- IF ConstPar & ((t IS PCT.Array) OR (t IS PCT.Record)) THEN VarPar := TRUE;
- END;
- WHILE i < n DO
- scope.CreatePar(PCT.Internal, VarPar, name[i], pflags, t, pos[i], (* fof *) res); (* ejz *)
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos[i], name[i]) END;
- INC(i)
- END
- END FPSection;
- PROCEDURE FormalPars(scope: PCT.ProcScope; VAR rtype: PCT.Struct; pflags: SET); (* ejz *)
- VAR o: PCT.Symbol; res: WORD;
- BEGIN
- rtype := PCT.NoType;
- IF sym = lparen THEN
- scanner.Get(sym);
- IF sym # rparen THEN
- FPSection(scope, pflags); (* ejz *)
- WHILE sym = semicolon DO
- scanner.Get(sym); FPSection(scope, pflags) (* ejz *)
- END;
- END;
- Check(rparen);
- IF sym = colon THEN
- scanner.Get(sym);
- IF sym = object THEN
- rtype := PCT.Ptr;
- scanner.Get(sym)
- ELSIF sym = array THEN
- scanner.Get(sym);
- ArrayType(rtype, FALSE (* fof *));
- ELSE
- Qualident(o);
- IF (o IS PCT.Type) THEN
- rtype := o.type
- ELSE
- Error(52, scanner.errpos);
- rtype := PCT.UndefType
- END
- END;
- IF (rtype IS PCT.Array) & (rtype(PCT.Array).mode = PCT.open) THEN Error(91, scanner.errpos) END;
- (* ug *) IF (rtype # PCT.UndefType) & PCT.ContainsPointer(rtype) THEN
- scope.CreatePar(PCT.Internal, TRUE, PCT.PtrReturnType, pflags, rtype, 0 (* fof *), res);
- END
- ELSIF scope.formalParCount = 0 THEN (* fn *)
- PCM.Warning (916, scanner.errpos, "");
- END
- END;
- IF {PCT.CParam, PCT.WinAPIParam} * pflags # {} (* fof for Linux *) THEN scope.ReversePars() END (* ejz *)
- END FormalPars;
- PROCEDURE CheckOperator(scope: PCT.ProcScope; VAR name: PCS.Name; rtype: PCT.Struct; pos: LONGINT);
- VAR
- opStr: ARRAY PCS.MaxStrLen OF CHAR;
- p: PCT.Parameter;
- recScope: PCT.RecScope;
- PROCEDURE CheckCardinality(nofparam: LONGINT): BOOLEAN;
- BEGIN
- CASE opStr[0] OF
- | "+", "-": RETURN (nofparam = 1) OR (nofparam = 2)
- | "~": RETURN (opStr[1] = 0X) & (nofparam = 1)
- | "[": RETURN nofparam > 0
- ELSE RETURN nofparam = 2
- END;
- END CheckCardinality;
- BEGIN
- StringPool.GetString(name, opStr);
- IF ~CheckCardinality(scope.formalParCount) THEN
- Error(143, pos); (* invalid number of formal parameters *)
- END;
- IF opStr = ":=" THEN
- IF rtype # PCT.NoType THEN
- Error(147, pos); (* operator ":=" has no return value *)
- END;
- IF ~scope.firstPar.ref THEN
- Error(148, pos); (* first parameter of ":=" must be VAR *)
- END;
- IF (scope.firstPar.nextPar # NIL) & (scope.firstPar.type = scope.firstPar.nextPar.type) THEN
- PCM.Warning(PCM.InvalidCode, pos, "Warning: both parameters of identical type");
- END
- ELSIF opStr = "[]" THEN
- IF (scope = NIL) OR (scope.parent = NIL) OR ~(scope.parent IS PCT.RecScope) THEN
- Error(990, pos) (* operator "[]" only allowed in record scope *)
- ELSE
- recScope := scope.parent(PCT.RecScope);
- IF rtype = PCT.NoType THEN
- name := StringPool.GetIndex1(PCT.AssignIndexer);
- ELSE
- name := StringPool.GetIndex1(PCT.ReadIndexer);
- END
- END
- ELSE
- IF rtype = PCT.NoType THEN
- Error(141, pos); (* all other operators must have a return value *)
- END
- END;
- p := scope.firstPar;
- WHILE (p # NIL) & PCT.IsBasic(p.type) DO
- p := p.nextPar;
- END;
- (* Ignore "[]" because SELF is an implicit parameter *)
- IF (opStr # "[]") & (p = NIL) THEN
- Error(146, pos); (* at least one parameter must not be a basic type *)
- END;
- END CheckOperator;
- PROCEDURE RecordType(VAR t: PCT.Struct; pointed: BOOLEAN);
- VAR recstruct: PCT.Record; ptr: PCT.Pointer; recscope: PCT.RecScope; recparser: RecordParser; bpos: LONGINT; res: WORD;
- intf: ARRAY 32 OF PCT.Interface;
- BEGIN
- t := PCT.NoType;
- (* fof removed NOTAG, doesn't have any effect
- IF sym = lbrak THEN
- scanner.Get(sym);
- IF sym = ident THEN
- IF scanner.name # notag THEN Error(scanner.name, scanner.errpos) END
- ELSE Error(scanner.name, scanner.errpos) END;
- scanner.Get(sym); Check(rbrak)
- END;
- *)
- IF sym = lparen THEN scanner.Get(sym); bpos := scanner.errpos; Type(t, noname); Check(rparen) END;
- NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
- IF pointed THEN
- ptr := PCT.NewClass(t, intf, recscope, FALSE, res);
- IF res # PCT.Ok THEN Error(res, bpos) END;
- recstruct := ptr.baseR;
- t := ptr
- ELSE
- recstruct := PCT.NewRecord(t, recscope, {}, FALSE, res);
- IF res # PCT.Ok THEN Error(res, bpos) END;
- t := recstruct
- END;
- PCT.AddRecord(scope, recstruct);
- NEW(recparser, sync, recscope, scanner, sym); (* let the record parser take care of this *)
- SkipScope;
- END RecordType;
- PROCEDURE Interface(): PCT.Interface;
- VAR o: PCT.Symbol; p: PCT.Pointer;
- BEGIN
- Qualident(o);
- IF (o # NIL) & (o IS PCT.Type) & (o.type IS PCT.Pointer) THEN
- p := o.type(PCT.Pointer);
- IF (p.baseR # NIL) & (PCT.interface IN p.baseR.mode) THEN
- RETURN p
- END
- END;
- PCM.Error(200, scanner.errpos, "not a definition");
- RETURN NIL
- END Interface;
- PROCEDURE ObjectType(VAR t: PCT.Struct; name: StringPool.Index);
- VAR recstruct: PCT.Record; ptr: PCT.Pointer; recscope: PCT.RecScope; parser: ObjectParser; bpos, i: LONGINT; res: WORD;
- intf: ARRAY 32 OF PCT.Interface;
- BEGIN
- t := PCT.NoType;
- IF sym = lparen THEN scanner.Get(sym); bpos := scanner.errpos; Type(t, noname); Check(rparen) END;
- IF sym = implements THEN
- INCL(PCM.codeOptions, PCM.UseDefinitions); (* type declaration -> interface registration *)
- INCL(PCM.codeOptions, PCM.ExportDefinitions);
- scanner.Get(sym);
- i := 1;
- intf[0] := Interface();
- WHILE sym = comma DO
- scanner.Get(sym); intf[i] := Interface(); INC(i)
- END
- END;
- NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
- ptr := PCT.NewClass(t, intf, recscope, FALSE, res);
- IF res # PCT.Ok THEN Error(res, bpos) END;
- recstruct := ptr.baseR;
- t := ptr;
- PCT.AddRecord(scope, recstruct);
- NEW(parser, sync, recscope, scanner, sym); (* let the record parser take care of this *)
- SkipScope;
- IF name # noname THEN
- IF sym # ident THEN
- PCM.ErrorN(ident, scanner.errpos, name)
- ELSIF name # scanner.name THEN
- PCM.ErrorN(4, scanner.errpos, name); scanner.Get(sym)
- ELSE
- scanner.Get(sym)
- END
- END
- END ObjectType;
- PROCEDURE DefinitionType(pos: LONGINT; VAR t: PCT.Struct; name: StringPool.Index);
- VAR intf: ARRAY 1 OF PCT.Interface; parser: InterfaceParser; recscope: PCT.RecScope; int: PCT.Interface; res: WORD;
- BEGIN
- INCL(PCM.codeOptions, PCM.ExportDefinitions);
- IF sym = refines THEN
- scanner.Get(sym);
- intf[0] := Interface()
- END;
- Check(semicolon);
- NEW(recscope); PCT.SetOwner(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE);
- int := PCT.NewInterface(intf, recscope, FALSE, res);
- IF res # PCT.Ok THEN Error(res, pos) END;
- t := int;
- PCT.AddRecord(scope, int.baseR);
- NEW(parser, sync, recscope, scanner, sym);
- WHILE sym # end DO scanner.Get(sym) END;
- scanner.Get(sym);
- IF name # noname THEN
- IF sym # ident THEN
- PCM.ErrorN(ident, scanner.errpos, name)
- ELSIF name # scanner.name THEN
- PCM.ErrorN(4, scanner.errpos, name); scanner.Get(sym)
- ELSE
- scanner.Get(sym)
- END
- END
- END DefinitionType;
- (** fof >> *)
- PROCEDURE TensorType( VAR t: PCT.Struct );
- VAR aarray: PCT.Tensor; base: PCT.Struct; res: WORD;
- BEGIN
- Type( base, noname ); NEW( aarray ); t := aarray; PCT.InitTensor( aarray, base, res );
- IF res # PCT.Ok THEN Error( res, scanner.errpos ) END;
- t := aarray;
- END TensorType;
- (** << fof *)
- PROCEDURE ArrayType (VAR t: PCT.Struct; enhArray: BOOLEAN (* fof *));
- VAR index: PCB.Expression; array: PCT.Array; pos0, pos: LONGINT; res: WORD; base: PCT.Struct;
- (** fof >> *)
- earray: PCT.EnhArray; first: BOOLEAN; aarray: PCT.Tensor;
- (** << fof *)
- BEGIN
- pos0 := scanner.errpos;
- (* fof removed NOTAG, doesn't have any effect
- IF sym = lbrak THEN
- scanner.Get(sym);
- IF sym = ident THEN
- IF scanner.name # notag THEN Error(scanner.name, scanner.errpos) END
- ELSE Error(scanner.name, scanner.errpos) END;
- scanner.Get(sym); Check(rbrak)
- END;
- *)
- (** fof >> *)
- IF (~enhArray) & (sym = lbrak) THEN enhArray := TRUE; scanner.Get( sym ); first := TRUE ELSE first := FALSE END;
- IF first & (sym = PCS.qmark) THEN
- scanner.Get( sym ); Check( rbrak ); Check( of ); TensorType( t );
- ELSIF enhArray THEN
- IF sym = times THEN scanner.Get( sym ); index := NIL; ELSE SimpleExpr( index ); END;
- IF sym = rbrak THEN
- scanner.Get( sym ); Check( of ); pos := scanner.errpos; Type( base, noname );
- ELSIF sym = comma THEN scanner.Get( sym ); pos := scanner.errpos; ArrayType( base, TRUE )
- ELSE Error( rbrak, scanner.errpos ); t := PCT.UndefType; RETURN
- END;
- IF index = NIL THEN (* open enh array *)
- NEW( earray ); t := earray; PCT.InitOpenEnhArray( earray, base, {PCT.open}, res );
- IF res # PCT.Ok THEN Error( res, pos ) END;
- ELSIF ~PCT.IsCardinalType( index.type ) THEN (* invalid type *)
- Error( 51, pos ); t := PCT.UndefType
- ELSIF index IS PCB.Const THEN (* static enh array *)
- NEW( earray ); t := earray; PCT.InitStaticEnhArray( earray, index( PCB.Const ).con.int, base, {PCT.static}, res );
- ELSE (* dynamic sized enh array *)
- (* t := PCB.NewDynSizedEnhArray( index, base, res ); *)
- Error( 200, scanner.errpos ); t := PCT.UndefType; RETURN
- END;
- IF res # PCT.Ok THEN Error( res, pos ) END
- (** << fof *)
- ELSIF sym = of THEN
- scanner.Get(sym); pos := scanner.errpos; Type(base, noname);
- NEW(array); t := array;
- PCT.InitOpenArray(array, base, res);
- IF res # PCT.Ok THEN Error(res, pos) END
- ELSE
- SimpleExpr(index);
- IF sym = of THEN
- scanner.Get(sym); pos := scanner.errpos; Type(base, noname)
- ELSIF sym = comma THEN
- scanner.Get(sym); pos := scanner.errpos; ArrayType(base, FALSE (* fof *))
- ELSE
- Error(of, scanner.errpos); t := PCT.UndefType;
- RETURN
- END;
- IF ~PCT.IsCardinalType(index.type) THEN
- Error(51, pos); t := PCT.UndefType
- ELSIF index IS PCB.Const THEN
- NEW(array); t := array;
- PCT.InitStaticArray(array, index(PCB.Const).con.int, base, res)
- ELSE
- (*fof disabled semi-dynamic array functionality *)
- PCM.Error(50, pos, "");
- t := PCB.NewDynSizedArray(index, base, res)
- END;
- IF res # PCT.Ok THEN Error(res, pos) END
- END
- END ArrayType;
- PROCEDURE PointerType(VAR t: PCT.Struct; name: StringPool.Index);
- VAR pos, pos1: LONGINT; res: WORD; id: PCS.Name; o: PCT.Symbol; ptr: PCT.Pointer;
- BEGIN
- IF sym = record THEN
- scanner.Get(sym); RecordType(t, TRUE)
- ELSIF sym # ident THEN
- pos1:=scanner.errpos;
- Type(t, noname);
- NEW(ptr); PCT.InitPointer(ptr, t, res); t := ptr;
- IF res # PCT.Ok THEN Error(res, pos1) END
- ELSE (* ident own handling, because of forwards *)
- id := scanner.name;
- scanner.Get(sym);
- IF sym = period THEN (* Mod.Type *)
- o := PCT.Find(scope, scope, id, PCT.structdeclared, TRUE);
- IF o = NIL THEN
- Error(0, scanner.errpos);
- o := PCB.unknownObj
- ELSIF o IS PCT.Module THEN
- scanner.Get(sym);
- IF sym = ident THEN
- o := PCT.Find(scope, o(PCT.Module).scope, scanner.name, PCT.complete, TRUE);
- scanner.Get(sym);
- IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END
- ELSE
- Error(ident, scanner.errpos);
- o := PCB.unknownObj
- END
- END
- ELSE (* Type *)
- o := PCT.Find(scope, scope, id, PCT.local, TRUE);
- END;
- IF o = NIL THEN
- NEW(ptr);
- forwardPtr[nofForwardPtr].ptr := ptr;
- forwardPtr[nofForwardPtr].name := id;
- INC(nofForwardPtr);
- t := ptr
- ELSIF o IS PCT.Type THEN
- NEW(ptr); PCT.InitPointer(ptr, o.type, res); t := ptr;
- IF res # PCT.Ok THEN Error(res, pos) END
- ELSE
- Error(52, scanner.errpos); t := PCT.UndefType
- END
- END
- END PointerType;
- PROCEDURE Type (VAR t: PCT.Struct; name: StringPool.Index);
- VAR o: PCT.Symbol; procscope: PCT.ProcScope; pos: LONGINT; res: WORD;
- proc: PCT.Delegate; sf: SET;
- BEGIN
- pos := scanner.errpos;
- IF sym = array THEN
- Machine.AtomicInc(NArrays);
- scanner.Get(sym); ArrayType(t, FALSE (* fof *));
- ELSIF sym = record THEN
- Machine.AtomicInc(NRecords);
- scanner.Get(sym); RecordType(t, FALSE);
- ELSIF sym = pointer THEN
- Machine.AtomicInc(NPointers);
- scanner.Get(sym); Check(to); PointerType(t, noname);
- ELSIF sym = object THEN
- scanner.Get(sym);
- IF (sym = semicolon) OR (sym = rparen) THEN
- t := PCT.Ptr (* generic OBJECT *)
- ELSE
- Machine.AtomicInc(NObjects);
- ObjectType(t, name)
- END
- ELSIF sym = definition THEN
- Machine.AtomicInc(NDefinitions);
- scanner.Get(sym);
- DefinitionType(pos, t, name)
- ELSIF sym = procedure THEN
- Machine.AtomicInc(NProcedureTypes);
- scanner.Get(sym);
- TypeModifier(sf, {PCT.StaticMethodsOnly}, {PCT.StaticMethodsOnly, PCT.RealtimeProcType (* ug *), PCT.WinAPIParam, PCT.CParam} (* fof for Linux *) ); (* ejz *)
- IF (sf = {}) OR (sf = {PCT.RealtimeProc}) THEN Machine.AtomicInc(NDelegates) END;
- NEW(procscope); PCT.InitScope(procscope, scope, {}, FALSE); PCT.SetOwner(procscope);
- IF {PCT.CParam, PCT.WinAPIParam} * sf # {} (* fof for Linux *) THEN (* ejz *)
- IF scope IS PCT.ProcScope THEN
- PCM.Error(200, scanner.errpos, "invalid WINAPI proc")
- ELSIF PCT.CParam IN sf THEN (* fof for Linux *)
- procscope.SetCC( PCT.CLangCC )
- ELSE
- procscope.SetCC(PCT.WinAPICC)
- END
- END;
- FormalPars (procscope, t, sf - {PCT.StaticMethodsOnly}); (* ejz *)
- NEW(proc); PCT.InitDelegate(proc, t, procscope, sf, res);
- IF res # PCT.Ok THEN Error(res, pos) END;
- t := proc
- ELSE
- Qualident(o);
- IF (o IS PCT.Type) THEN
- t := o.type
- ELSE
- Error(52, scanner.errpos); t := PCT.UndefType
- END
- END
- END Type;
- PROCEDURE VarDecl;
- 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;
- BEGIN n := 1;
- pos[0] := scanner.errpos; (* fof *)
- IdentDef (id[0], TRUE);
- TypeModifier(flag[0], {}, {PCM.Untraced});
- WHILE sym = comma DO
- scanner.Get(sym);
- pos[n] := scanner.errpos; (* fof *)
- IdentDef (id[n], TRUE);
- TypeModifier(flag[n], {}, {PCM.Untraced});
- INC(n)
- END;
- Check(colon); Type(t, noname);
- c := 0;
- WHILE c < n DO
- scope.CreateVar(id[c].name, id[c].vis, flag[c], t, pos[c], (* fof *) NIL, res); INC(c);
- IF res # PCT.Ok THEN PCM.ErrorN(res, scanner.errpos, id[c-1].name) END
- END;
- END VarDecl;
- PROCEDURE TypeDecl;
- VAR i: IdentDefDesc; pos: LONGINT; res: WORD; t: PCT.Struct;
- BEGIN
- pos := scanner.errpos;
- IdentDef(i, FALSE); Check(eql); Type(t, i.name);
- scope.CreateType(i.name, i.vis, t, pos, (*fof*) res);
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END;
- END TypeDecl;
- PROCEDURE ConstDecl;
- VAR i: IdentDefDesc; x: PCB.Const; pos: LONGINT; res: WORD; long: HUGEINT;
- BEGIN
- pos := scanner.errpos;
- IdentDef(i, FALSE); Check(eql); ConstExpr(x);
- scope.CreateValue(i.name, i.vis, x.con, pos, (*fof*) res);
- IF x.con.type = PCT.Int64 THEN
- long := x.con.long;
- IF long DIV 2 <= LONG(MAX(LONGINT)) THEN
- (*!fof: replace this with a warning once everything is converted *)
- PCM.Error(-1,pos,"unsigned longint is a hugeint -> use SHORT");
- END;
- END;
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END
- END ConstDecl;
- PROCEDURE FixForwards;
- VAR obj: PCT.Symbol; state: SHORTINT; res: WORD;
- BEGIN
- state := PCT.structallocated;
- IF isRecord THEN state := PCT.structdeclared END;
- WHILE nofForwardPtr > 0 DO
- DEC(nofForwardPtr);
- obj := PCT.Find(scope, scope, forwardPtr[nofForwardPtr].name, state, TRUE);
- IF obj = NIL THEN
- PCM.ErrorN(128, scanner.errpos, forwardPtr[nofForwardPtr].name); obj := PCB.unknownObj
- END;
- PCT.InitPointer(forwardPtr[nofForwardPtr].ptr, obj.type, res);
- IF res # PCT.Ok THEN Error(res, scanner.errpos) END
- END
- END FixForwards;
- PROCEDURE ListOf(parse: PROCEDURE);
- BEGIN
- scanner.Get(sym);
- WHILE sym = ident DO
- parse;
- CheckSemicolons;
- END
- END ListOf;
- PROCEDURE DeclSeq;
- VAR t: PCT.Struct; name: PCS.Name; pos: LONGINT; res: WORD;
- BEGIN
- WHILE sym = definition DO
- pos := scanner.errpos;
- scanner.Get(sym);
- name := scanner.name;
- Check(ident);
- DefinitionType(pos, t, name);
- Check(semicolon);
- scope.CreateType(name, PCT.Public, t, pos(*fof*), res);
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos, name) END
- END;
- LOOP
- IF sym = const THEN
- scanner.Get(sym);
- WHILE sym = ident DO
- ConstDecl;
- CheckSemicolons;
- END
- ELSIF sym = type THEN
- scanner.Get(sym);
- WHILE sym = ident DO
- TypeDecl;
- CheckSemicolons;
- END
- ELSIF sym = var THEN
- scanner.Get(sym);
- WHILE sym = ident DO
- VarDecl;
- CheckSemicolons;
- END
- ELSE
- EXIT
- END
- END;
- FixForwards;
- PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
- PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
- WHILE sym = procedure DO
- scanner.Get(sym); ProcDecl;
- IF sym # end THEN Check(semicolon) END
- END;
- PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos);
- savedsym := sym;
- savedscanner := scanner;
- scanner := PCS.ForkScanner(scanner);
- inspect := TRUE;
- Body(TRUE); (* suppress = TRUE *)
- scanner := savedscanner;
- sym := savedsym;
- inspect := FALSE;
- PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos);
- END DeclSeq;
- (* --------------------------------------------------------- *)
- (* Active Oberon Language Productions *)
- (* Implementation Section *)
- PROCEDURE Qualident (VAR o: PCT.Symbol); (*Qualident = [ident "."] ident*)
- (* returns the object or unknownObj *)
- VAR pos: LONGINT;
- BEGIN
- IF sym = ident THEN
- IF scanner.name = self THEN
- o := PCT.Find(scope, scope, PCT.SelfName, PCT.procdeclared, TRUE)
- ELSIF scope.state >= PCT.procdeclared THEN (*parsing code*)
- o := PCT.Find(scope, scope, scanner.name, PCT.procdeclared, TRUE)
- ELSIF isRecord THEN
- o := PCT.Find(scope, scope, scanner.name, PCT.structdeclared, TRUE) (*break scope <-> recordscope cycle*)
- ELSE
- o := PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE)
- END;
- pos := scanner.errpos; scanner.Get(sym);
- IF o = NIL THEN
- Error(0, pos); o := PCB.unknownObj
- ELSIF (sym = period) & (o IS PCT.Module) THEN (*semantic check needed because of language design*)
- scanner.Get(sym);
- IF sym = ident THEN
- o := PCT.Find(scope, o(PCT.Module).scope, scanner.name, PCT.procdeclared(*PCT.complete*), TRUE);
- scanner.Get(sym);
- IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
- ELSE Error(ident, scanner.errpos);
- END
- END
- ELSE o := PCB.unknownObj; Error(ident, scanner.errpos);
- END;
- END Qualident;
- PROCEDURE GetModule(VAR o: PCT.Symbol);
- BEGIN
- IF sym = ident THEN
- o := PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE);
- ELSE
- o := PCB.unknownObj; Error(ident, scanner.errpos);
- END;
- END GetModule;
- (** fof >> *)
- PROCEDURE Range( VAR exp, texp, bexp: PCB.Expression ): BOOLEAN;
- VAR isRange: BOOLEAN;
- BEGIN
- exp := NIL; texp := NIL; bexp := NIL;
- IF sym = times THEN isRange := TRUE; scanner.Get( sym );
- ELSIF sym = upto THEN (* ".." without first argument *)
- ELSE Expr( exp ); isRange := FALSE;
- END;
- IF (sym = upto) THEN
- isRange := TRUE; scanner.Get( sym );
- IF (sym = ident) & (scanner.name = StringPool.GetIndex1( "MAX" )) THEN
- scanner.Get( sym );
- IF sym = by THEN
- (* Error( 200, scanner.errpos ); *)
- scanner.Get( sym ); Expr( bexp );
- END;
- ELSIF sym = by THEN (* ".." without second argument *)
- scanner.Get( sym ); Expr( bexp );
- ELSIF (sym = comma) OR (sym = rbrak) OR (sym = rparen) THEN RETURN TRUE;
- ELSE
- Expr( texp );
- IF sym = by THEN
- (* Error( 200, scanner.errpos ); *)
- scanner.Get( sym ); Expr( bexp );
- END;
- END;
- END;
- RETURN isRange;
- END Range;
- (** << fof *)
- PROCEDURE ExprList(VAR x: PCB.ExprList);
- VAR y: PCB.Expression;
- texp, bexp: PCB.Expression; z: PCB.Const; range: BOOLEAN; (* fof *)
- BEGIN
- (** fof >> *)
- LOOP
- IF Range( y, texp, bexp ) THEN
- IF y = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( 0, PCT.Int32 ) ); y := z; END;
- IF texp = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( MAX( LONGINT ), PCT.Int32 ) ); texp := z END;
- IF bexp = NIL THEN NEW( z, scanner.errpos, PCT.NewIntConst( 1, PCT.Int32 ) ); bexp := z END;
- x.Append( y ); x.Append( texp ); x.Append( bexp );
- ELSE x.Append( y );
- END;
- IF sym = comma THEN scanner.Get( sym ); ELSE EXIT END;
- END; (* loop *)
- (** << fof *)
- (*
- Expr(y); x.Append(y);
- WHILE sym = comma DO
- scanner.Get(sym); Expr(y); x.Append(y)
- END
- *)
- END ExprList;
- PROCEDURE GetGuard(search: PCT.Scope; symbol: PCT.Symbol): PCT.Symbol;
- BEGIN
- WHILE search # NIL DO
- IF search IS PCT.WithScope THEN
- IF search(PCT.WithScope).withSym = symbol THEN
- RETURN search(PCT.WithScope).withGuard;
- END;
- END;
- search := search.parent;
- END;
- RETURN NIL;
- END GetGuard;
- PROCEDURE Designator(VAR x: PCB.Designator);
- VAR o: PCT.Symbol; exp: PCB.Expression; y: PCB.Designator;
- guard: PCT.Symbol;
- ovlarray: BOOLEAN; m: PCT.Method;
- (** fof >> *)
- texp, bexp: PCB.Expression; (* from .. to BY by *)
- range: BOOLEAN; atype: PCT.Struct; idx: PCB.EnhIndex; aidx: PCB.AnyIndex;
- (** << fof *)
- BEGIN
- LOOP
- IF x IS PCB.Var THEN
- guard := GetGuard(scope, x(PCB.Var).obj);
- IF guard # NIL THEN
- x := PCB.NewGuard(scanner.errpos, x, guard, FALSE);
- END;
- ELSIF x IS PCB.Field THEN
- guard := GetGuard(scope, x(PCB.Field).field);
- IF guard # NIL THEN
- x := PCB.NewGuard(scanner.errpos, x, guard, FALSE);
- END
- END;
- IF sym = period THEN
- scanner.Get(sym);
- IF sym = ident THEN
- x := PCB.NewField(codescope, x, scanner.name, scanner.errpos); scanner.Get(sym)
- ELSE
- Error(ident, scanner.errpos)
- END
- ELSIF sym = lbrak THEN
- ovlarray := FALSE;
- IF x.type IS PCT.Pointer THEN
- IF (x.type(PCT.Pointer).base IS PCT.Record) THEN
- m := PCT.FindIndexer(x.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.ReadIndexer));
- IF m = NIL THEN
- m := PCT.FindIndexer(x.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.AssignIndexer))
- END;
- ovlarray := m # NIL;
- END;
- END;
- IF ovlarray THEN
- RETURN
- (** fof >> *)
- ELSIF x.type IS PCT.EnhArray THEN (* enhanced array treatment *)
- idx := PCB.NewEnhIndex( scanner.errpos, x ); x := idx;
- (* NEW( idx, scanner.errpos, x ); x := idx; *)
- scanner.Get( sym );
- LOOP
- IF Range( exp, texp, bexp ) THEN (* ranged expression of the form [exp] .. [texp] [BY bexp] *)
- idx.AppendRange( scanner.errpos, exp, texp, bexp );
- ELSE (* exp is already parsed *)
- idx.AppendIndex( scanner.errpos, exp );
- END;
- IF sym # comma THEN EXIT END;
- scanner.Get( sym )
- END;
- Check( rbrak ); idx.Finish;
- ELSIF x.type IS PCT.Tensor THEN (* any array treatment *)
- NEW( aidx, scanner.errpos, x ); x := aidx; scanner.Get( sym );
- LOOP
- IF sym = filler THEN scanner.Get( sym ); aidx.AppendFiller( scanner.errpos );
- ELSIF Range( exp, texp, bexp ) THEN (* ranged expression of the form [exp] .. [texp] [BY bexp] *)
- (* idx.AppendRange( scanner.errpos, exp, texp, bexp ); *)
- aidx.AppendRange( scanner.errpos, exp, texp, bexp );
- ELSE (* exp is already parsed *)
- aidx.AppendIndex( scanner.errpos, exp );
- END;
- IF sym # comma THEN EXIT END;
- scanner.Get( sym )
- END;
- Check( rbrak ); aidx.Finish;
- (** << fof *)
- ELSE
- (** fof >> *)
- range := FALSE; atype := x.type;
- (*IF x IS PCB.Range THEN PCM.Error( -1, scanner.errpos, "ranges cannot be indexed directly" ); END; *)
- (** << fof *)
- scanner.Get(sym);
- LOOP
- Expr(exp); x := PCB.NewIndex(scanner.errpos, x, exp);
- IF sym # comma THEN EXIT END;
- scanner.Get(sym)
- END;
- Check(rbrak)
- END
- ELSIF sym = arrow THEN
- x := PCB.NewDeref(scanner.errpos, x);
- scanner.Get(sym)
- ELSIF (sym = lparen) & PCB.IsInterface(x) THEN
- INCL(PCM.codeOptions, PCM.UseDefinitions); (* use lookup and call *)
- scanner.Get(sym);
- Qualident(o);
- y := PCB.MakeNode(scanner.errpos, codescope, o);
- Designator(y);
- Check(rparen);
- x := PCB.Interface(x, y)
- (*ELSIF (sym=lparen) & (x IS PCB.Type) THEN
- scanner.Get(sym); Expr(y); Check(rparen);
- x := PCB.NewConversion(scanner.errpos,y,x.type);
- *)
- ELSIF (sym = lparen) & ~x.IsCallable() & (scope.state >= PCT.procdeclared) THEN (*needs semantic check because of ambiguous language design*)
- (*in declaration phase only expressions make sense!*)
- scanner.Get(sym); Qualident (o); Check(rparen);
- x:=PCB.NewGuard(scanner.errpos, x, o, FALSE)
- ELSE
- EXIT (* -> ENDLOOP *)
- END;
- END (* LOOP *)
- END Designator;
- PROCEDURE Element(VAR x: PCB.Expression);
- VAR y: PCB.Expression; pos: LONGINT;
- BEGIN
- Expr(x);
- IF sym = upto THEN
- pos:=scanner.errpos;
- scanner.Get(sym); Expr(y); x:=PCB.NewDOp(pos, PCC.setfn, x, y) (*this operator cannot be overwritten*)
- ELSE
- x := PCB.NewMOp(scanner.errpos, NIL, PCC.setfn, x); (*this operator cannot be overwritten*)
- END
- END Element;
- PROCEDURE Set(VAR x: PCB.Expression);
- VAR y: PCB.Expression; pos: LONGINT;
- BEGIN
- scanner.Get(sym);
- IF sym # rbrace THEN
- Element(x);
- WHILE sym = comma DO
- pos:=scanner.errpos;
- scanner.Get(sym); Element(y); x := PCB.NewDOp(pos, plus, x, y);
- END
- ELSE
- x := PCB.NewSetValue(scanner.errpos, {})
- END;
- Check(rbrace)
- END Set;
- (** fof >> *)
- PROCEDURE MathArray( VAR x: PCB.Expression );
- (* temporary patch to make array expressions work. This will be improved in the new compiler *)
- VAR array: PCB.ArrayExpression;
- len: ARRAY 32 OF LONGINT;
- dim: LONGINT; type: PCT.Struct;
- name: ARRAY 256 OF CHAR;
- error: BOOLEAN;
- bytes: POINTER TO ARRAY OF SYSTEM.BYTE;
- pos: LONGINT; size: LONGINT;
- PROCEDURE Parse( a: PCB.ArrayExpression );
- VAR array: PCB.ArrayExpression; first,aq: PCB.ArrayQ;
- BEGIN
- NEW(aq); first := aq; a.pos := scanner.errpos;
- scanner.Get( sym );
- IF sym = lbrak THEN
- LOOP
- NEW( array ); Parse( array ); aq.e := array; aq.pos := scanner.errpos;
- IF sym = comma THEN
- scanner.Get( sym );
- IF sym # lbrak THEN PCM.Error( lbrak, scanner.errpos, "[ expected" ); EXIT; END;
- NEW( aq.next ); aq := aq.next;
- ELSE EXIT
- END;
- END;
- ELSE
- LOOP
- aq.pos := scanner.errpos; Expr( aq.e );
- IF sym = comma THEN scanner.Get( sym ); ELSE EXIT END;
- NEW( aq.next ); aq := aq.next;
- END;
- END;
- Check( rbrak );
- a.SetArray(first);
- END Parse;
- PROCEDURE CheckLens( a: PCB.ArrayQ; d: LONGINT );
- VAR l, pos: LONGINT;
- BEGIN
- IF d > dim THEN dim := d END;
- l := 0;
- WHILE (a # NIL ) DO
- pos := a.pos;
- IF a.e IS PCB.ArrayExpression THEN CheckLens( a.e(PCB.ArrayExpression).array, d + 1 ) END;
- a := a.next; INC( l );
- END;
- IF len[d] = 0 THEN
- (* KernelLog.String("len["); KernelLog.Int(d,0); KernelLog.String("] = "); KernelLog.Int(l,0); KernelLog.Ln; *)
- len[d] := l
- ELSIF len[d] # l THEN PCM.Error( 999, pos, "array dimensions must be of equal size" );
- ELSE (* KernelLog.String("(len["); KernelLog.Int(d,0); KernelLog.String("] ok)"); KernelLog.Ln; *)
- END;
- END CheckLens;
- PROCEDURE GetType( a: PCB.ArrayQ );
- VAR name: ARRAY 64 OF CHAR;
- BEGIN
- WHILE (a # NIL ) DO
- IF a.e IS PCB.ArrayExpression THEN GetType( a.e(PCB.ArrayExpression).array )
- ELSE
- PCT.GetTypeName( a.e.type, name );
- (* KernelLog.String("Type: "); KernelLog.String(name); KernelLog.Ln; *)
- IF type = NIL THEN type := a.e.type
- ELSIF a.e.type = type THEN (* ok *)
- ELSIF PCT.IsBasic( a.e.type ) & PCT.IsBasic( type ) THEN
- IF (PCT.TypeDistance( type, a.e.type ) > 0) THEN type := a.e.type END;
- ELSE error := TRUE; PCM.Error( 999, a.pos, "invalid type" );
- END;
- END;
- a := a.next;
- END;
- END GetType;
- PROCEDURE Convert( a: PCB.ArrayQ );
- VAR e: PCB.Expression;
- BEGIN
- WHILE (a # NIL ) DO
- 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;
- a := a.next;
- END;
- END Convert;
- PROCEDURE FillConst( a: PCB.ArrayQ );
- VAR s: SHORTINT; i: INTEGER; l: LONGINT; r: REAL; x: LONGREAL; con: PCT.Const;
- BEGIN
- WHILE (a # NIL ) DO
- IF a.e IS PCB.ArrayExpression THEN FillConst( a.e(PCB.ArrayExpression).array )
- ELSE
- IF a.e IS PCB.Const THEN
- con := a.e( PCB.Const ).con;
- IF type = PCT.Int8 THEN s := SHORT( SHORT( con.int ) ); SYSTEM.MOVE( ADDRESSOF( s ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Int16 THEN i := SHORT( con.int ); SYSTEM.MOVE( ADDRESSOF( i ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Int32 THEN l := con.int; SYSTEM.MOVE( ADDRESSOF( l ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Float32 THEN r := SHORT( con.real ); SYSTEM.MOVE( ADDRESSOF( r ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Float64 THEN x := con.real; SYSTEM.MOVE( ADDRESSOF( x ), ADDRESSOF( bytes[pos] ), size );
- ELSE PCM.Error( 200, a.pos, "basic types only" );
- END;
- ELSE
- IF type = PCT.Int8 THEN s := -1; SYSTEM.MOVE( ADDRESSOF( s ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Int16 THEN i := -1; SYSTEM.MOVE( ADDRESSOF( i ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Int32 THEN l := -1; SYSTEM.MOVE( ADDRESSOF( l ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Float32 THEN r := -1; SYSTEM.MOVE( ADDRESSOF( r ), ADDRESSOF( bytes[pos] ), size );
- ELSIF type = PCT.Float64 THEN x := -1; SYSTEM.MOVE( ADDRESSOF( x ), ADDRESSOF( bytes[pos] ), size );
- ELSE PCM.Error( 200, a.pos, "basic types only" );
- END;
- END;
- INC( pos, size );
- END;
- a := a.next;
- END;
- END FillConst;
- PROCEDURE IsConst(a: PCB.ArrayQ): BOOLEAN;
- VAR result: BOOLEAN;
- BEGIN
- result := TRUE;
- WHILE (a # NIL) & result DO
- IF a.e IS PCB.ArrayExpression THEN
- result := IsConst(a.e(PCB.ArrayExpression).array)
- ELSE
- result := a.e IS PCB.Const;
- END;
- a := a.next;
- END;
- RETURN result
- END IsConst;
- BEGIN
- error := FALSE;
- NEW( array); Parse( array ); dim := -1; CheckLens( array.array, 0 );
- (*KernelLog.String("dim="); KernelLog.Int(dim+1,0); KernelLog.Ln; *)
- type := NIL; GetType( array.array );
- IF error THEN RETURN END;
- PCT.GetTypeName( type, name );
- (* KernelLog.String("Common type: "); KernelLog.String(name); KernelLog.Ln; *)
- IF ~error THEN
- Convert( array.array );
- (* KernelLog.String("is const");*)
- IF type = PCT.Int8 THEN size := 1
- ELSIF type = PCT.Int16 THEN size := 2
- ELSIF type = PCT.Int32 THEN size := 4
- ELSIF type = PCT.Float32 THEN size := 4
- ELSIF type = PCT.Float64 THEN size := 8
- END;
- IF IsConst(array.array) THEN
- NEW( bytes, size * pos ); pos := 0;
- FillConst( array.array );
- x := PCB.NewArrayValue( scanner.errpos, bytes^, len, dim + 1, type );
- ELSE
- array.SetType(PCT.MakeArrayType(len,dim+1,type,size));
- x := array;
- END;
- END;
- ASSERT(x#NIL);
- END MathArray;
- (** << fof *)
- PROCEDURE Factor(VAR x: PCB.Expression);
- VAR el: PCB.ExprList; d, dh: PCB.Designator; o: PCT.Symbol; h: PCT.Variable; hiddenVarName : StringPool.Index;
- rtype: PCT.Struct; pos: LONGINT; mod: PCT.Symbol; ap: PCB.AnyProc; res : WORD;
- m: PCT.Proc;
- pars: ARRAY 1 OF PCB.Expression; (* ug *)
- (** fof >> *)
- c: PCB.ConstDesignator; y: PCB.Expression; wasNot: BOOLEAN;
- (** << fof *)
- BEGIN
- pos := scanner.errpos;
- wasNot := FALSE; (* fof *)
- IF sym = number THEN
- CASE scanner.numtyp OF
- | PCS.char: x := PCB.NewIntValue(scanner.errpos, scanner.intval, PCT.GetCharType(scanner.intval))
- | PCS.integer: x := PCB.NewIntValue(scanner.errpos, scanner.intval, PCT.GetIntType(scanner.intval))
- | PCS.longinteger: x := PCB.NewLongIntValue(scanner.errpos, scanner.longintval)
- | PCS.real: x := PCB.NewFloatValue(scanner.errpos, scanner.realval, PCT.Float32)
- | PCS.longreal: x := PCB.NewFloatValue(scanner.errpos, scanner.lrlval, PCT.Float64)
- END;
- scanner.Get(sym)
- ELSIF sym = string THEN
- x := PCB.NewStrValue(scanner.errpos, scanner.str); scanner.Get(sym)
- ELSIF sym = nil THEN
- x:=PCB.NewNILValue(scanner.errpos); scanner.Get(sym)
- ELSIF sym = true THEN
- x := PCB.NewBoolValue(scanner.errpos, TRUE); scanner.Get(sym)
- ELSIF sym = false THEN
- x := PCB.NewBoolValue(scanner.errpos, FALSE); scanner.Get(sym)
- ELSIF sym = lbrace THEN (*Set*)
- Set(x)
- (** fof >> *)
- ELSIF sym = lbrak THEN (* constant array *)
- MathArray( x );
- IF x IS PCB.ArrayExpression THEN
- scope.CreateHiddenVarName(hiddenVarName);
- scope.CreateVar(hiddenVarName, PCT.Hidden, {}, x.type, pos, o, res);
- h := scope.FindHiddenVar(pos, o);
- dh := PCB.MakeNode(scanner.errpos, codescope, h);
- x(PCB.ArrayExpression).d := dh
- END;
- (** << fof *)
- ELSIF sym = lparen THEN (*Subexpression*)
- scanner.Get(sym); Expr(x) ; Check(rparen)
- ELSIF (sym=not) THEN
- wasNot := TRUE; (* fof *)
- scanner.Get(sym);
- IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~(PCM.NoOpOverloading IN PCM.parserOptions) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- Factor(y (* fof *));
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic((* fof *) y.type) THEN
- x := PCB.NewMOp(scanner.errpos, scope, not, y (* fof *))
- ELSE
- pars[0] := y (* fof *);
- x := CallOperator(not, mod, pars, pos);
- END;
- ELSIF (sym = ident) THEN
- Qualident(o);
- IF o IS PCT.Value THEN
- (** fof >> *)
- IF (o( PCT.Value ).const # NIL ) &
- (o( PCT.Value ).const.type IS PCT.EnhArray) THEN (* may be used as designator *)
- d := PCB.MakeNode( scanner.errpos, codescope, o ); Designator( d ); x := d;
- ELSE
- (** << fof *)
- x := PCB.NewValue(scanner.errpos, o)
- END; (** fof *)
- ELSE
- IF (sym = lparen) & (o IS PCT.Type) THEN
- scanner.Get(sym);
- Expr(x); Check(rparen);
- x := PCB.NewConversion(scanner.errpos,x,o.type);
- ELSE
- d := PCB.MakeNode(scanner.errpos, codescope, o); Designator(d);
- IF PCB.IsProcReturningPointer(d, rtype) & inspect THEN
- scope.CreateHiddenVarName(hiddenVarName);
- scope.CreateVar(hiddenVarName, PCT.Hidden, {}, rtype, pos, o, res);
- END;
- IF (sym = lparen) THEN
- el := PCB.NewExprList(scanner.errpos, d);
- scanner.Get(sym);
- IF sym # rparen THEN ExprList(el) END;
- IF PCB.IsProcReturningPointer(d, rtype) THEN
- h := scope.FindHiddenVar(pos, o);
- ASSERT(h # NIL);
- dh := PCB.MakeNode(scanner.errpos, codescope, h);
- el.Append(dh)
- END;
- Check(rparen);
- IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
- x := PCB.NewFuncCall(scanner.errpos, d, el, scopelevel);
- ELSIF (sym = lbrak) THEN
- (* Find PCT.ReadIndexer method in scope of the type. *)
- m := PCT.FindIndexer(d.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.ReadIndexer));
- IF m # NIL THEN
- NEW(ap, scanner.errpos, scope, m, d (* SELF *));
- d := ap;
- el:=PCB.NewExprList(scanner.errpos, d);
- scanner.Get(sym);
- IF sym # rbrak THEN ExprList(el) END;
- Check(rbrak);
- x := PCB.NewFuncCall(scanner.errpos, d, el, scopelevel);
- END
- ELSE x := d
- END
- END
- END;
- ELSE
- Error(13, scanner.errpos); x:=PCB.InvalidExpr; scanner.Get(sym)
- END;
- (** fof >> *)
- (* suffix *)
- IF sym = PCS.transpose THEN
- IF wasNot THEN (* transpose operator has higher precedence than not, reevaluate expression: *)
- x := PCB.NewMOp( scanner.errpos, scope, transpose, y ); x := PCB.NewMOp( scanner.errpos, scope, not, x );
- ELSE x := PCB.NewMOp( scanner.errpos, scope, transpose, x );
- END;
- scanner.Get( sym );
- END;
- (** << fof *)
- END Factor;
- PROCEDURE Term(VAR x: PCB.Expression);
- VAR
- y : PCB.Expression; op: PCS.Token; pos: LONGINT;
- mod: PCT.Symbol;
- pars: ARRAY 2 OF PCB.Expression; (* ug *)
- BEGIN
- Factor(x);
- WHILE (sym >= times) & (sym <= and) OR (sym >= backslash) & (sym <= egeq) (* fof *) DO
- pos:=scanner.errpos; op := sym; scanner.Get(sym);
- mod := NIL;
- IF AllowOverloadedModule & (* fof *) (sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- Factor(y);
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
- x := PCB.NewDOp(pos, op, x, y)
- ELSE
- pars[0] := x; pars[1] := y; (* ug *)
- x := CallOperator(op, mod, pars, pos);
- END
- END
- END Term;
- PROCEDURE CallAssignmentOp(op: PCS.Token; mod: PCT.Symbol; p1: PCB.Designator; p2: PCB.Expression; pos: LONGINT; suppress: BOOLEAN);
- VAR
- pars: ARRAY 2 OF PCT.Struct;
- name: PCS.Name; o: PCT.Symbol; d: PCB.Designator; el: PCB.ExprList;
- parents: BOOLEAN;
- searchScope: PCT.Scope;
- BEGIN
- PCS.GetOpName(op, name);
- IF (mod # NIL) & (mod IS PCT.Module) THEN
- searchScope := mod(PCT.Module).scope;
- parents := FALSE;
- ELSE
- searchScope := scope;
- parents := TRUE;
- END;
- (* o := GetOperator(name, pars^, pos); *)
- pars[0] := p1.type; pars[1] := p2.type;
- o := PCT.FindOperator(scope, searchScope, parents, name, pars, LEN(pars), pos);
- IF o = NIL THEN
- (* Error(137, pos); (* operator not defined *) *)
- PCB.Assign(code, suppress, p1, p2, FALSE (*fof*));
- ELSE
- d := PCB.MakeNode(pos, codescope, o);
- Designator(d);
- el := PCB.NewExprList(pos, d);
- el.Append(p1);
- el.Append(p2);
- (* RETURN PCB.NewFuncCall(pos, d, el, scopelevel); *)
- PCB.CallProc(code, suppress, d, el,scopelevel);
- END;
- END CallAssignmentOp;
- PROCEDURE CallOperator(op: PCS.Token; mod: PCT.Symbol; pars: ARRAY OF PCB.Expression; pos: LONGINT): PCB.Expression;
- VAR
- name: PCS.Name; o: PCT.Symbol; d: PCB.Designator; el: PCB.ExprList;
- parents: BOOLEAN;
- searchScope: PCT.Scope;
- args: ARRAY 2 OF PCT.Struct;
- dh: PCB.Designator; h: PCT.Variable; hiddenVarName : StringPool.Index;
- rtype: PCT.Struct; res: WORD; i : LONGINT;
- BEGIN
- PCS.GetOpName(op, name);
- IF (mod # NIL) & (mod IS PCT.Module) THEN
- searchScope := mod(PCT.Module).scope;
- parents := FALSE;
- ELSE
- searchScope := scope;
- parents := TRUE;
- END;
- FOR i := 0 TO LEN(pars)-1 DO
- args[i] := pars[i].type
- END;
- o := PCT.FindOperator(scope, searchScope, parents, name, args, LEN(pars), pos);
- IF o = NIL THEN
- (* Error(137, pos); (* operator not defined *) *)
- IF LEN(pars) = 1 THEN
- RETURN PCB.NewMOp(pos, scope, op, pars[0])
- ELSE
- RETURN PCB.NewDOp(pos, op, pars[0], pars[1])
- END
- END;
- d := PCB.MakeNode(pos, codescope, o); Designator(d);
- IF PCB.IsProcReturningPointer(d, rtype) & inspect THEN
- scope.CreateHiddenVarName(hiddenVarName);
- scope.CreateVar(hiddenVarName, PCT.Hidden, {}, rtype, pos, o, res);
- END;
- el := PCB.NewExprList(pos, d);
- FOR i := 0 TO LEN(pars)-1 DO
- el.Append(pars[i])
- END;
- IF PCB.IsProcReturningPointer(d, rtype) THEN
- h := scope.FindHiddenVar(pos, o);
- ASSERT(h # NIL);
- dh := PCB.MakeNode(pos, codescope, h);
- el.Append(dh)
- END;
- IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
- RETURN PCB.NewFuncCall(pos, d, el, scopelevel);
- END CallOperator;
- PROCEDURE SimpleExpr(VAR x: PCB.Expression);
- VAR y: PCB.Expression; op: PCS.Token; pos: LONGINT;
- mod: PCT.Symbol;
- pars1: ARRAY 1 OF PCB.Expression; pars2: ARRAY 2 OF PCB.Expression; (* ug *)
- BEGIN
- IF (sym = plus) OR (sym = minus) THEN
- pos := scanner.errpos;
- op := sym; scanner.Get(sym);
- IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~(PCM.NoOpOverloading IN PCM.parserOptions) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- Term(x);
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type) THEN
- x := PCB.NewMOp(pos, scope, op, x)
- ELSE
- pars1[0] := x;
- x := CallOperator(op, mod, pars1, pos);
- END
- ELSE
- Term(x)
- END;
- WHILE (sym >= plus) & (sym <= or) DO
- pos:=scanner.errpos;
- op := sym; scanner.Get(sym);
- mod := NIL;
- IF AllowOverloadedModule & (* fof *) (sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- Term(y);
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
- x := PCB.NewDOp(pos, op, x, y)
- ELSE
- pars2[0] := x; pars2[1] := y; (* ug *)
- x := CallOperator(op, mod, pars2, pos);
- END
- END
- END SimpleExpr;
- PROCEDURE Expr(VAR x: PCB.Expression);
- VAR y: PCB.Expression; op: PCS.Token; pos: LONGINT;
- mod: PCT.Symbol;
- pars : ARRAY 2 OF PCB.Expression; (* ug *)
- BEGIN
- SimpleExpr(x);
- IF (sym >= eql) & (sym <= is) THEN
- pos:=scanner.errpos;
- op := sym; scanner.Get(sym);
- IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(x.type)) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- SimpleExpr(y);
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(x.type) & PCT.IsBasic(y.type)) THEN
- x := PCB.NewDOp(pos, op, x, y)
- ELSE
- pars[0] := x; pars[1] := y; (* ug *)
- x := CallOperator(op, mod, pars, pos);
- END
- END
- END Expr;
- PROCEDURE ConstExpr(VAR x: PCB.Const);
- VAR pos: LONGINT; y: PCB.Expression;
- BEGIN
- pos := scanner.errpos;
- Expr(y);
- x := PCB.ConstExpression(pos, y)
- END ConstExpr;
- PROCEDURE Case(body, suppress: BOOLEAN; VAR awaitCount: LONGINT; VAR caseinfo: PCB.CaseInfo);
- VAR x, y: PCB.Const; firstline: BOOLEAN;
- BEGIN
- firstline := TRUE;
- LOOP
- ConstExpr(x); y := x;
- IF sym = upto THEN
- scanner.Get(sym); ConstExpr(y);
- END;
- PCB.CaseLine(code, suppress, caseinfo, x, y, firstline);
- firstline := FALSE;
- IF sym # comma THEN EXIT END;
- scanner.Get(sym)
- END;
- Check(colon);
- StatementSeq(body, suppress, awaitCount)
- END Case;
- PROCEDURE If(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
- VAR cond: PCB.Expression; info: PCB.LoopInfo; ifsuppress, elsifclause: BOOLEAN;
- BEGIN
- (* if/elsif already checked *)
- elsifclause := FALSE;
- LOOP
- Expr(cond); Check(then);
- ifsuppress := PCB.If(code, suppress, info, cond, elsifclause);
- StatementSeq(body, suppress OR ifsuppress, awaitCount);
- IF sym # elsif THEN EXIT END;
- elsifclause := TRUE;
- scanner.Get(sym);
- END;
- IF sym = else THEN
- scanner.Get(sym);
- ifsuppress := PCB.Else(code, suppress, info);
- StatementSeq(body, suppress OR ifsuppress, awaitCount)
- END;
- PCB.EndIf(code, suppress, info);
- Check(end)
- END If;
- PROCEDURE BlockModifier(allowBody, suppress: BOOLEAN; VAR locked: BOOLEAN);
- VAR x: PCB.Const; c: LONGINT; res: WORD;
- BEGIN
- IF sym = lbrace THEN
- locked := FALSE;
- IF ~suppress THEN
- scanner.Get(sym);
- LOOP
- IF sym = ident THEN
- IF scanner.name = exclusive THEN
- Machine.AtomicInc(NExclusive);
- IF allowBody THEN Machine.AtomicInc(NExclusiveMain) END;
- PCT.SetMode(scope, PCT.exclusive, res);
- scanner.Get(sym);
- locked := TRUE
- ELSIF allowBody & (scanner.name = active) THEN
- Machine.AtomicInc(NActive);
- PCT.SetMode(scope, PCT.active, res);
- scanner.Get(sym)
- ELSIF allowBody & (scanner.name = realtime) THEN
- PCT.SetProcFlag(scope, PCT.RealtimeProc, res);
- scanner.Get(sym)
- ELSIF allowBody & (scanner.name = safe) THEN
- PCT.SetMode(scope, PCT.safe, res);
- scanner.Get(sym)
- ELSIF allowBody & (scanner.name = priority) THEN
- scanner.Get(sym);
- IF sym = lparen THEN
- scanner.Get(sym); ConstExpr(x); Check(rparen);
- IF ~PCT.IsCardinalType(x.type) THEN
- c:=0; Error(51, scanner.errpos)
- ELSIF x.type # PCT.Int8 THEN
- c := 0; Error(220, scanner.errpos)
- ELSE
- c := x.con.int
- END
- ELSE
- c:=0
- END;
- IF isRecord THEN
- scope.parent(PCT.RecScope).owner.prio := c;
- ELSE
- PCM.Error(200, scanner.errpos, "priority only for records")
- END
- ELSE Error(0, scanner.errpos); scanner.Get(sym) (*skip the ident, probably a typo*)
- END;
- IF res # PCT.Ok THEN Error(res, scanner.errpos); res := 0 END
- ELSE
- Check (ident);
- END;
- IF sym # comma THEN EXIT END;
- scanner.Get(sym)
- END;
- IF PCT.IsRealtimeScope(scope) THEN
- IF isRecord THEN
- scope.parent(PCT.RecScope).owner.prio := Objects.Realtime (* ug: realtime scope enforces priority realtime of active object *)
- END
- END;
- IF locked THEN
- IF PCT.IsRealtimeScope(scope) THEN Error(162, scanner.errpos) END;
- END;
- ELSE
- REPEAT scanner.Get(sym) UNTIL (sym = rbrace) OR (sym = eof);
- END;
- Check(rbrace)
- END
- END BlockModifier;
- PROCEDURE StatementBlock(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
- VAR lock: BOOLEAN;
- BEGIN
- (*sym = begin*)
- scanner.Get(sym);
- BlockModifier(body, suppress, lock);
- IF ~inspect & body & notifyScope THEN PCT.ChangeState(scope.parent, PCT.modeavailable, scanner.errpos) END; (*NEW waits for it*)
- IF ~suppress & lock THEN
- IF locked THEN Error(246, scanner.errpos) END;
- locked := TRUE;
- unlockOnExit := looplevel > 0;
- PCB.Lock(code, scope, scanner.errpos, TRUE);
- StatementSeq(body, suppress, awaitCount);
- PCB.Lock(code, scope, scanner.errpos, FALSE);
- unlockOnExit := FALSE;
- locked := FALSE
- ELSE
- StatementSeq(body, suppress, awaitCount)
- END;
- Check(end)
- END StatementBlock;
- PROCEDURE CallNewOnObject (code: PCC.Code; suppress: BOOLEAN; proc: PCB.Designator; params: PCB.ExprList; curlevel: SHORTINT);
- VAR varName: StringPool.Index; symbol: PCT.Variable; res: WORD; parameters: PCB.ExprList; item: PCB.Expression; tempVar: PCB.Designator;
- BEGIN
- symbol := codescope.FindHiddenVar (-PCB.newfn, codescope);
- ASSERT (suppress OR (symbol # NIL));
- IF symbol = NIL THEN
- codescope.CreateHiddenVarName(varName);
- codescope.CreateVar(varName, PCT.Hidden, {}, PCT.Ptr, -PCB.newfn, codescope, res);
- symbol := codescope.lastHiddenVar;
- END;
- symbol.type := params.first.type;
- parameters := PCB.NewExprList (params.pos, proc);
- tempVar := PCB.MakeNode (params.first.pos, codescope, symbol);
- parameters.Append (tempVar); item := params.first.link; WHILE item # NIL DO parameters.Append (item); item := item.link END;
- PCB.CallProc(code, suppress, proc, parameters, scopelevel);
- PCB.Assign (code, suppress, params.first(PCB.Designator), tempVar, FALSE);
- END CallNewOnObject;
- PROCEDURE StatementSeq(body, suppress: BOOLEAN; VAR awaitCount: LONGINT);
- VAR d, d1: PCB.Designator; x, y: PCB.Expression; c: PCB.Const; o, o1: PCT.Symbol;
- param: PCB.ExprList; pos, stack: LONGINT; res: WORD;
- oldscope: PCT.Scope; s: PCT.WithScope; procscope: PCT.ProcScope;
- awaitparser: AwaitParser;
- loopinfo: PCB.LoopInfo; caseinfo: PCB.CaseInfo;
- first, ifsuppress, oldUnlockOnExit: BOOLEAN;
- oldforcount, i: LONGINT;
- mod: PCT.Symbol;
- name: StringPool.Index;
- proc: PCT.Proc; procScope: PCT.ProcScope;
- module: PCT.Module; modScope: PCT.ModScope;
- returnPos, temp: POINTER TO ARRAY OF LONGINT;
- ap: PCB.AnyProc; m: PCT.Method; indexer: BOOLEAN;
- sproc: PCB.SProc;
- ae: PCB.ArrayExpression;
- be: PCB.BuiltInEl;
- arrayType: PCT.EnhArray;
- aindex: POINTER TO ARRAY OF LONGINT;
- PROCEDURE AssignIndices(ae: PCB.ArrayExpression; dim: LONGINT);
- VAR a: PCB.ArrayQ; index: PCB.EnhIndex; i,j: LONGINT;
- BEGIN
- a := ae.array;
- i := 0;
- WHILE a # NIL DO
- aindex[dim] := i;
- IF a.e IS PCB.ArrayExpression THEN
- AssignIndices(a.e(PCB.ArrayExpression),dim+1);
- ELSE
- index := PCB.NewEnhIndex(d.pos,d);
- FOR j := 0 TO LEN(aindex)-1 DO
- index.AppendIndex(a.e.pos,PCB.NewIntValue(0,aindex[j],PCT.Int32));
- END;
- PCB.Assign(code,suppress, index, a.e, FALSE);
- END;
- INC(i); a := a.next;
- END;
- END AssignIndices;
- BEGIN
- LOOP
- IF (sym < ident) THEN
- Error(ident, scanner.errpos);
- REPEAT scanner.Get(sym) UNTIL sym >= ident
- ELSIF (sym = semicolon) THEN
- PCM.Warning(315, scanner.errpos, "");
- END;
- pos:=scanner.errpos;
- IF ~suppress THEN PCC.NewInstr(code, pos) END;
- CASE sym OF
- | ident:
- Qualident(o);
- d := PCB.MakeNode(scanner.errpos, codescope, o); Designator(d);
- (* If the leftside of the assignment uses an indexer *)
- indexer := FALSE;
- IF sym = lbrak THEN
- m := PCT.FindIndexer(d.type(PCT.Pointer).base(PCT.Record).scope, StringPool.GetIndex1(PCT.AssignIndexer));
- IF m # NIL THEN
- NEW(ap, scanner.errpos, scope, m, d (* SELF *));
- d := ap;
- param:=PCB.NewExprList(scanner.errpos, d);
- scanner.Get(sym);
- IF sym # rbrak THEN ExprList(param) END;
- Check(rbrak);
- indexer := TRUE;
- END
- END;
- IF sym = becomes THEN
- scanner.Get(sym);
- mod := NIL;
- IF AllowOverloadedModule & (* fof *)(sym = lbrak) & ~((PCM.NoOpOverloading IN PCM.parserOptions) OR PCT.IsBasic(d.type)) THEN
- scanner.Get(sym);
- GetModule(mod);
- scanner.Get(sym);
- Check(rbrak);
- END;
- Expr(y);
- IF (PCM.NoOpOverloading IN PCM.parserOptions) OR (PCT.IsBasic(d.type) & PCT.IsBasic(y.type)) THEN
- PCB.Assign(code, suppress, d, y, FALSE (* fof *));
- ELSIF indexer THEN
- param.Append(y);
- IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
- PCB.CallProc(code, suppress, d, param, scopelevel)
- ELSE
- CallAssignmentOp(becomes, mod, d, y, scanner.errpos, suppress)
- END
- ELSIF ~indexer THEN
- param:=PCB.NewExprList(scanner.errpos, d);
- IF sym = lparen THEN
- scanner.Get(sym);
- IF sym # rparen THEN ExprList(param) END;
- Check(rparen)
- END;
- IF PCT.IsRealtimeScope(scope) & ~PCB.IsRealtimeProc(d, scanner.errpos) THEN Error(160, scanner.errpos) END; (* ug *)
- 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
- CallNewOnObject (code, suppress, d, param, scopelevel);
- ELSE
- PCB.CallProc(code, suppress, d, param, scopelevel);
- END;
- ELSE
- HALT(MAX(INTEGER));
- END (* if -> proccall *);
- indexer := FALSE;
- | if:
- scanner.Get(sym); If(FALSE, suppress, awaitCount)
- | with:
- first := TRUE;
- REPEAT
- IF (sym = bar) & first THEN
- PCM.Error(end, scanner.errpos, "Oberon-2 WITH not supported");
- first := FALSE
- END;
- scanner.Get(sym); (*skip with or bar *)
- IF sym = ident THEN
- Qualident(o);
- IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
- d:=PCB.MakeNode(scanner.errpos, codescope, o);
- ELSE
- Error(ident, scanner.errpos); d:=PCB.InvalidDesig
- END;
- Check(colon); Qualident(o1); d1:=PCB.MakeNode(scanner.errpos, codescope, o1);
- NEW(s); PCT.InitScope(s, scope, {}, FALSE); PCT.SetOwner(s);
- IF (o # NIL) & (o IS PCT.Variable) THEN
- s.withSym := o;
- s.withGuard := o1;
- ELSE
- Error(130, pos);
- END;
- oldscope := scope; scope := s;
- PCT.ChangeState(s, PCT.complete, scanner.errpos);
- Check(do);
- ifsuppress := PCB.If(code, suppress, loopinfo, PCB.NewMOp(scanner.errpos, NIL, not, PCB.NewDOp(scanner.errpos, is, d, d1)), FALSE);
- PCB.Trap(code, suppress OR ifsuppress, PCM.WithTrap);
- ifsuppress := PCB.Else(code, suppress, loopinfo);
- StatementSeq(FALSE, suppress OR ifsuppress, awaitCount);
- PCB.EndIf(code, suppress, loopinfo);
- scope := oldscope;
- UNTIL sym # bar;
- IF sym = else THEN
- IF first THEN PCM.Error(end, scanner.errpos, "Oberon-2 WITH not supported") END;
- scanner.Get(sym);
- StatementSeq(FALSE, TRUE, awaitCount)
- END;
- Check(end)
- | case:
- scanner.Get(sym); Expr(x); Check(of);
- PCB.Case(code, suppress, caseinfo, x);
- LOOP
- IF sym < bar THEN Case(FALSE, suppress, awaitCount, caseinfo) END;
- IF sym = bar THEN scanner.Get(sym) ELSE EXIT END
- END;
- PCB.CaseElse(code, suppress, caseinfo);
- IF sym = else THEN
- scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount)
- ELSE
- PCB.Trap(code, suppress, PCM.CaseTrap)
- END;
- PCB.CaseEnd(code, suppress, caseinfo);
- Check(end);
- | while:
- scanner.Get(sym); Expr(x); pos := scanner.errpos; Check(do);
- PCB.While(code, suppress, loopinfo, x);
- StatementSeq(FALSE, suppress, awaitCount); Check(end);
- PCB.EndLoop(code, suppress, loopinfo);
- | repeat:
- PCB.BeginLoop(code, suppress, loopinfo);
- scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount); Check(until); Expr(x);
- PCB.Repeat(code, suppress, loopinfo, x);
- | for:
- scanner.Get(sym);
- IF sym = ident THEN
- o:=PCT.Find(scope, scope, scanner.name, PCT.structallocated, TRUE);
- IF o = NIL THEN Error(0, scanner.errpos); o := PCB.unknownObj END;
- d:=PCB.MakeNode(scanner.errpos, codescope, o); scanner.Get(sym)
- ELSE
- Error(ident, scanner.errpos); d:=PCB.InvalidDesig
- END;
- Check(becomes); Expr(x);
- Check(to); Expr(y);
- IF sym = by THEN scanner.Get(sym); ConstExpr(c) ELSE c:=PCB.NewIntValue(scanner.errpos, 1, PCT.Int8)(*PCB.One*) END;
- PCB.BeginFor(code, suppress, pos, d, x, y, c, loopinfo);
- stack := PCC.GetStaticSize(d.type);
- INC(stack, (-stack) MOD 4); (*align*)
- stack := stack DIV 4;
- INC(forexitcount, stack); INC(forretcount, stack);
- Check(do); StatementSeq(FALSE, suppress, awaitCount); Check(end);
- DEC(forexitcount, stack); DEC(forretcount, stack);
- PCB.EndFor(code, suppress, pos, d, c, loopinfo)
- | loop:
- oldforcount := forexitcount; forexitcount := 0;
- loopinfo := curloop; INC(looplevel);
- oldUnlockOnExit := unlockOnExit; unlockOnExit := FALSE;
- PCB.BeginLoop(code, suppress, curloop);
- scanner.Get(sym); StatementSeq(FALSE, suppress, awaitCount); Check(end);
- PCB.EndLoop(code, suppress, curloop);
- unlockOnExit := oldUnlockOnExit;
- curloop := loopinfo; DEC(looplevel);
- forexitcount := oldforcount
- | exit:
- pos:=scanner.errpos; scanner.Get(sym);
- IF looplevel = 0 THEN
- Error(exit, scanner.errpos)
- ELSE
- IF unlockOnExit THEN
- PCB.Lock(code, scope, scanner.errpos, FALSE);
- END;
- PCB.Exit(code, suppress, curloop, forexitcount);
- suppress := TRUE
- END
- | return:
- IF returnPos = NIL THEN (* retcount = 0 *)
- NEW(returnPos,128);
- returnPos[0] := scanner.errpos;
- ELSE
- ASSERT(retcount # 0);
- IF retcount >= LEN(returnPos) THEN
- NEW(temp, LEN(returnPos) * 2);
- FOR i := 0 TO LEN(returnPos) - 1 DO
- temp[i] := returnPos[i];
- END;
- returnPos := temp
- END;
- returnPos[retcount] := scanner.errpos
- END;
- scanner.Get(sym);
- IF sym < semicolon THEN Expr(x); ELSE x := NIL END;
- PCB.Return(code, suppress, codescope, pos, x, locked, forretcount); (*use the declaration scope!*)
- INC(retcount); suppress := TRUE;
- | passivate:
- IF (~locked) & (~suppress) THEN
- PCM.Warning(314, scanner.errpos, "");
- END;
- scanner.Get(sym);
- Check(lparen);
- scope.CreateAwaitProcName(name, awaitCount); INC(awaitCount);
- IF inspect THEN
- NEW(procscope); PCT.InitScope(procscope, scope, {}, FALSE);
- PCT.SetOwner(procscope);
- scope.CreateProc(name, PCT.Internal, {}, procscope, PCT.Bool, pos, res);
- NEW(awaitparser, sync, procscope, scanner, sym);
- END;
- Expr(x); (* ug: instead of not existing SkipExpr() *)
- PCB.Await(code, suppress, scope, pos, name);
- Check(rparen);
- IF PCT.IsRealtimeScope(scope) THEN Error(162, scanner.errpos) END;
- | begin:
- StatementBlock(FALSE, suppress, awaitCount)
- | finally:
- IF ~suppress THEN
- IF body THEN
- IF fincount > 0 THEN
- Error(162, scanner.errpos);
- ELSE
- IF retcount > 0 THEN
- IF returnPos = NIL THEN
- Error(161, scanner.errpos);
- ELSE
- FOR i:= 0 TO LEN(returnPos) - 1 DO
- Error(161, returnPos[i]);
- END;
- END;
- END;
- END;
- IF (fincount = 0) & (retcount = 0) THEN
- IF (scope # NIL) & (scope IS PCT.ProcScope) THEN
- procScope := scope(PCT.ProcScope);
- proc := procScope.ownerO;
- PCB.Finally(pos, code, proc);
- ELSIF (scope # NIL) & (scope IS PCT.ModScope) THEN
- modScope := scope(PCT.ModScope);
- module := modScope.owner;
- PCB.Finally(pos, code, module);
- END;
- END;
- ELSE
- Error(160, scanner.errpos);
- END;
- INC(fincount)
- END;
- scanner.Get(sym); StatementSeq(body, suppress, awaitCount); (* Parse the rest recursive*)
- ELSE
- (* Error(end) *)
- END;
- IF sym = semicolon THEN scanner.Get(sym)
- ELSIF (sym <= ident) OR (if <= sym) & (sym <= return) THEN Error(semicolon, scanner.errpos)
- ELSIF sym = finally THEN
- ELSE EXIT
- END
- END (*loop*)
- END StatementSeq;
- PROCEDURE Body(suppress : BOOLEAN);
- VAR
- owner: PCT.Proc;
- name: ARRAY 32 OF CHAR;
- export: BOOLEAN;
- awaitCount: LONGINT; (* parsing a body starts with awaitCount = 0 *)
- BEGIN
- IF sym = begin THEN
- IF suppress THEN
- StatementBlock(TRUE, suppress, awaitCount)
- ELSE
- retcount := 0;
- fincount := 0;
- PCT.GetScopeName(scope, name);
- IF inline THEN Error(200, scanner.errpos) END;
- code := PCB.Enter(scope);
- StatementBlock(TRUE, suppress, awaitCount);
- IF (scope # NIL) & (scope IS PCT.ProcScope) THEN
- owner := scope(PCT.ProcScope).ownerO;
- IF (owner.type # PCT.NoType) & (retcount = 0) THEN
- PCM.Warning(313, scanner.errpos, "")
- END
- END;
- PCB.Leave(code, scope, FALSE)
- END
- ELSIF sym = codeToken THEN
- IF ~suppress THEN
- INCL(PCT.System.flags, PCT.used);
- export := (scope IS PCT.ModScope) OR
- ((scope IS PCT.ProcScope) & (PCT.Public * scope(PCT.ProcScope).ownerO.vis # {}));
- IF Assemble = NIL THEN (*no assembler installed*)
- PCM.Error(0, scanner.errpos, "no assembler available")
- ELSIF inline THEN
- scope.code := Assemble(scanner, scope, export, TRUE)
- ELSE
- code := PCB.Enter(scope);
- PCB.Inline(code, Assemble(scanner, scope, export, FALSE));
- PCB.Leave(code, scope, TRUE)
- END
- END;
- scanner.SkipUntilNextEnd (sym);
- Check(end)
- ELSE
- IF ~suppress THEN
- code := PCB.Enter(scope);
- PCB.Leave(code, scope, FALSE);
- END;
- IF (sym = var) OR (sym = const) OR (sym = type) THEN
- PCM.Error(43, scanner.errpos, "data decl after proc decl")
- ELSIF (sym # end) THEN
- Error(43, scanner.errpos)
- ELSE
- scanner.Get(sym)
- END
- END
- END Body;
- PROCEDURE ProcDecl;
- VAR
- procparser: ProcedureParser; procscope: PCT.ProcScope; pos: LONGINT; res: WORD;
- i: IdentDefDesc; flags: SET; rtype: PCT.Struct; forward, suppress : BOOLEAN;
- opName: PCS.Name; pflags: SET; right: SHORTINT; (* ejz *)
- opStr: ARRAY PCS.MaxStrLen OF CHAR;
- BEGIN
- flags := {}; forward := FALSE; pflags := {}; (* ejz *)
- CASE sym OF
- | minus:
- INCL(flags, PCT.Inline); scanner.Get(sym)
- | and:
- INCL(flags, PCT.Constructor); scanner.Get(sym)
- | times:
- (*compatibility with Ceres, ignore*)
- scanner.Get(sym);
- PCM.Error(237, scanner.errpos, "")
- | arrow:
- forward := TRUE; scanner.Get(sym);
- PCM.Warning(238, scanner.errpos, "")
- | lbrak, lbrace: (* ejz *)
- IF sym = lbrak THEN right := rbrak ELSE right := rbrace END;
- REPEAT
- scanner.Get(sym);
- IF (sym = ident) & (scanner.name = winapi) THEN
- (* scope proc is winapi *)
- CheckSysImported(scope.module);
- INCL(pflags, PCT.WinAPIParam);
- ELSIF (sym = ident) & (scanner.name = clang) THEN (* fof for Linux *)
- (* scope proc is c *)
- CheckSysImported(scope.module);
- INCL( pflags, PCT.CParam );
- ELSIF (sym = ident) & (scanner.name = realtime) THEN
- INCL(flags, PCT.RealtimeProc);
- ELSE
- PCM.Error(200, scanner.errpos, "unknown calling convention")
- END;
- scanner.Get(sym);
- UNTIL sym # comma;
- Check(right);
- IF (PCT.RealtimeProc IN flags) & (sym = minus) THEN
- INCL(flags, PCT.Inline); scanner.Get(sym)
- END
- ELSE
- END;
- pos:=scanner.errpos;
- IF PCM.NoOpOverloading IN PCM.parserOptions THEN
- IF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
- suppress := TRUE;
- PCM.Error(200, scanner.errpos, "operators not supported")
- END;
- IdentDef(i, FALSE);
- ELSE
- IF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
- OperatorDef(i, FALSE);
- INCL(flags, PCT.Operator);
- StringPool.GetString(i.name, opStr);
- IF (opStr # "[]") & (scope IS PCT.RecScope) THEN
- PCM.Error(140, scanner.errpos, "");
- ELSIF opStr = "[]" THEN
- INCL(flags, PCT.Indexer)
- END;
- ELSE
- IdentDef(i, FALSE);
- END;
- END;
- NEW(procscope); PCT.InitScope(procscope, scope, {PCT.AutodeclareSelf}, FALSE);
- IF {PCT.CParam, PCT.WinAPIParam} * pflags # {} (* fof for Linux *) THEN (* ejz *)
- IF scope IS PCT.ProcScope THEN (* ejz *)
- PCM.Error(200, scanner.errpos, "invalid WINAPI proc")
- ELSIF PCT.CParam IN pflags THEN (* fof for Linux *)
- procscope.SetCC( PCT.CLangCC )
- ELSE
- procscope.SetCC(PCT.WinAPICC)
- END
- END;
- PCT.SetOwner(procscope);
- FormalPars(procscope, rtype, pflags); (* ejz *)
- IF PCT.Operator IN flags THEN CheckOperator(procscope, i.name, rtype, pos) END;
- IF forward THEN RETURN END; (*don't register this procedure, just ignore it*)
- Check(semicolon);
- scope.CreateProc(i.name, i.vis, flags, procscope, rtype, pos(*fof*), res);
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos, i.name) END;
- NEW(procparser, sync, procscope, PCT.Inline IN flags, scanner, sym); (*parse the rest of scope*)
- SkipScope; (* skip the record scope, the other parser is parsing it *)
- IF suppress THEN
- scanner.Get(sym)
- ELSIF (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN
- opName := StringPool.GetIndex1(scanner.str);
- IF (opName # i.name) & ~(PCT.Indexer IN flags) THEN
- PCM.ErrorN(4, scanner.errpos, i.name)
- ELSIF (PCT.Indexer IN flags) & (scanner.str # "[]") THEN
- PCM.ErrorN(4, scanner.errpos, i.name)
- END;
- scanner.Get(sym);
- ELSIF sym = ident THEN
- IF scanner.name # i.name THEN PCM.ErrorN(4, scanner.errpos, i.name) END; (*[S8;1;2]*)
- scanner.Get(sym)
- ELSE PCM.ErrorN(ident, scanner.errpos, i.name)
- END
- END ProcDecl;
- PROCEDURE SkipScope;
- VAR cnt: LONGINT;
- BEGIN
- (*skip decl section*)
- WHILE (sym # eof) & (sym # begin) & (sym # end) & (sym # codeToken) DO
- IF (sym = record) THEN
- scanner.Get(sym); SkipScope
- ELSIF (sym = object) THEN
- scanner.Get(sym);
- IF (sym # semicolon) & (sym # rparen) THEN SkipScope END
- ELSIF sym = procedure THEN
- scanner.Get(sym);
- IF sym = lbrace THEN (* allow REALTIME and/or DELEGATE modifier *)
- WHILE sym # rbrace DO scanner.Get(sym) END;
- scanner.Get(sym);
- END;
- IF (sym = and) OR (sym = minus) THEN scanner.Get(sym) END;
- IF (sym = ident) OR (sym = string) OR (sym = number) & (scanner.numtyp = PCS.char) THEN SkipScope END;
- ELSE
- scanner.Get(sym)
- END
- END;
- (*skip statseq *)
- IF sym = begin THEN
- scanner.Get(sym); cnt := 1;
- WHILE cnt > 0 DO
- IF (sym = if) OR (sym = case) OR (sym = while) OR (sym = for) OR (sym = loop) OR (sym = with) OR (sym = begin) THEN
- INC(cnt)
- ELSIF sym = end THEN
- DEC(cnt)
- ELSIF sym = eof THEN
- cnt := 0
- END;
- scanner.Get(sym)
- END
- ELSIF sym = codeToken THEN
- scanner.SkipUntilNextEnd (sym);
- scanner.Get(sym)
- ELSIF sym = end THEN
- scanner.Get(sym);
- END;
- END SkipScope;
- (** fof >> *)
- PROCEDURE Epilog;
- END Epilog;
- (** << fof *)
- BEGIN {ACTIVE}
- IF die THEN sync.Exit; RETURN END;
- PCT.SetOwner(scope);
- DeclSeq;
- Body(FALSE); (* suppress = FALSE *)
- Epilog; (* fof *)
- PCT.ChangeState(scope, PCT.complete, scanner.errpos);
- sync.Exit
- END Parser;
- (** fof >> *)
- CustomArrayParser = OBJECT (Parser)
- VAR
- bodyscope: PCT.ProcScope; old: PCT.Scope;
- PROCEDURE Body(suppress: BOOLEAN); (*override Parser.Body*)
- BEGIN
- IF sym = begin THEN
- scope := bodyscope; codescope := scope;
- notifyScope := ~suppress;
- Body^(suppress);
- IF inspect THEN (* body was inspected for hidden variables *)
- PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
- ELSE (* normal code generation *)
- PCT.ChangeState(scope, PCT.complete, scanner.errpos)
- END;
- scope := old; codescope := scope
- ELSE
- IF (sym = var) OR (sym = const) OR (sym = type) THEN
- PCM.Error(43, scanner.errpos, "data decl after proc decl")
- ELSIF (sym # end) THEN
- Error(43, scanner.errpos)
- ELSE
- scanner.Get(sym)
- END
- END
- END Body;
- PROCEDURE DeclSeq; (* vars and procs are allowed, no const and types *)
- VAR res: WORD;
- BEGIN
- LOOP
- (* allow ident w/o var, to minimize the misleading err 83 in the rest of the module *)
- IF (sym = var) OR (sym = ident) THEN
- IF sym = var THEN scanner.Get(sym) ELSE PCM.Error(end, scanner.errpos, "or maybe VAR") END;
- WHILE sym = ident DO
- VarDecl;
- IF sym # end THEN
- CheckSemicolons;
- END;
- END
- ELSIF sym = semicolon THEN
- CheckSemicolons; (* advances to next symbol *)
- ELSE EXIT
- END
- END;
- FixForwards;
- PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
- PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
- WHILE sym = procedure DO
- scanner.Get(sym); ProcDecl;
- IF sym # end THEN Check(semicolon) END
- END;
- IF sym = begin THEN
- old := scope;
- NEW(bodyscope); PCT.InitScope(bodyscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(bodyscope);
- scope.CreateProc(PCT.BodyName, PCT.Public, {}, bodyscope, PCT.NoType, scanner.errpos(*fof*), res); ASSERT(res = PCT.Ok);
- PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos); (* ug: must be done explicitly here in order to allow cross method calls of objects *)
- PCT.ChangeState(bodyscope, PCT.procdeclared, scanner.errpos);
- savedsym := sym;
- savedscanner := scanner;
- scanner := PCS.ForkScanner(scanner);
- inspect := TRUE;
- Body(TRUE); (* suppress = TRUE *)
- scanner := savedscanner;
- sym := savedsym;
- inspect := FALSE
- END
- END DeclSeq;
- PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.CustomArrayScope; s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- isRecord := TRUE;
- scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
- scanner := PCS.ForkScanner(s);
- END InitRec;
- END CustomArrayParser;
- (** << fof *)
- ObjectParser = OBJECT (Parser)
- VAR
- bodyscope: PCT.ProcScope; old: PCT.Scope;
- PROCEDURE Body(suppress: BOOLEAN); (*override Parser.Body*)
- BEGIN
- IF sym = begin THEN
- scope := bodyscope; codescope := scope;
- notifyScope := ~suppress;
- Body^(suppress);
- IF inspect THEN (* body was inspected for hidden variables *)
- PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
- ELSE (* normal code generation *)
- PCT.ChangeState(scope, PCT.complete, scanner.errpos)
- END;
- scope := old; codescope := scope
- ELSE
- IF (sym = var) OR (sym = const) OR (sym = type) THEN
- PCM.Error(43, scanner.errpos, "data decl after proc decl")
- ELSIF (sym # end) THEN
- Error(43, scanner.errpos)
- ELSE
- scanner.Get(sym)
- END
- END
- END Body;
- PROCEDURE DeclSeq; (* vars and procs are allowed, no const and types *)
- VAR res: WORD;
- BEGIN
- LOOP
- (* allow ident w/o var, to minimize the misleading err 83 in the rest of the module *)
- IF (sym = var) OR (sym = ident) THEN
- IF sym = var THEN scanner.Get(sym) ELSE PCM.Error(end, scanner.errpos, "or maybe VAR") END;
- WHILE sym = ident DO
- VarDecl;
- IF sym # end THEN
- CheckSemicolons;
- END;
- END
- ELSIF sym = semicolon THEN
- CheckSemicolons; (* advances to next symbol *)
- ELSE EXIT
- END
- END;
- FixForwards;
- PCT.ChangeState(scope, PCT.structdeclared, scanner.errpos);
- PCT.ChangeState(scope, PCT.structallocated, scanner.errpos);
- WHILE sym = procedure DO
- scanner.Get(sym); ProcDecl;
- IF sym # end THEN Check(semicolon) END
- END;
- IF sym = begin THEN
- old := scope;
- NEW(bodyscope); PCT.InitScope(bodyscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(bodyscope);
- scope.CreateProc(PCT.BodyName, PCT.Public, {}, bodyscope, PCT.NoType, scanner.errpos(*fof*), res); ASSERT(res = PCT.Ok);
- PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos); (* ug: must be done explicitly here in order to allow cross method calls of objects *)
- PCT.ChangeState(bodyscope, PCT.procdeclared, scanner.errpos);
- savedsym := sym;
- savedscanner := scanner;
- scanner := PCS.ForkScanner(scanner);
- inspect := TRUE;
- Body(TRUE); (* suppress = TRUE *)
- scanner := savedscanner;
- sym := savedsym;
- inspect := FALSE
- END
- END DeclSeq;
- PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- isRecord := TRUE;
- scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
- scanner := PCS.ForkScanner(s);
- END InitRec;
- END ObjectParser;
- RecordParser = OBJECT (Parser)
- PROCEDURE Body(suppress: BOOLEAN);
- BEGIN
- Check(end)
- END Body;
- PROCEDURE DeclSeq; (* the DeclSeq of a record is a simplified DeclSeq, but nevertheless different *)
- BEGIN
- LOOP
- IF sym = semicolon THEN
- CheckSemicolons; (* advances to next symbol *)
- ELSIF sym = ident THEN VarDecl;
- ELSE EXIT
- END
- END;
- FixForwards; (*anonymous declaration possible!*)
- PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos);
- PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
- END DeclSeq;
- PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- isRecord := TRUE;
- scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
- scanner := PCS.ForkScanner(s);
- END InitRec;
- END RecordParser;
- InterfaceParser = OBJECT (Parser)
- PROCEDURE Body(suppress: BOOLEAN);
- BEGIN
- Check(end)
- END Body;
- PROCEDURE DeclSeq;
- VAR name: PCS.Name; procscope: PCT.ProcScope; t: PCT.Struct; pos: LONGINT; res: WORD;
- BEGIN
- WHILE sym = procedure DO
- pos := scanner.errpos;
- scanner.Get(sym);
- name := scanner.name;
- Check(ident);
- NEW(procscope); PCT.InitScope(procscope, scope, {PCT.AutodeclareSelf}, FALSE); PCT.SetOwner(procscope);
- FormalPars (procscope, t, {});
- scope.CreateProc(name, PCT.Public, {}, procscope, t, pos(*fof*), res);
- IF res # PCT.Ok THEN PCM.ErrorN(res, pos, name) END;
- Check(semicolon);
- PCT.ChangeState(procscope, PCT.structdeclared, scanner.errpos)
- END;
- PCT.ChangeState(scope, PCT.procdeclared, scanner.errpos)
- END DeclSeq;
- PROCEDURE & InitRec*(sync: Barrier; recscope: PCT.RecScope; s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- isRecord := TRUE;
- scope := recscope; codescope := recscope; SELF.sym := sym; scopelevel := 0; looplevel := 0;
- scanner := PCS.ForkScanner(s);
- END InitRec;
- END InterfaceParser;
- (* Parse a procedure, beginning from the parameters to the END. This only fills the scope,
- the symbol has to be inserted by the caller *)
- ProcedureParser = OBJECT (Parser)
- PROCEDURE & InitProc*(sync: Barrier; procscope: PCT.ProcScope; inline: BOOLEAN; VAR s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- SELF.inline := inline;
- scope := procscope; codescope := procscope; scanner := s; SELF.sym := sym;
- scopelevel := procscope.ownerO.level; looplevel := 0;
- scanner := PCS.ForkScanner(s)
- END InitProc;
- END ProcedureParser;
- (* Parse the condition in an AWAIT statement as a separate procedure *)
- AwaitParser = OBJECT(Parser)
- PROCEDURE DeclSeq;
- BEGIN
- PCT.ChangeState(scope, PCT.hiddenvarsdeclared, scanner.errpos)
- END DeclSeq;
- PROCEDURE Body(suppress: BOOLEAN);
- VAR x: PCB.Expression;
- BEGIN
- code := PCB.Enter(scope);
- Expr(x);
- PCB.Return(code, suppress, codescope, scanner.errpos, x, FALSE, 0); (*use the declaration scope!*)
- PCB.Leave(code, scope, FALSE);
- END Body;
- PROCEDURE &Init*(sync: Barrier; procscope: PCT.ProcScope; VAR s: PCS.Scanner; sym: PCS.Token);
- BEGIN
- sync.Enter; SELF.sync := sync;
- scope := procscope; codescope := procscope; scanner := s; SELF.sym := sym;
- scopelevel := procscope.ownerO.level; looplevel := 0;
- scanner := PCS.ForkScanner(s)
- END Init;
- END AwaitParser;
- ModuleParser = OBJECT (Parser)
- VAR modscope: PCT.ModScope; (*cached value*)
- PROCEDURE ImportList;
- VAR alias, name: StringPool.Index; new: PCT.Module; res: WORD;
- BEGIN
- LOOP
- IF sym # ident THEN Error(ident, scanner.errpos); EXIT END;
- alias := scanner.name;
- scanner.Get(sym);
- IF sym = becomes THEN
- scanner.Get(sym);
- IF sym = ident THEN
- name := scanner.name;
- ELSIF sym = string THEN
- name := StringPool.GetIndex1(scanner.str) (*scanner.str is read-only and GetIndex has a VAR....*)
- ELSE
- Error(ident, scanner.errpos); EXIT
- END;
- scanner.Get(sym)
- ELSE
- name := alias;
- END;
- IF name # PCT.System.name THEN
- IF sym = in THEN
- scanner.Get(sym);
- CreateContext (name, scanner.name);
- Check (ident);
- ELSE
- CreateContext (name, modscope.owner.context);
- END;
- END;
- PCT.Import(modscope.owner, new, name);
- IF new = NIL THEN
- PCM.ErrorN(152, scanner.errpos, name)
- ELSE
- IF new # PCT.System THEN
- modscope.owner.AddDirectImp(new);
- END;
- modscope.AddModule(alias, new, scanner.errpos, (* fof *) res); (*must create copy, otherwise list fields get overwritten*)
- IF res # PCT.Ok THEN PCM.ErrorN(res, scanner.errpos, alias) END
- END;
- IF sym = comma THEN scanner.Get(sym)
- ELSE EXIT
- END
- END;
- Check(semicolon)
- END ImportList;
- PROCEDURE ParseInterface;
- VAR mod: PCT.Module; sf, flags: SET; name, label, context: PCS.Name;
- BEGIN
- IF sym = module THEN scanner.Get(sym);
- IF sym = ident THEN
- name := scanner.name; label := name;
- scanner.Get(sym);
- IF sym = in THEN
- scanner.Get(sym);
- context := scanner.name;
- IF (scanner.str # "Oberon") & (scanner.str # "A2") THEN
- PCM.Error (133, scanner.errpos, scanner.str)
- END;
- Check (ident);
- ELSE
- StringPool.GetIndex (Modules.DefaultContext, context);
- END;
- CreateContext (name, context);
- TypeModifier(sf, {}, {PCT.Overloading});
- PCT.InitScope(scope, NIL, sf, FALSE);
- mod := PCT.NewModule(name, FALSE, flags, modscope);
- mod.context := context; mod.label := label;
- Check(semicolon);
- IF sym = import THEN scanner.Get(sym); ImportList END
- ELSE Error(ident, scanner.errpos)
- END
- ELSE Error(16, scanner.errpos)
- END;
- die := PCM.error
- END ParseInterface;
- PROCEDURE Await*;
- VAR count, inside: LONGINT;
- BEGIN
- sync.Await;
- sync.Stats(count, inside);
- IF inside > 0 THEN
- PCM.LogWStr(" ("); PCM.LogWNum(inside); PCM.LogW("/"); PCM.LogWNum(count); PCM.LogWStr(")")
- END;
- PCM.error := PCM.error OR (inside > 0)
- END Await;
- PROCEDURE & InitModule*(modscope: PCT.ModScope; s: PCS.Scanner);
- VAR recscope: PCT.RecScope; rec: PCT.Record; res: WORD;i, j: LONGINT; (** fof *)
- BEGIN
- Machine.AtomicInc(NModules);
- NEW(sync, 10(*timeout*)); sync.Enter;
- scope := modscope; codescope := modscope; scanner := s; s.Get(sym); scopelevel := 0; looplevel := 0;
- PCT.SetOwner(scope);
- SELF.modscope := modscope;
- PCArrays.InitScope( modscope ); (* fof *)
- (*predefined variables*)
- scope.CreateVar(PCT.SelfName, PCT.Internal, {PCM.Untraced}, PCT.Ptr, 0, (*fof*) NIL, res); (*module self, used for module locking*)
- ASSERT(res = PCT.Ok);
- ParseInterface;
- IF ~die THEN
- (*predefined types*)
- NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
- rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
- scope.CreateType(deltype, PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(procfld, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(self, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
- PCC.delegate := rec;
- NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
- rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
- scope.CreateType(hiddenptr, PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(ptrfld, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
- PCC.hdptr := rec;
- (** fof >> *)
- (* keyword "RANGE" support
- NEW(recscope); PCT.InitScope(recscope, scope, {PCT.SuperclassAvailable}, FALSE); PCT.SetOwner(recscope);
- rec := PCT.NewRecord(PCT.NoType, recscope, {PCT.SystemType}, FALSE, res); ASSERT(res = PCT.Ok);
- scope.CreateType(StringPool.GetIndex1("RANGE"), PCT.Internal, rec, 0 (*fof*), res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Int32, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- recscope.CreateVar(PCT.Anonymous, PCT.Internal, {}, PCT.Set, 0 (*fof*) , NIL, res); ASSERT(res = PCT.Ok);
- PCT.ChangeState(recscope, PCT.complete, scanner.errpos);
- PCC.range := rec;
- *)
- FOR i := 0 TO LEN( PCC.anyarr ) - 1 DO
- NEW( recscope ); PCT.InitScope( recscope, scope, {PCT.SuperclassAvailable}, FALSE ); PCT.SetOwner( recscope ); rec := PCT.NewRecord( PCT.NoType, recscope, {PCT.SystemType}, FALSE , res );
- ASSERT( res = PCT.Ok );
- (*scope.CreateType(hiddenptr, PCT.Internal, rec, 0 (*fof*) ,res); ASSERT(res = PCT.Ok);*)
- recscope.CreateVar( ptrfld, PCT.Internal, {}, PCT.Ptr, 0 (*fof*) , NIL, res );
- 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;
- PCT.ChangeState( recscope, PCT.complete, scanner.errpos ); PCC.anyarr[i] := rec;
- END;
- (** << fof *)
- PCC.topscope := modscope;
- END
- END InitModule;
- (** fof >> *)
- PROCEDURE Epilog;
- VAR res: WORD; sym: PCT.Symbol; var: PCT.Variable;
- BEGIN
- (* check if the array module has been used in PCArrays. If so then put it into the scope to protect from unloading *)
- IF PCArrays.ArrayModule # NIL THEN (* must be done here by this process *)
- IF modscope.owner.name = PCArrays.ArrayModuleIdx THEN HALT( 100 ) END;
- modscope.AddModule( PCArrays.ArrayModuleIdx, PCArrays.ArrayModule, 0, res );
- modscope.owner.AddDirectImp( PCArrays.ArrayModule ); (* makes the use of ArrayBase visible, may be omitted *)
- END;
- Epilog^;
- END Epilog;
- (** << fof *)
- END ModuleParser;
- (** fof 070731 >> *)
- PROCEDURE InitializationWarning( s: PCT.Symbol );
- VAR par: PCT.Parameter; name: ARRAY 256 OF CHAR;
- BEGIN
- (*
- IF s # NIL THEN
- StringPool.GetString( s.name, name );
- PCM.LogWStr(name); PCM.LogWLn;
- END;
- *)
- IF (s = NIL) OR (s.pos = 0) THEN RETURN
- ELSIF s IS PCT.Parameter THEN
- par := s( PCT.Parameter );
- IF ~(PCT.written IN par.flags) THEN
- IF ((par.type IS PCT.Array)
- (*
- OR
- (par.type IS PCT.Record)
- *)
- ) &
- ~(PCM.ReadOnly IN par.flags) THEN
- StringPool.GetString( s.name, name );
- PCM.Warning( 917, par.pos, name );
- PCT.RemoveWarning( par );
- (*
- ELSIF ~(PCM.ReadOnly IN par.flags) & par.ref THEN PCM.Warning( 901, par.pos, "VAR parameter not initialized" );
- too verbose
- *)
- END;
- END;
- ELSIF s IS PCT.LocalVar THEN
- IF ~(PCT.written IN s.flags) & ({PCT.PublicW} * s.vis = {}) THEN
- StringPool.GetString( s.name, name );
- PCM.Warning( 901, s.pos, name );
- PCT.RemoveWarning(s);
- END;
- ELSIF s IS PCT.GlobalVar THEN
- IF ~(PCT.written IN s.flags) & ({PCT.PublicW} * s.vis = {}) THEN
- StringPool.GetString( s.name, name );
- PCM.Warning(901,s.pos,name);
- PCT.RemoveWarning(s);
- END;
- END;
- END InitializationWarning;
- PROCEDURE UsageWarning( s: PCT.Symbol );
- VAR name: ARRAY 256 OF CHAR;
- BEGIN
- IF (s = NIL) OR (s.pos = 0) OR (s IS PCT.Parameter) (* too verbose *) THEN RETURN END;
- IF ~(PCT.used IN s.flags) &
- (PCT.Public * s.vis = {}) THEN
- StringPool.GetString( s.name, name );
- PCM.Warning( 900, s.pos, name );
- PCT.RemoveWarning( s );
- END;
- END UsageWarning;
- (* Generates a warning if a field has the same name as an inherited field *)
- PROCEDURE SameNameWarning(s : PCT.Symbol);
- VAR
- record : PCT.Record; warned : BOOLEAN;
- name : ARRAY 128 OF CHAR;
- PROCEDURE HasVar(scope : PCT.Scope; var : PCT.Variable) : BOOLEAN;
- VAR v : PCT.Variable;
- BEGIN
- ASSERT((scope # NIL) & (var # NIL));
- v := scope.firstVar;
- LOOP
- IF (v = NIL) OR (v.name = var.name) THEN EXIT; END;
- v := v.nextVar;
- END;
- RETURN v # NIL;
- END HasVar;
- BEGIN
- IF (s = NIL) OR (s.pos = 0) THEN RETURN END;
- IF (s IS PCT.Variable) & (s.inScope # NIL) & (s.inScope IS PCT.RecScope) & (s.inScope(PCT.RecScope).owner # NIL) THEN
- warned := FALSE;
- record := s.inScope(PCT.RecScope).owner.brec;
- WHILE (record # NIL) & (record.scope # NIL) & (~warned) DO
- IF HasVar(record.scope, s(PCT.Variable)) THEN
- warned := TRUE;
- StringPool.GetString(s.name, name);
- PCM.Warning(914, s.pos, name);
- PCT.RemoveWarning( s );
- END;
- record := record.brec;
- END;
- END;
- END SameNameWarning;
- (* Generates a warning if a symbol is exported but the scope containing it is not *)
- PROCEDURE UselessExportWarning(s : PCT.Symbol);
- VAR recScope : PCT.RecScope; name : ARRAY 128 OF CHAR;
- BEGIN
- IF (s = NIL) OR (s.pos = 0) OR (s.vis * PCT.Public = {}) THEN RETURN; END;
- IF (s.inScope # NIL) THEN
- IF (s.inScope IS PCT.RecScope) THEN
- recScope := s.inScope (PCT.RecScope);
- IF recScope.owner # NIL THEN
- IF ((recScope.owner.owner # NIL) & (recScope.owner.owner.vis * PCT.Public = {})) (* RECORD *)
- OR
- ((recScope.owner.ptr # NIL) & (recScope.owner.ptr.owner # NIL) &
- (recScope.owner.ptr.owner.vis * PCT.Public = {})) (* POINTER TO RECORD or OBJECT *)
- THEN
- IF (s IS PCT.Method) &
- ((s(PCT.Method).boundTo.scope(PCT.RecScope).initproc = s) OR
- ((s(PCT.Method).boundTo.scope(PCT.RecScope).body = s))) THEN
- (* Constructors and bodies are always public *)
- RETURN;
- END;
- IF (s IS PCT.Method) &
- ((s(PCT.Method).super = NIL) OR (s(PCT.Method).super.vis * PCT.Public = {})) THEN
- (* not autoexported *)
- StringPool.GetString(s.name, name);
- PCM.Warning(915, s.pos, name);
- PCT.RemoveWarning(s);
- END;
- END;
- END;
- ELSIF (s IS PCT.Proc) & (s.inScope IS PCT.ProcScope) THEN
- StringPool.GetString(s.name, name);
- PCM.Warning(915, s.pos, name);
- PCT.RemoveWarning(s);
- END;
- END;
- END UselessExportWarning;
- PROCEDURE ScopeWarnings(scope: PCT.Scope);
- VAR s: PCT.Symbol;
- BEGIN
- s := scope.sorted;
- WHILE (s # NIL ) DO
- UsageWarning( s ); InitializationWarning( s );
- SameNameWarning( s ); (* sven stauber *)
- UselessExportWarning( s );
- s := s.sorted;
- END;
- END ScopeWarnings;
- PROCEDURE ImportListWarnings( mod: PCT.Module );
- VAR i: LONGINT;
- BEGIN
- IF mod.sysImported & (PCT.System.flags * {PCT.used} = {}) THEN
- PCM.Warning( 900, PCT.System.pos, "SYSTEM");
- END;
- IF mod.directImps = NIL THEN RETURN END;
- FOR i := 0 TO LEN( mod.directImps ) - 1 DO
- UsageWarning( mod.directImps[i] );
- END;
- END ImportListWarnings;
- (** << fof *)
- PROCEDURE ParseModule*(scope: PCT.ModScope; s: PCS.Scanner);
- VAR parser: ModuleParser; name: StringPool.Index; sym: PCS.Token;
- BEGIN
- (* There's one global symbol representing the SYSTEM pseudo module. Clear the used flag before parsing the module
- so we can detect whether SYSTEM is used after parsing *)
- EXCL(PCT.System.flags, PCT.used);
- (* note: can use s directly instead of parser.scanner, because the module parser uses the same scanner *)
- NEW(parser, scope, s);
- parser.Await;
- IF ~parser.die THEN
- IF (PCM.Warnings IN PCM.parserOptions) THEN
- PCT.TraverseScopes(parser.modscope,ScopeWarnings); (*fof*)
- ImportListWarnings( parser.modscope.module ); (*fof*)
- END;
- name := scope.owner(PCT.Module).label;
- IF parser.sym = ident THEN
- IF s.name # name THEN PCM.ErrorN(4, s.errpos, s.name) END;
- s.Get(sym);
- IF sym = period THEN (* s.Get(sym) *) ELSE PCM.Error(period, s.errpos, "") END;
- ELSE PCM.ErrorN(ident, s.errpos, name)
- END
- END
- END ParseModule;
- PROCEDURE CreateString(VAR idx: StringPool.Index; str: ARRAY OF CHAR); (*to insert string constants*)
- BEGIN StringPool.GetIndex(str, idx)
- END CreateString;
- PROCEDURE CreateContext (VAR name: StringPool.Index; context: StringPool.Index);
- VAR string, temp: ARRAY 64 OF CHAR;
- BEGIN
- StringPool.GetString (context, string);
- IF string # Modules.DefaultContext THEN
- Strings.Append (string, "-");
- StringPool.GetString (name, temp);
- Strings.Append (string, temp);
- StringPool.GetIndex (string, name);
- END;
- END CreateContext;
- BEGIN
- CreateString(untraced, "UNTRACED");
- CreateString(delegate, "DELEGATE");
- CreateString(overloading, "OVERLOADING");
- CreateString(self, "SELF");
- CreateString(exclusive, "EXCLUSIVE");
- CreateString(active, "ACTIVE");
- CreateString(safe, "SAFE");
- CreateString(priority, "PRIORITY");
- CreateString(realtime, "REALTIME");
- CreateString(deltype, "@Delegate");
- CreateString(hiddenptr, "@HdPtrDesc");
- CreateString(procfld, "proc");
- CreateString(ptrfld, "ptr");
- CreateString(winapi, "WINAPI"); (* ejz *)
- CreateString( clang, "C" ); (* fof for Linux Version *)
- CreateString(notag, "NOTAG"); (* sz *)
- noname := -1
- END PCP.
- (*
- 08.08.07 sst Added SameNameWarning, UselessExportWarning & AWAIT not in exclusive block warning
- 24.06.03 prk Check that name after END is the same as declared after MODULE
- 21.07.02 prk EXIT in an exclusive block must release lock
- 05.02.02 prk PCT.Find cleanup
- 11.12.01 prk problem parsing invalid WITH syntax fixed
- 22.11.01 prk improved flag handling
- 19.11.01 prk definitions
- 17.11.01 prk more flexible type handling of integer constants
- 16.11.01 prk constant folding of reals done with maximal precision
- 16.11.01 prk improved error message when operators and Oberon-2 WITH found
- 01.11.01 prk improved error handling for OBJECT without VAR
- 14.09.01 prk PRIORITY modifier, error messages improved
- 29.08.01 prk PCT functions: return "res" instead of taking "pos"
- 27.08.01 prk PCT.Insert removed, use Create procedures instead
- 27.08.01 prk scope.unsorted list removed; use var, proc, const and type lists instead
- 17.08.01 prk overloading
- 09.08.01 prk Symbol Table Loader Plugin
- 11.07.01 prk support for fields and methods with same name in scope
- 06.07.01 prk mark object explicitly
- 05.07.01 prk import interface redesigned
- 04.07.01 prk SkipScope, seek for END in CODE bodies, ignore other keywords
- 04.07.01 prk scope flags added, remove imported
- 02.07.01 prk access flags, new design
- 27.06.01 prk StringPool cleaned up
- 27.06.01 prk ProcScope.CreatePar added
- 21.06.01 prk using stringpool index instead of array of char
- 15.06.01 prk support for duplicate scope entries
- 14.06.01 prk type descs for dynamic arrays of ptrs generated by the compiler
- 12.06.01 prk Interfaces
- 30.05.01 prk destination (\d) compiler-option to install the back-end
- 17.05.01 prk Delegates
- 10.05.01 prk remove temporary for-counter when EXIT inside a for-loop
- 08.05.01 prk PCT interface cleanup. Use InitX instead of New*, allows type extension
- 26.04.01 prk separation of RECORD and OBJECT in the parser
- 29.03.01 prk Java imports
- *)
|