SymTab.mod 97 KB

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