SymTab.mod 101 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359
  1. IMPLEMENTATION MODULE SymTab;
  2. IMPORT FileIO;
  3. FROM Storage IMPORT ALLOCATE; (* gm2 needs this for NEW substitution *)
  4. CONST
  5. MaxTypes = 4096;
  6. MaxVt = 1024; (* total virtual-method slots across all classes *)
  7. MaxPend = 256;
  8. MaxMods = 64;
  9. ResDepth = 64;
  10. MaxPP = 1024; (* total procedure-type parameter slots *)
  11. MaxEnumLit = 8192; (* enumeration literals, for export/import *)
  12. (* descriptor forms *)
  13. FNone = 0; FAlias = 1; FSub = 2; FEnum = 3; FArray = 4;
  14. FRecord = 5; FSet = 6; FPtr = 7; FStr = 8;
  15. FInt = 9; FReal = 10; FChar = 11; FBool = 12;
  16. FClass = 13; FOpenArr = 14; FNil = 15; FLong = 16; FProc = 17;
  17. FUChar = 18; FUStr = 19;
  18. (* signatures compared by the strict 231 check are bounded to this many
  19. formals (self-hosting uses far fewer). *)
  20. MaxSnap = 16;
  21. HighSnap = MaxSnap - 1;
  22. TYPE
  23. SymPtr = POINTER TO SymNode;
  24. ScopePtr = POINTER TO ScopeNode;
  25. FieldPtr = POINTER TO FieldNode;
  26. SymNode = RECORD
  27. name : Name;
  28. kind : INTEGER;
  29. typ : TypeIndex;
  30. scope : ScopePtr; (* owning scope *)
  31. left : SymPtr; (* BST links within the owning scope *)
  32. right : SymPtr;
  33. rslt : TypeIndex; (* KindProc result type, InvalidType = none *)
  34. plink : SymPtr; (* next formal, positional chain *)
  35. isVar : BOOLEAN; (* KindParam: VAR formal *)
  36. fwd : BOOLEAN; (* KindProc: FORWARD body pending *)
  37. virt : BOOLEAN; (* KindProc: VIRTUAL method *)
  38. fdep : CARDINAL; (* KindProc: lexical function-nesting depth *)
  39. snapRes : TypeIndex; (* KindProc: DEFINITION result (ResumeProc) *)
  40. snapT : ARRAY [0 .. MaxSnap - 1] OF TypeIndex; (* DEF formal types *)
  41. snapV : ARRAY [0 .. MaxSnap - 1] OF BOOLEAN; (* DEF formal VARs *)
  42. nSnap : CARDINAL; (* KindProc: number of snapshot formals *)
  43. fsnap : BOOLEAN; (* KindProc: signature snapshotted, compare *)
  44. vslot : INTEGER; (* KindProc VIRTUAL: vtable slot (-1 = none) *)
  45. hasBody : BOOLEAN; (* KindProc: a body was resumed/emitted *)
  46. ext : BOOLEAN; (* KindProc: EXTERNAL (no body emitted) *)
  47. link : Name; (* KindProc: external link (C) name *)
  48. varargs : BOOLEAN; (* KindProc: C varargs (FROM libc IMPORT) *)
  49. sym : Name; (* base symbol name (differs from name for
  50. qualified aliases) *)
  51. mod : Name; (* defining module (for QBE global names) *)
  52. uid : CARDINAL; (* KindProc: unique id for name mangling *)
  53. val : Name; (* KindConst: literal value text, "" if none *)
  54. END;
  55. ScopeNode = RECORD
  56. parent : ScopePtr; (* scope tree link *)
  57. root : SymPtr; (* BST root of this scope's symbols *)
  58. level : CARDINAL;
  59. link : ScopePtr; (* creation-order chain for PrintTable *)
  60. ofRec : TypeIndex; (* record/class whose members live here *)
  61. END;
  62. FieldNode = RECORD
  63. name : Name;
  64. typ : TypeIndex;
  65. owner : TypeIndex;
  66. next : FieldPtr; (* next field of the same owner *)
  67. off : INTEGER; (* declaration-order byte offset *)
  68. ord : CARDINAL; (* declaration rank (chain is reverse) *)
  69. END;
  70. VAR
  71. curScope : ScopePtr;
  72. scopeList : ScopePtr; (* all scopes, creation order *)
  73. scopeTail : ScopePtr;
  74. fields : FieldPtr; (* all record fields, newest first *)
  75. nFields : CARDINAL;
  76. pend : ARRAY [0 .. MaxPend - 1] OF SymPtr;
  77. nPend : CARDINAL;
  78. pendF : ARRAY [0 .. MaxPend - 1] OF FieldPtr;
  79. nPendF : CARDINAL;
  80. tform : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  81. tref : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
  82. tbytebuf : ARRAY [0 .. MaxTypes - 1] OF BOOLEAN; (* ARRAY OF BYTE open formal (gm2 ext) *)
  83. tlo : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  84. thi : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  85. tenum : ARRAY [0 .. MaxTypes - 1] OF CARDINAL; (* enum literal count *)
  86. (* Enumeration literals, keyed by their enum type: an enum type's
  87. literals are exported/imported together with the type (ISO). *)
  88. enumLitN : CARDINAL;
  89. enumLitDone : ARRAY [0 .. MaxTypes - 1] OF BOOLEAN;
  90. enumLitStart : ARRAY [0 .. MaxTypes - 1] OF CARDINAL;
  91. enumLitNm : ARRAY [0 .. MaxEnumLit * 64 - 1] OF CHAR; (* flat *)
  92. (* module-level forward type references awaiting completion *)
  93. pfwdN : CARDINAL;
  94. pfwdName : ARRAY [0 .. 255] OF Name;
  95. pfwdT : ARRAY [0 .. 255] OF TypeIndex;
  96. (* deferred procedure bodies (two-phase parse): a skipped body's own
  97. scope, saved while still current, restored for the re-parse pass *)
  98. uidBase : ARRAY [0 .. 1023] OF Name; (* uid -> base name (mangling) *)
  99. nDefer : CARDINAL;
  100. deferProc : ARRAY [0 .. 255] OF SymPtr;
  101. deferScope : ARRAY [0 .. 255] OF ScopePtr;
  102. tparent : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
  103. tscope : ARRAY [0 .. MaxTypes - 1] OF ScopePtr;
  104. tdone : ARRAY [0 .. MaxTypes - 1] OF BOOLEAN;
  105. (* per-class vtables: each class owns a slice of the shared pool *)
  106. vtBase : ARRAY [0 .. MaxTypes - 1] OF CARDINAL;
  107. nVirt : ARRAY [0 .. MaxTypes - 1] OF CARDINAL;
  108. vtName : ARRAY [0 .. MaxVt - 1] OF Name; (* virtual method name *)
  109. vtUid : ARRAY [0 .. MaxVt - 1] OF CARDINAL; (* its uid *)
  110. vtTop : CARDINAL;
  111. vtBuilt : ARRAY [0 .. MaxTypes - 1] OF BOOLEAN;
  112. tvptr : ARRAY [0 .. MaxTypes - 1] OF INTEGER; (* vptr field offset, -1 none *)
  113. vtl : ARRAY [0 .. MaxTypes - 1] OF TypeIndex; (* classes with a vtable *)
  114. nVtl : CARDINAL;
  115. (* class whose CLASS IMPLEMENTATION body is currently open (nested
  116. impls stack); bare method names resolve against it *)
  117. implStk : ARRAY [0 .. 15] OF TypeIndex;
  118. nImpl : CARDINAL;
  119. tvtag : ARRAY [0 .. MaxTypes - 1] OF BOOLEAN; (* record has variants *)
  120. ttag : ARRAY [0 .. MaxTypes - 1] OF FieldPtr; (* variant CASE selector *)
  121. alo : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  122. ahi : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  123. blo : ARRAY [0 .. 7] OF INTEGER;
  124. bhi : ARRAY [0 .. 7] OF INTEGER;
  125. nBounds : CARDINAL;
  126. nTypes : CARDINAL;
  127. curProc : SymPtr; (* heading being declared *)
  128. curPTail : SymPtr; (* positional param chain tail *)
  129. snapT : ARRAY [0 .. 15] OF TypeIndex; (* signature snapshot scratch *)
  130. snapV : ARRAY [0 .. 15] OF BOOLEAN;
  131. procStk : ARRAY [0 .. 15] OF SymPtr;
  132. nProc : CARDINAL;
  133. nextUid : CARDINAL;
  134. dInt, dCard, dReal, dChar, dBool, dNil, dAddr, dLong : TypeIndex;
  135. dUChar : TypeIndex; (* UCHAR: 32-bit codepoint *)
  136. dBitset : TypeIndex; (* BITSET = SET OF [0..15] *)
  137. dProc : TypeIndex; (* PROC: parameterless procedure type *)
  138. globScope : ScopePtr; (* the global scope (module names live here) *)
  139. curMod : INTEGER; (* current registry slot, -1 between units *)
  140. curUnit : INTEGER; (* UnitProg/Def/Impl, -1 between units *)
  141. nMods : CARDINAL;
  142. modNames : ARRAY [0 .. MaxMods - 1] OF Name;
  143. modScopes : ARRAY [0 .. MaxMods - 1] OF ScopePtr;
  144. modKind : ARRAY [0 .. MaxMods - 1] OF INTEGER;
  145. modImpl : ARRAY [0 .. MaxMods - 1] OF BOOLEAN;
  146. haveProg : BOOLEAN;
  147. typeBlockDepth : CARDINAL; (* > 0 inside a TYPE block *)
  148. procp : ARRAY [0 .. MaxPP - 1] OF TypeIndex; (* proc-type params *)
  149. procvis : ARRAY [0 .. MaxPP - 1] OF BOOLEAN; (* VAR flags *)
  150. procstart : ARRAY [0 .. MaxTypes - 1] OF CARDINAL;
  151. procn : ARRAY [0 .. MaxTypes - 1] OF CARDINAL;
  152. nProcP : CARDINAL;
  153. (* ---------------- strings ---------------- *)
  154. PROCEDURE Assign (VAR dest: ARRAY OF CHAR; src: ARRAY OF CHAR);
  155. VAR i : CARDINAL;
  156. BEGIN
  157. i := 0;
  158. WHILE (i < HIGH(dest)) AND (src[i] # CHR(0)) DO
  159. dest[i] := src[i]; INC(i)
  160. END;
  161. dest[i] := CHR(0)
  162. END Assign;
  163. PROCEDURE Equal (a, b: ARRAY OF CHAR): BOOLEAN;
  164. VAR i : CARDINAL;
  165. BEGIN
  166. i := 0;
  167. LOOP
  168. IF a[i] # b[i] THEN RETURN FALSE END;
  169. IF a[i] = CHR(0) THEN RETURN TRUE END;
  170. INC(i)
  171. END
  172. END Equal;
  173. PROCEDURE Less (a, b: ARRAY OF CHAR): BOOLEAN;
  174. (* Lexicographic order on NUL-terminated strings (BST key order). *)
  175. VAR i : CARDINAL;
  176. BEGIN
  177. i := 0;
  178. LOOP
  179. IF a[i] # b[i] THEN RETURN ORD(a[i]) < ORD(b[i]) END;
  180. IF a[i] = CHR(0) THEN RETURN FALSE END;
  181. INC(i)
  182. END
  183. END Less;
  184. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  185. VAR i : CARDINAL;
  186. BEGIN
  187. i := 0;
  188. WHILE (i < HIGH(s)) AND (s[i] # CHR(0)) DO INC(i) END;
  189. RETURN i
  190. END StrLen;
  191. PROCEDURE ConstInt (q: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  192. VAR i, d: CARDINAL;
  193. neg: BOOLEAN;
  194. BEGIN
  195. v := 0; i := 0; neg := FALSE;
  196. IF q[0] = "-" THEN neg := TRUE; i := 1 END;
  197. IF (i >= HIGH(q)) OR (q[i] = CHR(0)) THEN RETURN FALSE END;
  198. WHILE (i < HIGH(q)) AND (q[i] # CHR(0)) DO
  199. d := ORD(q[i]);
  200. IF (d < ORD("0")) OR (d > ORD("9")) THEN RETURN FALSE END;
  201. v := v * 10 + VAL(INTEGER, d - ORD("0")); INC(i)
  202. END;
  203. IF neg THEN v := -v END;
  204. RETURN TRUE
  205. END ConstInt;
  206. (* ---------------- scope tree + per-scope BST ---------------- *)
  207. PROCEDURE NewScope (parent: ScopePtr; level: CARDINAL): ScopePtr;
  208. (* Heap-allocates a scope and appends it to the creation chain. *)
  209. VAR s: ScopePtr;
  210. BEGIN
  211. NEW(s);
  212. s^.parent := parent;
  213. s^.root := NIL;
  214. s^.level := level;
  215. s^.link := NIL;
  216. s^.ofRec := InvalidType;
  217. IF scopeList = NIL THEN scopeList := s ELSE scopeTail^.link := s END;
  218. scopeTail := s;
  219. RETURN s
  220. END NewScope;
  221. PROCEDURE TreeFind (root: SymPtr; name: ARRAY OF CHAR): SymPtr;
  222. (* BST search within one scope; NIL if absent. *)
  223. BEGIN
  224. WHILE root # NIL DO
  225. IF Equal(root^.name, name) THEN RETURN root END;
  226. IF Less(name, root^.name) THEN root := root^.left
  227. ELSE root := root^.right
  228. END
  229. END;
  230. RETURN NIL
  231. END TreeFind;
  232. PROCEDURE TreeInsert (s: ScopePtr; node: SymPtr): BOOLEAN;
  233. (* BST insert of node into scope s; FALSE on duplicate. *)
  234. VAR cur, parent: SymPtr;
  235. goLeft: BOOLEAN;
  236. BEGIN
  237. cur := s^.root; parent := NIL; goLeft := FALSE;
  238. WHILE cur # NIL DO
  239. IF Equal(cur^.name, node^.name) THEN RETURN FALSE END;
  240. parent := cur;
  241. IF Less(node^.name, cur^.name) THEN
  242. cur := cur^.left; goLeft := TRUE
  243. ELSE
  244. cur := cur^.right; goLeft := FALSE
  245. END
  246. END;
  247. node^.left := NIL;
  248. node^.right := NIL;
  249. node^.scope := s;
  250. IF parent = NIL THEN s^.root := node
  251. ELSIF goLeft THEN parent^.left := node
  252. ELSE parent^.right := node
  253. END;
  254. RETURN TRUE
  255. END TreeInsert;
  256. PROCEDURE FindScope (name: ARRAY OF CHAR; s0: ScopePtr): SymPtr;
  257. (* Innermost visible node from scope s0, or NIL; walks the chain up. *)
  258. VAR s: ScopePtr;
  259. r: SymPtr;
  260. BEGIN
  261. s := s0;
  262. WHILE s # NIL DO
  263. r := TreeFind(s^.root, name);
  264. IF r # NIL THEN RETURN r END;
  265. s := s^.parent
  266. END;
  267. RETURN NIL
  268. END FindScope;
  269. PROCEDURE Find (name: ARRAY OF CHAR): SymPtr;
  270. (* Innermost visible node or NIL; walks the scope chain up. *)
  271. BEGIN
  272. RETURN FindScope(name, curScope)
  273. END Find;
  274. PROCEDURE SetNodeMod (node: SymPtr);
  275. (* Records the defining module for global-symbol naming. *)
  276. BEGIN
  277. IF curMod >= 0 THEN Assign(node^.mod, modNames[curMod])
  278. ELSE node^.mod[0] := CHR(0)
  279. END
  280. END SetNodeMod;
  281. PROCEDURE RawEnter (name: ARRAY OF CHAR; kind: INTEGER): SymPtr;
  282. (* Heap-allocates a symbol and links it into the current scope's
  283. BST; NIL on duplicate (node released to nobody: dropped). *)
  284. VAR node: SymPtr;
  285. BEGIN
  286. NEW(node);
  287. Assign(node^.name, name);
  288. Assign(node^.sym, name);
  289. SetNodeMod(node);
  290. node^.kind := kind;
  291. node^.typ := InvalidType;
  292. node^.scope := curScope;
  293. node^.left := NIL;
  294. node^.right := NIL;
  295. node^.val[0] := CHR(0);
  296. node^.fsnap := FALSE; (* no DEFINITION signature snapshotted *)
  297. node^.ext := FALSE;
  298. node^.varargs := FALSE;
  299. IF NOT TreeInsert(curScope, node) THEN RETURN NIL END;
  300. RETURN node
  301. END RawEnter;
  302. PROCEDURE Enter (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  303. BEGIN
  304. RETURN RawEnter(name, kind) # NIL
  305. END Enter;
  306. PROCEDURE ReenterModGlobal (name: ARRAY OF CHAR; kind: INTEGER;
  307. modName: ARRAY OF CHAR): BOOLEAN;
  308. VAR node: SymPtr;
  309. BEGIN
  310. node := RawEnter(name, kind);
  311. IF node = NIL THEN RETURN FALSE END;
  312. Assign(node^.mod, modName);
  313. RETURN TRUE
  314. END ReenterModGlobal;
  315. PROCEDURE EnterPending (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  316. VAR node: SymPtr;
  317. BEGIN
  318. node := RawEnter(name, kind);
  319. IF (node # NIL) AND (nPend < MaxPend) THEN
  320. pend[nPend] := node; INC(nPend)
  321. END;
  322. RETURN node # NIL
  323. END EnterPending;
  324. PROCEDURE VarParamOk (actual, formal: TypeIndex): BOOLEAN;
  325. (* Addressable-designator compatibility for VAR formals: same type,
  326. or fixed array into open array with same element type, or string
  327. literal into open CHAR array. *)
  328. VAR fa, fe: TypeIndex;
  329. BEGIN
  330. IF (actual = InvalidType) OR (formal = InvalidType) THEN
  331. RETURN TRUE
  332. END;
  333. IF SameType(actual, formal) THEN RETURN TRUE END;
  334. (* ADDRESS is interchangeable with any pointer for VAR params
  335. (ADDRESS is a predefined alias, so ClassOf is enough here) *)
  336. IF (formal = dAddr) AND (ClassOf(actual) = ClPtr) THEN
  337. RETURN TRUE
  338. END;
  339. IF (actual = dAddr) AND (ClassOf(formal) = ClPtr) THEN
  340. RETURN TRUE
  341. END;
  342. IF IsOpenArray(formal)
  343. AND (ClassOf(actual) = ClArray) AND (ArrayDepth(actual) = 1) THEN
  344. fa := ArrayElem(actual); fe := ArrayElem(formal);
  345. IF SameType(fa, fe) THEN RETURN TRUE END
  346. END;
  347. IF IsOpenArray(formal) AND (ClassOf(actual) = ClStr) THEN
  348. fe := ArrayElem(formal);
  349. IF ClassOf(fe) = ClChar THEN RETURN TRUE END
  350. END;
  351. IF IsOpenArray(formal) AND (ClassOf(actual) = ClUStr) THEN
  352. fe := ArrayElem(formal);
  353. IF ClassOf(fe) = ClUChar THEN RETURN TRUE END
  354. END;
  355. (* gm2 compatibility: a scalar VAR actual of a *different* type is
  356. accepted when it has the same storage footprint (e.g. INTEGER for
  357. VAR WORD, SHORTREAL for VAR WORD). Composite types stay strict. *)
  358. IF (ClassOf(actual) # ClArray) AND (ClassOf(actual) # ClRecord)
  359. AND (ClassOf(actual) # ClClass)
  360. AND (ClassOf(formal) # ClArray) AND (ClassOf(formal) # ClRecord)
  361. AND (ClassOf(formal) # ClClass)
  362. AND (ObjectSize(actual) > 0) AND (ObjectSize(actual) = ObjectSize(formal)) THEN
  363. RETURN TRUE
  364. END;
  365. RETURN FALSE
  366. END VarParamOk;
  367. PROCEDURE FormalOk (a, b: TypeIndex): BOOLEAN;
  368. (* Value-formal equivalence for the strict 231 check: the same type, or
  369. both integer-family (one family per the scalar model), or two
  370. string-compatible types. *)
  371. BEGIN
  372. IF (a = InvalidType) OR (b = InvalidType) THEN
  373. (* an unresolved type is not honest evidence; treat as ok so a
  374. single root 221/201 is not multiplied by 231 *)
  375. RETURN TRUE
  376. END;
  377. IF SameType(a, b) THEN RETURN TRUE END;
  378. IF IsIntFamily(a) AND IsIntFamily(b) THEN RETURN TRUE END;
  379. (* Open-array formals are structurally compatible when their element
  380. types match: each `ARRAY OF T` declaration allocates a fresh
  381. descriptor, so a DEFINITION/IMPLEMENTATION pair never shares the
  382. type index and SameType would otherwise reject it. *)
  383. IF IsOpenArray(a) AND IsOpenArray(b) THEN
  384. RETURN SameType(ArrayElem(a), ArrayElem(b))
  385. END;
  386. (* Procedure types are built fresh per parse, so a
  387. DEFINITION/IMPLEMENTATION pair never shares the index; compare
  388. structurally (same result and parameter types). *)
  389. IF (tform[Resolve(a)] = FProc) AND (tform[Resolve(b)] = FProc) THEN
  390. RETURN ProcTypesOk(Resolve(a), Resolve(b))
  391. END;
  392. RETURN StrCompat(a, b)
  393. END FormalOk;
  394. PROCEDURE FixPending (t: TypeIndex) : BOOLEAN;
  395. (* Assigns type t to all pending entries, clears the buffer, and
  396. returns TRUE. When the current procedure heading resumed a
  397. DEFINITION (snapshot present), this is where a formal's type is
  398. known, so the just-typed formals are compared against the
  399. snapshot: FALSE = a strict-231 mismatch. *)
  400. VAR i, base, k, n: CARDINAL;
  401. f: SymPtr;
  402. isV, ok: BOOLEAN;
  403. BEGIN
  404. n := nPend; (* formals typed by this call *)
  405. i := 0;
  406. WHILE i < nPend DO
  407. pend[i]^.typ := t; INC(i)
  408. END;
  409. nPend := 0;
  410. IF (curProc = NIL) OR (curProc^.nSnap = 0) THEN RETURN TRUE END;
  411. (* number of formals already in the chain *)
  412. base := 0;
  413. f := curProc^.plink;
  414. WHILE f # NIL DO INC(base); f := f^.plink END;
  415. IF base > curProc^.nSnap THEN RETURN FALSE END;
  416. (* the just-typed formals are chain indexes base-n .. base-1 *)
  417. FOR k := 0 TO n - 1 DO
  418. IF base >= n THEN
  419. (* walk to index base-n+k *)
  420. f := curProc^.plink;
  421. i := 0;
  422. WHILE (i < base - n + k) AND (f # NIL) DO
  423. f := f^.plink; INC(i)
  424. END;
  425. IF f # NIL THEN
  426. isV := f^.isVar;
  427. IF isV THEN ok := VarParamOk(f^.typ, curProc^.snapT[base - n + k])
  428. ELSE ok := FormalOk(f^.typ, curProc^.snapT[base - n + k]) END;
  429. IF (isV # curProc^.snapV[base - n + k]) OR NOT ok THEN
  430. RETURN FALSE
  431. END
  432. END
  433. END
  434. END;
  435. RETURN TRUE
  436. END FixPending;
  437. PROCEDURE PendCount (): CARDINAL;
  438. BEGIN
  439. RETURN nPend
  440. END PendCount;
  441. PROCEDURE PendName (i: CARDINAL; VAR n: Name);
  442. BEGIN
  443. IF i < nPend THEN Assign(n, pend[i]^.name)
  444. ELSE n[0] := CHR(0)
  445. END
  446. END PendName;
  447. PROCEDURE Resolve (t: TypeIndex): TypeIndex;
  448. VAR n: CARDINAL;
  449. BEGIN
  450. n := 0;
  451. WHILE (n < ResDepth) AND (t >= 0) AND (t < VAL(INTEGER, nTypes))
  452. AND (tform[t] = FAlias) DO
  453. t := tref[t]; INC(n)
  454. END;
  455. IF (t < 0) OR (t >= VAL(INTEGER, nTypes)) THEN
  456. RETURN InvalidType
  457. END;
  458. RETURN t
  459. END Resolve;
  460. PROCEDURE ParentOf (t: TypeIndex): TypeIndex;
  461. (* The single parent class of t, or InvalidType. *)
  462. VAR r: TypeIndex;
  463. BEGIN
  464. r := Resolve(t);
  465. IF (r >= 0) AND (r < VAL(INTEGER, nTypes))
  466. AND (tform[r] = FClass) THEN
  467. RETURN tparent[r]
  468. END;
  469. RETURN InvalidType
  470. END ParentOf;
  471. PROCEDURE PushProc (node: SymPtr);
  472. BEGIN
  473. IF nProc <= HIGH(procStk) THEN
  474. procStk[nProc] := node; INC(nProc)
  475. END
  476. END PushProc;
  477. PROCEDURE OwnField (rec: TypeIndex; name: ARRAY OF CHAR): FieldPtr;
  478. (* A field declared directly in rec (no parent walk). *)
  479. VAR f: FieldPtr;
  480. BEGIN
  481. IF (rec < 0) OR (rec >= VAL(INTEGER, nTypes)) THEN RETURN NIL END;
  482. IF (tform[rec] # FRecord) AND (tform[rec] # FClass) THEN RETURN NIL END;
  483. f := fields;
  484. WHILE f # NIL DO
  485. IF (f^.owner = rec) AND Equal(f^.name, name) THEN RETURN f END;
  486. f := f^.next
  487. END;
  488. RETURN NIL
  489. END OwnField;
  490. PROCEDURE FindField (rec: TypeIndex; name: ARRAY OF CHAR): FieldPtr;
  491. (* Looks in rec, then up the single-inheritance chain. *)
  492. VAR f: FieldPtr;
  493. r, p: TypeIndex;
  494. guard: CARDINAL;
  495. BEGIN
  496. f := OwnField(rec, name);
  497. IF f # NIL THEN RETURN f END;
  498. r := Resolve(rec);
  499. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN NIL END;
  500. guard := 0;
  501. p := ParentOf(r);
  502. WHILE (p # InvalidType) AND (guard < ResDepth) DO
  503. f := OwnField(p, name);
  504. IF f # NIL THEN RETURN f END;
  505. r := p;
  506. p := ParentOf(r);
  507. INC(guard)
  508. END;
  509. RETURN NIL
  510. END FindField;
  511. PROCEDURE FieldPending (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  512. VAR f: FieldPtr;
  513. BEGIN
  514. IF FindField(rec, name) # NIL THEN RETURN FALSE END;
  515. NEW(f);
  516. Assign(f^.name, name);
  517. f^.typ := InvalidType;
  518. f^.owner := rec;
  519. f^.next := fields;
  520. fields := f;
  521. IF (rec >= 0) AND (rec < VAL(INTEGER, nTypes)) THEN
  522. tdone[rec] := FALSE
  523. END;
  524. IF nPendF < MaxPend THEN
  525. pendF[nPendF] := f; INC(nPendF)
  526. END;
  527. INC(nFields);
  528. RETURN TRUE
  529. END FieldPending;
  530. PROCEDURE FixPendingF (rec: TypeIndex; t: TypeIndex);
  531. VAR i, j: CARDINAL;
  532. BEGIN
  533. i := 0;
  534. WHILE i < nPendF DO
  535. IF pendF[i]^.owner = rec THEN
  536. pendF[i]^.typ := t;
  537. (* remove by swap with last *)
  538. j := nPendF - 1;
  539. pendF[i] := pendF[j];
  540. DEC(nPendF)
  541. ELSE
  542. INC(i)
  543. END
  544. END
  545. END FixPendingF;
  546. PROCEDURE Lookup (name: ARRAY OF CHAR): BOOLEAN;
  547. BEGIN
  548. RETURN Find(name) # NIL
  549. END Lookup;
  550. PROCEDURE SymType (name: ARRAY OF CHAR): TypeIndex;
  551. VAR node: SymPtr;
  552. BEGIN
  553. node := Find(name);
  554. IF node = NIL THEN RETURN InvalidType END;
  555. RETURN node^.typ
  556. END SymType;
  557. PROCEDURE SetSymType (name: ARRAY OF CHAR; t: TypeIndex);
  558. VAR node: SymPtr;
  559. BEGIN
  560. node := Find(name);
  561. IF node # NIL THEN node^.typ := t END
  562. END SetSymType;
  563. PROCEDURE SymKind (name: ARRAY OF CHAR): INTEGER;
  564. VAR node: SymPtr;
  565. BEGIN
  566. node := Find(name);
  567. IF node = NIL THEN RETURN -1 END;
  568. RETURN node^.kind
  569. END SymKind;
  570. PROCEDURE SetSymVal (name: ARRAY OF CHAR; v: ARRAY OF CHAR);
  571. VAR node: SymPtr;
  572. BEGIN
  573. node := Find(name);
  574. IF node # NIL THEN Assign(node^.val, v) END
  575. END SetSymVal;
  576. PROCEDURE GetSymVal (name: ARRAY OF CHAR; VAR v: ARRAY OF CHAR): BOOLEAN;
  577. VAR node: SymPtr;
  578. BEGIN
  579. node := Find(name);
  580. IF node = NIL THEN
  581. v[0] := CHR(0); RETURN FALSE
  582. END;
  583. IF node^.val[0] = CHR(0) THEN
  584. v[0] := CHR(0); RETURN FALSE
  585. END;
  586. Assign(v, node^.val);
  587. RETURN TRUE
  588. END GetSymVal;
  589. PROCEDURE PushScope;
  590. BEGIN
  591. curScope := NewScope(curScope, curScope^.level + 1)
  592. END PushScope;
  593. PROCEDURE PopScope;
  594. BEGIN
  595. (* Nodes stay allocated but become unreachable via the chain. *)
  596. IF curScope^.parent # NIL THEN curScope := curScope^.parent END
  597. END PopScope;
  598. (* ---------------- type descriptors (unchanged) ---------------- *)
  599. PROCEDURE NewDesc (form: INTEGER; ref: TypeIndex): TypeIndex;
  600. BEGIN
  601. IF nTypes >= MaxTypes THEN RETURN InvalidType END;
  602. tform[nTypes] := form;
  603. tref[nTypes] := ref;
  604. tbytebuf[nTypes] := FALSE;
  605. tdone[nTypes] := FALSE;
  606. tvtag[nTypes] := FALSE;
  607. vtBase[nTypes] := 0;
  608. nVirt[nTypes] := 0;
  609. vtBuilt[nTypes] := FALSE;
  610. tvptr[nTypes] := -1;
  611. ttag[nTypes] := NIL;
  612. INC(nTypes);
  613. RETURN VAL(INTEGER, nTypes - 1)
  614. END NewDesc;
  615. PROCEDURE NewAlias (): TypeIndex;
  616. BEGIN
  617. RETURN NewDesc(FAlias, InvalidType)
  618. END NewAlias;
  619. PROCEDURE EnterTypeParam (name: ARRAY OF CHAR): BOOLEAN;
  620. (* A generic formal type parameter: an unresolved alias type. The
  621. definition and implementation modules repeat the formals, so a
  622. second entry of the same name reuses the first. *)
  623. VAR t: TypeIndex;
  624. BEGIN
  625. IF Lookup(name) AND (SymKind(name) = KindType) THEN RETURN TRUE END;
  626. t := NewAlias();
  627. IF t = InvalidType THEN RETURN FALSE END;
  628. IF NOT Enter(name, KindType) THEN RETURN FALSE END;
  629. SetSymType(name, t);
  630. RETURN TRUE
  631. END EnterTypeParam;
  632. PROCEDURE EnterTypeParamBound (name: ARRAY OF CHAR;
  633. actual: TypeIndex): BOOLEAN;
  634. (* A generic formal type parameter bound to a concrete actual: an alias
  635. type whose target is the actual, entered in the current (module)
  636. scope. Used during instantiation re-parse. *)
  637. VAR t: TypeIndex;
  638. BEGIN
  639. IF Lookup(name) AND (SymKind(name) = KindType) THEN RETURN TRUE END;
  640. t := NewAlias();
  641. IF t = InvalidType THEN RETURN FALSE END;
  642. IF NOT Enter(name, KindType) THEN RETURN FALSE END;
  643. SetSymType(name, t);
  644. SetTarget(t, actual);
  645. RETURN TRUE
  646. END EnterTypeParamBound;
  647. PROCEDURE NewSubR (lo, hi: INTEGER): TypeIndex;
  648. VAR t: TypeIndex;
  649. BEGIN
  650. t := NewDesc(FSub, InvalidType);
  651. IF t # InvalidType THEN tlo[t] := lo; thi[t] := hi END;
  652. RETURN t
  653. END NewSubR;
  654. PROCEDURE NewEnum (): TypeIndex;
  655. BEGIN
  656. RETURN NewDesc(FEnum, InvalidType)
  657. END NewEnum;
  658. PROCEDURE SetEnumCount (t: TypeIndex; n: CARDINAL);
  659. VAR r: TypeIndex;
  660. BEGIN
  661. r := Resolve(t);
  662. IF (r # InvalidType) AND (tform[r] = FEnum) THEN tenum[r] := n END
  663. END SetEnumCount;
  664. PROCEDURE EnumCount (t: TypeIndex): CARDINAL;
  665. VAR r: TypeIndex;
  666. BEGIN
  667. r := Resolve(t);
  668. IF (r = InvalidType) OR (tform[r] # FEnum) THEN RETURN 0 END;
  669. RETURN tenum[r]
  670. END EnumCount;
  671. PROCEDURE LitPut (off: CARDINAL; name: ARRAY OF CHAR);
  672. VAR i: CARDINAL;
  673. BEGIN
  674. i := 0;
  675. WHILE (i < 63) AND (name[i] # CHR(0)) AND (off + i <= HIGH(enumLitNm)) DO
  676. enumLitNm[off + i] := name[i]; INC(i)
  677. END;
  678. IF off + i <= HIGH(enumLitNm) THEN enumLitNm[off + i] := CHR(0) END
  679. END LitPut;
  680. PROCEDURE LitGet (off: CARDINAL; VAR name: Name);
  681. VAR i: CARDINAL;
  682. BEGIN
  683. i := 0;
  684. WHILE (i < 63) AND (off + i <= HIGH(enumLitNm))
  685. AND (enumLitNm[off + i] # CHR(0)) DO
  686. name[i] := enumLitNm[off + i]; INC(i)
  687. END;
  688. name[i] := CHR(0)
  689. END LitGet;
  690. PROCEDURE NoteEnumLit (t: TypeIndex; name: ARRAY OF CHAR);
  691. (* Registers one enumeration literal (called by the grammar's Enum). *)
  692. VAR r: TypeIndex;
  693. BEGIN
  694. r := Resolve(t);
  695. IF r = InvalidType THEN RETURN END;
  696. IF enumLitN >= MaxEnumLit THEN RETURN END;
  697. IF NOT enumLitDone[r] THEN
  698. enumLitStart[r] := enumLitN; enumLitDone[r] := TRUE
  699. END;
  700. LitPut(enumLitN * 64, name); INC(enumLitN)
  701. END NoteEnumLit;
  702. PROCEDURE OrdStr (v: INTEGER; VAR s: Name);
  703. VAR buf: ARRAY [0 .. 15] OF CHAR;
  704. n, i, m: CARDINAL;
  705. BEGIN
  706. IF v < 0 THEN m := 0 ELSE m := VAL(CARDINAL, v) END;
  707. n := 0;
  708. IF m = 0 THEN buf[0] := "0"; n := 1 END;
  709. WHILE (m > 0) AND (n < HIGH(buf)) DO
  710. buf[n] := CHR(ORD("0") + m MOD 10); m := m DIV 10; INC(n)
  711. END;
  712. i := 0;
  713. WHILE i < n DO s[i] := buf[n - 1 - i]; INC(i) END;
  714. s[n] := CHR(0)
  715. END OrdStr;
  716. PROCEDURE EnumLitName (t: TypeIndex; i: CARDINAL; VAR name: Name);
  717. VAR r: TypeIndex; base: CARDINAL;
  718. BEGIN
  719. name[0] := CHR(0);
  720. r := Resolve(t);
  721. IF (r = InvalidType) OR NOT enumLitDone[r] OR (i >= tenum[r]) THEN
  722. RETURN
  723. END;
  724. base := enumLitStart[r] + i;
  725. IF base < MaxEnumLit THEN LitGet(base * 64, name) END
  726. END EnumLitName;
  727. PROCEDURE EnterEnumLits (t: TypeIndex): CARDINAL;
  728. (* Makes an enum type's literals visible in the current scope (the type
  729. was just declared/imported). Returns how many were newly entered. *)
  730. VAR r: TypeIndex; i, n, added: CARDINAL; nm: Name; node: SymPtr;
  731. BEGIN
  732. r := Resolve(t);
  733. IF (r = InvalidType) OR (tform[r] # FEnum) THEN RETURN 0 END;
  734. added := 0;
  735. n := tenum[r];
  736. i := 0;
  737. WHILE i < n DO
  738. EnumLitName(t, i, nm);
  739. IF (nm[0] # CHR(0)) AND (TreeFind(curScope^.root, nm) = NIL) THEN
  740. node := RawEnter(nm, KindConst);
  741. IF node # NIL THEN
  742. node^.typ := t;
  743. OrdStr(VAL(INTEGER, i), node^.val);
  744. INC(added)
  745. END
  746. END;
  747. INC(i)
  748. END;
  749. RETURN added
  750. END EnterEnumLits;
  751. PROCEDURE NewArrayB (elem: TypeIndex; lo, hi: INTEGER): TypeIndex;
  752. VAR t: TypeIndex;
  753. BEGIN
  754. t := NewDesc(FArray, elem);
  755. IF t # InvalidType THEN alo[t] := lo; ahi[t] := hi END;
  756. RETURN t
  757. END NewArrayB;
  758. PROCEDURE NewOpenArray (elem: TypeIndex): TypeIndex;
  759. BEGIN
  760. RETURN NewDesc(FOpenArr, elem)
  761. END NewOpenArray;
  762. PROCEDURE BoundBegin;
  763. BEGIN
  764. nBounds := 0
  765. END BoundBegin;
  766. PROCEDURE BoundAdd (lo, hi: INTEGER): BOOLEAN;
  767. BEGIN
  768. IF nBounds > HIGH(blo) THEN RETURN FALSE END;
  769. blo[nBounds] := lo; bhi[nBounds] := hi; INC(nBounds);
  770. RETURN TRUE
  771. END BoundAdd;
  772. PROCEDURE BoundCount (): CARDINAL;
  773. BEGIN RETURN nBounds END BoundCount;
  774. PROCEDURE BoundLo (i: CARDINAL): INTEGER;
  775. BEGIN
  776. IF i < nBounds THEN RETURN blo[i] ELSE RETURN 0 END
  777. END BoundLo;
  778. PROCEDURE BoundHi (i: CARDINAL): INTEGER;
  779. BEGIN
  780. IF i < nBounds THEN RETURN bhi[i] ELSE RETURN -1 END
  781. END BoundHi;
  782. PROCEDURE NewRecord (): TypeIndex;
  783. BEGIN
  784. RETURN NewDesc(FRecord, -1)
  785. END NewRecord;
  786. PROCEDURE NewSet (base: TypeIndex): TypeIndex;
  787. BEGIN
  788. RETURN NewDesc(FSet, base)
  789. END NewSet;
  790. PROCEDURE NewPtr (base: TypeIndex): TypeIndex;
  791. BEGIN
  792. RETURN NewDesc(FPtr, base)
  793. END NewPtr;
  794. PROCEDURE NewStr (): TypeIndex;
  795. BEGIN
  796. RETURN NewDesc(FStr, InvalidType)
  797. END NewStr;
  798. PROCEDURE NewUStr (): TypeIndex;
  799. BEGIN
  800. RETURN NewDesc(FUStr, InvalidType)
  801. END NewUStr;
  802. PROCEDURE NewClass (): TypeIndex;
  803. VAR t: TypeIndex;
  804. BEGIN
  805. t := NewDesc(FClass, InvalidType);
  806. IF t # InvalidType THEN
  807. tparent[t] := InvalidType; tscope[t] := NIL
  808. END;
  809. RETURN t
  810. END NewClass;
  811. PROCEDURE SetParent (t, p: TypeIndex);
  812. BEGIN
  813. IF (t >= 0) AND (t < VAL(INTEGER, nTypes)) AND (tform[t] = FClass) THEN
  814. tparent[t] := p
  815. END
  816. END SetParent;
  817. PROCEDURE Unresolved (t: TypeIndex): BOOLEAN;
  818. (* TRUE for a not-yet-completed type: an unbound alias whose target is
  819. still InvalidType (a generic formal, or a forward/pending type). *)
  820. BEGIN
  821. RETURN Resolve(t) = InvalidType
  822. END Unresolved;
  823. PROCEDURE IsOrdinal (t: TypeIndex): BOOLEAN;
  824. (* An ordinal type: integer family, CHAR, UCHAR, BOOLEAN or an
  825. enumeration (drives CASE/variant selectors). *)
  826. VAR c: INTEGER;
  827. BEGIN
  828. IF Resolve(t) = InvalidType THEN RETURN FALSE END;
  829. c := ClassOf(t);
  830. RETURN (c = ClInt) OR (c = ClChar) OR (c = ClUChar)
  831. OR (c = ClBool) OR (c = ClEnum)
  832. END IsOrdinal;
  833. PROCEDURE ResetFields (rec: TypeIndex);
  834. (* Starts a fresh variant branch: drops any still-pending fields of
  835. rec (their identifiers saw no ":" yet) and clears its layout so
  836. the next branch overlays from the tag slot. Field names already
  837. committed in an earlier branch stay in the record's scope. *)
  838. VAR i: CARDINAL;
  839. r: TypeIndex;
  840. BEGIN
  841. r := Resolve(rec);
  842. i := 0;
  843. WHILE i < nPendF DO
  844. IF pendF[i]^.owner = r THEN
  845. nPendF := nPendF - 1;
  846. pendF[i] := pendF[nPendF]
  847. ELSE
  848. INC(i)
  849. END
  850. END;
  851. IF (r >= 0) AND (r < VAL(INTEGER, nTypes)) THEN
  852. tdone[r] := FALSE
  853. END
  854. END ResetFields;
  855. PROCEDURE SetVariantTag (rec: TypeIndex; name: ARRAY OF CHAR);
  856. (* Records the variant CASE selector field of rec (by name); called
  857. just after the tag's type is fixed, before the variant branches. *)
  858. VAR r: TypeIndex;
  859. BEGIN
  860. r := Resolve(rec);
  861. IF (r >= 0) AND (r < VAL(INTEGER, nTypes)) THEN
  862. ttag[r] := FindField(r, name)
  863. END
  864. END SetVariantTag;
  865. PROCEDURE MarkVariant (rec: TypeIndex);
  866. (* Records that this record has a variant part (its fields overlap
  867. from the tag slot on, so whole-record comparison is 236). *)
  868. VAR r: TypeIndex;
  869. BEGIN
  870. r := Resolve(rec);
  871. IF (r >= 0) AND (r < VAL(INTEGER, nTypes)) THEN
  872. tvtag[r] := TRUE
  873. END
  874. END MarkVariant;
  875. PROCEDURE IsVariant (rec: TypeIndex): BOOLEAN;
  876. VAR r: TypeIndex;
  877. BEGIN
  878. r := Resolve(rec);
  879. IF (r >= 0) AND (r < VAL(INTEGER, nTypes)) THEN
  880. RETURN tvtag[r]
  881. END;
  882. RETURN FALSE
  883. END IsVariant;
  884. PROCEDURE PushClassScope (t: TypeIndex);
  885. VAR r: TypeIndex;
  886. BEGIN
  887. r := Resolve(t);
  888. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN END;
  889. PushScope;
  890. tscope[r] := curScope
  891. END PushClassScope;
  892. PROCEDURE SetTarget (t, base: TypeIndex);
  893. BEGIN
  894. IF (t >= 0) AND (t < VAL(INTEGER, nTypes)) AND (tform[t] = FAlias) THEN
  895. tref[t] := base
  896. END
  897. END SetTarget;
  898. PROCEDURE IntType (): TypeIndex;
  899. BEGIN RETURN dInt END IntType;
  900. PROCEDURE UCharType (): TypeIndex;
  901. BEGIN RETURN dUChar END UCharType;
  902. PROCEDURE AddrType (): TypeIndex;
  903. BEGIN RETURN dAddr END AddrType;
  904. PROCEDURE LongType (): TypeIndex;
  905. BEGIN RETURN dLong END LongType;
  906. PROCEDURE RealType (): TypeIndex;
  907. BEGIN RETURN dReal END RealType;
  908. PROCEDURE CharType (): TypeIndex;
  909. BEGIN RETURN dChar END CharType;
  910. PROCEDURE BoolType (): TypeIndex;
  911. BEGIN RETURN dBool END BoolType;
  912. PROCEDURE ClassOf (t: TypeIndex): INTEGER;
  913. VAR r: TypeIndex;
  914. BEGIN
  915. r := Resolve(t);
  916. IF r = InvalidType THEN
  917. (* an opaque/undeclared alias (e.g. gm2's String) is pointer-like *)
  918. IF (t >= 0) AND (t < VAL(INTEGER, nTypes))
  919. AND (tform[t] = FAlias) THEN
  920. RETURN ClPtr
  921. END;
  922. RETURN ClInvalid
  923. END;
  924. CASE tform[r] OF
  925. FInt : RETURN ClInt
  926. | FLong : RETURN ClLong
  927. | FReal : RETURN ClReal
  928. | FChar : RETURN ClChar
  929. | FBool : RETURN ClBool
  930. | FEnum : RETURN ClEnum
  931. | FArray : RETURN ClArray
  932. | FOpenArr : RETURN ClArray
  933. | FRecord : RETURN ClRecord
  934. | FSet : RETURN ClSet
  935. | FPtr : RETURN ClPtr
  936. | FStr : RETURN ClStr
  937. | FClass : RETURN ClClass
  938. | FProc : RETURN ClProc
  939. | FUChar : RETURN ClUChar
  940. | FUStr : RETURN ClUStr
  941. | FNil : RETURN ClNil
  942. | FSub : IF tref[r] = InvalidType THEN RETURN ClInt
  943. ELSE RETURN ClassOf(tref[r]) END
  944. ELSE RETURN ClInvalid
  945. END
  946. END ClassOf;
  947. PROCEDURE IsIntFamily (t: TypeIndex): BOOLEAN;
  948. BEGIN
  949. RETURN ClassOf(t) = ClInt
  950. END IsIntFamily;
  951. PROCEDURE IsLongFamily (t: TypeIndex): BOOLEAN;
  952. BEGIN
  953. RETURN ClassOf(t) = ClLong
  954. END IsLongFamily;
  955. PROCEDURE SameType (a, b: TypeIndex): BOOLEAN;
  956. BEGIN
  957. IF (a = InvalidType) OR (b = InvalidType) THEN RETURN TRUE END;
  958. RETURN Resolve(a) = Resolve(b)
  959. END SameType;
  960. PROCEDURE FieldExists (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  961. BEGIN
  962. RETURN FindField(Resolve(rec), name) # NIL
  963. END FieldExists;
  964. PROCEDURE FieldType (rec: TypeIndex; name: ARRAY OF CHAR): TypeIndex;
  965. VAR f: FieldPtr;
  966. BEGIN
  967. f := FindField(Resolve(rec), name);
  968. IF f = NIL THEN RETURN InvalidType END;
  969. RETURN f^.typ
  970. END FieldType;
  971. PROCEDURE ArrayElem (t: TypeIndex): TypeIndex;
  972. VAR r: TypeIndex;
  973. BEGIN
  974. r := Resolve(t);
  975. IF (r = InvalidType) OR ((tform[r] # FArray)
  976. AND (tform[r] # FOpenArr)) THEN
  977. RETURN InvalidType
  978. END;
  979. RETURN tref[r]
  980. END ArrayElem;
  981. PROCEDURE IsOpenArray (t: TypeIndex): BOOLEAN;
  982. VAR r: TypeIndex;
  983. BEGIN
  984. r := Resolve(t);
  985. IF r = InvalidType THEN RETURN FALSE END;
  986. RETURN tform[r] = FOpenArr
  987. END IsOpenArray;
  988. PROCEDURE MarkByteBuf (t: TypeIndex);
  989. (* Marks an open-array type as an `ARRAY OF BYTE` formal (the gm2
  990. untyped-buffer extension): a scalar actual is then accepted. *)
  991. VAR r: TypeIndex;
  992. BEGIN
  993. r := Resolve(t);
  994. IF r # InvalidType THEN tbytebuf[r] := TRUE END
  995. END MarkByteBuf;
  996. PROCEDURE IsByteBuf (t: TypeIndex): BOOLEAN;
  997. VAR r: TypeIndex;
  998. BEGIN
  999. r := Resolve(t);
  1000. IF r = InvalidType THEN RETURN FALSE END;
  1001. RETURN tbytebuf[r]
  1002. END IsByteBuf;
  1003. PROCEDURE ByteBufOk (at, ft: TypeIndex): BOOLEAN;
  1004. (* gm2 compatibility: a scalar, pointer or string actual is accepted
  1005. for an `ARRAY OF BYTE` formal (the callee sees a byte buffer). *)
  1006. VAR c: INTEGER;
  1007. BEGIN
  1008. IF NOT IsByteBuf(ft) THEN RETURN FALSE END;
  1009. c := ClassOf(at);
  1010. RETURN (c = ClInt) OR (c = ClChar) OR (c = ClBool) OR (c = ClEnum)
  1011. OR (c = ClPtr) OR (c = ClLong) OR (c = ClStr)
  1012. END ByteBufOk;
  1013. PROCEDURE ArrayLo (t: TypeIndex): INTEGER;
  1014. VAR r: TypeIndex;
  1015. BEGIN
  1016. r := Resolve(t);
  1017. IF (r = InvalidType) OR (tform[r] # FArray) THEN RETURN 0 END;
  1018. RETURN alo[r]
  1019. END ArrayLo;
  1020. PROCEDURE ArrayHi (t: TypeIndex): INTEGER;
  1021. VAR r: TypeIndex;
  1022. BEGIN
  1023. r := Resolve(t);
  1024. IF (r = InvalidType) OR (tform[r] # FArray) THEN RETURN 0 END;
  1025. RETURN ahi[r]
  1026. END ArrayHi;
  1027. PROCEDURE ArrayLen (t: TypeIndex): CARDINAL;
  1028. VAR r: TypeIndex;
  1029. lo, hi: INTEGER;
  1030. BEGIN
  1031. r := Resolve(t);
  1032. IF (r = InvalidType) OR (tform[r] # FArray) THEN RETURN 0 END;
  1033. lo := alo[r]; hi := ahi[r];
  1034. IF hi < lo THEN RETURN 0 END;
  1035. RETURN VAL(CARDINAL, hi - lo + 1)
  1036. END ArrayLen;
  1037. PROCEDURE ArrayDepth (t: TypeIndex): CARDINAL;
  1038. VAR r: TypeIndex;
  1039. d: CARDINAL;
  1040. BEGIN
  1041. d := 0; r := Resolve(t);
  1042. WHILE (r # InvalidType) AND ((tform[r] = FArray)
  1043. OR (tform[r] = FOpenArr)) DO
  1044. INC(d); r := Resolve(tref[r])
  1045. END;
  1046. RETURN d
  1047. END ArrayDepth;
  1048. PROCEDURE SubBounds (t: TypeIndex; VAR lo, hi: INTEGER): BOOLEAN;
  1049. VAR r: TypeIndex;
  1050. BEGIN
  1051. lo := 0; hi := -1;
  1052. r := Resolve(t);
  1053. IF (r = InvalidType) OR (tform[r] # FSub)
  1054. OR (tref[r] # InvalidType) THEN
  1055. RETURN FALSE
  1056. END;
  1057. lo := tlo[r]; hi := thi[r];
  1058. RETURN TRUE
  1059. END SubBounds;
  1060. PROCEDURE SetBase (t: TypeIndex): TypeIndex;
  1061. VAR r: TypeIndex;
  1062. BEGIN
  1063. r := Resolve(t);
  1064. IF (r = InvalidType) OR (tform[r] # FSet) THEN
  1065. RETURN InvalidType
  1066. END;
  1067. RETURN tref[r]
  1068. END SetBase;
  1069. PROCEDURE SetSpan (t: TypeIndex; VAR lo, n: INTEGER): BOOLEAN;
  1070. (* Base span for mask sizing; FALSE when unsuitable. Internal. *)
  1071. VAR b, r: TypeIndex;
  1072. blo, bhi: INTEGER;
  1073. BEGIN
  1074. lo := 0; n := 0;
  1075. b := SetBase(t);
  1076. IF b = InvalidType THEN RETURN FALSE END;
  1077. r := Resolve(b);
  1078. IF r = InvalidType THEN RETURN FALSE END;
  1079. IF tform[r] = FBool THEN lo := 0; n := 2; RETURN TRUE END;
  1080. IF tform[r] = FChar THEN lo := 0; n := 256; RETURN TRUE END;
  1081. IF tform[r] = FEnum THEN
  1082. IF tenum[r] = 0 THEN RETURN FALSE END;
  1083. lo := 0; n := VAL(INTEGER, tenum[r]); RETURN TRUE
  1084. END;
  1085. IF (tform[r] = FSub) AND (tref[r] = InvalidType)
  1086. AND SubBounds(b, blo, bhi) AND (bhi >= blo)
  1087. AND (bhi - blo < 65536) THEN
  1088. lo := blo; n := bhi - blo + 1; RETURN TRUE
  1089. END;
  1090. RETURN FALSE
  1091. END SetSpan;
  1092. PROCEDURE SetWords (t: TypeIndex): CARDINAL;
  1093. VAR lo, n: INTEGER;
  1094. BEGIN
  1095. IF NOT SetSpan(t, lo, n) THEN RETURN 0 END;
  1096. RETURN VAL(CARDINAL, (n + 31) DIV 32)
  1097. END SetWords;
  1098. PROCEDURE SetBaseLo (t: TypeIndex): INTEGER;
  1099. VAR lo, n: INTEGER;
  1100. BEGIN
  1101. IF NOT SetSpan(t, lo, n) THEN RETURN 0 END;
  1102. RETURN lo
  1103. END SetBaseLo;
  1104. PROCEDURE SetCount (t: TypeIndex): CARDINAL;
  1105. VAR lo, n: INTEGER;
  1106. BEGIN
  1107. IF NOT SetSpan(t, lo, n) THEN RETURN 0 END;
  1108. RETURN VAL(CARDINAL, n)
  1109. END SetCount;
  1110. PROCEDURE TypeBounds (t: TypeIndex; VAR lo, hi: INTEGER): BOOLEAN;
  1111. (* The ordinal bounds of a type, for MIN/MAX: subrange/array bounds,
  1112. CHAR/UCHAR, BOOLEAN, enumeration, or a set's base span. *)
  1113. VAR r: TypeIndex;
  1114. c: INTEGER;
  1115. BEGIN
  1116. lo := 0; hi := -1;
  1117. r := Resolve(t);
  1118. IF r = InvalidType THEN RETURN FALSE END;
  1119. IF tform[r] = FSub THEN RETURN SubBounds(r, lo, hi) END;
  1120. IF tform[r] = FArray THEN lo := alo[r]; hi := ahi[r]; RETURN TRUE END;
  1121. c := ClassOf(r);
  1122. IF c = ClChar THEN lo := 0; hi := 255; RETURN TRUE END;
  1123. IF c = ClUChar THEN lo := 0; hi := 1114111; RETURN TRUE END;
  1124. IF c = ClBool THEN lo := 0; hi := 1; RETURN TRUE END;
  1125. IF c = ClEnum THEN
  1126. lo := 0;
  1127. IF tenum[r] = 0 THEN hi := -1
  1128. ELSE hi := VAL(INTEGER, tenum[r]) - 1
  1129. END;
  1130. RETURN TRUE
  1131. END;
  1132. IF c = ClSet THEN
  1133. lo := SetBaseLo(r);
  1134. IF SetCount(r) = 0 THEN hi := lo - 1
  1135. ELSE hi := lo + VAL(INTEGER, SetCount(r)) - 1
  1136. END;
  1137. RETURN TRUE
  1138. END;
  1139. IF c = ClInt THEN
  1140. lo := -2147483648; hi := 2147483647; RETURN TRUE
  1141. END;
  1142. RETURN FALSE
  1143. END TypeBounds;
  1144. PROCEDURE PtrBase (t: TypeIndex): TypeIndex;
  1145. VAR r: TypeIndex;
  1146. BEGIN
  1147. r := Resolve(t);
  1148. IF (r = InvalidType) OR (tform[r] # FPtr) THEN
  1149. RETURN InvalidType
  1150. END;
  1151. RETURN tref[r]
  1152. END PtrBase;
  1153. (* ---------------- procedure types (step 8.5) ---------------- *)
  1154. PROCEDURE NewProcType (res: TypeIndex): TypeIndex;
  1155. VAR t: TypeIndex;
  1156. BEGIN
  1157. t := NewDesc(FProc, res);
  1158. IF t = InvalidType THEN RETURN t END;
  1159. procstart[t] := nProcP;
  1160. procn[t] := 0;
  1161. RETURN t
  1162. END NewProcType;
  1163. PROCEDURE ProcTypeAdd (t: TypeIndex; isVar: BOOLEAN; pt: TypeIndex);
  1164. VAR r: TypeIndex;
  1165. BEGIN
  1166. r := Resolve(t);
  1167. IF (r = InvalidType) OR (tform[r] # FProc) THEN RETURN END;
  1168. IF nProcP < MaxPP THEN
  1169. procp[nProcP] := pt;
  1170. procvis[nProcP] := isVar;
  1171. INC(nProcP); INC(procn[r])
  1172. END
  1173. END ProcTypeAdd;
  1174. PROCEDURE SetProcTypeRes (t: TypeIndex; res: TypeIndex);
  1175. VAR r: TypeIndex;
  1176. BEGIN
  1177. r := Resolve(t);
  1178. IF (r # InvalidType) AND (tform[r] = FProc) THEN tref[r] := res END
  1179. END SetProcTypeRes;
  1180. PROCEDURE ProcTypeNPar (t: TypeIndex): CARDINAL;
  1181. VAR r: TypeIndex;
  1182. BEGIN
  1183. r := Resolve(t);
  1184. IF (r = InvalidType) OR (tform[r] # FProc) THEN RETURN 0 END;
  1185. RETURN procn[r]
  1186. END ProcTypeNPar;
  1187. PROCEDURE ProcTypeParamType (t: TypeIndex; i: CARDINAL): TypeIndex;
  1188. VAR r: TypeIndex;
  1189. BEGIN
  1190. r := Resolve(t);
  1191. IF (r = InvalidType) OR (tform[r] # FProc) OR (i >= procn[r]) THEN
  1192. RETURN InvalidType
  1193. END;
  1194. RETURN procp[procstart[r] + i]
  1195. END ProcTypeParamType;
  1196. PROCEDURE ProcTypeParamIsVar (t: TypeIndex; i: CARDINAL): BOOLEAN;
  1197. VAR r: TypeIndex;
  1198. BEGIN
  1199. r := Resolve(t);
  1200. IF (r = InvalidType) OR (tform[r] # FProc) OR (i >= procn[r]) THEN
  1201. RETURN FALSE
  1202. END;
  1203. RETURN procvis[procstart[r] + i]
  1204. END ProcTypeParamIsVar;
  1205. PROCEDURE ProcTypeRes (t: TypeIndex): TypeIndex;
  1206. VAR r: TypeIndex;
  1207. BEGIN
  1208. r := Resolve(t);
  1209. IF (r = InvalidType) OR (tform[r] # FProc) THEN
  1210. RETURN InvalidType
  1211. END;
  1212. RETURN tref[r]
  1213. END ProcTypeRes;
  1214. PROCEDURE ProcTypeOf (name: ARRAY OF CHAR): TypeIndex;
  1215. VAR node, p: SymPtr;
  1216. t: TypeIndex;
  1217. k: CARDINAL;
  1218. BEGIN
  1219. node := Find(name);
  1220. IF node = NIL THEN RETURN InvalidType END;
  1221. IF node^.kind # KindProc THEN RETURN InvalidType END;
  1222. t := NewDesc(FProc, node^.rslt);
  1223. IF t = InvalidType THEN RETURN t END;
  1224. procstart[t] := nProcP;
  1225. k := 0;
  1226. p := node^.plink;
  1227. WHILE (p # NIL) AND (nProcP < MaxPP) DO
  1228. procp[nProcP] := p^.typ;
  1229. procvis[nProcP] := p^.isVar;
  1230. INC(nProcP); INC(k);
  1231. p := p^.plink
  1232. END;
  1233. procn[t] := k;
  1234. RETURN t
  1235. END ProcTypeOf;
  1236. PROCEDURE ElemBytes (t: TypeIndex): CARDINAL;
  1237. (* element size of array descriptor t (bytes) *)
  1238. VAR cls: INTEGER;
  1239. BEGIN
  1240. cls := ClassOf(ArrayElem(t));
  1241. IF cls = ClChar THEN RETURN 1 END;
  1242. IF cls = ClReal THEN RETURN 8 END;
  1243. IF (cls = ClArray) OR (cls = ClPtr) OR (cls = ClRecord)
  1244. OR (cls = ClClass) OR (cls = ClProc) THEN
  1245. RETURN 8
  1246. END;
  1247. RETURN 4
  1248. END ElemBytes;
  1249. PROCEDURE IsCharArray (t: TypeIndex): BOOLEAN;
  1250. BEGIN RETURN ClassOf(ArrayElem(t)) = ClChar END IsCharArray;
  1251. PROCEDURE ArrObjSize (t: TypeIndex): CARDINAL;
  1252. (* full inline size of a fixed array: header (count) + packed elements
  1253. (+1 terminator byte for CHAR arrays) *)
  1254. VAR n: CARDINAL;
  1255. BEGIN
  1256. n := ArrayLen(t) * ElemBytes(t);
  1257. IF IsCharArray(t) THEN n := n + 1 END;
  1258. RETURN 8 + n
  1259. END ArrObjSize;
  1260. PROCEDURE TypeSizeD (t: TypeIndex; depth: CARDINAL): CARDINAL;
  1261. (* Inline footprint in bytes: scalars 4/8, sets words*4, pointers,
  1262. open and fixed arrays 8 (descriptor address — array objects live
  1263. separately); records sum members. Depth guards cycles (not 223). *)
  1264. VAR r: TypeIndex;
  1265. f: FieldPtr;
  1266. tagF: FieldPtr;
  1267. n, plain, high: CARDINAL;
  1268. BEGIN
  1269. IF depth > ResDepth THEN RETURN 0 END;
  1270. r := Resolve(t);
  1271. IF r = InvalidType THEN RETURN 0 END;
  1272. CASE tform[r] OF
  1273. FInt, FBool, FChar, FUChar : RETURN 4
  1274. | FLong : RETURN 8
  1275. | FReal : RETURN 8
  1276. | FEnum, FSub : RETURN 4
  1277. | FSet : RETURN SetWords(t) * 4
  1278. | FPtr, FOpenArr, FArray, FProc, FUStr : RETURN 8
  1279. | FRecord, FClass :
  1280. n := 0;
  1281. IF (tform[r] = FClass) AND (tparent[r] # InvalidType) THEN
  1282. (* single inheritance: parent fields (and its vptr) come first *)
  1283. n := TypeSizeD(tparent[r], depth + 1)
  1284. END;
  1285. IF (tform[r] = FClass) AND (tvptr[r] >= 0)
  1286. AND (tvptr[r] = VAL(INTEGER, n)) THEN
  1287. (* this class introduces its vptr here *)
  1288. n := n + 8
  1289. END;
  1290. IF tvtag[r] AND (ttag[r] # NIL) THEN
  1291. (* variant record: plain fields (declared before the tag) pack
  1292. normally; the tag and every variant field overlay in one
  1293. slot, so the record is plainSize + max(tag, variants). *)
  1294. plain := 0; high := 0;
  1295. f := fields;
  1296. WHILE f # NIL DO
  1297. IF f^.owner = r THEN
  1298. IF f^.ord < ttag[r]^.ord THEN
  1299. (* a plain field, packed before the tag *)
  1300. IF ClassOf(f^.typ) = ClArray THEN
  1301. plain := plain + ArrObjSize(f^.typ)
  1302. ELSE
  1303. plain := plain + TypeSizeD(f^.typ, depth + 1)
  1304. END
  1305. ELSIF f = ttag[r] THEN
  1306. (* the tag itself: its own slot *)
  1307. IF ClassOf(f^.typ) = ClArray THEN
  1308. plain := plain + ArrObjSize(f^.typ)
  1309. ELSE
  1310. plain := plain + TypeSizeD(f^.typ, depth + 1)
  1311. END
  1312. ELSE
  1313. (* a variant field: overlay in the region after the tag *)
  1314. IF ClassOf(f^.typ) = ClArray THEN
  1315. IF ArrObjSize(f^.typ) > high THEN
  1316. high := ArrObjSize(f^.typ)
  1317. END
  1318. ELSE
  1319. IF TypeSizeD(f^.typ, depth + 1) > high THEN
  1320. high := TypeSizeD(f^.typ, depth + 1)
  1321. END
  1322. END
  1323. END
  1324. END;
  1325. f := f^.next
  1326. END;
  1327. RETURN n + plain + high (* n = parent size, if any *)
  1328. END;
  1329. f := fields;
  1330. WHILE f # NIL DO
  1331. IF f^.owner = r THEN
  1332. IF ClassOf(f^.typ) = ClArray THEN
  1333. n := n + ArrObjSize(f^.typ) (* inline array field *)
  1334. ELSE
  1335. n := n + TypeSizeD(f^.typ, depth + 1)
  1336. END
  1337. END;
  1338. f := f^.next
  1339. END;
  1340. RETURN n
  1341. | FAlias :
  1342. RETURN TypeSizeD(tref[r], depth + 1)
  1343. ELSE RETURN 0
  1344. END
  1345. END TypeSizeD;
  1346. PROCEDURE TypeSize (t: TypeIndex): CARDINAL;
  1347. BEGIN
  1348. RETURN TypeSizeD(t, 0)
  1349. END TypeSize;
  1350. PROCEDURE FieldSize (t: TypeIndex): CARDINAL;
  1351. (* inline footprint of a record field: fixed arrays are inline objects *)
  1352. BEGIN
  1353. IF ClassOf(t) = ClArray THEN RETURN ArrObjSize(t) END;
  1354. RETURN TypeSizeD(t, 0)
  1355. END FieldSize;
  1356. PROCEDURE ObjectSize (t: TypeIndex): CARDINAL;
  1357. (* full allocation footprint: arrays 8 + count*elem, else TypeSize.
  1358. Used by SYSTEM.SIZE/TSIZE. *)
  1359. VAR r: TypeIndex;
  1360. BEGIN
  1361. r := Resolve(t);
  1362. IF (r # InvalidType) AND ((tform[r] = FArray)
  1363. OR (tform[r] = FOpenArr)) THEN
  1364. RETURN 8 + ArrayLen(t) * ElemBytes(t)
  1365. END;
  1366. RETURN TypeSize(t)
  1367. END ObjectSize;
  1368. PROCEDURE BuildVTable (ct: TypeIndex);
  1369. (* Assigns ct its virtual-method slots: the parent's are inherited
  1370. first (a same-named virtual method overrides in place), then ct's
  1371. own new virtual methods append. Each method node records its slot
  1372. in vslot. Idempotent. *)
  1373. VAR r, p: TypeIndex;
  1374. s: ScopePtr;
  1375. k: CARDINAL;
  1376. PROCEDURE AddMeth (node: SymPtr);
  1377. (* override an inherited slot or append a new one *)
  1378. VAR found: BOOLEAN; j: CARDINAL;
  1379. BEGIN
  1380. IF (node^.kind # KindProc) OR NOT node^.virt THEN RETURN END;
  1381. found := FALSE; j := 0;
  1382. WHILE (j < nVirt[r]) AND NOT found DO
  1383. IF Equal(vtName[vtBase[r] + j], node^.name) THEN
  1384. vtUid[vtBase[r] + j] := node^.uid;
  1385. node^.vslot := VAL(INTEGER, j);
  1386. found := TRUE
  1387. END;
  1388. INC(j)
  1389. END;
  1390. IF NOT found AND (vtTop < MaxVt) THEN
  1391. Assign(vtName[vtTop], node^.name);
  1392. vtUid[vtTop] := node^.uid;
  1393. node^.vslot := VAL(INTEGER, nVirt[r]);
  1394. INC(vtTop); INC(nVirt[r])
  1395. END
  1396. END AddMeth;
  1397. PROCEDURE Walk (node: SymPtr);
  1398. BEGIN
  1399. IF node = NIL THEN RETURN END;
  1400. Walk(node^.left);
  1401. AddMeth(node);
  1402. Walk(node^.right)
  1403. END Walk;
  1404. BEGIN
  1405. r := Resolve(ct);
  1406. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN END;
  1407. IF vtBuilt[r] THEN RETURN END; (* already built *)
  1408. s := tscope[r];
  1409. IF s = NIL THEN RETURN END;
  1410. vtBase[r] := vtTop;
  1411. nVirt[r] := 0;
  1412. (* inherit the parent's slots *)
  1413. p := ParentOf(r);
  1414. IF p # InvalidType THEN
  1415. IF NOT vtBuilt[p] THEN BuildVTable(p) END;
  1416. k := 0;
  1417. WHILE (k < nVirt[p]) AND (vtTop < MaxVt) DO
  1418. Assign(vtName[vtTop], vtName[vtBase[p] + k]);
  1419. vtUid[vtTop] := vtUid[vtBase[p] + k];
  1420. INC(vtTop); INC(nVirt[r]);
  1421. INC(k)
  1422. END
  1423. END;
  1424. (* ct's own virtual methods: override or append *)
  1425. Walk(s^.root);
  1426. (* vptr field offset: inherited from a parent that already has one,
  1427. else introduced after the parent's fields (or at 0) *)
  1428. IF (p # InvalidType) AND (nVirt[p] > 0) THEN
  1429. tvptr[r] := tvptr[p]
  1430. ELSIF nVirt[r] > 0 THEN
  1431. IF p # InvalidType THEN tvptr[r] := VAL(INTEGER, TypeSizeD(p, 0))
  1432. ELSE tvptr[r] := 0
  1433. END
  1434. ELSE tvptr[r] := -1
  1435. END;
  1436. IF (nVirt[r] > 0) AND (nVtl < MaxTypes) THEN
  1437. vtl[nVtl] := r; INC(nVtl)
  1438. END;
  1439. vtBuilt[r] := TRUE
  1440. END BuildVTable;
  1441. PROCEDURE ComputeOffsets (r: TypeIndex);
  1442. (* Declaration-order offsets over the (prepend-built, hence reverse)
  1443. field chain, plus declaration ranks. Array fields count 8
  1444. (pointer-sized in records, matching the locked layout).
  1445. A record with a variant part lays every field from the first tag
  1446. slot on at that slot's offset (all variant fields overlap), and
  1447. the record's size is the largest such field. *)
  1448. VAR f: FieldPtr;
  1449. tagF: FieldPtr; (* the variant CASE selector field *)
  1450. total, high, tagSize, varOff, baseOff: INTEGER;
  1451. cnt, ord: CARDINAL;
  1452. off, p: INTEGER;
  1453. BEGIN
  1454. (* a class with a parent lays its own fields after the parent's *)
  1455. baseOff := 0;
  1456. IF (tform[r] = FClass) AND (tparent[r] # InvalidType) THEN
  1457. p := Resolve(tparent[r]);
  1458. IF p # InvalidType THEN
  1459. IF NOT vtBuilt[p] THEN BuildVTable(p) END;
  1460. IF NOT tdone[p] THEN ComputeOffsets(p) END;
  1461. baseOff := VAL(INTEGER, TypeSizeD(p, 0))
  1462. END
  1463. END;
  1464. (* a class that introduces (rather than inherits) a vptr reserves
  1465. 8 bytes for it after the parent's fields *)
  1466. IF (tform[r] = FClass) AND (tvptr[r] >= 0)
  1467. AND (tvptr[r] = baseOff) THEN
  1468. baseOff := baseOff + 8
  1469. END;
  1470. IF NOT tvtag[r] THEN
  1471. (* plain record/class: declaration-ordered, tightly packed *)
  1472. total := baseOff; cnt := 0;
  1473. f := fields;
  1474. WHILE f # NIL DO
  1475. IF f^.owner = r THEN
  1476. total := total + VAL(INTEGER, FieldSize(f^.typ));
  1477. INC(cnt)
  1478. END;
  1479. f := f^.next
  1480. END;
  1481. off := total; ord := cnt;
  1482. f := fields;
  1483. WHILE f # NIL DO
  1484. IF f^.owner = r THEN
  1485. off := off - VAL(INTEGER, FieldSize(f^.typ));
  1486. DEC(ord);
  1487. f^.off := off;
  1488. f^.ord := ord
  1489. END;
  1490. f := f^.next
  1491. END;
  1492. tdone[r] := TRUE;
  1493. RETURN
  1494. END;
  1495. (* variant record. Fields declared before the CASE tag pack
  1496. normally; the tag starts the overlay region and every variant
  1497. field (declared after the tag) overlays at the tag's slot.
  1498. Ranks are reverse-declaration (0 = last declared), so the tag
  1499. has rank = number-of-fields-after-it, and plain fields have
  1500. larger ranks. *)
  1501. tagF := ttag[r];
  1502. IF tagF = NIL THEN
  1503. (* no tag recorded (malformed); fall back to plain layout *)
  1504. tvtag[r] := FALSE;
  1505. ComputeOffsets(r);
  1506. RETURN
  1507. END;
  1508. cnt := 0;
  1509. f := fields;
  1510. WHILE f # NIL DO
  1511. IF f^.owner = r THEN INC(cnt) END;
  1512. f := f^.next
  1513. END;
  1514. ord := cnt;
  1515. f := fields;
  1516. WHILE f # NIL DO
  1517. IF f^.owner = r THEN DEC(ord); f^.ord := ord END;
  1518. f := f^.next
  1519. END;
  1520. (* plain fields: pack in declaration order up to the tag *)
  1521. total := 0;
  1522. f := fields;
  1523. WHILE f # NIL DO
  1524. IF (f^.owner = r) AND (f^.ord < tagF^.ord) THEN
  1525. total := total + VAL(INTEGER, FieldSize(f^.typ))
  1526. END;
  1527. f := f^.next
  1528. END;
  1529. off := total;
  1530. f := fields;
  1531. WHILE f # NIL DO
  1532. IF (f^.owner = r) AND (f^.ord < tagF^.ord) THEN
  1533. off := off - VAL(INTEGER, FieldSize(f^.typ));
  1534. f^.off := off
  1535. END;
  1536. f := f^.next
  1537. END;
  1538. (* the tag occupies its own slot after the plain fields; every
  1539. variant field overlays in the region after the tag *)
  1540. tagF^.off := total;
  1541. varOff := total + VAL(INTEGER, FieldSize(tagF^.typ));
  1542. f := fields;
  1543. WHILE f # NIL DO
  1544. IF (f^.owner = r) AND (f^.ord > tagF^.ord) THEN
  1545. f^.off := varOff
  1546. END;
  1547. f := f^.next
  1548. END;
  1549. tdone[r] := TRUE
  1550. END ComputeOffsets;
  1551. PROCEDURE LayoutClass (t: TypeIndex);
  1552. (* Computes a class's vtable and field offsets (and thus its size). *)
  1553. VAR r: TypeIndex;
  1554. BEGIN
  1555. r := Resolve(t);
  1556. IF (r # InvalidType) AND (tform[r] = FClass) THEN
  1557. IF NOT vtBuilt[r] THEN BuildVTable(r) END;
  1558. IF NOT tdone[r] THEN ComputeOffsets(r) END
  1559. END
  1560. END LayoutClass;
  1561. PROCEDURE LayoutRecord (t: TypeIndex);
  1562. (* Computes a record's field offsets / size now (idempotent). *)
  1563. VAR r: TypeIndex;
  1564. BEGIN
  1565. r := Resolve(t);
  1566. IF (r # InvalidType) AND (tform[r] = FRecord)
  1567. AND NOT tdone[r] THEN
  1568. ComputeOffsets(r)
  1569. END
  1570. END LayoutRecord;
  1571. PROCEDURE FieldOffset (rec: TypeIndex; name: ARRAY OF CHAR): INTEGER;
  1572. VAR r: TypeIndex;
  1573. f: FieldPtr;
  1574. BEGIN
  1575. r := Resolve(rec);
  1576. IF (r = InvalidType) OR ((tform[r] # FRecord)
  1577. AND (tform[r] # FClass)) THEN
  1578. RETURN -1
  1579. END;
  1580. IF NOT tdone[r] THEN ComputeOffsets(r) END;
  1581. f := FindField(r, name);
  1582. IF f = NIL THEN RETURN -1 END;
  1583. RETURN f^.off
  1584. END FieldOffset;
  1585. PROCEDURE FieldCount (rec: TypeIndex): CARDINAL;
  1586. VAR r: TypeIndex;
  1587. f: FieldPtr;
  1588. n: CARDINAL;
  1589. BEGIN
  1590. n := 0;
  1591. r := Resolve(rec);
  1592. IF (r = InvalidType) OR ((tform[r] # FRecord)
  1593. AND (tform[r] # FClass)) THEN
  1594. RETURN 0
  1595. END;
  1596. f := fields;
  1597. WHILE f # NIL DO
  1598. IF f^.owner = r THEN INC(n) END;
  1599. f := f^.next
  1600. END;
  1601. RETURN n
  1602. END FieldCount;
  1603. PROCEDURE FieldName (rec: TypeIndex; i: CARDINAL; VAR name: Name);
  1604. (* i-th field in DECLARATION order (chain is reverse; ord ranks it). *)
  1605. VAR r: TypeIndex;
  1606. f: FieldPtr;
  1607. BEGIN
  1608. name[0] := CHR(0);
  1609. r := Resolve(rec);
  1610. IF (r = InvalidType) OR ((tform[r] # FRecord)
  1611. AND (tform[r] # FClass)) THEN
  1612. RETURN
  1613. END;
  1614. IF NOT tdone[r] THEN ComputeOffsets(r) END;
  1615. f := fields;
  1616. WHILE f # NIL DO
  1617. IF (f^.owner = r) AND (f^.ord = i) THEN
  1618. Assign(name, f^.name); RETURN
  1619. END;
  1620. f := f^.next
  1621. END
  1622. END FieldName;
  1623. PROCEDURE EnterFieldsOf (rec: TypeIndex);
  1624. (* Enters rec's own fields as KindField into the current scope. *)
  1625. VAR f: FieldPtr;
  1626. BEGIN
  1627. f := fields;
  1628. WHILE f # NIL DO
  1629. IF f^.owner = rec THEN
  1630. IF Enter(f^.name, KindField) THEN
  1631. SetSymType(f^.name, f^.typ)
  1632. END
  1633. END;
  1634. f := f^.next
  1635. END
  1636. END EnterFieldsOf;
  1637. PROCEDURE PushRecord (t: TypeIndex): BOOLEAN;
  1638. (* Pushes a scope with t's fields (and, for a class, its ancestors'
  1639. fields); caller must PopScope afterwards. Classes share the field
  1640. machinery (methods stay in the class scope itself). *)
  1641. VAR r, p: TypeIndex;
  1642. guard: CARDINAL;
  1643. BEGIN
  1644. r := Resolve(t);
  1645. IF (r < 0) OR ((tform[r] # FRecord) AND (tform[r] # FClass)) THEN
  1646. RETURN FALSE
  1647. END;
  1648. PushScope;
  1649. curScope^.ofRec := r;
  1650. EnterFieldsOf(r);
  1651. IF tform[r] = FClass THEN
  1652. guard := 0;
  1653. p := ParentOf(r);
  1654. WHILE (p # InvalidType) AND (guard < ResDepth) DO
  1655. EnterFieldsOf(p);
  1656. p := ParentOf(p);
  1657. INC(guard)
  1658. END
  1659. END;
  1660. RETURN TRUE
  1661. END PushRecord;
  1662. (* ---------------- classes ---------------- *)
  1663. PROCEDURE ClassMethodNode (t: TypeIndex; name: ARRAY OF CHAR): SymPtr;
  1664. (* The method symbol named name in class t or an ancestor, or NIL. *)
  1665. VAR r: TypeIndex;
  1666. s: ScopePtr;
  1667. node: SymPtr;
  1668. guard: CARDINAL;
  1669. BEGIN
  1670. r := Resolve(t);
  1671. guard := 0;
  1672. WHILE (r # InvalidType) AND (tform[r] = FClass) AND (guard < ResDepth) DO
  1673. s := tscope[r];
  1674. IF s # NIL THEN
  1675. node := TreeFind(s^.root, name);
  1676. IF (node # NIL) AND (node^.kind = KindProc) THEN RETURN node END
  1677. END;
  1678. r := ParentOf(r);
  1679. INC(guard)
  1680. END;
  1681. RETURN NIL
  1682. END ClassMethodNode;
  1683. PROCEDURE MethodExists (t: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  1684. (* TRUE when the class (or an ancestor) declares name as a method. *)
  1685. BEGIN
  1686. RETURN ClassMethodNode(t, name) # NIL
  1687. END MethodExists;
  1688. PROCEDURE ResumeMethod (ct: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  1689. (* Resumes a class's declared method for its CLASS IMPLEMENTATION
  1690. body: pushes the existing symbol (reusing its uid so calls bind),
  1691. clearing the formal chain for the body's own heading to rebuild. *)
  1692. VAR node: SymPtr;
  1693. BEGIN
  1694. node := ClassMethodNode(ct, name);
  1695. IF node = NIL THEN RETURN FALSE END;
  1696. node^.plink := NIL;
  1697. node^.hasBody := TRUE;
  1698. curProc := node;
  1699. curPTail := NIL;
  1700. PushProc(node);
  1701. PushScope;
  1702. RETURN TRUE
  1703. END ResumeMethod;
  1704. PROCEDURE ClassMethodUid (t: TypeIndex; name: ARRAY OF CHAR): CARDINAL;
  1705. VAR n: SymPtr;
  1706. BEGIN
  1707. n := ClassMethodNode(t, name);
  1708. IF n = NIL THEN RETURN 0 END;
  1709. RETURN n^.uid
  1710. END ClassMethodUid;
  1711. PROCEDURE ClassMethodNPar (t: TypeIndex; name: ARRAY OF CHAR): CARDINAL;
  1712. (* Number of user formals (excludes the hidden THIS). *)
  1713. VAR n: SymPtr;
  1714. p: SymPtr;
  1715. k: CARDINAL;
  1716. BEGIN
  1717. n := ClassMethodNode(t, name);
  1718. IF n = NIL THEN RETURN 0 END;
  1719. k := 0;
  1720. p := n^.plink;
  1721. WHILE p # NIL DO INC(k); p := p^.plink END;
  1722. IF k > 0 THEN DEC(k) END; (* drop THIS *)
  1723. RETURN k
  1724. END ClassMethodNPar;
  1725. PROCEDURE ClassMethodParamType (t: TypeIndex; name: ARRAY OF CHAR;
  1726. i: CARDINAL): TypeIndex;
  1727. (* Type of the i-th USER formal (index 0 skips the hidden THIS). *)
  1728. VAR n, p: SymPtr;
  1729. k: CARDINAL;
  1730. BEGIN
  1731. n := ClassMethodNode(t, name);
  1732. IF n = NIL THEN RETURN InvalidType END;
  1733. p := n^.plink;
  1734. IF p # NIL THEN p := p^.plink END; (* skip THIS *)
  1735. k := 0;
  1736. WHILE (p # NIL) AND (k < i) DO p := p^.plink; INC(k) END;
  1737. IF p = NIL THEN RETURN InvalidType END;
  1738. RETURN p^.typ
  1739. END ClassMethodParamType;
  1740. PROCEDURE ClassMethodParamIsVar (t: TypeIndex; name: ARRAY OF CHAR;
  1741. i: CARDINAL): BOOLEAN;
  1742. VAR n, p: SymPtr;
  1743. k: CARDINAL;
  1744. BEGIN
  1745. n := ClassMethodNode(t, name);
  1746. IF n = NIL THEN RETURN FALSE END;
  1747. p := n^.plink;
  1748. IF p # NIL THEN p := p^.plink END; (* skip THIS *)
  1749. k := 0;
  1750. WHILE (p # NIL) AND (k < i) DO p := p^.plink; INC(k) END;
  1751. IF p = NIL THEN RETURN FALSE END;
  1752. RETURN p^.isVar
  1753. END ClassMethodParamIsVar;
  1754. PROCEDURE ClassMethodRes (t: TypeIndex; name: ARRAY OF CHAR): TypeIndex;
  1755. VAR n: SymPtr;
  1756. BEGIN
  1757. n := ClassMethodNode(t, name);
  1758. IF n = NIL THEN RETURN InvalidType END;
  1759. RETURN n^.rslt
  1760. END ClassMethodRes;
  1761. PROCEDURE PushImplClass (ct: TypeIndex);
  1762. BEGIN
  1763. IF nImpl <= HIGH(implStk) THEN
  1764. implStk[nImpl] := ct; INC(nImpl)
  1765. END
  1766. END PushImplClass;
  1767. PROCEDURE PopImplClass;
  1768. BEGIN IF nImpl > 0 THEN DEC(nImpl) END
  1769. END PopImplClass;
  1770. PROCEDURE CurImplClass (): TypeIndex;
  1771. (* The class whose CLASS IMPLEMENTATION body is innermost open, or
  1772. InvalidType. Bare method names inside a body resolve against it. *)
  1773. BEGIN
  1774. IF nImpl = 0 THEN RETURN InvalidType END;
  1775. RETURN implStk[nImpl - 1]
  1776. END CurImplClass;
  1777. PROCEDURE VtClassCount (): CARDINAL;
  1778. BEGIN RETURN nVtl END VtClassCount;
  1779. PROCEDURE VtClassAt (k: CARDINAL): TypeIndex;
  1780. BEGIN
  1781. IF k >= nVtl THEN RETURN InvalidType END;
  1782. RETURN vtl[k]
  1783. END VtClassAt;
  1784. PROCEDURE IsSubclass (sub, sup: TypeIndex): BOOLEAN;
  1785. (* TRUE when sub is sup or inherits (transitively) from sup. *)
  1786. VAR r: TypeIndex;
  1787. guard: CARDINAL;
  1788. BEGIN
  1789. r := Resolve(sub);
  1790. sup := Resolve(sup);
  1791. guard := 0;
  1792. WHILE (r # InvalidType) AND (guard < ResDepth) DO
  1793. IF r = sup THEN RETURN TRUE END;
  1794. r := ParentOf(r);
  1795. INC(guard)
  1796. END;
  1797. RETURN FALSE
  1798. END IsSubclass;
  1799. PROCEDURE VptrOffset (ct: TypeIndex): INTEGER;
  1800. VAR r: TypeIndex;
  1801. BEGIN
  1802. r := Resolve(ct);
  1803. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN -1 END;
  1804. IF NOT vtBuilt[r] THEN BuildVTable(r) END;
  1805. RETURN tvptr[r]
  1806. END VptrOffset;
  1807. PROCEDURE HasVTable (ct: TypeIndex): BOOLEAN;
  1808. (* TRUE when ct has (or inherits) any virtual method. *)
  1809. VAR r: TypeIndex;
  1810. BEGIN
  1811. r := Resolve(ct);
  1812. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN FALSE END;
  1813. IF NOT vtBuilt[r] THEN BuildVTable(r) END;
  1814. RETURN nVirt[r] > 0
  1815. END HasVTable;
  1816. PROCEDURE VirtSlot (ct: TypeIndex; name: ARRAY OF CHAR): INTEGER;
  1817. (* Vtable slot of ct's method name, or -1 when it is not virtual. *)
  1818. VAR r: TypeIndex;
  1819. node: SymPtr;
  1820. BEGIN
  1821. node := ClassMethodNode(ct, name);
  1822. IF (node = NIL) OR NOT node^.virt THEN RETURN -1 END;
  1823. r := Resolve(ct);
  1824. IF NOT vtBuilt[r] THEN BuildVTable(r) END;
  1825. RETURN node^.vslot
  1826. END VirtSlot;
  1827. PROCEDURE VtCount (ct: TypeIndex): CARDINAL;
  1828. VAR r: TypeIndex;
  1829. BEGIN
  1830. r := Resolve(ct);
  1831. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN 0 END;
  1832. IF NOT vtBuilt[r] THEN BuildVTable(r) END;
  1833. RETURN nVirt[r]
  1834. END VtCount;
  1835. PROCEDURE VtName (ct: TypeIndex; k: CARDINAL; VAR name: Name): BOOLEAN;
  1836. VAR r: TypeIndex;
  1837. BEGIN
  1838. name[0] := CHR(0);
  1839. r := Resolve(ct);
  1840. IF (r = InvalidType) OR (k >= nVirt[r]) THEN RETURN FALSE END;
  1841. Assign(name, vtName[vtBase[r] + k]);
  1842. RETURN TRUE
  1843. END VtName;
  1844. PROCEDURE VtHasBody (ct: TypeIndex; k: CARDINAL): BOOLEAN;
  1845. (* TRUE when slot k's method has an emitted body (else the vtable
  1846. entry is a null pointer). *)
  1847. VAR r: TypeIndex;
  1848. node: SymPtr;
  1849. BEGIN
  1850. r := Resolve(ct);
  1851. IF (r = InvalidType) OR (k >= nVirt[r]) THEN RETURN FALSE END;
  1852. node := ClassMethodNode(r, vtName[vtBase[r] + k]);
  1853. IF node = NIL THEN RETURN FALSE END;
  1854. RETURN node^.hasBody
  1855. END VtHasBody;
  1856. PROCEDURE VtUid (ct: TypeIndex; k: CARDINAL): CARDINAL;
  1857. VAR r: TypeIndex;
  1858. BEGIN
  1859. r := Resolve(ct);
  1860. IF (r = InvalidType) OR (k >= nVirt[r]) THEN RETURN 0 END;
  1861. RETURN vtUid[vtBase[r] + k]
  1862. END VtUid;
  1863. PROCEDURE PushClassMembers (t: TypeIndex): BOOLEAN;
  1864. (* Pushes a scope with t's fields and its ancestors' fields
  1865. (inheritance) as KindField, for method bodies in CLASS
  1866. IMPLEMENTATION. Method NAMES are deliberately not copied; bodies
  1867. re-enter them fresh via ResumeMethod (copying would collide). *)
  1868. VAR r, p: TypeIndex;
  1869. s: ScopePtr;
  1870. guard: CARDINAL;
  1871. BEGIN
  1872. r := Resolve(t);
  1873. IF (r = InvalidType) OR (tform[r] # FClass) THEN RETURN FALSE END;
  1874. s := tscope[r];
  1875. IF s = NIL THEN RETURN FALSE END;
  1876. PushScope;
  1877. curScope^.ofRec := r;
  1878. EnterFieldsOf(r);
  1879. (* ancestors' fields, nearest first *)
  1880. guard := 0;
  1881. p := ParentOf(r);
  1882. WHILE (p # InvalidType) AND (guard < ResDepth) DO
  1883. EnterFieldsOf(p);
  1884. p := ParentOf(p);
  1885. INC(guard)
  1886. END;
  1887. RETURN TRUE
  1888. END PushClassMembers;
  1889. PROCEDURE MarkVirtual;
  1890. BEGIN
  1891. IF curProc # NIL THEN curProc^.virt := TRUE END
  1892. END MarkVirtual;
  1893. (* ---------------- procedures ---------------- *)
  1894. PROCEDURE EnterProc (name: ARRAY OF CHAR): BOOLEAN;
  1895. VAR node: SymPtr;
  1896. BEGIN
  1897. node := RawEnter(name, KindProc);
  1898. IF node = NIL THEN curProc := NIL; RETURN FALSE END;
  1899. node^.rslt := InvalidType;
  1900. node^.plink := NIL;
  1901. node^.isVar := FALSE;
  1902. node^.fwd := FALSE;
  1903. node^.virt := FALSE;
  1904. node^.ext := FALSE;
  1905. node^.fsnap := FALSE;
  1906. node^.link[0] := CHR(0);
  1907. node^.uid := nextUid; INC(nextUid);
  1908. IF node^.uid <= HIGH(uidBase) THEN Assign(uidBase[node^.uid], name) END;
  1909. node^.fdep := nProc;
  1910. node^.vslot := -1;
  1911. node^.hasBody := FALSE;
  1912. curProc := node;
  1913. curPTail := NIL;
  1914. PushProc(node);
  1915. PushScope;
  1916. RETURN TRUE
  1917. END EnterProc;
  1918. PROCEDURE DeclareCProc (name: ARRAY OF CHAR): BOOLEAN;
  1919. (* Enter name in the current scope as an external C procedure with a
  1920. permissive (varargs, no-result) signature. Used for intrinsic
  1921. `FROM libc IMPORT ...`; not pushed as the current proc. *)
  1922. VAR node: SymPtr;
  1923. BEGIN
  1924. node := RawEnter(name, KindProc);
  1925. IF node = NIL THEN RETURN FALSE END;
  1926. node^.rslt := InvalidType;
  1927. node^.plink := NIL;
  1928. node^.isVar := FALSE;
  1929. node^.fwd := FALSE;
  1930. node^.virt := FALSE;
  1931. node^.ext := TRUE;
  1932. node^.varargs := TRUE;
  1933. node^.fsnap := FALSE;
  1934. Assign(node^.link, name);
  1935. node^.uid := nextUid; INC(nextUid);
  1936. IF node^.uid <= HIGH(uidBase) THEN Assign(uidBase[node^.uid], name) END;
  1937. node^.fdep := nProc;
  1938. node^.vslot := -1;
  1939. node^.hasBody := TRUE;
  1940. RETURN TRUE
  1941. END DeclareCProc;
  1942. PROCEDURE Varargs (name: ARRAY OF CHAR): BOOLEAN;
  1943. (* TRUE for a C-varargs procedure (its calls skip arity/type checks). *)
  1944. VAR node: SymPtr;
  1945. BEGIN
  1946. node := Find(name);
  1947. IF node = NIL THEN RETURN FALSE END;
  1948. RETURN node^.varargs
  1949. END Varargs;
  1950. PROCEDURE ResumeProc (name: ARRAY OF CHAR): BOOLEAN;
  1951. (* Resumes a DEFINITION procedure heading for its IMPLEMENTATION
  1952. body. The definition's signature (result type, formals in order,
  1953. VAR-ness) is snapshotted before the implementation re-enters its
  1954. own formals; SetProcRes/FixPending then compare (strict 231). *)
  1955. VAR node, f: SymPtr;
  1956. i, n: CARDINAL;
  1957. BEGIN
  1958. IF curUnit # UnitImpl THEN RETURN FALSE END;
  1959. node := TreeFind(curScope^.root, name);
  1960. IF node = NIL THEN RETURN FALSE END;
  1961. IF node^.kind # KindProc THEN RETURN FALSE END;
  1962. (* snapshot the definition signature *)
  1963. node^.snapRes := node^.rslt;
  1964. node^.nSnap := 0;
  1965. n := 0;
  1966. f := node^.plink;
  1967. WHILE (f # NIL) AND (n <= HighSnap) DO
  1968. snapT[n] := f^.typ;
  1969. snapV[n] := f^.isVar;
  1970. INC(n);
  1971. f := f^.plink
  1972. END;
  1973. FOR i := 0 TO HighSnap DO
  1974. IF i < n THEN
  1975. node^.snapT[i] := snapT[i];
  1976. node^.snapV[i] := snapV[i]
  1977. END
  1978. END;
  1979. node^.nSnap := n;
  1980. node^.fsnap := TRUE;
  1981. node^.plink := NIL; (* implementation re-enters formals *)
  1982. curProc := node;
  1983. curPTail := NIL;
  1984. PushProc(node);
  1985. PushScope;
  1986. RETURN TRUE
  1987. END ResumeProc;
  1988. PROCEDURE ReenterProc (name: ARRAY OF CHAR): BOOLEAN;
  1989. VAR node: SymPtr;
  1990. BEGIN
  1991. node := TreeFind(curScope^.root, name);
  1992. IF node = NIL THEN RETURN FALSE END;
  1993. IF (node^.kind # KindProc) OR NOT node^.fwd THEN
  1994. RETURN FALSE
  1995. END;
  1996. node^.fwd := FALSE;
  1997. node^.plink := NIL; (* fresh signature; step 4 compares old vs new *)
  1998. curProc := node;
  1999. curPTail := NIL;
  2000. PushProc(node);
  2001. PushScope;
  2002. RETURN TRUE
  2003. END ReenterProc;
  2004. PROCEDURE EnterParam (name: ARRAY OF CHAR; isVar: BOOLEAN): BOOLEAN;
  2005. VAR node: SymPtr;
  2006. BEGIN
  2007. node := RawEnter(name, KindParam);
  2008. IF node = NIL THEN RETURN FALSE END;
  2009. node^.isVar := isVar;
  2010. node^.plink := NIL;
  2011. IF (nPend < MaxPend) THEN
  2012. pend[nPend] := node; INC(nPend)
  2013. END;
  2014. IF curProc # NIL THEN
  2015. IF curProc^.plink = NIL THEN curProc^.plink := node
  2016. ELSE curPTail^.plink := node
  2017. END;
  2018. curPTail := node
  2019. END;
  2020. RETURN TRUE
  2021. END EnterParam;
  2022. PROCEDURE EnterThisParam (cls: TypeIndex): BOOLEAN;
  2023. (* Enters the hidden first parameter THIS (a VAR param of the class
  2024. type) for a method heading. Field access inside the body binds
  2025. THIS as the WITH base. THIS is not left pending (it is emitted
  2026. explicitly by the heading, before any user formals). *)
  2027. VAR ok: BOOLEAN;
  2028. BEGIN
  2029. ok := EnterParam("THIS", TRUE);
  2030. nPend := 0;
  2031. RETURN ok
  2032. END EnterThisParam;
  2033. PROCEDURE SetProcRes (t: TypeIndex) : BOOLEAN;
  2034. (* Sets the current procedure's result type. If the heading resumed
  2035. a DEFINITION (ResumeProc), this is the strict-231 checkpoint: the
  2036. implementation's result type, formal count, formal types and
  2037. VAR-ness are compared against the snapshot; the outcome is
  2038. returned (TRUE = match). *)
  2039. VAR f, node: SymPtr;
  2040. i, n: CARDINAL;
  2041. isV: BOOLEAN;
  2042. BEGIN
  2043. IF curProc # NIL THEN curProc^.rslt := t END;
  2044. node := curProc;
  2045. IF (node = NIL) OR NOT node^.fsnap THEN RETURN TRUE END;
  2046. IF NOT FormalOk(t, node^.snapRes) THEN RETURN FALSE END;
  2047. (* count the implementation heading's formals *)
  2048. n := 0;
  2049. f := node^.plink;
  2050. WHILE (f # NIL) AND (n <= HighSnap) DO INC(n); f := f^.plink END;
  2051. IF n # node^.nSnap THEN RETURN FALSE END;
  2052. f := node^.plink;
  2053. i := 0;
  2054. WHILE f # NIL DO
  2055. IF i > HighSnap THEN RETURN FALSE END;
  2056. isV := f^.isVar;
  2057. IF isV # node^.snapV[i] THEN RETURN FALSE END;
  2058. IF isV THEN
  2059. IF NOT VarParamOk(f^.typ, node^.snapT[i]) THEN RETURN FALSE END
  2060. ELSE
  2061. IF NOT FormalOk(f^.typ, node^.snapT[i]) THEN RETURN FALSE END
  2062. END;
  2063. f := f^.plink;
  2064. INC(i)
  2065. END;
  2066. RETURN TRUE
  2067. END SetProcRes;
  2068. PROCEDURE ProcRes (name: ARRAY OF CHAR): TypeIndex;
  2069. VAR node: SymPtr;
  2070. BEGIN
  2071. node := Find(name);
  2072. IF node = NIL THEN RETURN InvalidType END;
  2073. IF node^.kind # KindProc THEN RETURN InvalidType END;
  2074. RETURN node^.rslt
  2075. END ProcRes;
  2076. PROCEDURE MarkFwd;
  2077. BEGIN
  2078. IF curProc # NIL THEN curProc^.fwd := TRUE END
  2079. END MarkFwd;
  2080. PROCEDURE MarkExternal (link: ARRAY OF CHAR);
  2081. (* Marks the current procedure EXTERNAL; link '' means "use the
  2082. procedure's own name" (must be a valid C symbol). *)
  2083. BEGIN
  2084. IF curProc = NIL THEN RETURN END;
  2085. curProc^.ext := TRUE;
  2086. IF link[0] = CHR(0) THEN Assign(curProc^.link, curProc^.name)
  2087. ELSE Assign(curProc^.link, link)
  2088. END
  2089. END MarkExternal;
  2090. PROCEDURE ProcLink (name: ARRAY OF CHAR; VAR link: Name): BOOLEAN;
  2091. VAR node: SymPtr;
  2092. BEGIN
  2093. node := Find(name);
  2094. IF node = NIL THEN RETURN FALSE END;
  2095. IF NOT node^.ext THEN RETURN FALSE END;
  2096. Assign(link, node^.link);
  2097. RETURN TRUE
  2098. END ProcLink;
  2099. PROCEDURE CloseProc;
  2100. BEGIN
  2101. IF nProc > 0 THEN DEC(nProc) END;
  2102. PopScope
  2103. END CloseProc;
  2104. PROCEDURE InProc (): BOOLEAN;
  2105. BEGIN
  2106. RETURN nProc > 0
  2107. END InProc;
  2108. PROCEDURE CurRes (): TypeIndex;
  2109. BEGIN
  2110. IF nProc = 0 THEN RETURN InvalidType END;
  2111. RETURN procStk[nProc - 1]^.rslt
  2112. END CurRes;
  2113. PROCEDURE ProcDepthOf (name: ARRAY OF CHAR): CARDINAL;
  2114. VAR node: SymPtr;
  2115. BEGIN
  2116. node := Find(name);
  2117. IF node = NIL THEN RETURN 0 END;
  2118. IF node^.kind # KindProc THEN RETURN 0 END;
  2119. RETURN node^.fdep
  2120. END ProcDepthOf;
  2121. PROCEDURE ProcUid (name: ARRAY OF CHAR): CARDINAL;
  2122. VAR node: SymPtr;
  2123. BEGIN
  2124. node := Find(name);
  2125. IF node = NIL THEN RETURN 0 END;
  2126. IF node^.kind # KindProc THEN RETURN 0 END;
  2127. RETURN node^.uid
  2128. END ProcUid;
  2129. PROCEDURE NthParam (node: SymPtr; i: CARDINAL): SymPtr;
  2130. BEGIN
  2131. node := node^.plink;
  2132. WHILE (i > 0) AND (node # NIL) DO
  2133. node := node^.plink; DEC(i)
  2134. END;
  2135. RETURN node
  2136. END NthParam;
  2137. PROCEDURE ProcNPar (name: ARRAY OF CHAR): CARDINAL;
  2138. VAR node, p: SymPtr;
  2139. n: CARDINAL;
  2140. BEGIN
  2141. node := Find(name);
  2142. IF node = NIL THEN RETURN 0 END;
  2143. IF node^.kind # KindProc THEN RETURN 0 END;
  2144. n := 0; p := node^.plink;
  2145. WHILE p # NIL DO INC(n); p := p^.plink END;
  2146. RETURN n
  2147. END ProcNPar;
  2148. PROCEDURE ParamType (name: ARRAY OF CHAR; i: CARDINAL): TypeIndex;
  2149. VAR node, p: SymPtr;
  2150. BEGIN
  2151. node := Find(name);
  2152. IF node = NIL THEN RETURN InvalidType END;
  2153. IF node^.kind # KindProc THEN RETURN InvalidType END;
  2154. p := NthParam(node, i);
  2155. IF p = NIL THEN RETURN InvalidType END;
  2156. RETURN p^.typ
  2157. END ParamType;
  2158. PROCEDURE ParamIsVar (name: ARRAY OF CHAR; i: CARDINAL): BOOLEAN;
  2159. VAR node, p: SymPtr;
  2160. BEGIN
  2161. node := Find(name);
  2162. IF node = NIL THEN RETURN FALSE END;
  2163. IF node^.kind # KindProc THEN RETURN FALSE END;
  2164. p := NthParam(node, i);
  2165. IF p = NIL THEN RETURN FALSE END;
  2166. RETURN p^.isVar
  2167. END ParamIsVar;
  2168. (* ---------------- modules / separate compilation (step 4.3) ---------------- *)
  2169. PROCEDURE EnterIn (s: ScopePtr; name: ARRAY OF CHAR;
  2170. kind: INTEGER): BOOLEAN;
  2171. VAR node: SymPtr;
  2172. BEGIN
  2173. NEW(node);
  2174. Assign(node^.name, name);
  2175. Assign(node^.sym, name);
  2176. node^.mod[0] := CHR(0);
  2177. node^.kind := kind;
  2178. node^.typ := InvalidType;
  2179. node^.scope := s;
  2180. node^.left := NIL;
  2181. node^.right := NIL;
  2182. node^.rslt := InvalidType;
  2183. node^.plink := NIL;
  2184. node^.isVar := FALSE;
  2185. node^.fwd := FALSE;
  2186. node^.virt := FALSE;
  2187. node^.ext := FALSE;
  2188. node^.link[0] := CHR(0);
  2189. node^.fdep := 0;
  2190. node^.uid := 0;
  2191. node^.val[0] := CHR(0);
  2192. IF NOT TreeInsert(s, node) THEN RETURN FALSE END;
  2193. RETURN TRUE
  2194. END EnterIn;
  2195. PROCEDURE FindMod (name: ARRAY OF CHAR): INTEGER;
  2196. VAR i : CARDINAL;
  2197. BEGIN
  2198. i := 0;
  2199. WHILE i < nMods DO
  2200. IF Equal(modNames[i], name) THEN RETURN VAL(INTEGER, i) END;
  2201. INC(i)
  2202. END;
  2203. RETURN -1
  2204. END FindMod;
  2205. PROCEDURE NewMod (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  2206. VAR idx : CARDINAL;
  2207. s : ScopePtr;
  2208. BEGIN
  2209. IF nMods >= MaxMods THEN RETURN FALSE END;
  2210. IF FindMod(name) # -1 THEN RETURN FALSE END;
  2211. idx := nMods;
  2212. Assign(modNames[idx], name);
  2213. s := NewScope(globScope, 1);
  2214. modScopes[idx] := s;
  2215. modKind[idx] := kind;
  2216. modImpl[idx] := FALSE;
  2217. INC(nMods);
  2218. (* the module name lives in the global scope *)
  2219. IF NOT EnterIn(globScope, name, KindModule) THEN
  2220. DEC(nMods); RETURN FALSE
  2221. END;
  2222. curMod := VAL(INTEGER, idx);
  2223. curUnit := kind;
  2224. curScope := s;
  2225. RETURN TRUE
  2226. END NewMod;
  2227. PROCEDURE BeginDef (name: ARRAY OF CHAR): BOOLEAN;
  2228. BEGIN
  2229. RETURN NewMod(name, UnitDef)
  2230. END BeginDef;
  2231. PROCEDURE BeginImpl (name: ARRAY OF CHAR): BOOLEAN;
  2232. VAR idx : INTEGER;
  2233. BEGIN
  2234. idx := FindMod(name);
  2235. IF idx = -1 THEN RETURN FALSE END;
  2236. IF (modKind[idx] # UnitDef) OR modImpl[idx] THEN RETURN FALSE END;
  2237. modImpl[idx] := TRUE;
  2238. curMod := idx;
  2239. curUnit := UnitImpl;
  2240. curScope := modScopes[idx];
  2241. RETURN TRUE
  2242. END BeginImpl;
  2243. PROCEDURE Reenter (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  2244. (* Re-enters an already-registered module's scope for an instantiation
  2245. re-parse (the refinement registered the instance name; the re-parsed
  2246. generic body must be filled into that same module). *)
  2247. VAR idx : INTEGER;
  2248. BEGIN
  2249. idx := FindMod(name);
  2250. IF idx = -1 THEN RETURN FALSE END;
  2251. curMod := idx;
  2252. curUnit := kind;
  2253. curScope := modScopes[idx];
  2254. RETURN TRUE
  2255. END Reenter;
  2256. PROCEDURE BeginProg (name: ARRAY OF CHAR): BOOLEAN;
  2257. VAR ok : BOOLEAN;
  2258. BEGIN
  2259. ok := NewMod(name, UnitProg);
  2260. IF ok THEN haveProg := TRUE END;
  2261. RETURN ok
  2262. END BeginProg;
  2263. PROCEDURE HaveProgram (): BOOLEAN;
  2264. BEGIN
  2265. RETURN haveProg
  2266. END HaveProgram;
  2267. PROCEDURE EndUnit;
  2268. BEGIN
  2269. curScope := globScope;
  2270. curMod := -1;
  2271. curUnit := -1
  2272. END EndUnit;
  2273. PROCEDURE EnterLowerScope (name: ARRAY OF CHAR): BOOLEAN;
  2274. (* Make a unit's module scope current while Lower re-emits it. Without
  2275. this, Lower runs in globScope and MaterializeGlobals copies the
  2276. unit's types there — which leaks them across units (and across
  2277. generic instantiations of the same generic). *)
  2278. VAR idx: INTEGER;
  2279. BEGIN
  2280. idx := FindMod(name);
  2281. IF idx = -1 THEN RETURN FALSE END;
  2282. curMod := idx; curScope := modScopes[idx];
  2283. RETURN TRUE
  2284. END EnterLowerScope;
  2285. PROCEDURE LeaveLowerScope;
  2286. BEGIN
  2287. curScope := globScope; curMod := -1
  2288. END LeaveLowerScope;
  2289. PROCEDURE ModKnown (name: ARRAY OF CHAR): BOOLEAN;
  2290. BEGIN
  2291. RETURN FindMod(name) # -1
  2292. END ModKnown;
  2293. PROCEDURE OpaqueBase (name: ARRAY OF CHAR): TypeIndex;
  2294. VAR node: SymPtr;
  2295. r : TypeIndex;
  2296. BEGIN
  2297. node := Find(name);
  2298. IF node = NIL THEN RETURN InvalidType END;
  2299. IF node^.kind # KindType THEN RETURN InvalidType END;
  2300. r := node^.typ;
  2301. IF (r < 0) OR (r >= VAL(INTEGER, nTypes)) THEN
  2302. RETURN InvalidType
  2303. END;
  2304. IF (tform[r] = FAlias) AND (tref[r] = InvalidType) THEN RETURN r END;
  2305. RETURN InvalidType
  2306. END OpaqueBase;
  2307. PROCEDURE BeginTypeBlock;
  2308. BEGIN
  2309. INC(typeBlockDepth)
  2310. END BeginTypeBlock;
  2311. PROCEDURE EndTypeBlock;
  2312. BEGIN
  2313. IF typeBlockDepth > 0 THEN DEC(typeBlockDepth) END
  2314. END EndTypeBlock;
  2315. PROCEDURE IsUnresolved (t: TypeIndex): BOOLEAN;
  2316. VAR r: TypeIndex;
  2317. BEGIN
  2318. IF (t < 0) OR (t >= VAL(INTEGER, nTypes)) THEN RETURN FALSE END;
  2319. r := t;
  2320. RETURN (tform[r] = FAlias) AND (tref[r] = InvalidType)
  2321. END IsUnresolved;
  2322. PROCEDURE ForwardType (name: ARRAY OF CHAR): TypeIndex;
  2323. (* Registers an undeclared type name as an opaque placeholder that a
  2324. later TYPE declaration completes. Active inside a TYPE block, and
  2325. at module declaration level (so a global may reference a type
  2326. declared further down). *)
  2327. VAR node: SymPtr;
  2328. t: TypeIndex;
  2329. BEGIN
  2330. IF (typeBlockDepth = 0) AND (nProc > 0) THEN
  2331. RETURN InvalidType
  2332. END;
  2333. node := Find(name);
  2334. IF node # NIL THEN
  2335. IF node^.kind = KindType THEN RETURN node^.typ END;
  2336. RETURN InvalidType
  2337. END;
  2338. IF NOT Enter(name, KindType) THEN RETURN InvalidType END;
  2339. t := NewAlias();
  2340. SetSymType(name, t);
  2341. IF (typeBlockDepth = 0) AND (pfwdN <= HIGH(pfwdName)) THEN
  2342. Assign(pfwdName[pfwdN], name);
  2343. pfwdT[pfwdN] := t;
  2344. INC(pfwdN)
  2345. END;
  2346. RETURN t
  2347. END ForwardType;
  2348. PROCEDURE FwdPending (): CARDINAL;
  2349. BEGIN RETURN pfwdN END FwdPending;
  2350. PROCEDURE FwdInfo (i: CARDINAL; VAR name: Name; VAR unresolved: BOOLEAN);
  2351. BEGIN
  2352. name[0] := CHR(0);
  2353. unresolved := FALSE;
  2354. IF i < pfwdN THEN
  2355. Assign(name, pfwdName[i]);
  2356. unresolved := Resolve(pfwdT[i]) = InvalidType
  2357. END
  2358. END FwdInfo;
  2359. PROCEDURE FwdClear;
  2360. BEGIN pfwdN := 0 END FwdClear;
  2361. PROCEDURE QualNode (mod, name: ARRAY OF CHAR): SymPtr;
  2362. VAR i : INTEGER;
  2363. BEGIN
  2364. i := FindMod(mod);
  2365. IF i = -1 THEN RETURN NIL END;
  2366. RETURN TreeFind(modScopes[i]^.root, name)
  2367. END QualNode;
  2368. PROCEDURE QualType (mod, name: ARRAY OF CHAR): TypeIndex;
  2369. VAR n : SymPtr;
  2370. BEGIN
  2371. n := QualNode(mod, name);
  2372. IF n = NIL THEN RETURN InvalidType END;
  2373. RETURN n^.typ
  2374. END QualType;
  2375. PROCEDURE QualNthParam (n: SymPtr; i: CARDINAL): SymPtr;
  2376. BEGIN
  2377. n := n^.plink;
  2378. WHILE (i > 0) AND (n # NIL) DO
  2379. n := n^.plink; DEC(i)
  2380. END;
  2381. RETURN n
  2382. END QualNthParam;
  2383. PROCEDURE ExportUp (name: ARRAY OF CHAR);
  2384. VAR src, node: SymPtr;
  2385. parent: ScopePtr;
  2386. BEGIN
  2387. IF curScope = NIL THEN RETURN END;
  2388. src := TreeFind(curScope^.root, name);
  2389. IF src = NIL THEN RETURN END;
  2390. parent := curScope^.parent;
  2391. IF parent = NIL THEN RETURN END;
  2392. IF TreeFind(parent^.root, name) # NIL THEN RETURN END;
  2393. NEW(node);
  2394. node^ := src^;
  2395. node^.left := NIL;
  2396. node^.right := NIL;
  2397. node^.scope := parent;
  2398. IF NOT TreeInsert(parent, node) THEN
  2399. (* duplicate at this level: ignore *)
  2400. END
  2401. END ExportUp;
  2402. PROCEDURE Materialize (mod, name: ARRAY OF CHAR): BOOLEAN;
  2403. (* FROM-import: clones mod's export into the current scope under
  2404. its plain name. *)
  2405. VAR src, node : SymPtr;
  2406. BEGIN
  2407. src := QualNode(mod, name);
  2408. IF src = NIL THEN RETURN FALSE END;
  2409. (* already visible (repeat import): nothing to do *)
  2410. IF TreeFind(curScope^.root, name) # NIL THEN RETURN TRUE END;
  2411. NEW(node);
  2412. node^ := src^;
  2413. node^.left := NIL;
  2414. node^.right := NIL;
  2415. node^.scope := curScope;
  2416. IF NOT TreeInsert(curScope, node) THEN RETURN FALSE END;
  2417. RETURN TRUE
  2418. END Materialize;
  2419. PROCEDURE MaterializeReplace (mod, name: ARRAY OF CHAR): BOOLEAN;
  2420. (* Like Materialize, but when `name` is already visible it is updated in
  2421. place to the given module's symbol. Lower re-emits one unit at a time
  2422. and every unit has its own `scopeTop`/`EOL`/..., so the current unit's
  2423. global must win GlobalRef; the plain Materialize keeps the first one. *)
  2424. VAR src, node, l, r : SymPtr; sc : ScopePtr;
  2425. BEGIN
  2426. src := QualNode(mod, name);
  2427. IF src = NIL THEN RETURN FALSE END;
  2428. node := TreeFind(curScope^.root, name);
  2429. IF node # NIL THEN
  2430. l := node^.left; r := node^.right; sc := node^.scope;
  2431. node^ := src^;
  2432. node^.left := l; node^.right := r; node^.scope := sc;
  2433. RETURN TRUE
  2434. END;
  2435. NEW(node);
  2436. node^ := src^;
  2437. node^.left := NIL;
  2438. node^.right := NIL;
  2439. node^.scope := curScope;
  2440. IF NOT TreeInsert(curScope, node) THEN RETURN FALSE END;
  2441. RETURN TRUE
  2442. END MaterializeReplace;
  2443. PROCEDURE BuildAlias (mod, name: ARRAY OF CHAR; VAR alias: Name);
  2444. (* alias := "<mod>$<name>" (a key no identifier can collide with). *)
  2445. VAR i, j : CARDINAL;
  2446. BEGIN
  2447. i := 0;
  2448. WHILE (i < HIGH(alias)) AND (mod[i] # CHR(0)) DO
  2449. alias[i] := mod[i]; INC(i)
  2450. END;
  2451. IF i < HIGH(alias) THEN alias[i] := "$"; INC(i) END;
  2452. j := 0;
  2453. WHILE (i < HIGH(alias)) AND (name[j] # CHR(0)) DO
  2454. alias[i] := name[j]; INC(i); INC(j)
  2455. END;
  2456. IF i <= HIGH(alias) THEN alias[i] := CHR(0) END
  2457. END BuildAlias;
  2458. PROCEDURE MaterializeAlias (mod, name: ARRAY OF CHAR;
  2459. VAR alias: Name): BOOLEAN;
  2460. (* Qualified access: clones mod's export under a per-module alias
  2461. key so same-named exports of different modules never collide.
  2462. The node keeps sym = name and mod = defining module, so QBE
  2463. symbols (data and calls) resolve correctly. *)
  2464. VAR src, node : SymPtr;
  2465. BEGIN
  2466. src := QualNode(mod, name);
  2467. IF src = NIL THEN RETURN FALSE END;
  2468. BuildAlias(mod, name, alias);
  2469. IF TreeFind(curScope^.root, alias) = NIL THEN
  2470. NEW(node);
  2471. node^ := src^;
  2472. Assign(node^.name, alias); (* BST key *)
  2473. Assign(node^.sym, name); (* real symbol name *)
  2474. node^.left := NIL;
  2475. node^.right := NIL;
  2476. node^.scope := curScope;
  2477. IF NOT TreeInsert(curScope, node) THEN RETURN FALSE END
  2478. END;
  2479. RETURN TRUE
  2480. END MaterializeAlias;
  2481. PROCEDURE SymMod (name: ARRAY OF CHAR; VAR m: Name): BOOLEAN;
  2482. (* The defining module of the visible entry ("" for a local). *)
  2483. VAR node: SymPtr;
  2484. BEGIN
  2485. m[0] := CHR(0);
  2486. node := Find(name);
  2487. IF node = NIL THEN RETURN FALSE END;
  2488. Assign(m, node^.mod);
  2489. RETURN TRUE
  2490. END SymMod;
  2491. PROCEDURE AliasProc (formalName: ARRAY OF CHAR; mod, actualName: ARRAY OF CHAR): BOOLEAN;
  2492. (* Generic procedure formal: clone the actual procedure's symbol
  2493. (uid/mod/params/result) under formalName in the current scope, so a
  2494. call through the formal resolves to the actual. *)
  2495. VAR src, node: SymPtr;
  2496. BEGIN
  2497. src := QualNode(mod, actualName);
  2498. IF src = NIL THEN
  2499. src := Find(actualName) (* same-module actual *)
  2500. END;
  2501. IF src = NIL THEN RETURN FALSE END;
  2502. IF TreeFind(curScope^.root, formalName) # NIL THEN RETURN TRUE END;
  2503. NEW(node);
  2504. node^ := src^;
  2505. Assign(node^.name, formalName);
  2506. node^.left := NIL;
  2507. node^.right := NIL;
  2508. node^.scope := curScope;
  2509. IF NOT TreeInsert(curScope, node) THEN RETURN FALSE END;
  2510. RETURN TRUE
  2511. END AliasProc;
  2512. PROCEDURE QualProcInfo (mod, name: ARRAY OF CHAR; VAR uid, depth: CARDINAL;
  2513. VAR res: TypeIndex; VAR ext: BOOLEAN): BOOLEAN;
  2514. (* Proc facts of a qualified (module-qualified) procedure name. *)
  2515. VAR n: SymPtr;
  2516. BEGIN
  2517. n := QualNode(mod, name);
  2518. IF n = NIL THEN RETURN FALSE END;
  2519. uid := n^.uid; depth := n^.fdep; res := n^.rslt; ext := n^.ext;
  2520. RETURN n^.kind = KindProc
  2521. END QualProcInfo;
  2522. PROCEDURE ProcBaseByUid (uid: CARDINAL; VAR base: Name): BOOLEAN;
  2523. (* Base (mangling) name of a procedure by its uid. Lets a proc alias or
  2524. a call target whose scope is gone still mangle correctly. *)
  2525. BEGIN
  2526. base[0] := CHR(0);
  2527. IF (uid > HIGH(uidBase)) OR (uidBase[uid][0] = CHR(0)) THEN RETURN FALSE END;
  2528. Assign(base, uidBase[uid]);
  2529. RETURN TRUE
  2530. END ProcBaseByUid;
  2531. PROCEDURE SymBase (name: ARRAY OF CHAR; VAR base: Name): BOOLEAN;
  2532. (* Base symbol name of the visible entry (differs from `name` for
  2533. qualified aliases). *)
  2534. VAR node: SymPtr;
  2535. BEGIN
  2536. node := Find(name);
  2537. IF node = NIL THEN RETURN FALSE END;
  2538. Assign(base, node^.sym);
  2539. RETURN TRUE
  2540. END SymBase;
  2541. PROCEDURE GlobalRef (name: ARRAY OF CHAR; VAR g: Name): BOOLEAN;
  2542. (* QBE global-symbol name for a module-level entry: "<mod>_<sym>".
  2543. FALSE when name is not a module-level symbol. *)
  2544. VAR node: SymPtr;
  2545. i, j : CARDINAL;
  2546. BEGIN
  2547. node := Find(name);
  2548. IF node = NIL THEN RETURN FALSE END;
  2549. IF node^.mod[0] = CHR(0) THEN RETURN FALSE END;
  2550. i := 0;
  2551. WHILE (i < HIGH(g)) AND (node^.mod[i] # CHR(0)) DO
  2552. g[i] := node^.mod[i]; INC(i)
  2553. END;
  2554. IF i < HIGH(g) THEN g[i] := "_"; INC(i) END;
  2555. j := 0;
  2556. WHILE (i < HIGH(g)) AND (node^.sym[j] # CHR(0)) DO
  2557. g[i] := node^.sym[j]; INC(i); INC(j)
  2558. END;
  2559. IF i <= HIGH(g) THEN g[i] := CHR(0) END;
  2560. RETURN TRUE
  2561. END GlobalRef;
  2562. PROCEDURE DeferReset;
  2563. (* Fresh deferral table per unit (the parser's span table is per-parse;
  2564. the driver-equivalent reset lives in the M2 action). *)
  2565. BEGIN
  2566. nDefer := 0
  2567. END DeferReset;
  2568. PROCEDURE DeferBody (): CARDINAL;
  2569. (* Records the current procedure's own scope for a skipped body. Call
  2570. at skip time, when curScope is the proc scope (heading parsed,
  2571. params entered, body not yet parsed). Returns the deferral index,
  2572. or 65535 when there is no current procedure or the table is full. *)
  2573. BEGIN
  2574. IF curProc = NIL THEN RETURN 65535 END;
  2575. IF nDefer > HIGH(deferProc) THEN RETURN 65535 END;
  2576. deferProc[nDefer] := curProc;
  2577. deferScope[nDefer] := curScope;
  2578. INC(nDefer);
  2579. RETURN nDefer - 1
  2580. END DeferBody;
  2581. PROCEDURE ReenterDeferred (idx: CARDINAL): BOOLEAN;
  2582. (* Restores a deferred body scope for the re-parse pass: the saved proc
  2583. scope becomes current again (params visible; locals are entered once
  2584. here) and the proc stack is re-armed for InProc/CurRes. The
  2585. Block-end CloseProc pops back to the enclosing scope. *)
  2586. BEGIN
  2587. IF idx >= nDefer THEN RETURN FALSE END;
  2588. IF deferProc[idx] = NIL THEN RETURN FALSE END;
  2589. curProc := deferProc[idx];
  2590. curScope := deferScope[idx];
  2591. PushProc(curProc);
  2592. RETURN TRUE
  2593. END ReenterDeferred;
  2594. PROCEDURE ParamName (name: ARRAY OF CHAR; i: CARDINAL;
  2595. VAR pname: Name): BOOLEAN;
  2596. (* The i-th formal's name, for the re-parse pass QbeGen replay
  2597. (sibling of ProcNPar/ParamType/ParamIsVar). *)
  2598. VAR node, p: SymPtr; k: CARDINAL;
  2599. BEGIN
  2600. pname[0] := CHR(0);
  2601. node := Find(name);
  2602. IF node = NIL THEN RETURN FALSE END;
  2603. IF node^.kind # KindProc THEN RETURN FALSE END;
  2604. p := node^.plink; k := 0;
  2605. WHILE (p # NIL) AND (k < i) DO p := p^.plink; INC(k) END;
  2606. IF p = NIL THEN RETURN FALSE END;
  2607. Assign(pname, p^.name);
  2608. RETURN TRUE
  2609. END ParamName;
  2610. PROCEDURE ImportFrom (mod, name: ARRAY OF CHAR): BOOLEAN;
  2611. VAR n: SymPtr;
  2612. BEGIN
  2613. IF NOT Materialize(mod, name) THEN RETURN FALSE END;
  2614. (* a type is imported together with its enumeration literals *)
  2615. n := QualNode(mod, name);
  2616. IF n # NIL THEN IF EnterEnumLits(n^.typ) > 0 THEN END END;
  2617. RETURN TRUE
  2618. END ImportFrom;
  2619. (* ---------------- predicates (unchanged) ---------------- *)
  2620. PROCEDURE BaseSpanOk (b: TypeIndex): BOOLEAN;
  2621. (* TRUE for set-suitable bases: bool, char, subranges ≤ 256 wide. *)
  2622. VAR r: TypeIndex;
  2623. lo, hi: INTEGER;
  2624. BEGIN
  2625. r := Resolve(b);
  2626. IF r = InvalidType THEN RETURN TRUE END;
  2627. IF tform[r] = FBool THEN RETURN TRUE END;
  2628. IF tform[r] = FChar THEN RETURN TRUE END;
  2629. IF (tform[r] = FEnum) AND (tenum[r] >= 1) AND (tenum[r] <= 256) THEN
  2630. RETURN TRUE (* a set base over an enumeration *)
  2631. END;
  2632. IF (tform[r] = FSub) AND (tref[r] = InvalidType)
  2633. AND SubBounds(b, lo, hi) AND (hi >= lo) AND (hi - lo < 256) THEN
  2634. RETURN TRUE
  2635. END;
  2636. RETURN FALSE
  2637. END BaseSpanOk;
  2638. PROCEDURE SetBasesOk (a, b: TypeIndex): BOOLEAN;
  2639. (* base compatibility for two SET types: same, or both suitable
  2640. (masks compare over min words + zero-check extras) *)
  2641. BEGIN
  2642. IF SameType(a, b) THEN RETURN TRUE END;
  2643. RETURN BaseSpanOk(a) AND BaseSpanOk(b)
  2644. END SetBasesOk;
  2645. PROCEDURE ParamTypesOk (x, y: TypeIndex): BOOLEAN;
  2646. (* Procedure-type formal compatibility: identical, or an open array
  2647. matching an open/fixed 1-D array of the same element type (open
  2648. arrays are distinct descriptors, so index equality is too strict). *)
  2649. BEGIN
  2650. IF SameType(x, y) THEN RETURN TRUE END;
  2651. IF (x = InvalidType) OR (y = InvalidType) THEN RETURN TRUE END;
  2652. IF IsOpenArray(x) AND (ClassOf(y) = ClArray) AND (ArrayDepth(y) = 1) THEN
  2653. RETURN SameType(ArrayElem(x), ArrayElem(y))
  2654. END;
  2655. IF IsOpenArray(y) AND (ClassOf(x) = ClArray) AND (ArrayDepth(x) = 1) THEN
  2656. RETURN SameType(ArrayElem(x), ArrayElem(y))
  2657. END;
  2658. RETURN FALSE
  2659. END ParamTypesOk;
  2660. PROCEDURE ProcTypesOk (a, b: TypeIndex): BOOLEAN;
  2661. (* Structural compatibility of two procedure types: same result and
  2662. same parameter types / VAR flags. *)
  2663. VAR i, n: CARDINAL;
  2664. BEGIN
  2665. IF (tform[a] # FProc) OR (tform[b] # FProc) THEN RETURN FALSE END;
  2666. IF NOT SameType(tref[a], tref[b]) THEN RETURN FALSE END;
  2667. n := procn[a];
  2668. IF n # procn[b] THEN RETURN FALSE END;
  2669. i := 0;
  2670. WHILE i < n DO
  2671. IF procvis[procstart[a] + i] # procvis[procstart[b] + i] THEN
  2672. RETURN FALSE
  2673. END;
  2674. IF NOT ParamTypesOk(procp[procstart[a] + i],
  2675. procp[procstart[b] + i]) THEN
  2676. RETURN FALSE
  2677. END;
  2678. INC(i)
  2679. END;
  2680. RETURN TRUE
  2681. END ProcTypesOk;
  2682. PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
  2683. VAR rs, rd: TypeIndex;
  2684. BEGIN
  2685. IF (src = InvalidType) OR (dst = InvalidType) THEN RETURN TRUE END;
  2686. rs := Resolve(src); rd := Resolve(dst);
  2687. IF rs = rd THEN RETURN TRUE END;
  2688. IF (rs = InvalidType) OR (rd = InvalidType) THEN RETURN TRUE END;
  2689. IF (tform[rs] = FSet) AND (tform[rd] = FSet) THEN
  2690. RETURN SetBasesOk(tref[rs], tref[rd])
  2691. END;
  2692. IF (tform[rs] = FProc) AND (tform[rd] = FProc) THEN
  2693. RETURN ProcTypesOk(rs, rd)
  2694. END;
  2695. IF (ClassOf(src) = ClArray) AND (ClassOf(dst) = ClArray) THEN
  2696. (* a fixed 1-D array is compatible with an open formal of the
  2697. same element type (value or VAR) *)
  2698. IF IsOpenArray(dst) AND (ArrayDepth(src) = 1) THEN
  2699. RETURN SameType(ArrayElem(src), ArrayElem(dst))
  2700. END;
  2701. RETURN SameType(src, dst)
  2702. END;
  2703. IF (ClassOf(src) = ClStr) AND (ClassOf(dst) = ClArray) THEN
  2704. RETURN (ArrayDepth(dst) = 1)
  2705. AND (ClassOf(ArrayElem(dst)) = ClChar)
  2706. END;
  2707. IF (ClassOf(src) = ClUStr) AND (ClassOf(dst) = ClArray) THEN
  2708. (* a U"..." literal assigns/ passes to a 1-D ARRAY OF UCHAR by
  2709. content copy (count-clamped, UCHAR-0 terminated). *)
  2710. RETURN (ArrayDepth(dst) = 1)
  2711. AND (ClassOf(ArrayElem(dst)) = ClUChar)
  2712. END;
  2713. IF ClassOf(src) = ClNil THEN
  2714. RETURN ClassOf(dst) = ClPtr
  2715. END;
  2716. (* ADDRESS assigns to/from any pointer (check before the subclass
  2717. test, which returns early) *)
  2718. IF (Resolve(src) = dAddr) AND (ClassOf(dst) = ClPtr) THEN
  2719. RETURN TRUE
  2720. END;
  2721. IF (Resolve(dst) = dAddr) AND (ClassOf(src) = ClPtr) THEN
  2722. RETURN TRUE
  2723. END;
  2724. (* POINTER TO Derived assigns to POINTER TO Base (subtyping) *)
  2725. IF (ClassOf(src) = ClPtr) AND (ClassOf(dst) = ClPtr) THEN
  2726. RETURN IsSubclass(PtrBase(src), PtrBase(dst))
  2727. END;
  2728. (* a procedure value is a code address: it assigns to/from a
  2729. pointer (PROC is mapped onto ADDRESS) *)
  2730. IF (ClassOf(src) = ClProc) AND (ClassOf(dst) = ClPtr) THEN
  2731. RETURN TRUE
  2732. END;
  2733. IF (ClassOf(src) = ClPtr) AND (ClassOf(dst) = ClProc) THEN
  2734. RETURN TRUE
  2735. END;
  2736. IF (ClassOf(src) = ClInt) AND (ClassOf(dst) = ClInt) THEN
  2737. RETURN TRUE
  2738. END;
  2739. IF (ClassOf(src) = ClInt) AND (ClassOf(dst) = ClLong) THEN
  2740. RETURN TRUE
  2741. END;
  2742. IF (ClassOf(src) = ClInt) AND (ClassOf(dst) = ClReal) THEN
  2743. RETURN TRUE
  2744. END;
  2745. RETURN FALSE
  2746. END Assignable;
  2747. PROCEDURE ArithCheck (l, r: TypeIndex; divmod: BOOLEAN;
  2748. VAR res: TypeIndex): BOOLEAN;
  2749. BEGIN
  2750. res := InvalidType;
  2751. IF (Resolve(l) = InvalidType) OR (Resolve(r) = InvalidType) THEN RETURN TRUE END;
  2752. IF (IsLongFamily(l) AND IsLongFamily(r))
  2753. OR (IsLongFamily(l) AND IsIntFamily(r))
  2754. OR (IsIntFamily(l) AND IsLongFamily(r)) THEN
  2755. res := dLong; RETURN TRUE
  2756. END;
  2757. IF IsIntFamily(l) AND IsIntFamily(r) THEN
  2758. res := dInt; RETURN TRUE
  2759. END;
  2760. IF NOT divmod AND (ClassOf(l) = ClReal) AND (ClassOf(r) = ClReal) THEN
  2761. res := dReal; RETURN TRUE
  2762. END;
  2763. RETURN FALSE
  2764. END ArithCheck;
  2765. PROCEDURE BoolCheck (t: TypeIndex): BOOLEAN;
  2766. BEGIN
  2767. IF Resolve(t) = InvalidType THEN RETURN TRUE END;
  2768. RETURN ClassOf(t) = ClBool
  2769. END BoolCheck;
  2770. PROCEDURE IsStrType (t: TypeIndex): BOOLEAN;
  2771. (* A string literal, or a 1-D ARRAY OF CHAR. *)
  2772. VAR c: TypeIndex;
  2773. BEGIN
  2774. c := Resolve(t);
  2775. IF c = InvalidType THEN RETURN FALSE END;
  2776. IF ClassOf(c) = ClStr THEN RETURN TRUE END;
  2777. IF (ClassOf(c) = ClArray) AND (ArrayDepth(c) = 1) THEN
  2778. RETURN ClassOf(ArrayElem(c)) = ClChar
  2779. END;
  2780. RETURN FALSE
  2781. END IsStrType;
  2782. PROCEDURE UStrCompat (l, r: TypeIndex): BOOLEAN;
  2783. (* Both operands are UString literals (ClUStr): `+` concatenates. *)
  2784. BEGIN
  2785. RETURN (l # InvalidType) AND (r # InvalidType)
  2786. AND (ClassOf(l) = ClUStr) AND (ClassOf(r) = ClUStr)
  2787. END UStrCompat;
  2788. PROCEDURE IsUCharArray (t: TypeIndex): BOOLEAN;
  2789. (* A 1-D ARRAY OF UCHAR: a destination for U"..." content copy. *)
  2790. VAR c: TypeIndex;
  2791. BEGIN
  2792. c := Resolve(t);
  2793. IF c = InvalidType THEN RETURN FALSE END;
  2794. IF (ClassOf(c) = ClArray) AND (ArrayDepth(c) = 1) THEN
  2795. RETURN ClassOf(ArrayElem(c)) = ClUChar
  2796. END;
  2797. RETURN FALSE
  2798. END IsUCharArray;
  2799. PROCEDURE StrCompat (l, r: TypeIndex): BOOLEAN;
  2800. (* Both operands are string-compatible (content equality via the
  2801. shim); used for `=`/`#` only. *)
  2802. BEGIN
  2803. RETURN IsStrType(l) AND IsStrType(r)
  2804. END StrCompat;
  2805. PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
  2806. VAR rl, rr: TypeIndex;
  2807. BEGIN
  2808. IF (Resolve(l) = InvalidType) OR (Resolve(r) = InvalidType) THEN RETURN TRUE END;
  2809. IF ClassOf(l) = ClNil THEN
  2810. RETURN (ClassOf(r) = ClNil) OR (ClassOf(r) = ClPtr)
  2811. END;
  2812. IF ClassOf(r) = ClNil THEN
  2813. RETURN (ClassOf(l) = ClNil) OR (ClassOf(l) = ClPtr)
  2814. END;
  2815. (* gm2 ext: any two set types compare =/# (word-wise equality);
  2816. a set CASE selector uses this too. *)
  2817. IF (ClassOf(l) = ClSet) AND (ClassOf(r) = ClSet) THEN RETURN TRUE END;
  2818. IF SameType(l, r) THEN
  2819. (* Whole-array, string, record and class equality are not
  2820. built-in (213); compare member-wise instead. *)
  2821. IF (ClassOf(l) = ClArray) OR (ClassOf(l) = ClStr)
  2822. OR (ClassOf(l) = ClRecord) OR (ClassOf(l) = ClClass) THEN
  2823. IF StrCompat(l, r) THEN RETURN TRUE END; (* string content *)
  2824. RETURN FALSE
  2825. END;
  2826. RETURN TRUE
  2827. END;
  2828. IF StrCompat(l, r) THEN RETURN TRUE END;
  2829. IF IsIntFamily(l) AND IsIntFamily(r) THEN RETURN TRUE END;
  2830. IF (ClassOf(l) = ClLong) AND (ClassOf(r) = ClLong) THEN
  2831. RETURN TRUE
  2832. END;
  2833. IF (ClassOf(l) = ClLong) AND IsIntFamily(r) THEN RETURN TRUE END;
  2834. IF IsIntFamily(l) AND (ClassOf(r) = ClLong) THEN RETURN TRUE END;
  2835. IF (ClassOf(l) = ClReal) AND (ClassOf(r) = ClReal) THEN
  2836. RETURN TRUE
  2837. END;
  2838. IF (ClassOf(l) = ClChar) AND (ClassOf(r) = ClChar) THEN
  2839. RETURN TRUE
  2840. END;
  2841. IF (ClassOf(l) = ClUChar) AND (ClassOf(r) = ClUChar) THEN
  2842. RETURN TRUE
  2843. END;
  2844. IF (ClassOf(l) = ClBool) AND (ClassOf(r) = ClBool) THEN
  2845. RETURN TRUE
  2846. END;
  2847. rl := Resolve(l); rr := Resolve(r);
  2848. IF (rl = InvalidType) OR (rr = InvalidType) THEN RETURN TRUE END;
  2849. IF (tform[rl] = FSet) AND (tform[rr] = FSet) THEN
  2850. RETURN SetBasesOk(tref[rl], tref[rr])
  2851. END;
  2852. RETURN FALSE
  2853. END EqCheck;
  2854. PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
  2855. BEGIN
  2856. IF (Resolve(l) = InvalidType) OR (Resolve(r) = InvalidType) THEN RETURN TRUE END;
  2857. IF IsIntFamily(l) AND IsIntFamily(r) THEN RETURN TRUE END;
  2858. IF (ClassOf(l) = ClLong) AND (ClassOf(r) = ClLong) THEN
  2859. RETURN TRUE
  2860. END;
  2861. IF (ClassOf(l) = ClLong) AND IsIntFamily(r) THEN RETURN TRUE END;
  2862. IF IsIntFamily(l) AND (ClassOf(r) = ClLong) THEN RETURN TRUE END;
  2863. IF (ClassOf(l) = ClReal) AND (ClassOf(r) = ClReal) THEN
  2864. RETURN TRUE
  2865. END;
  2866. IF (ClassOf(l) = ClChar) AND (ClassOf(r) = ClChar) THEN
  2867. RETURN TRUE
  2868. END;
  2869. IF (ClassOf(l) = ClUChar) AND (ClassOf(r) = ClUChar) THEN
  2870. RETURN TRUE
  2871. END;
  2872. IF (ClassOf(l) = ClEnum) AND SameType(l, r) THEN RETURN TRUE END;
  2873. RETURN FALSE
  2874. END OrdCheck;
  2875. PROCEDURE SetElemClassOk (c: INTEGER): BOOLEAN;
  2876. (* TRUE for an element class acceptable in a set constructor. *)
  2877. BEGIN
  2878. RETURN (c = ClInt) OR (c = ClChar) OR (c = ClBool)
  2879. OR (c = ClEnum) OR (c = ClUChar)
  2880. END SetElemClassOk;
  2881. PROCEDURE InCheck (l, set: TypeIndex): BOOLEAN;
  2882. VAR rs, b: TypeIndex;
  2883. BEGIN
  2884. IF (Resolve(l) = InvalidType) OR (Resolve(set) = InvalidType) THEN RETURN TRUE END;
  2885. rs := Resolve(set);
  2886. IF (rs = InvalidType) OR (tform[rs] # FSet) THEN RETURN FALSE END;
  2887. b := tref[rs];
  2888. IF SameType(l, b) THEN RETURN TRUE END;
  2889. IF IsIntFamily(l) AND IsIntFamily(b) THEN RETURN TRUE END;
  2890. IF (ClassOf(l) = ClChar) AND (ClassOf(b) = ClChar) THEN
  2891. RETURN TRUE
  2892. END;
  2893. (* lenient: small int/char/bool/enum tested against suitable sets;
  2894. the span trap decides out-of-range at runtime *)
  2895. IF ((ClassOf(l) = ClInt) OR (ClassOf(l) = ClChar)
  2896. OR (ClassOf(l) = ClBool) OR (ClassOf(l) = ClEnum))
  2897. AND (SetWords(set) > 0) THEN
  2898. RETURN TRUE
  2899. END;
  2900. RETURN FALSE
  2901. END InCheck;
  2902. PROCEDURE RelCheck (l, r: TypeIndex; op: INTEGER): BOOLEAN;
  2903. BEGIN
  2904. IF (Resolve(l) = InvalidType) OR (Resolve(r) = InvalidType) THEN RETURN TRUE END;
  2905. IF op = OpIn THEN RETURN InCheck(l, r) END;
  2906. IF (op = OpEq) OR (op = OpNeq1) OR (op = OpNeq2) THEN
  2907. RETURN EqCheck(l, r)
  2908. END;
  2909. RETURN OrdCheck(l, r)
  2910. END RelCheck;
  2911. (* ---------------- init ---------------- *)
  2912. PROCEDURE Predef (name: ARRAY OF CHAR; kind: INTEGER; t: TypeIndex);
  2913. BEGIN
  2914. IF Enter(name, kind) THEN SetSymType(name, t) END
  2915. END Predef;
  2916. PROCEDURE AddFormal (pr: SymPtr; t: TypeIndex; isVar: BOOLEAN);
  2917. (* Appends a formal-position node to procedure pr's plink chain.
  2918. These formals are not in any scope: they exist only to give the
  2919. external builtin a signature the caller checks against. *)
  2920. VAR p, q: SymPtr;
  2921. BEGIN
  2922. IF pr = NIL THEN RETURN END;
  2923. NEW(p);
  2924. p^.name[0] := CHR(0);
  2925. p^.sym[0] := CHR(0);
  2926. p^.mod[0] := CHR(0);
  2927. p^.kind := KindParam;
  2928. p^.typ := t;
  2929. p^.scope := NIL;
  2930. p^.left := NIL; p^.right := NIL;
  2931. p^.rslt := InvalidType;
  2932. p^.plink := NIL;
  2933. p^.isVar := isVar;
  2934. p^.fwd := FALSE; p^.virt := FALSE;
  2935. p^.fdep := 0;
  2936. p^.snapRes := InvalidType;
  2937. p^.nSnap := 0;
  2938. p^.fsnap := FALSE;
  2939. p^.vslot := -1;
  2940. p^.hasBody := FALSE;
  2941. p^.ext := FALSE; p^.varargs := FALSE;
  2942. p^.link[0] := CHR(0);
  2943. p^.uid := 0;
  2944. p^.val[0] := CHR(0);
  2945. IF pr^.plink = NIL THEN
  2946. pr^.plink := p
  2947. ELSE
  2948. q := pr^.plink;
  2949. WHILE q^.plink # NIL DO q := q^.plink END;
  2950. q^.plink := p
  2951. END
  2952. END AddFormal;
  2953. PROCEDURE PredefCProc (name, cname: ARRAY OF CHAR; res: TypeIndex): SymPtr;
  2954. (* Defines an external C procedure in the global scope with an
  2955. explicit (not varargs) signature; formals are added with AddFormal. *)
  2956. VAR node: SymPtr;
  2957. BEGIN
  2958. node := RawEnter(name, KindProc);
  2959. IF node = NIL THEN RETURN NIL END;
  2960. node^.rslt := res;
  2961. node^.plink := NIL;
  2962. node^.isVar := FALSE;
  2963. node^.fwd := FALSE;
  2964. node^.virt := FALSE;
  2965. node^.ext := TRUE;
  2966. node^.varargs := FALSE;
  2967. node^.fsnap := FALSE;
  2968. Assign(node^.link, cname);
  2969. node^.uid := nextUid; INC(nextUid);
  2970. node^.fdep := 0;
  2971. node^.vslot := -1;
  2972. node^.hasBody := TRUE;
  2973. RETURN node
  2974. END PredefCProc;
  2975. PROCEDURE Init;
  2976. VAR pr: SymPtr;
  2977. BEGIN
  2978. scopeList := NIL; scopeTail := NIL;
  2979. fields := NIL; nFields := 0;
  2980. nPend := 0; nPendF := 0;
  2981. nTypes := 0; nProc := 0; nBounds := 0; nextUid := 0;
  2982. vtTop := 0; nVtl := 0; nImpl := 0;
  2983. curProc := NIL; curPTail := NIL;
  2984. nMods := 0; curMod := -1; curUnit := -1; haveProg := FALSE;
  2985. curScope := NewScope(NIL, 0);
  2986. globScope := curScope;
  2987. dInt := NewDesc(FInt, InvalidType);
  2988. dCard := NewDesc(FInt, InvalidType);
  2989. dReal := NewDesc(FReal, InvalidType);
  2990. dChar := NewDesc(FChar, InvalidType);
  2991. dBool := NewDesc(FBool, InvalidType);
  2992. dNil := NewDesc(FNil, InvalidType);
  2993. dAddr := NewDesc(FPtr, InvalidType); (* ADDRESS: pointer-sized *)
  2994. dLong := NewDesc(FLong, InvalidType); (* LONGINT/LONGCARD: 64-bit *)
  2995. dUChar := NewDesc(FUChar, InvalidType);
  2996. dBitset := NewSet(NewSubR(0, 15)); (* BITSET *)
  2997. dProc := NewProcType(InvalidType); (* PROC: no params, no result *)
  2998. Predef("INTEGER", KindPredef, dInt);
  2999. Predef("CARDINAL", KindPredef, dCard);
  3000. Predef("SHORTINT", KindPredef, dInt);
  3001. Predef("LONGINT", KindPredef, dLong);
  3002. Predef("SHORTCARD", KindPredef, dCard);
  3003. Predef("REAL", KindPredef, dReal);
  3004. Predef("LONGREAL", KindPredef, dReal);
  3005. Predef("CHAR", KindPredef, dChar);
  3006. Predef("BOOLEAN", KindPredef, dBool);
  3007. Predef("TRUE", KindConst, dBool);
  3008. Predef("FALSE", KindConst, dBool);
  3009. Predef("ADDRESS", KindPredef, dAddr);
  3010. Predef("UCHAR", KindPredef, dUChar);
  3011. Predef("BITSET", KindPredef, dBitset);
  3012. (* SYSTEM storage types (PIM/gm2): mapped onto V3's integer family
  3013. (BYTE/WORD -> the 32-bit ordinal, LONGWORD -> LONGINT, the
  3014. address forms -> ADDRESS) so `FROM SYSTEM IMPORT BYTE;` and
  3015. `ARRAY OF BYTE` resolve. *)
  3016. Predef("BYTE", KindPredef, dCard);
  3017. Predef("SBYTE", KindPredef, dInt);
  3018. Predef("WORD", KindPredef, dCard);
  3019. Predef("SWORD", KindPredef, dInt);
  3020. Predef("LONGWORD", KindPredef, dLong);
  3021. Predef("SHORTADDR", KindPredef, dAddr);
  3022. Predef("LONGADDR", KindPredef, dAddr);
  3023. Predef("PROC", KindPredef, dAddr);
  3024. Predef("LOC", KindPredef, dAddr);
  3025. (* gm2 sized/scalar names (mapped onto V3's families) *)
  3026. Predef("LONGCARD", KindPredef, dLong);
  3027. Predef("SHORTREAL", KindPredef, dReal);
  3028. Predef("REAL32", KindPredef, dReal);
  3029. Predef("REAL64", KindPredef, dReal);
  3030. Predef("INTEGER8", KindPredef, dInt);
  3031. Predef("INTEGER16", KindPredef, dInt);
  3032. Predef("INTEGER32", KindPredef, dInt);
  3033. Predef("INTEGER64", KindPredef, dLong);
  3034. Predef("CARDINAL8", KindPredef, dCard);
  3035. Predef("CARDINAL16", KindPredef, dCard);
  3036. Predef("CARDINAL32", KindPredef, dCard);
  3037. Predef("CARDINAL64", KindPredef, dLong);
  3038. (* PIM/SYSTEM coroutines: PROCESS is pointer-sized; the three
  3039. builtins bind to C helpers in the runtime shim. Signatures:
  3040. NEWPROCESS(P: PROC; A: ADDRESS; n: CARDINAL; VAR c: PROCESS);
  3041. TRANSFER(VAR a, b: PROCESS);
  3042. IOTRANSFER(VAR a, b: PROCESS; interruptNo: CARDINAL). *)
  3043. Predef("PROCESS", KindPredef, dAddr);
  3044. pr := PredefCProc("NEWPROCESS", "m2_newprocess", InvalidType);
  3045. AddFormal(pr, dProc, FALSE);
  3046. AddFormal(pr, dAddr, FALSE);
  3047. AddFormal(pr, dCard, FALSE);
  3048. AddFormal(pr, dAddr, TRUE);
  3049. pr := PredefCProc("TRANSFER", "m2_transfer", InvalidType);
  3050. AddFormal(pr, dAddr, TRUE);
  3051. AddFormal(pr, dAddr, TRUE);
  3052. pr := PredefCProc("IOTRANSFER", "m2_iotransfer", InvalidType);
  3053. AddFormal(pr, dAddr, TRUE);
  3054. AddFormal(pr, dAddr, TRUE);
  3055. AddFormal(pr, dCard, FALSE);
  3056. Predef("NIL", KindConst, dNil)
  3057. END Init;
  3058. (* ---------------- listing ---------------- *)
  3059. PROCEDURE WriteKind (kind: INTEGER);
  3060. BEGIN
  3061. CASE kind OF
  3062. KindConst : FileIO.WriteString(FileIO.StdOut, "CONST")
  3063. | KindType : FileIO.WriteString(FileIO.StdOut, "TYPE")
  3064. | KindVar : FileIO.WriteString(FileIO.StdOut, "VAR")
  3065. | KindImport : FileIO.WriteString(FileIO.StdOut, "IMPORT")
  3066. | KindModule : FileIO.WriteString(FileIO.StdOut, "MODULE")
  3067. | KindPredef : FileIO.WriteString(FileIO.StdOut, "PREDEF")
  3068. | KindField : FileIO.WriteString(FileIO.StdOut, "FIELD")
  3069. | KindProc : FileIO.WriteString(FileIO.StdOut, "PROC")
  3070. | KindParam : FileIO.WriteString(FileIO.StdOut, "PARAM")
  3071. ELSE FileIO.WriteString(FileIO.StdOut, "???")
  3072. END
  3073. END WriteKind;
  3074. PROCEDURE WriteNode (node: SymPtr);
  3075. BEGIN
  3076. IF node = NIL THEN RETURN END;
  3077. WriteNode(node^.left);
  3078. FileIO.WriteString(FileIO.StdOut, " ");
  3079. FileIO.WriteString(FileIO.StdOut, node^.name);
  3080. FileIO.WriteString(FileIO.StdOut, " : ");
  3081. WriteKind(node^.kind);
  3082. FileIO.WriteString(FileIO.StdOut, " #");
  3083. FileIO.WriteInt(FileIO.StdOut, node^.typ, 1);
  3084. FileIO.WriteLn(FileIO.StdOut);
  3085. WriteNode(node^.right)
  3086. END WriteNode;
  3087. PROCEDURE PrintTable;
  3088. VAR s: ScopePtr;
  3089. BEGIN
  3090. FileIO.WriteLn(FileIO.StdOut);
  3091. FileIO.WriteString(FileIO.StdOut, "--- Symbol table ---");
  3092. FileIO.WriteLn(FileIO.StdOut);
  3093. s := scopeList;
  3094. WHILE s # NIL DO
  3095. WriteNode(s^.root);
  3096. s := s^.link
  3097. END
  3098. END PrintTable;
  3099. BEGIN
  3100. Init
  3101. END SymTab.