SymTab.mod 69 KB

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