SymTab.mod 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. IMPLEMENTATION MODULE SymTab;
  2. IMPORT FileIO;
  3. FROM Storage IMPORT ALLOCATE;
  4. FROM SYSTEM IMPORT TSIZE;
  5. CONST
  6. MaxTypes = 256;
  7. MaxPend = 64;
  8. ResDepth = 64;
  9. (* descriptor forms *)
  10. FNone = 0; FAlias = 1; FSub = 2; FEnum = 3; FArray = 4;
  11. FRecord = 5; FSet = 6; FPtr = 7; FStr = 8;
  12. FInt = 9; FReal = 10; FChar = 11; FBool = 12;
  13. TYPE
  14. SymPtr = POINTER TO SymNode;
  15. ScopePtr = POINTER TO ScopeNode;
  16. FieldPtr = POINTER TO FieldNode;
  17. SymNode = RECORD
  18. name : Name;
  19. kind : INTEGER;
  20. typ : TypeIndex;
  21. scope : ScopePtr; (* owning scope *)
  22. left : SymPtr; (* BST links within the owning scope *)
  23. right : SymPtr;
  24. rslt : TypeIndex; (* KindProc result type, InvalidType = none *)
  25. plink : SymPtr; (* next formal, positional chain *)
  26. isVar : BOOLEAN; (* KindParam: VAR formal *)
  27. fwd : BOOLEAN; (* KindProc: FORWARD body pending *)
  28. END;
  29. ScopeNode = RECORD
  30. parent : ScopePtr; (* scope tree link *)
  31. root : SymPtr; (* BST root of this scope's symbols *)
  32. level : CARDINAL;
  33. link : ScopePtr; (* creation-order chain for PrintTable *)
  34. END;
  35. FieldNode = RECORD
  36. name : Name;
  37. typ : TypeIndex;
  38. owner : TypeIndex;
  39. next : FieldPtr; (* next field of the same owner *)
  40. END;
  41. VAR
  42. curScope : ScopePtr;
  43. scopeList : ScopePtr; (* all scopes, creation order *)
  44. scopeTail : ScopePtr;
  45. fields : FieldPtr; (* all record fields, newest first *)
  46. nFields : CARDINAL;
  47. pend : ARRAY [0 .. MaxPend - 1] OF SymPtr;
  48. nPend : CARDINAL;
  49. pendF : ARRAY [0 .. MaxPend - 1] OF FieldPtr;
  50. nPendF : CARDINAL;
  51. tform : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  52. tref : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
  53. tlo : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  54. thi : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  55. nTypes : CARDINAL;
  56. curProc : SymPtr; (* heading being declared *)
  57. curPTail : SymPtr; (* positional param chain tail *)
  58. dInt, dCard, dReal, dChar, dBool : TypeIndex;
  59. (* ---------------- strings ---------------- *)
  60. PROCEDURE Assign (VAR dest: ARRAY OF CHAR; src: ARRAY OF CHAR);
  61. VAR i : CARDINAL;
  62. BEGIN
  63. i := 0;
  64. WHILE (i < HIGH(dest)) & (src[i] # 0C) DO
  65. dest[i] := src[i]; INC(i)
  66. END;
  67. dest[i] := 0C
  68. END Assign;
  69. PROCEDURE Equal (a, b: ARRAY OF CHAR): BOOLEAN;
  70. VAR i : CARDINAL;
  71. BEGIN
  72. i := 0;
  73. LOOP
  74. IF a[i] # b[i] THEN RETURN FALSE END;
  75. IF a[i] = 0C THEN RETURN TRUE END;
  76. INC(i)
  77. END
  78. END Equal;
  79. PROCEDURE Less (a, b: ARRAY OF CHAR): BOOLEAN;
  80. (* Lexicographic order on NUL-terminated strings (BST key order). *)
  81. VAR i : CARDINAL;
  82. BEGIN
  83. i := 0;
  84. LOOP
  85. IF a[i] # b[i] THEN RETURN ORD(a[i]) < ORD(b[i]) END;
  86. IF a[i] = 0C THEN RETURN FALSE END;
  87. INC(i)
  88. END
  89. END Less;
  90. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  91. VAR i : CARDINAL;
  92. BEGIN
  93. i := 0;
  94. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  95. RETURN i
  96. END StrLen;
  97. PROCEDURE ConstInt (q: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  98. VAR i, d: CARDINAL;
  99. neg: BOOLEAN;
  100. BEGIN
  101. v := 0; i := 0; neg := FALSE;
  102. IF q[0] = "-" THEN neg := TRUE; i := 1 END;
  103. IF (i >= HIGH(q)) OR (q[i] = 0C) THEN RETURN FALSE END;
  104. WHILE (i < HIGH(q)) & (q[i] # 0C) DO
  105. d := ORD(q[i]);
  106. IF (d < ORD("0")) OR (d > ORD("9")) THEN RETURN FALSE END;
  107. v := v * 10 + VAL(INTEGER, d - ORD("0")); INC(i)
  108. END;
  109. IF neg THEN v := -v END;
  110. RETURN TRUE
  111. END ConstInt;
  112. (* ---------------- scope tree + per-scope BST ---------------- *)
  113. PROCEDURE NewScope (parent: ScopePtr; level: CARDINAL): ScopePtr;
  114. (* Heap-allocates a scope and appends it to the creation chain. *)
  115. VAR s: ScopePtr;
  116. BEGIN
  117. ALLOCATE(s, TSIZE(ScopeNode));
  118. s^.parent := parent;
  119. s^.root := NIL;
  120. s^.level := level;
  121. s^.link := NIL;
  122. IF scopeList = NIL THEN scopeList := s ELSE scopeTail^.link := s END;
  123. scopeTail := s;
  124. RETURN s
  125. END NewScope;
  126. PROCEDURE TreeFind (root: SymPtr; name: ARRAY OF CHAR): SymPtr;
  127. (* BST search within one scope; NIL if absent. *)
  128. BEGIN
  129. WHILE root # NIL DO
  130. IF Equal(root^.name, name) THEN RETURN root END;
  131. IF Less(name, root^.name) THEN root := root^.left
  132. ELSE root := root^.right
  133. END
  134. END;
  135. RETURN NIL
  136. END TreeFind;
  137. PROCEDURE TreeInsert (s: ScopePtr; node: SymPtr): BOOLEAN;
  138. (* BST insert of node into scope s; FALSE on duplicate. *)
  139. VAR cur, parent: SymPtr;
  140. goLeft: BOOLEAN;
  141. BEGIN
  142. cur := s^.root; parent := NIL; goLeft := FALSE;
  143. WHILE cur # NIL DO
  144. IF Equal(cur^.name, node^.name) THEN RETURN FALSE END;
  145. parent := cur;
  146. IF Less(node^.name, cur^.name) THEN
  147. cur := cur^.left; goLeft := TRUE
  148. ELSE
  149. cur := cur^.right; goLeft := FALSE
  150. END
  151. END;
  152. node^.left := NIL;
  153. node^.right := NIL;
  154. node^.scope := s;
  155. IF parent = NIL THEN s^.root := node
  156. ELSIF goLeft THEN parent^.left := node
  157. ELSE parent^.right := node
  158. END;
  159. RETURN TRUE
  160. END TreeInsert;
  161. PROCEDURE Find (name: ARRAY OF CHAR): SymPtr;
  162. (* Innermost visible node or NIL; walks the scope chain up. *)
  163. VAR s: ScopePtr;
  164. r: SymPtr;
  165. BEGIN
  166. s := curScope;
  167. WHILE s # NIL DO
  168. r := TreeFind(s^.root, name);
  169. IF r # NIL THEN RETURN r END;
  170. s := s^.parent
  171. END;
  172. RETURN NIL
  173. END Find;
  174. PROCEDURE RawEnter (name: ARRAY OF CHAR; kind: INTEGER): SymPtr;
  175. (* Heap-allocates a symbol and links it into the current scope's
  176. BST; NIL on duplicate (node released to nobody: dropped). *)
  177. VAR node: SymPtr;
  178. BEGIN
  179. ALLOCATE(node, TSIZE(SymNode));
  180. Assign(node^.name, name);
  181. node^.kind := kind;
  182. node^.typ := InvalidType;
  183. node^.scope := curScope;
  184. node^.left := NIL;
  185. node^.right := NIL;
  186. IF ~TreeInsert(curScope, node) THEN RETURN NIL END;
  187. RETURN node
  188. END RawEnter;
  189. PROCEDURE Enter (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  190. BEGIN
  191. RETURN RawEnter(name, kind) # NIL
  192. END Enter;
  193. PROCEDURE EnterPending (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  194. VAR node: SymPtr;
  195. BEGIN
  196. node := RawEnter(name, kind);
  197. IF (node # NIL) & (nPend < MaxPend) THEN
  198. pend[nPend] := node; INC(nPend)
  199. END;
  200. RETURN node # NIL
  201. END EnterPending;
  202. PROCEDURE FixPending (t: TypeIndex);
  203. VAR i: CARDINAL;
  204. BEGIN
  205. i := 0;
  206. WHILE i < nPend DO
  207. pend[i]^.typ := t; INC(i)
  208. END;
  209. nPend := 0
  210. END FixPending;
  211. PROCEDURE PendCount (): CARDINAL;
  212. BEGIN
  213. RETURN nPend
  214. END PendCount;
  215. PROCEDURE PendName (i: CARDINAL; VAR n: Name);
  216. BEGIN
  217. IF i < nPend THEN Assign(n, pend[i]^.name)
  218. ELSE n[0] := 0C
  219. END
  220. END PendName;
  221. PROCEDURE FindField (rec: TypeIndex; name: ARRAY OF CHAR): FieldPtr;
  222. VAR f: FieldPtr;
  223. BEGIN
  224. IF (rec < 0) OR (rec >= VAL(INTEGER, nTypes)) THEN RETURN NIL END;
  225. IF tform[rec] # FRecord THEN RETURN NIL END;
  226. f := fields;
  227. WHILE f # NIL DO
  228. IF (f^.owner = rec) & Equal(f^.name, name) THEN RETURN f END;
  229. f := f^.next
  230. END;
  231. RETURN NIL
  232. END FindField;
  233. PROCEDURE FieldPending (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  234. VAR f: FieldPtr;
  235. BEGIN
  236. IF FindField(rec, name) # NIL THEN RETURN FALSE END;
  237. ALLOCATE(f, TSIZE(FieldNode));
  238. Assign(f^.name, name);
  239. f^.typ := InvalidType;
  240. f^.owner := rec;
  241. f^.next := fields;
  242. fields := f;
  243. IF nPendF < MaxPend THEN
  244. pendF[nPendF] := f; INC(nPendF)
  245. END;
  246. INC(nFields);
  247. RETURN TRUE
  248. END FieldPending;
  249. PROCEDURE FixPendingF (rec: TypeIndex; t: TypeIndex);
  250. VAR i, j: CARDINAL;
  251. BEGIN
  252. i := 0;
  253. WHILE i < nPendF DO
  254. IF pendF[i]^.owner = rec THEN
  255. pendF[i]^.typ := t;
  256. (* remove by swap with last *)
  257. j := nPendF - 1;
  258. pendF[i] := pendF[j];
  259. DEC(nPendF)
  260. ELSE
  261. INC(i)
  262. END
  263. END
  264. END FixPendingF;
  265. PROCEDURE Lookup (name: ARRAY OF CHAR): BOOLEAN;
  266. BEGIN
  267. RETURN Find(name) # NIL
  268. END Lookup;
  269. PROCEDURE SymType (name: ARRAY OF CHAR): TypeIndex;
  270. VAR node: SymPtr;
  271. BEGIN
  272. node := Find(name);
  273. IF node = NIL THEN RETURN InvalidType END;
  274. RETURN node^.typ
  275. END SymType;
  276. PROCEDURE SetSymType (name: ARRAY OF CHAR; t: TypeIndex);
  277. VAR node: SymPtr;
  278. BEGIN
  279. node := Find(name);
  280. IF node # NIL THEN node^.typ := t END
  281. END SetSymType;
  282. PROCEDURE SymKind (name: ARRAY OF CHAR): INTEGER;
  283. VAR node: SymPtr;
  284. BEGIN
  285. node := Find(name);
  286. IF node = NIL THEN RETURN -1 END;
  287. RETURN node^.kind
  288. END SymKind;
  289. PROCEDURE PushScope;
  290. BEGIN
  291. curScope := NewScope(curScope, curScope^.level + 1)
  292. END PushScope;
  293. PROCEDURE PopScope;
  294. BEGIN
  295. (* Nodes stay allocated but become unreachable via the chain. *)
  296. IF curScope^.parent # NIL THEN curScope := curScope^.parent END
  297. END PopScope;
  298. (* ---------------- type descriptors (unchanged) ---------------- *)
  299. PROCEDURE NewDesc (form: INTEGER; ref: TypeIndex): TypeIndex;
  300. BEGIN
  301. IF nTypes >= MaxTypes THEN RETURN InvalidType END;
  302. tform[nTypes] := form;
  303. tref[nTypes] := ref;
  304. INC(nTypes);
  305. RETURN VAL(INTEGER, nTypes - 1)
  306. END NewDesc;
  307. PROCEDURE NewAlias (): TypeIndex;
  308. BEGIN
  309. RETURN NewDesc(FAlias, InvalidType)
  310. END NewAlias;
  311. PROCEDURE NewSub (base: TypeIndex): TypeIndex;
  312. BEGIN
  313. RETURN NewDesc(FSub, base)
  314. END NewSub;
  315. PROCEDURE NewSubR (lo, hi: INTEGER): TypeIndex;
  316. VAR t: TypeIndex;
  317. BEGIN
  318. t := NewDesc(FSub, InvalidType);
  319. IF t # InvalidType THEN tlo[t] := lo; thi[t] := hi END;
  320. RETURN t
  321. END NewSubR;
  322. PROCEDURE NewEnum (): TypeIndex;
  323. BEGIN
  324. RETURN NewDesc(FEnum, InvalidType)
  325. END NewEnum;
  326. PROCEDURE NewArray (elem: TypeIndex): TypeIndex;
  327. BEGIN
  328. RETURN NewDesc(FArray, elem)
  329. END NewArray;
  330. PROCEDURE NewRecord (): TypeIndex;
  331. BEGIN
  332. RETURN NewDesc(FRecord, -1)
  333. END NewRecord;
  334. PROCEDURE NewSet (base: TypeIndex): TypeIndex;
  335. BEGIN
  336. RETURN NewDesc(FSet, base)
  337. END NewSet;
  338. PROCEDURE NewPtr (base: TypeIndex): TypeIndex;
  339. BEGIN
  340. RETURN NewDesc(FPtr, base)
  341. END NewPtr;
  342. PROCEDURE NewStr (): TypeIndex;
  343. BEGIN
  344. RETURN NewDesc(FStr, InvalidType)
  345. END NewStr;
  346. PROCEDURE SetTarget (t, base: TypeIndex);
  347. BEGIN
  348. IF (t >= 0) & (t < VAL(INTEGER, nTypes)) & (tform[t] = FAlias) THEN
  349. tref[t] := base
  350. END
  351. END SetTarget;
  352. PROCEDURE Resolve (t: TypeIndex): TypeIndex;
  353. VAR n: CARDINAL;
  354. BEGIN
  355. n := 0;
  356. WHILE (n < ResDepth) & (t >= 0) & (t < VAL(INTEGER, nTypes))
  357. & (tform[t] = FAlias) DO
  358. t := tref[t]; INC(n)
  359. END;
  360. IF (t < 0) OR (t >= VAL(INTEGER, nTypes)) THEN
  361. RETURN InvalidType
  362. END;
  363. RETURN t
  364. END Resolve;
  365. PROCEDURE IntType (): TypeIndex;
  366. BEGIN RETURN dInt END IntType;
  367. PROCEDURE RealType (): TypeIndex;
  368. BEGIN RETURN dReal END RealType;
  369. PROCEDURE CharType (): TypeIndex;
  370. BEGIN RETURN dChar END CharType;
  371. PROCEDURE BoolType (): TypeIndex;
  372. BEGIN RETURN dBool END BoolType;
  373. PROCEDURE ClassOf (t: TypeIndex): INTEGER;
  374. VAR r: TypeIndex;
  375. BEGIN
  376. r := Resolve(t);
  377. IF r = InvalidType THEN RETURN ClInvalid END;
  378. CASE tform[r] OF
  379. FInt : RETURN ClInt
  380. | FReal : RETURN ClReal
  381. | FChar : RETURN ClChar
  382. | FBool : RETURN ClBool
  383. | FEnum : RETURN ClEnum
  384. | FArray : RETURN ClArray
  385. | FRecord : RETURN ClRecord
  386. | FSet : RETURN ClSet
  387. | FPtr : RETURN ClPtr
  388. | FStr : RETURN ClStr
  389. | FSub : IF tref[r] = InvalidType THEN RETURN ClInt
  390. ELSE RETURN ClassOf(tref[r]) END
  391. ELSE RETURN ClInvalid
  392. END
  393. END ClassOf;
  394. PROCEDURE IsIntFamily (t: TypeIndex): BOOLEAN;
  395. BEGIN
  396. RETURN ClassOf(t) = ClInt
  397. END IsIntFamily;
  398. PROCEDURE SameType (a, b: TypeIndex): BOOLEAN;
  399. BEGIN
  400. IF (a = InvalidType) OR (b = InvalidType) THEN RETURN TRUE END;
  401. RETURN Resolve(a) = Resolve(b)
  402. END SameType;
  403. PROCEDURE FieldExists (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  404. BEGIN
  405. RETURN FindField(Resolve(rec), name) # NIL
  406. END FieldExists;
  407. PROCEDURE FieldType (rec: TypeIndex; name: ARRAY OF CHAR): TypeIndex;
  408. VAR f: FieldPtr;
  409. BEGIN
  410. f := FindField(Resolve(rec), name);
  411. IF f = NIL THEN RETURN InvalidType END;
  412. RETURN f^.typ
  413. END FieldType;
  414. PROCEDURE ArrayElem (t: TypeIndex): TypeIndex;
  415. VAR r: TypeIndex;
  416. BEGIN
  417. r := Resolve(t);
  418. IF (r = InvalidType) OR (tform[r] # FArray) THEN
  419. RETURN InvalidType
  420. END;
  421. RETURN tref[r]
  422. END ArrayElem;
  423. PROCEDURE PtrBase (t: TypeIndex): TypeIndex;
  424. VAR r: TypeIndex;
  425. BEGIN
  426. r := Resolve(t);
  427. IF (r = InvalidType) OR (tform[r] # FPtr) THEN
  428. RETURN InvalidType
  429. END;
  430. RETURN tref[r]
  431. END PtrBase;
  432. PROCEDURE PushRecord (t: TypeIndex): BOOLEAN;
  433. (* Pushes a scope with t's fields; caller must PopScope afterwards. *)
  434. VAR r: TypeIndex;
  435. f: FieldPtr;
  436. BEGIN
  437. r := Resolve(t);
  438. IF (r < 0) OR (tform[r] # FRecord) THEN RETURN FALSE END;
  439. PushScope;
  440. f := fields;
  441. WHILE f # NIL DO
  442. IF f^.owner = r THEN
  443. IF Enter(f^.name, KindField) THEN
  444. SetSymType(f^.name, f^.typ)
  445. END
  446. END;
  447. f := f^.next
  448. END;
  449. RETURN TRUE
  450. END PushRecord;
  451. (* ---------------- procedures ---------------- *)
  452. PROCEDURE EnterProc (name: ARRAY OF CHAR): BOOLEAN;
  453. VAR node: SymPtr;
  454. BEGIN
  455. node := RawEnter(name, KindProc);
  456. IF node = NIL THEN curProc := NIL; RETURN FALSE END;
  457. node^.rslt := InvalidType;
  458. node^.plink := NIL;
  459. node^.isVar := FALSE;
  460. node^.fwd := FALSE;
  461. curProc := node;
  462. curPTail := NIL;
  463. PushScope;
  464. RETURN TRUE
  465. END EnterProc;
  466. PROCEDURE ReenterProc (name: ARRAY OF CHAR): BOOLEAN;
  467. VAR node: SymPtr;
  468. BEGIN
  469. node := TreeFind(curScope^.root, name);
  470. IF (node = NIL) OR (node^.kind # KindProc) OR ~node^.fwd THEN
  471. RETURN FALSE
  472. END;
  473. node^.fwd := FALSE;
  474. node^.plink := NIL; (* fresh signature; step 4 compares old vs new *)
  475. curProc := node;
  476. curPTail := NIL;
  477. PushScope;
  478. RETURN TRUE
  479. END ReenterProc;
  480. PROCEDURE EnterParam (name: ARRAY OF CHAR; isVar: BOOLEAN): BOOLEAN;
  481. VAR node: SymPtr;
  482. BEGIN
  483. node := RawEnter(name, KindParam);
  484. IF node = NIL THEN RETURN FALSE END;
  485. node^.isVar := isVar;
  486. node^.plink := NIL;
  487. IF (nPend < MaxPend) THEN
  488. pend[nPend] := node; INC(nPend)
  489. END;
  490. IF curProc # NIL THEN
  491. IF curProc^.plink = NIL THEN curProc^.plink := node
  492. ELSE curPTail^.plink := node
  493. END;
  494. curPTail := node
  495. END;
  496. RETURN TRUE
  497. END EnterParam;
  498. PROCEDURE SetProcRes (t: TypeIndex);
  499. BEGIN
  500. IF curProc # NIL THEN curProc^.rslt := t END
  501. END SetProcRes;
  502. PROCEDURE ProcRes (name: ARRAY OF CHAR): TypeIndex;
  503. VAR node: SymPtr;
  504. BEGIN
  505. node := Find(name);
  506. IF (node = NIL) OR (node^.kind # KindProc) THEN
  507. RETURN InvalidType
  508. END;
  509. RETURN node^.rslt
  510. END ProcRes;
  511. PROCEDURE MarkFwd;
  512. BEGIN
  513. IF curProc # NIL THEN curProc^.fwd := TRUE END
  514. END MarkFwd;
  515. (* ---------------- predicates (unchanged) ---------------- *)
  516. PROCEDURE SetBasesOk (a, b: TypeIndex): BOOLEAN;
  517. (* base compatibility for two SET types *)
  518. BEGIN
  519. IF SameType(a, b) THEN RETURN TRUE END;
  520. IF IsIntFamily(a) & IsIntFamily(b) THEN RETURN TRUE END;
  521. IF (ClassOf(a) = ClChar) & (ClassOf(b) = ClChar) THEN
  522. RETURN TRUE
  523. END;
  524. RETURN FALSE
  525. END SetBasesOk;
  526. PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
  527. VAR rs, rd: TypeIndex;
  528. BEGIN
  529. IF (src = InvalidType) OR (dst = InvalidType) THEN RETURN TRUE END;
  530. rs := Resolve(src); rd := Resolve(dst);
  531. IF rs = rd THEN RETURN TRUE END;
  532. IF (rs = InvalidType) OR (rd = InvalidType) THEN RETURN TRUE END;
  533. IF (tform[rs] = FSet) & (tform[rd] = FSet) THEN
  534. RETURN SetBasesOk(tref[rs], tref[rd])
  535. END;
  536. IF (ClassOf(src) = ClInt) & (ClassOf(dst) = ClInt) THEN
  537. RETURN TRUE
  538. END;
  539. IF (ClassOf(src) = ClInt) & (ClassOf(dst) = ClReal) THEN
  540. RETURN TRUE
  541. END;
  542. IF (ClassOf(src) = ClStr) & (ClassOf(dst) = ClArray) THEN
  543. RETURN TRUE
  544. END;
  545. RETURN FALSE
  546. END Assignable;
  547. PROCEDURE ArithCheck (l, r: TypeIndex; divmod: BOOLEAN;
  548. VAR res: TypeIndex): BOOLEAN;
  549. BEGIN
  550. res := InvalidType;
  551. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  552. IF IsIntFamily(l) & IsIntFamily(r) THEN
  553. res := dInt; RETURN TRUE
  554. END;
  555. IF ~divmod & (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  556. res := dReal; RETURN TRUE
  557. END;
  558. RETURN FALSE
  559. END ArithCheck;
  560. PROCEDURE UnaryCheck (t: TypeIndex; VAR res: TypeIndex): BOOLEAN;
  561. BEGIN
  562. res := InvalidType;
  563. IF t = InvalidType THEN RETURN TRUE END;
  564. IF IsIntFamily(t) THEN res := dInt; RETURN TRUE END;
  565. IF ClassOf(t) = ClReal THEN res := dReal; RETURN TRUE END;
  566. RETURN FALSE
  567. END UnaryCheck;
  568. PROCEDURE BoolCheck (t: TypeIndex): BOOLEAN;
  569. BEGIN
  570. IF t = InvalidType THEN RETURN TRUE END;
  571. RETURN ClassOf(t) = ClBool
  572. END BoolCheck;
  573. PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
  574. VAR rl, rr: TypeIndex;
  575. BEGIN
  576. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  577. IF SameType(l, r) THEN RETURN TRUE END;
  578. IF IsIntFamily(l) & IsIntFamily(r) THEN RETURN TRUE END;
  579. IF (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  580. RETURN TRUE
  581. END;
  582. IF (ClassOf(l) = ClChar) & (ClassOf(r) = ClChar) THEN
  583. RETURN TRUE
  584. END;
  585. IF (ClassOf(l) = ClBool) & (ClassOf(r) = ClBool) THEN
  586. RETURN TRUE
  587. END;
  588. IF (ClassOf(l) = ClStr) & (ClassOf(r) = ClStr) THEN
  589. RETURN TRUE
  590. END;
  591. rl := Resolve(l); rr := Resolve(r);
  592. IF (rl = InvalidType) OR (rr = InvalidType) THEN RETURN TRUE END;
  593. IF (tform[rl] = FSet) & (tform[rr] = FSet) THEN
  594. RETURN SetBasesOk(tref[rl], tref[rr])
  595. END;
  596. RETURN FALSE
  597. END EqCheck;
  598. PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
  599. BEGIN
  600. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  601. IF IsIntFamily(l) & IsIntFamily(r) THEN RETURN TRUE END;
  602. IF (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  603. RETURN TRUE
  604. END;
  605. IF (ClassOf(l) = ClChar) & (ClassOf(r) = ClChar) THEN
  606. RETURN TRUE
  607. END;
  608. IF (ClassOf(l) = ClEnum) & SameType(l, r) THEN RETURN TRUE END;
  609. RETURN FALSE
  610. END OrdCheck;
  611. PROCEDURE InCheck (l, set: TypeIndex): BOOLEAN;
  612. VAR rs, b: TypeIndex;
  613. BEGIN
  614. IF (l = InvalidType) OR (set = InvalidType) THEN RETURN TRUE END;
  615. rs := Resolve(set);
  616. IF (rs = InvalidType) OR (tform[rs] # FSet) THEN RETURN FALSE END;
  617. b := tref[rs];
  618. IF SameType(l, b) THEN RETURN TRUE END;
  619. IF IsIntFamily(l) & IsIntFamily(b) THEN RETURN TRUE END;
  620. IF (ClassOf(l) = ClChar) & (ClassOf(b) = ClChar) THEN
  621. RETURN TRUE
  622. END;
  623. RETURN FALSE
  624. END InCheck;
  625. PROCEDURE RelCheck (l, r: TypeIndex; op: INTEGER): BOOLEAN;
  626. BEGIN
  627. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  628. IF op = OpIn THEN RETURN InCheck(l, r) END;
  629. IF (op = OpEq) OR (op = OpNeq1) OR (op = OpNeq2) THEN
  630. RETURN EqCheck(l, r)
  631. END;
  632. RETURN OrdCheck(l, r)
  633. END RelCheck;
  634. PROCEDURE SetElemCheck (first, elem: TypeIndex): BOOLEAN;
  635. BEGIN
  636. IF (first = InvalidType) OR (elem = InvalidType) THEN
  637. RETURN TRUE
  638. END;
  639. IF SameType(first, elem) THEN RETURN TRUE END;
  640. IF IsIntFamily(first) & IsIntFamily(elem) THEN RETURN TRUE END;
  641. RETURN FALSE
  642. END SetElemCheck;
  643. PROCEDURE SetFor (elem: TypeIndex): TypeIndex;
  644. VAR e: TypeIndex;
  645. BEGIN
  646. e := Resolve(elem);
  647. IF e = InvalidType THEN e := dInt END;
  648. RETURN NewSet(e)
  649. END SetFor;
  650. (* ---------------- init ---------------- *)
  651. PROCEDURE Predef (name: ARRAY OF CHAR; kind: INTEGER; t: TypeIndex);
  652. BEGIN
  653. IF Enter(name, kind) THEN SetSymType(name, t) END
  654. END Predef;
  655. PROCEDURE Init;
  656. BEGIN
  657. scopeList := NIL; scopeTail := NIL;
  658. fields := NIL; nFields := 0;
  659. nPend := 0; nPendF := 0;
  660. nTypes := 0;
  661. curProc := NIL; curPTail := NIL;
  662. curScope := NewScope(NIL, 0);
  663. dInt := NewDesc(FInt, InvalidType);
  664. dCard := NewDesc(FInt, InvalidType);
  665. dReal := NewDesc(FReal, InvalidType);
  666. dChar := NewDesc(FChar, InvalidType);
  667. dBool := NewDesc(FBool, InvalidType);
  668. Predef("INTEGER", KindPredef, dInt);
  669. Predef("CARDINAL", KindPredef, dCard);
  670. Predef("SHORTINT", KindPredef, dInt);
  671. Predef("LONGINT", KindPredef, dInt);
  672. Predef("REAL", KindPredef, dReal);
  673. Predef("LONGREAL", KindPredef, dReal);
  674. Predef("CHAR", KindPredef, dChar);
  675. Predef("BOOLEAN", KindPredef, dBool);
  676. Predef("TRUE", KindConst, dBool);
  677. Predef("FALSE", KindConst, dBool);
  678. Predef("NIL", KindConst, InvalidType)
  679. END Init;
  680. (* ---------------- listing ---------------- *)
  681. PROCEDURE WriteKind (kind: INTEGER);
  682. BEGIN
  683. CASE kind OF
  684. KindConst : FileIO.WriteString(FileIO.StdOut, "CONST")
  685. | KindType : FileIO.WriteString(FileIO.StdOut, "TYPE")
  686. | KindVar : FileIO.WriteString(FileIO.StdOut, "VAR")
  687. | KindImport : FileIO.WriteString(FileIO.StdOut, "IMPORT")
  688. | KindModule : FileIO.WriteString(FileIO.StdOut, "MODULE")
  689. | KindPredef : FileIO.WriteString(FileIO.StdOut, "PREDEF")
  690. | KindField : FileIO.WriteString(FileIO.StdOut, "FIELD")
  691. | KindProc : FileIO.WriteString(FileIO.StdOut, "PROC")
  692. | KindParam : FileIO.WriteString(FileIO.StdOut, "PARAM")
  693. ELSE FileIO.WriteString(FileIO.StdOut, "???")
  694. END
  695. END WriteKind;
  696. PROCEDURE WriteNode (node: SymPtr);
  697. BEGIN
  698. IF node = NIL THEN RETURN END;
  699. WriteNode(node^.left);
  700. FileIO.WriteString(FileIO.StdOut, " ");
  701. FileIO.WriteString(FileIO.StdOut, node^.name);
  702. FileIO.WriteString(FileIO.StdOut, " : ");
  703. WriteKind(node^.kind);
  704. FileIO.WriteString(FileIO.StdOut, " #");
  705. FileIO.WriteInt(FileIO.StdOut, node^.typ, 1);
  706. FileIO.WriteLn(FileIO.StdOut);
  707. WriteNode(node^.right)
  708. END WriteNode;
  709. PROCEDURE PrintTable;
  710. VAR s: ScopePtr;
  711. BEGIN
  712. FileIO.WriteLn(FileIO.StdOut);
  713. FileIO.WriteString(FileIO.StdOut, "--- Symbol table ---");
  714. FileIO.WriteLn(FileIO.StdOut);
  715. s := scopeList;
  716. WHILE s # NIL DO
  717. WriteNode(s^.root);
  718. s := s^.link
  719. END
  720. END PrintTable;
  721. BEGIN
  722. Init
  723. END SymTab.