SymTab.mod 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. IMPLEMENTATION MODULE SymTab;
  2. IMPORT FileIO;
  3. CONST
  4. MaxTypes = 256;
  5. MaxFields = 512;
  6. MaxPend = 64;
  7. MaxMarks = 16;
  8. ResDepth = 64;
  9. MaxProcs = 64;
  10. MaxParams = 256;
  11. MaxPDepth = 16;
  12. NoSlot = -1000;
  13. (* descriptor forms *)
  14. FNone = 0; FAlias = 1; FSub = 2; FEnum = 3; FArray = 4;
  15. FRecord = 5; FSet = 6; FPtr = 7; FStr = 8;
  16. FInt = 9; FReal = 10; FChar = 11; FBool = 12;
  17. TYPE
  18. Symbol = RECORD
  19. name : Name;
  20. kind : INTEGER;
  21. typ : TypeIndex;
  22. lev : CARDINAL;
  23. slot : INTEGER; (* frame slot (params >= 3, locals negative) *)
  24. pdep : CARDINAL; (* proc depth at declaration *)
  25. pnum : INTEGER; (* proc number (0 = not a procedure) *)
  26. END;
  27. Field = RECORD
  28. name : Name;
  29. typ : TypeIndex;
  30. owner : TypeIndex;
  31. next : INTEGER; (* index of next field of same owner, -1 = end *)
  32. END;
  33. ProcRec = RECORD
  34. ret : TypeIndex; (* InvalidType = proper procedure *)
  35. fret : TypeIndex; (* forward heading return type *)
  36. fwd : BOOLEAN; (* body still pending *)
  37. everFwd : BOOLEAN; (* had a forward heading *)
  38. fHead : INTEGER; (* forward param list *)
  39. fTail : INTEGER;
  40. dHead : INTEGER; (* define param list *)
  41. dTail : INTEGER;
  42. END;
  43. ParamRec = RECORD
  44. typ : TypeIndex;
  45. isVar : BOOLEAN;
  46. next : INTEGER;
  47. END;
  48. VAR
  49. syms : ARRAY [0 .. MaxSyms - 1] OF Symbol;
  50. nSyms : CARDINAL;
  51. curLev : CARDINAL;
  52. marks : ARRAY [0 .. MaxMarks - 1] OF CARDINAL;
  53. mtop : CARDINAL;
  54. pend : ARRAY [0 .. MaxPend - 1] OF CARDINAL;
  55. nPend : CARDINAL;
  56. pendF : ARRAY [0 .. MaxPend - 1] OF CARDINAL;
  57. nPendF : CARDINAL;
  58. tform : ARRAY [0 .. MaxTypes - 1] OF INTEGER;
  59. tref : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
  60. nTypes : CARDINAL;
  61. fields : ARRAY [0 .. MaxFields - 1] OF Field;
  62. nFields : CARDINAL;
  63. dInt, dCard, dReal, dChar, dBool : TypeIndex;
  64. procs : ARRAY [1 .. MaxProcs] OF ProcRec;
  65. nProcs : CARDINAL;
  66. params : ARRAY [0 .. MaxParams - 1] OF ParamRec;
  67. nParams : CARDINAL;
  68. pdep : CARDINAL;
  69. curProc : INTEGER;
  70. procSt : ARRAY [0 .. MaxPDepth] OF INTEGER;
  71. locCnt : ARRAY [0 .. MaxPDepth] OF CARDINAL;
  72. parCnt : ARRAY [0 .. MaxPDepth] OF CARDINAL;
  73. retSt : ARRAY [0 .. MaxPDepth] OF TypeIndex;
  74. (* ---------------- strings ---------------- *)
  75. PROCEDURE Assign (VAR dest: ARRAY OF CHAR; src: ARRAY OF CHAR);
  76. VAR i : CARDINAL;
  77. BEGIN
  78. i := 0;
  79. WHILE (i < HIGH(dest)) & (src[i] # 0C) DO
  80. dest[i] := src[i]; INC(i)
  81. END;
  82. dest[i] := 0C
  83. END Assign;
  84. PROCEDURE Equal (a, b: ARRAY OF CHAR): BOOLEAN;
  85. VAR i : CARDINAL;
  86. BEGIN
  87. i := 0;
  88. LOOP
  89. IF a[i] # b[i] THEN RETURN FALSE END;
  90. IF a[i] = 0C THEN RETURN TRUE END;
  91. INC(i)
  92. END
  93. END Equal;
  94. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  95. VAR i : CARDINAL;
  96. BEGIN
  97. i := 0;
  98. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  99. RETURN i
  100. END StrLen;
  101. (* ---------------- symbols and scopes ---------------- *)
  102. PROCEDURE Find (name: ARRAY OF CHAR): INTEGER;
  103. (* innermost visible index or -1 *)
  104. VAR i : CARDINAL;
  105. BEGIN
  106. i := nSyms;
  107. WHILE i > 0 DO
  108. DEC(i);
  109. IF Equal(syms[i].name, name) THEN RETURN VAL(INTEGER, i) END
  110. END;
  111. RETURN -1
  112. END Find;
  113. PROCEDURE RawEnter (name: ARRAY OF CHAR; kind: INTEGER): INTEGER;
  114. (* index or -1 when full *)
  115. BEGIN
  116. IF nSyms >= MaxSyms THEN RETURN -1 END;
  117. Assign(syms[nSyms].name, name);
  118. syms[nSyms].kind := kind;
  119. syms[nSyms].typ := InvalidType;
  120. syms[nSyms].lev := curLev;
  121. syms[nSyms].slot := NoSlot;
  122. syms[nSyms].pdep := pdep;
  123. syms[nSyms].pnum := 0;
  124. IF (kind = KindVar) & (pdep > 0) THEN
  125. syms[nSyms].slot := -(1 + VAL(INTEGER, locCnt[pdep]));
  126. INC(locCnt[pdep])
  127. END;
  128. INC(nSyms);
  129. RETURN VAL(INTEGER, nSyms - 1)
  130. END RawEnter;
  131. PROCEDURE DupInLevel (name: ARRAY OF CHAR): BOOLEAN;
  132. VAR i : CARDINAL;
  133. BEGIN
  134. i := nSyms;
  135. WHILE (i > 0) & (syms[i - 1].lev = curLev) DO
  136. DEC(i);
  137. IF Equal(syms[i].name, name) THEN RETURN TRUE END
  138. END;
  139. RETURN FALSE
  140. END DupInLevel;
  141. PROCEDURE Enter (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  142. BEGIN
  143. IF DupInLevel(name) THEN RETURN FALSE END;
  144. RETURN RawEnter(name, kind) # -1
  145. END Enter;
  146. PROCEDURE EnterPending (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
  147. VAR idx : INTEGER;
  148. BEGIN
  149. IF DupInLevel(name) THEN RETURN FALSE END;
  150. idx := RawEnter(name, kind);
  151. IF (idx # -1) & (nPend < MaxPend) THEN
  152. pend[nPend] := VAL(CARDINAL, idx); INC(nPend)
  153. END;
  154. RETURN idx # -1
  155. END EnterPending;
  156. PROCEDURE FixPending (t: TypeIndex);
  157. VAR i : CARDINAL;
  158. BEGIN
  159. i := 0;
  160. WHILE i < nPend DO
  161. syms[pend[i]].typ := t; INC(i)
  162. END;
  163. nPend := 0
  164. END FixPending;
  165. PROCEDURE PendCount (): CARDINAL;
  166. BEGIN
  167. RETURN nPend
  168. END PendCount;
  169. PROCEDURE PendName (i: CARDINAL; VAR n: Name);
  170. BEGIN
  171. IF i < nPend THEN Assign(n, syms[pend[i]].name)
  172. ELSE n[0] := 0C
  173. END
  174. END PendName;
  175. PROCEDURE FindField (rec: TypeIndex; name: ARRAY OF CHAR): INTEGER;
  176. VAR i : INTEGER;
  177. BEGIN
  178. IF (rec < 0) OR (rec >= VAL(INTEGER, nTypes)) THEN RETURN -1 END;
  179. IF tform[rec] # FRecord THEN RETURN -1 END;
  180. i := tref[rec];
  181. WHILE i # -1 DO
  182. IF Equal(fields[i].name, name) THEN RETURN i END;
  183. i := fields[i].next
  184. END;
  185. RETURN -1
  186. END FindField;
  187. PROCEDURE FieldPending (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  188. BEGIN
  189. IF FindField(rec, name) # -1 THEN RETURN FALSE END;
  190. IF nFields >= MaxFields THEN RETURN FALSE END;
  191. Assign(fields[nFields].name, name);
  192. fields[nFields].typ := InvalidType;
  193. fields[nFields].owner := rec;
  194. fields[nFields].next := tref[rec];
  195. tref[rec] := VAL(INTEGER, nFields);
  196. IF nPendF < MaxPend THEN
  197. pendF[nPendF] := nFields; INC(nPendF)
  198. END;
  199. INC(nFields);
  200. RETURN TRUE
  201. END FieldPending;
  202. PROCEDURE FixPendingF (rec: TypeIndex; t: TypeIndex);
  203. VAR i, j : CARDINAL;
  204. BEGIN
  205. i := 0;
  206. WHILE i < nPendF DO
  207. IF fields[pendF[i]].owner = rec THEN
  208. fields[pendF[i]].typ := t;
  209. (* remove by swap with last *)
  210. j := nPendF - 1;
  211. pendF[i] := pendF[j];
  212. DEC(nPendF)
  213. ELSE
  214. INC(i)
  215. END
  216. END
  217. END FixPendingF;
  218. PROCEDURE Lookup (name: ARRAY OF CHAR): BOOLEAN;
  219. BEGIN
  220. RETURN Find(name) # -1
  221. END Lookup;
  222. PROCEDURE SymType (name: ARRAY OF CHAR): TypeIndex;
  223. VAR idx : INTEGER;
  224. BEGIN
  225. idx := Find(name);
  226. IF idx = -1 THEN RETURN InvalidType END;
  227. RETURN syms[idx].typ
  228. END SymType;
  229. PROCEDURE SetSymType (name: ARRAY OF CHAR; t: TypeIndex);
  230. VAR idx : INTEGER;
  231. BEGIN
  232. idx := Find(name);
  233. IF idx # -1 THEN syms[idx].typ := t END
  234. END SetSymType;
  235. PROCEDURE SymKind (name: ARRAY OF CHAR): INTEGER;
  236. VAR idx : INTEGER;
  237. BEGIN
  238. idx := Find(name);
  239. IF idx = -1 THEN RETURN -1 END;
  240. RETURN syms[idx].kind
  241. END SymKind;
  242. PROCEDURE PushScope;
  243. BEGIN
  244. IF mtop < MaxMarks THEN marks[mtop] := nSyms; INC(mtop) END;
  245. INC(curLev)
  246. END PushScope;
  247. PROCEDURE PopScope;
  248. BEGIN
  249. IF mtop > 0 THEN DEC(mtop); nSyms := marks[mtop] END;
  250. IF curLev > 0 THEN DEC(curLev) END
  251. END PopScope;
  252. (* ---------------- type descriptors ---------------- *)
  253. PROCEDURE NewDesc (form: INTEGER; ref: TypeIndex): TypeIndex;
  254. BEGIN
  255. IF nTypes >= MaxTypes THEN RETURN InvalidType END;
  256. tform[nTypes] := form;
  257. tref[nTypes] := ref;
  258. INC(nTypes);
  259. RETURN VAL(INTEGER, nTypes - 1)
  260. END NewDesc;
  261. PROCEDURE NewAlias (): TypeIndex;
  262. BEGIN
  263. RETURN NewDesc(FAlias, InvalidType)
  264. END NewAlias;
  265. PROCEDURE NewSub (base: TypeIndex): TypeIndex;
  266. BEGIN
  267. RETURN NewDesc(FSub, base)
  268. END NewSub;
  269. PROCEDURE NewEnum (): TypeIndex;
  270. BEGIN
  271. RETURN NewDesc(FEnum, InvalidType)
  272. END NewEnum;
  273. PROCEDURE NewArray (elem: TypeIndex): TypeIndex;
  274. BEGIN
  275. RETURN NewDesc(FArray, elem)
  276. END NewArray;
  277. PROCEDURE NewRecord (): TypeIndex;
  278. BEGIN
  279. RETURN NewDesc(FRecord, -1)
  280. END NewRecord;
  281. PROCEDURE NewSet (base: TypeIndex): TypeIndex;
  282. BEGIN
  283. RETURN NewDesc(FSet, base)
  284. END NewSet;
  285. PROCEDURE NewPtr (base: TypeIndex): TypeIndex;
  286. BEGIN
  287. RETURN NewDesc(FPtr, base)
  288. END NewPtr;
  289. PROCEDURE NewStr (): TypeIndex;
  290. BEGIN
  291. RETURN NewDesc(FStr, InvalidType)
  292. END NewStr;
  293. PROCEDURE SetTarget (t, base: TypeIndex);
  294. BEGIN
  295. IF (t >= 0) & (t < VAL(INTEGER, nTypes)) & (tform[t] = FAlias) THEN
  296. tref[t] := base
  297. END
  298. END SetTarget;
  299. PROCEDURE Resolve (t: TypeIndex): TypeIndex;
  300. VAR n : CARDINAL;
  301. BEGIN
  302. n := 0;
  303. WHILE (n < ResDepth) & (t >= 0) & (t < VAL(INTEGER, nTypes))
  304. & (tform[t] = FAlias) DO
  305. t := tref[t]; INC(n)
  306. END;
  307. IF (t < 0) OR (t >= VAL(INTEGER, nTypes)) THEN
  308. RETURN InvalidType
  309. END;
  310. RETURN t
  311. END Resolve;
  312. PROCEDURE IntType (): TypeIndex;
  313. BEGIN RETURN dInt END IntType;
  314. PROCEDURE RealType (): TypeIndex;
  315. BEGIN RETURN dReal END RealType;
  316. PROCEDURE CharType (): TypeIndex;
  317. BEGIN RETURN dChar END CharType;
  318. PROCEDURE BoolType (): TypeIndex;
  319. BEGIN RETURN dBool END BoolType;
  320. PROCEDURE ClassOf (t: TypeIndex): INTEGER;
  321. VAR r : TypeIndex;
  322. BEGIN
  323. r := Resolve(t);
  324. IF r = InvalidType THEN RETURN ClInvalid END;
  325. CASE tform[r] OF
  326. FInt : RETURN ClInt
  327. | FReal : RETURN ClReal
  328. | FChar : RETURN ClChar
  329. | FBool : RETURN ClBool
  330. | FEnum : RETURN ClEnum
  331. | FArray : RETURN ClArray
  332. | FRecord : RETURN ClRecord
  333. | FSet : RETURN ClSet
  334. | FPtr : RETURN ClPtr
  335. | FStr : RETURN ClStr
  336. | FSub : RETURN ClassOf(tref[r])
  337. ELSE RETURN ClInvalid
  338. END
  339. END ClassOf;
  340. PROCEDURE IsIntFamily (t: TypeIndex): BOOLEAN;
  341. BEGIN
  342. RETURN ClassOf(t) = ClInt
  343. END IsIntFamily;
  344. PROCEDURE SameType (a, b: TypeIndex): BOOLEAN;
  345. BEGIN
  346. IF (a = InvalidType) OR (b = InvalidType) THEN RETURN TRUE END;
  347. RETURN Resolve(a) = Resolve(b)
  348. END SameType;
  349. PROCEDURE FieldExists (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
  350. BEGIN
  351. RETURN FindField(Resolve(rec), name) # -1
  352. END FieldExists;
  353. PROCEDURE FieldType (rec: TypeIndex; name: ARRAY OF CHAR): TypeIndex;
  354. VAR i : INTEGER;
  355. BEGIN
  356. i := FindField(Resolve(rec), name);
  357. IF i = -1 THEN RETURN InvalidType END;
  358. RETURN fields[i].typ
  359. END FieldType;
  360. PROCEDURE ArrayElem (t: TypeIndex): TypeIndex;
  361. VAR r : TypeIndex;
  362. BEGIN
  363. r := Resolve(t);
  364. IF (r = InvalidType) OR (tform[r] # FArray) THEN
  365. RETURN InvalidType
  366. END;
  367. RETURN tref[r]
  368. END ArrayElem;
  369. PROCEDURE PtrBase (t: TypeIndex): TypeIndex;
  370. VAR r : TypeIndex;
  371. BEGIN
  372. r := Resolve(t);
  373. IF (r = InvalidType) OR (tform[r] # FPtr) THEN
  374. RETURN InvalidType
  375. END;
  376. RETURN tref[r]
  377. END PtrBase;
  378. PROCEDURE PushRecord (t: TypeIndex): BOOLEAN;
  379. (* Pushes a scope with t's fields; caller must PopScope afterwards. *)
  380. VAR r, i : INTEGER;
  381. BEGIN
  382. r := Resolve(t);
  383. IF (r < 0) OR (tform[r] # FRecord) THEN RETURN FALSE END;
  384. PushScope;
  385. i := tref[r];
  386. WHILE i # -1 DO
  387. IF Enter(fields[i].name, KindField) THEN
  388. SetSymType(fields[i].name, fields[i].typ)
  389. END;
  390. i := fields[i].next
  391. END;
  392. RETURN TRUE
  393. END PushRecord;
  394. (* ---------------- predicates ---------------- *)
  395. PROCEDURE SetBasesOk (a, b: TypeIndex): BOOLEAN;
  396. (* base compatibility for two SET types *)
  397. BEGIN
  398. IF SameType(a, b) THEN RETURN TRUE END;
  399. IF IsIntFamily(a) & IsIntFamily(b) THEN RETURN TRUE END;
  400. IF (ClassOf(a) = ClChar) & (ClassOf(b) = ClChar) THEN
  401. RETURN TRUE
  402. END;
  403. RETURN FALSE
  404. END SetBasesOk;
  405. PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
  406. VAR rs, rd : TypeIndex;
  407. BEGIN
  408. IF (src = InvalidType) OR (dst = InvalidType) THEN RETURN TRUE END;
  409. rs := Resolve(src); rd := Resolve(dst);
  410. IF rs = rd THEN RETURN TRUE END;
  411. IF (rs = InvalidType) OR (rd = InvalidType) THEN RETURN TRUE END;
  412. IF (tform[rs] = FSet) & (tform[rd] = FSet) THEN
  413. RETURN SetBasesOk(tref[rs], tref[rd])
  414. END;
  415. IF (ClassOf(src) = ClInt) & (ClassOf(dst) = ClInt) THEN
  416. RETURN TRUE
  417. END;
  418. IF (ClassOf(src) = ClInt) & (ClassOf(dst) = ClReal) THEN
  419. RETURN TRUE
  420. END;
  421. IF (ClassOf(src) = ClStr) & (ClassOf(dst) = ClArray) THEN
  422. RETURN TRUE
  423. END;
  424. RETURN FALSE
  425. END Assignable;
  426. PROCEDURE ArithCheck (l, r: TypeIndex; divmod: BOOLEAN;
  427. VAR res: TypeIndex): BOOLEAN;
  428. BEGIN
  429. res := InvalidType;
  430. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  431. IF IsIntFamily(l) & IsIntFamily(r) THEN
  432. res := dInt; RETURN TRUE
  433. END;
  434. IF ~divmod & (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  435. res := dReal; RETURN TRUE
  436. END;
  437. RETURN FALSE
  438. END ArithCheck;
  439. PROCEDURE UnaryCheck (t: TypeIndex; VAR res: TypeIndex): BOOLEAN;
  440. BEGIN
  441. res := InvalidType;
  442. IF t = InvalidType THEN RETURN TRUE END;
  443. IF IsIntFamily(t) THEN res := dInt; RETURN TRUE END;
  444. IF ClassOf(t) = ClReal THEN res := dReal; RETURN TRUE END;
  445. RETURN FALSE
  446. END UnaryCheck;
  447. PROCEDURE BoolCheck (t: TypeIndex): BOOLEAN;
  448. BEGIN
  449. IF t = InvalidType THEN RETURN TRUE END;
  450. RETURN ClassOf(t) = ClBool
  451. END BoolCheck;
  452. PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
  453. VAR rl, rr : TypeIndex;
  454. BEGIN
  455. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  456. IF SameType(l, r) THEN RETURN TRUE END;
  457. IF IsIntFamily(l) & IsIntFamily(r) THEN RETURN TRUE END;
  458. IF (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  459. RETURN TRUE
  460. END;
  461. IF (ClassOf(l) = ClChar) & (ClassOf(r) = ClChar) THEN
  462. RETURN TRUE
  463. END;
  464. IF (ClassOf(l) = ClBool) & (ClassOf(r) = ClBool) THEN
  465. RETURN TRUE
  466. END;
  467. IF (ClassOf(l) = ClStr) & (ClassOf(r) = ClStr) THEN
  468. RETURN TRUE
  469. END;
  470. rl := Resolve(l); rr := Resolve(r);
  471. IF (rl = InvalidType) OR (rr = InvalidType) THEN RETURN TRUE END;
  472. IF (tform[rl] = FSet) & (tform[rr] = FSet) THEN
  473. RETURN SetBasesOk(tref[rl], tref[rr])
  474. END;
  475. RETURN FALSE
  476. END EqCheck;
  477. PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
  478. BEGIN
  479. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  480. IF IsIntFamily(l) & IsIntFamily(r) THEN RETURN TRUE END;
  481. IF (ClassOf(l) = ClReal) & (ClassOf(r) = ClReal) THEN
  482. RETURN TRUE
  483. END;
  484. IF (ClassOf(l) = ClChar) & (ClassOf(r) = ClChar) THEN
  485. RETURN TRUE
  486. END;
  487. IF (ClassOf(l) = ClEnum) & SameType(l, r) THEN RETURN TRUE END;
  488. RETURN FALSE
  489. END OrdCheck;
  490. PROCEDURE InCheck (l, set: TypeIndex): BOOLEAN;
  491. VAR rs, b : TypeIndex;
  492. BEGIN
  493. IF (l = InvalidType) OR (set = InvalidType) THEN RETURN TRUE END;
  494. rs := Resolve(set);
  495. IF (rs = InvalidType) OR (tform[rs] # FSet) THEN RETURN FALSE END;
  496. b := tref[rs];
  497. IF SameType(l, b) THEN RETURN TRUE END;
  498. IF IsIntFamily(l) & IsIntFamily(b) THEN RETURN TRUE END;
  499. IF (ClassOf(l) = ClChar) & (ClassOf(b) = ClChar) THEN
  500. RETURN TRUE
  501. END;
  502. RETURN FALSE
  503. END InCheck;
  504. PROCEDURE RelCheck (l, r: TypeIndex; op: INTEGER): BOOLEAN;
  505. BEGIN
  506. IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
  507. IF op = OpIn THEN RETURN InCheck(l, r) END;
  508. IF (op = OpEq) OR (op = OpNeq1) OR (op = OpNeq2) THEN
  509. RETURN EqCheck(l, r)
  510. END;
  511. RETURN OrdCheck(l, r)
  512. END RelCheck;
  513. PROCEDURE SetElemCheck (first, elem: TypeIndex): BOOLEAN;
  514. BEGIN
  515. IF (first = InvalidType) OR (elem = InvalidType) THEN
  516. RETURN TRUE
  517. END;
  518. IF SameType(first, elem) THEN RETURN TRUE END;
  519. IF IsIntFamily(first) & IsIntFamily(elem) THEN RETURN TRUE END;
  520. RETURN FALSE
  521. END SetElemCheck;
  522. PROCEDURE SetFor (elem: TypeIndex): TypeIndex;
  523. VAR e : TypeIndex;
  524. BEGIN
  525. e := Resolve(elem);
  526. IF e = InvalidType THEN e := dInt END;
  527. RETURN NewSet(e)
  528. END SetFor;
  529. (* ---------------- procedures ---------------- *)
  530. PROCEDURE NewParamRec (typ: TypeIndex; isVar: BOOLEAN): INTEGER;
  531. BEGIN
  532. IF nParams >= MaxParams THEN RETURN -1 END;
  533. params[nParams].typ := typ;
  534. params[nParams].isVar := isVar;
  535. params[nParams].next := -1;
  536. INC(nParams);
  537. RETURN VAL(INTEGER, nParams - 1)
  538. END NewParamRec;
  539. PROCEDURE AppParam (p: INTEGER; fwd: BOOLEAN);
  540. (* Appends param record p to the current proc's forward/define list. *)
  541. VAR tail : INTEGER;
  542. BEGIN
  543. IF (curProc < 1) OR (curProc > VAL(INTEGER, nProcs)) THEN RETURN END;
  544. IF fwd THEN
  545. IF procs[curProc].fHead = -1 THEN procs[curProc].fHead := p
  546. ELSE
  547. tail := procs[curProc].fHead;
  548. WHILE params[tail].next # -1 DO tail := params[tail].next END;
  549. params[tail].next := p
  550. END;
  551. procs[curProc].fTail := p
  552. ELSE
  553. IF procs[curProc].dHead = -1 THEN procs[curProc].dHead := p
  554. ELSE
  555. tail := procs[curProc].dHead;
  556. WHILE params[tail].next # -1 DO tail := params[tail].next END;
  557. params[tail].next := p
  558. END;
  559. procs[curProc].dTail := p
  560. END
  561. END AppParam;
  562. PROCEDURE EnterProc (name: ARRAY OF CHAR): BOOLEAN;
  563. VAR idx : INTEGER;
  564. BEGIN
  565. IF DupInLevel(name) THEN RETURN FALSE END;
  566. IF nProcs >= MaxProcs THEN RETURN FALSE END;
  567. idx := RawEnter(name, KindProc);
  568. IF idx = -1 THEN RETURN FALSE END;
  569. INC(nProcs);
  570. syms[idx].pnum := VAL(INTEGER, nProcs);
  571. procs[nProcs].ret := InvalidType;
  572. procs[nProcs].fret := InvalidType;
  573. procs[nProcs].fwd := FALSE;
  574. procs[nProcs].everFwd := FALSE;
  575. procs[nProcs].fHead := -1;
  576. procs[nProcs].fTail := -1;
  577. procs[nProcs].dHead := -1;
  578. procs[nProcs].dTail := -1;
  579. curProc := VAL(INTEGER, nProcs);
  580. RETURN TRUE
  581. END EnterProc;
  582. PROCEDURE IsForward (name: ARRAY OF CHAR): BOOLEAN;
  583. VAR idx : INTEGER;
  584. BEGIN
  585. idx := Find(name);
  586. IF idx = -1 THEN RETURN FALSE END;
  587. IF syms[idx].kind # KindProc THEN RETURN FALSE END;
  588. IF syms[idx].pnum < 1 THEN RETURN FALSE END;
  589. RETURN procs[syms[idx].pnum].fwd
  590. END IsForward;
  591. PROCEDURE ReuseProc (name: ARRAY OF CHAR);
  592. VAR idx : INTEGER;
  593. BEGIN
  594. idx := Find(name);
  595. IF idx = -1 THEN RETURN END;
  596. curProc := syms[idx].pnum;
  597. IF (curProc >= 1) & (curProc <= VAL(INTEGER, nProcs)) THEN
  598. procs[curProc].fwd := FALSE;
  599. procs[curProc].dHead := -1;
  600. procs[curProc].dTail := -1
  601. END
  602. END ReuseProc;
  603. PROCEDURE OpenProcScope;
  604. BEGIN
  605. IF pdep < MaxPDepth THEN INC(pdep) END;
  606. PushScope;
  607. locCnt[pdep] := 0;
  608. parCnt[pdep] := 0;
  609. procSt[pdep] := curProc;
  610. retSt[pdep] := InvalidType
  611. END OpenProcScope;
  612. PROCEDURE CloseProc;
  613. BEGIN
  614. PopScope;
  615. IF pdep > 0 THEN DEC(pdep) END;
  616. curProc := procSt[pdep]
  617. END CloseProc;
  618. PROCEDURE EnterParam (name: ARRAY OF CHAR; isVar: BOOLEAN;
  619. t: TypeIndex): BOOLEAN;
  620. VAR idx, pi : INTEGER;
  621. BEGIN
  622. IF DupInLevel(name) THEN RETURN FALSE END;
  623. IF isVar THEN idx := RawEnter(name, KindVarPar)
  624. ELSE idx := RawEnter(name, KindParam)
  625. END;
  626. IF idx = -1 THEN RETURN FALSE END;
  627. SetSymType(name, t);
  628. syms[idx].slot := 3 + VAL(INTEGER, parCnt[pdep]);
  629. INC(parCnt[pdep]);
  630. pi := NewParamRec(t, isVar);
  631. IF pi # -1 THEN AppParam(pi, FALSE) END;
  632. RETURN TRUE
  633. END EnterParam;
  634. PROCEDURE SetProcRet (t: TypeIndex): BOOLEAN;
  635. BEGIN
  636. IF (curProc < 1) OR (curProc > VAL(INTEGER, nProcs)) THEN
  637. RETURN TRUE
  638. END;
  639. IF procs[curProc].everFwd
  640. & ~SameType(t, procs[curProc].fret) THEN
  641. RETURN FALSE
  642. END;
  643. procs[curProc].ret := t;
  644. IF pdep > 0 THEN retSt[pdep] := t END;
  645. RETURN TRUE
  646. END SetProcRet;
  647. PROCEDURE VerifyProc (): BOOLEAN;
  648. VAR fi, di : INTEGER;
  649. BEGIN
  650. IF (curProc < 1) OR (curProc > VAL(INTEGER, nProcs)) THEN
  651. RETURN TRUE
  652. END;
  653. IF ~procs[curProc].everFwd THEN RETURN TRUE END;
  654. fi := procs[curProc].fHead; di := procs[curProc].dHead;
  655. WHILE (fi # -1) & (di # -1) DO
  656. IF (params[fi].isVar # params[di].isVar)
  657. OR ~SameType(params[fi].typ, params[di].typ) THEN
  658. RETURN FALSE
  659. END;
  660. fi := params[fi].next; di := params[di].next
  661. END;
  662. RETURN (fi = -1) & (di = -1)
  663. END VerifyProc;
  664. PROCEDURE SetForward;
  665. BEGIN
  666. IF (curProc < 1) OR (curProc > VAL(INTEGER, nProcs)) THEN RETURN END;
  667. procs[curProc].fwd := TRUE;
  668. procs[curProc].everFwd := TRUE;
  669. procs[curProc].fret := procs[curProc].ret;
  670. procs[curProc].fHead := procs[curProc].dHead;
  671. procs[curProc].fTail := procs[curProc].dTail;
  672. procs[curProc].dHead := -1;
  673. procs[curProc].dTail := -1
  674. END SetForward;
  675. PROCEDURE AnyForward (): BOOLEAN;
  676. VAR i : CARDINAL;
  677. BEGIN
  678. i := 1;
  679. WHILE i <= nProcs DO
  680. IF procs[i].fwd THEN RETURN TRUE END;
  681. INC(i)
  682. END;
  683. RETURN FALSE
  684. END AnyForward;
  685. PROCEDURE ProcNum (name: ARRAY OF CHAR): INTEGER;
  686. VAR idx : INTEGER;
  687. BEGIN
  688. idx := Find(name);
  689. IF idx = -1 THEN RETURN -1 END;
  690. IF syms[idx].kind # KindProc THEN RETURN -1 END;
  691. RETURN syms[idx].pnum
  692. END ProcNum;
  693. PROCEDURE SigHead (name: ARRAY OF CHAR): INTEGER;
  694. (* Param list head: define list if present, else forward list. *)
  695. VAR n : INTEGER;
  696. BEGIN
  697. n := ProcNum(name);
  698. IF n < 1 THEN RETURN -1 END;
  699. IF procs[n].dHead # -1 THEN RETURN procs[n].dHead END;
  700. RETURN procs[n].fHead
  701. END SigHead;
  702. PROCEDURE ProcRet (name: ARRAY OF CHAR): TypeIndex;
  703. VAR n : INTEGER;
  704. BEGIN
  705. n := ProcNum(name);
  706. IF n < 1 THEN RETURN InvalidType END;
  707. RETURN procs[n].ret
  708. END ProcRet;
  709. PROCEDURE ProcNPar (name: ARRAY OF CHAR): CARDINAL;
  710. VAR h : INTEGER;
  711. c : CARDINAL;
  712. BEGIN
  713. h := SigHead(name); c := 0;
  714. WHILE h # -1 DO INC(c); h := params[h].next END;
  715. RETURN c
  716. END ProcNPar;
  717. PROCEDURE ParamType (name: ARRAY OF CHAR; i: CARDINAL): TypeIndex;
  718. VAR h : INTEGER;
  719. BEGIN
  720. h := SigHead(name);
  721. WHILE (h # -1) & (i > 0) DO h := params[h].next; DEC(i) END;
  722. IF h = -1 THEN RETURN InvalidType END;
  723. RETURN params[h].typ
  724. END ParamType;
  725. PROCEDURE ParamIsVar (name: ARRAY OF CHAR; i: CARDINAL): BOOLEAN;
  726. VAR h : INTEGER;
  727. BEGIN
  728. h := SigHead(name);
  729. WHILE (h # -1) & (i > 0) DO h := params[h].next; DEC(i) END;
  730. IF h = -1 THEN RETURN FALSE END;
  731. RETURN params[h].isVar
  732. END ParamIsVar;
  733. PROCEDURE SymSlot (name: ARRAY OF CHAR): INTEGER;
  734. VAR idx : INTEGER;
  735. BEGIN
  736. idx := Find(name);
  737. IF idx = -1 THEN RETURN NoSlot END;
  738. RETURN syms[idx].slot
  739. END SymSlot;
  740. PROCEDURE SymDepth (name: ARRAY OF CHAR): INTEGER;
  741. VAR idx : INTEGER;
  742. BEGIN
  743. idx := Find(name);
  744. IF idx = -1 THEN RETURN 0 END;
  745. RETURN VAL(INTEGER, syms[idx].pdep)
  746. END SymDepth;
  747. PROCEDURE CurDepth (): INTEGER;
  748. BEGIN
  749. RETURN VAL(INTEGER, pdep)
  750. END CurDepth;
  751. PROCEDURE CurProc (): INTEGER;
  752. BEGIN
  753. RETURN curProc
  754. END CurProc;
  755. PROCEDURE CurNPar (): CARDINAL;
  756. BEGIN
  757. RETURN parCnt[pdep]
  758. END CurNPar;
  759. PROCEDURE CurRet (): TypeIndex;
  760. BEGIN
  761. IF pdep = 0 THEN RETURN InvalidType END;
  762. RETURN retSt[pdep]
  763. END CurRet;
  764. PROCEDURE InProc (): BOOLEAN;
  765. BEGIN
  766. RETURN pdep > 0
  767. END InProc;
  768. PROCEDURE InFunction (): BOOLEAN;
  769. BEGIN
  770. RETURN (pdep > 0) & (retSt[pdep] # InvalidType)
  771. END InFunction;
  772. PROCEDURE ProcNLocals (): CARDINAL;
  773. BEGIN
  774. IF pdep = 0 THEN RETURN 0 END;
  775. RETURN locCnt[pdep]
  776. END ProcNLocals;
  777. (* ---------------- init ---------------- *)
  778. PROCEDURE Predef (name: ARRAY OF CHAR; kind: INTEGER; t: TypeIndex);
  779. BEGIN
  780. IF Enter(name, kind) THEN SetSymType(name, t) END
  781. END Predef;
  782. PROCEDURE Init;
  783. BEGIN
  784. nSyms := 0; curLev := 0; mtop := 0;
  785. nPend := 0; nPendF := 0;
  786. nTypes := 0; nFields := 0;
  787. nProcs := 0; nParams := 0;
  788. pdep := 0; curProc := 0;
  789. procSt[0] := 0; locCnt[0] := 0; parCnt[0] := 0;
  790. retSt[0] := InvalidType;
  791. dInt := NewDesc(FInt, InvalidType);
  792. dCard := NewDesc(FInt, InvalidType);
  793. dReal := NewDesc(FReal, InvalidType);
  794. dChar := NewDesc(FChar, InvalidType);
  795. dBool := NewDesc(FBool, InvalidType);
  796. Predef("INTEGER", KindPredef, dInt);
  797. Predef("CARDINAL", KindPredef, dCard);
  798. Predef("SHORTINT", KindPredef, dInt);
  799. Predef("LONGINT", KindPredef, dInt);
  800. Predef("REAL", KindPredef, dReal);
  801. Predef("LONGREAL", KindPredef, dReal);
  802. Predef("CHAR", KindPredef, dChar);
  803. Predef("BOOLEAN", KindPredef, dBool);
  804. Predef("TRUE", KindConst, dBool);
  805. Predef("FALSE", KindConst, dBool);
  806. Predef("NIL", KindConst, InvalidType)
  807. END Init;
  808. (* ---------------- listing ---------------- *)
  809. PROCEDURE WriteKind (kind: INTEGER);
  810. BEGIN
  811. CASE kind OF
  812. KindConst : FileIO.WriteString(FileIO.StdOut, "CONST")
  813. | KindType : FileIO.WriteString(FileIO.StdOut, "TYPE")
  814. | KindVar : FileIO.WriteString(FileIO.StdOut, "VAR")
  815. | KindImport : FileIO.WriteString(FileIO.StdOut, "IMPORT")
  816. | KindModule : FileIO.WriteString(FileIO.StdOut, "MODULE")
  817. | KindPredef : FileIO.WriteString(FileIO.StdOut, "PREDEF")
  818. | KindField : FileIO.WriteString(FileIO.StdOut, "FIELD")
  819. ELSE FileIO.WriteString(FileIO.StdOut, "???")
  820. END
  821. END WriteKind;
  822. PROCEDURE PrintTable;
  823. VAR i : CARDINAL;
  824. BEGIN
  825. FileIO.WriteLn(FileIO.StdOut);
  826. FileIO.WriteString(FileIO.StdOut, "--- Symbol table ---");
  827. FileIO.WriteLn(FileIO.StdOut);
  828. i := 0;
  829. WHILE i < nSyms DO
  830. FileIO.WriteString(FileIO.StdOut, " ");
  831. FileIO.WriteString(FileIO.StdOut, syms[i].name);
  832. FileIO.WriteString(FileIO.StdOut, " : ");
  833. WriteKind(syms[i].kind);
  834. FileIO.WriteString(FileIO.StdOut, " #");
  835. FileIO.WriteInt(FileIO.StdOut, syms[i].typ, 1);
  836. FileIO.WriteLn(FileIO.StdOut);
  837. INC(i)
  838. END
  839. END PrintTable;
  840. BEGIN
  841. Init
  842. END SymTab.