SymTab.mod 82 KB

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