| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- DEFINITION MODULE SymTab;
- (* Symbol table with static type checking for the M2c compiler
- (Modula-2 program modules, procedures arrive in a later phase).
- - flat scopes with levels: globals at level 0, WITH statement
- bodies push the record's fields as an inner scope (shadowing
- allowed, duplicates within one level rejected)
- - every symbol carries a type descriptor index (InvalidType if
- unknown, e.g. imported names); unknown types suppress follow-on
- errors to avoid cascades
- - type descriptors: aliases (one per TYPE declaration, so
- self-references such as POINTER TO Person resolve), subranges,
- enumerations, arrays, records (with field lists), sets,
- pointers, predefined types, string literals
- - INTEGER, CARDINAL and subranges thereof form one lenient
- "integer family"; mixed INTEGER/REAL arithmetic is rejected *)
- CONST
- MaxSyms = 256;
- InvalidType = -1;
- (* symbol kinds *)
- KindConst = 0;
- KindType = 1;
- KindVar = 2;
- KindImport = 3;
- KindModule = 4;
- KindPredef = 5;
- KindField = 6;
- KindProc = 7;
- KindParam = 8;
- KindVarPar = 9;
- (* type classes returned by ClassOf *)
- ClInvalid = 0;
- ClInt = 1;
- ClReal = 2;
- ClChar = 3;
- ClBool = 4;
- ClEnum = 5;
- ClArray = 6;
- ClRecord = 7;
- ClSet = 8;
- ClPtr = 9;
- ClStr = 10;
- (* operator codes for RelCheck *)
- OpEq = 0; OpNeq1 = 1; OpNeq2 = 2;
- OpLt = 3; OpLe = 4; OpGt = 5; OpGe = 6;
- OpIn = 7;
- (* operator codes for AddOp / MulOp *)
- OpAdd = 0; OpSub = 1; OpOr = 2;
- OpTimes = 0; OpSlash = 1; OpDiv = 2; OpMod = 3; OpAnd = 4;
- TYPE
- Name = ARRAY [0 .. 63] OF CHAR;
- TypeIndex = INTEGER;
- (* ---------------- symbols and scopes ---------------- *)
- PROCEDURE Init;
- (* Clears the table and enters predefined identifiers
- (INTEGER, CARDINAL, SHORTINT, LONGINT, REAL, LONGREAL, CHAR,
- BOOLEAN, TRUE, FALSE, NIL). *)
- PROCEDURE Enter (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
- (* Enters name at the current scope level (type InvalidType).
- Returns FALSE on duplicate within the same level. *)
- PROCEDURE EnterPending (name: ARRAY OF CHAR; kind: INTEGER): BOOLEAN;
- (* Like Enter, but remembers the entry for a later FixPending call
- (used for VAR identifier lists whose type is parsed afterwards).
- Returns FALSE on duplicate (entry not recorded). *)
- PROCEDURE FixPending (t: TypeIndex);
- (* Assigns type t to all pending entries, clears the buffer. *)
- PROCEDURE PendCount (): CARDINAL;
- (* Number of entries currently waiting for FixPending. *)
- PROCEDURE PendName (i: CARDINAL; VAR n: Name);
- (* Name of the i-th pending entry (empty string if out of range).
- Used by the backend to emit storage for VAR lists whose
- type is parsed after the identifiers. *)
- PROCEDURE FieldPending (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
- (* Records a field name for record descriptor rec (type fixed later
- with FixPendingF). Returns FALSE on duplicate field. *)
- PROCEDURE FixPendingF (rec: TypeIndex; t: TypeIndex);
- (* Assigns type t to pending fields owned by rec. *)
- PROCEDURE Lookup (name: ARRAY OF CHAR): BOOLEAN;
- (* TRUE if name is visible (innermost scope wins). *)
- PROCEDURE SymType (name: ARRAY OF CHAR): TypeIndex;
- (* Type of innermost visible entry, InvalidType if absent. *)
- PROCEDURE SetSymType (name: ARRAY OF CHAR; t: TypeIndex);
- (* Sets type of innermost visible entry. *)
- PROCEDURE SymKind (name: ARRAY OF CHAR): INTEGER;
- (* Kind of innermost visible entry, -1 if absent. *)
- PROCEDURE Equal (a, b: ARRAY OF CHAR): BOOLEAN;
- PROCEDURE PushScope;
- PROCEDURE PopScope;
- (* WITH statement support: PushRecord pushes a record's fields. *)
- PROCEDURE SymLev (name: ARRAY OF CHAR): INTEGER;
- (* Scope level at declaration (-1 if absent). *)
- (* ---------------- local modules (single-file, step 6) *)
- (* Local MODULEs live at program level (no nesting, no bodies).
- EXPORT names are resolved at END (before PopScope) into an export
- table keyed by (module, name); MGen stores module vars qualified
- ("M.x") so FindVar has no collisions. *)
- PROCEDURE EnterModule (name: ARRAY OF CHAR): BOOLEAN;
- (* Enters KindModule + pushes body scope + module context.
- FALSE on duplicate. *)
- PROCEDURE ModuleAddExp (name: ARRAY OF CHAR): BOOLEAN;
- (* Records an export name for the current module (checked for
- duplicates in the export list). FALSE if not in a module. *)
- PROCEDURE ExitModule(): BOOLEAN;
- (* Resolves exports against the body scope, pops scope + context.
- TRUE if every EXPORT name was declared (FALSE = ghost export). *)
- PROCEDURE InModule (): BOOLEAN;
- (* TRUE inside a local MODULE body (including its procedures). *)
- PROCEDURE CurModName (VAR m: Name);
- (* Top module name, empty if none. *)
- PROCEDURE ExpKind (mod, exp: ARRAY OF CHAR): INTEGER;
- (* Exported kind, -1 if absent. *)
- PROCEDURE ExpType (mod, exp: ARRAY OF CHAR): TypeIndex;
- (* Exported type (InvalidType if absent / not a type-ish export). *)
- PROCEDURE ExpProc (mod, exp: ARRAY OF CHAR): INTEGER;
- (* Exported proc number, -1 if absent / not a procedure. *)
- PROCEDURE ExpQual (mod, exp: ARRAY OF CHAR; VAR qual: Name);
- (* Qualified MGen name ("M.x"), empty if absent / not a variable
- or constant. *)
- PROCEDURE SelfKind (mod, exp: ARRAY OF CHAR): INTEGER;
- (* Kind of exp as M.exp from inside M itself (live body scope,
- since exports resolve only at END). -1 if not applicable. *)
- PROCEDURE SelfQual (exp: ARRAY OF CHAR; VAR qual: Name);
- (* CurMod.exp for a self reference (call only when SelfKind # -1). *)
- (* ---------------- separate compilation units (step 11) *)
- (* DEFINITION modules publish every declared name into the export
- tables and record an in-memory interface (side table: kind, type,
- proc number); the body scope is popped. IMPLEMENTATION modules
- re-enter that interface into a fresh scope (no new MGen slots),
- match procedure headings via the forward machinery (231 on
- mismatch), and must supply every body (231). All units share one
- image: globals/procs accumulate, library inits run first.
- FROM-imported names materialize as real alias symbols (procs
- share the original number, so call checking is unchanged);
- VAR/CONST aliases map to the definition's global via GlobAlias. *)
- PROCEDURE ExitDefinition (): BOOLEAN;
- (* Publishes the current module scope, records the interface,
- pops scope + context. FALSE when a phase cap breaks (too many
- definitions, names, or exports). *)
- PROCEDURE OpenImplementation (name: ARRAY OF CHAR): BOOLEAN;
- (* Re-enters a recorded interface for its implementation body.
- FALSE when no definition is known (stale state untouched). *)
- PROCEDURE CloseImplementation (): BOOLEAN;
- (* 231-check (every definition proc got a body), pops scope +
- context. State is popped even on FALSE. *)
- PROCEDURE IsDefMod (name: ARRAY OF CHAR): BOOLEAN;
- (* TRUE for a module with a recorded definition interface. *)
- PROCEDURE ImpBind (mod, exp: ARRAY OF CHAR): BOOLEAN;
- (* Records a FROM-import alias target ("mod.exp"). FALSE when the
- export is unknown or the alias table is full. *)
- PROCEDURE ImpUnbind (name: ARRAY OF CHAR);
- (* Drops an alias binding (failed materialization cleanup). *)
- PROCEDURE EnterImpProc (name: ARRAY OF CHAR; pnum: INTEGER): BOOLEAN;
- (* Enters an imported procedure alias sharing pnum (signature and
- codegen resolve through the shared procs[] entry; the current
- procedure context is untouched). FALSE on duplicate or full. *)
- PROCEDURE GlobAlias (name: ARRAY OF CHAR; VAR q: Name): BOOLEAN;
- (* TRUE + qualified definition global ("M.x") for a VAR/CONST
- FROM-import alias (MGen slot lookup hook). *)
- PROCEDURE NoteProgram (): BOOLEAN;
- (* Claims the single program unit of the session (FALSE when one
- already exists). *)
- PROCEDURE PushRecord (t: TypeIndex): BOOLEAN;
- (* Pushes a scope containing t's fields (as KindField). FALSE if t
- is not a record type (or invalid). Caller must PopScope after. *)
- PROCEDURE PrintTable;
- (* ---------------- type descriptors ---------------- *)
- PROCEDURE NewAlias (): TypeIndex;
- PROCEDURE NewSub (base: TypeIndex): TypeIndex;
- PROCEDURE NewSubB (base: TypeIndex; lo, hi: INTEGER): TypeIndex;
- PROCEDURE NewEnum (): TypeIndex;
- PROCEDURE EnumAdd (t: TypeIndex);
- PROCEDURE NewArray (elem: TypeIndex): TypeIndex;
- PROCEDURE NewArrayB (elem: TypeIndex; lo, hi: INTEGER): TypeIndex;
- PROCEDURE NewOpen (elem: TypeIndex): TypeIndex;
- PROCEDURE IsOpen (t: TypeIndex): BOOLEAN;
- PROCEDURE NewRecord (): TypeIndex;
- PROCEDURE NewSet (base: TypeIndex): TypeIndex;
- PROCEDURE NewPtr (base: TypeIndex): TypeIndex;
- PROCEDURE NewStr (): TypeIndex;
- (* Fresh descriptors; base/elem may be InvalidType. InvalidType is
- returned when the table is full. *)
- PROCEDURE SetTarget (t, base: TypeIndex);
- (* Sets an alias target (TYPE declaration completion). *)
- PROCEDURE IntType (): TypeIndex;
- PROCEDURE RealType (): TypeIndex;
- PROCEDURE CharType (): TypeIndex;
- PROCEDURE BoolType (): TypeIndex;
- PROCEDURE ClassOf (t: TypeIndex): INTEGER;
- (* Resolves aliases; InvalidType maps to ClInvalid. *)
- PROCEDURE IsIntFamily (t: TypeIndex): BOOLEAN;
- (* INTEGER, CARDINAL or subrange thereof (Invalid suppresses). *)
- PROCEDURE SameType (a, b: TypeIndex): BOOLEAN;
- (* Same resolved descriptor (Invalid suppresses). *)
- PROCEDURE FieldExists (rec: TypeIndex; name: ARRAY OF CHAR): BOOLEAN;
- PROCEDURE FieldType (rec: TypeIndex; name: ARRAY OF CHAR): TypeIndex;
- PROCEDURE FieldOffset (rec: TypeIndex; name: ARRAY OF CHAR): INTEGER;
- PROCEDURE ArrayElem (t: TypeIndex): TypeIndex;
- PROCEDURE ArrayLo (t: TypeIndex): INTEGER;
- PROCEDURE ArrayHi (t: TypeIndex): INTEGER;
- PROCEDURE ArrayLen (t: TypeIndex): CARDINAL;
- PROCEDURE TypeSlots (t: TypeIndex): CARDINAL;
- PROCEDURE TypeLo (t: TypeIndex): INTEGER;
- PROCEDURE TypeHi (t: TypeIndex): INTEGER;
- PROCEDURE TypeLen (t: TypeIndex): CARDINAL;
- PROCEDURE PtrBase (t: TypeIndex): TypeIndex;
- (* ---------------- predicates used by grammar checks ---------------- *)
- (* All return TRUE if either operand is InvalidType (no cascades). *)
- PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
- (* Assignment compatibility (210). *)
- PROCEDURE ArithCheck (l, r: TypeIndex; divmod: BOOLEAN;
- VAR res: TypeIndex): BOOLEAN;
- (* + - * / (divmod FALSE) or DIV MOD (TRUE); res is result type (211). *)
- PROCEDURE UnaryCheck (t: TypeIndex; VAR res: TypeIndex): BOOLEAN;
- (* Unary + - (part of 211). *)
- PROCEDURE BoolCheck (t: TypeIndex): BOOLEAN;
- (* BOOLEAN required: NOT/AND/OR operands (212), conditions (214). *)
- PROCEDURE RelCheck (l, r: TypeIndex; op: INTEGER): BOOLEAN;
- (* = # <> < <= > >= IN (213/222 chosen by caller via op). *)
- PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
- (* = # compatibility, also reused for CASE label matching. *)
- PROCEDURE InCheck (l, set: TypeIndex): BOOLEAN;
- PROCEDURE SetElemCheck (first, elem: TypeIndex): BOOLEAN;
- PROCEDURE SetFor (elem: TypeIndex): TypeIndex;
- (* Fresh SET OF elem descriptor for set literals. *)
- PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
- (* ---------------- procedures ---------------- *)
- (* Step 3: nested procedures with value and VAR parameters, forward
- declarations, static scoping. Proc numbers start at 1 (0 is the
- module body); at most MaxProcs user procedures. *)
- PROCEDURE EnterProc (name: ARRAY OF CHAR): BOOLEAN;
- (* Enters a procedure name (KindProc, InvalidType) and assigns the
- next proc number. FALSE on duplicate or table full. Sets the
- current-proc context for following EnterParam/FwdParam calls. *)
- PROCEDURE AllocInitNum (): INTEGER;
- (* Reserves the next proc number for a module BEGIN init body
- (step 10). Init bodies share the procedure number pool so an
- init emitted before a later procedure's body can never steal
- that procedure's number. The slot has no symbol entry and no
- signature; -1 when the pool is full. *)
- PROCEDURE IsForward (name: ARRAY OF CHAR): BOOLEAN;
- (* TRUE if the visible entry is a forward-declared procedure
- whose body is still pending. *)
- PROCEDURE ReuseProc (name: ARRAY OF CHAR);
- (* Starts the full definition of a forward-declared procedure:
- keeps its number, switches signature recording to define mode. *)
- PROCEDURE OpenProcScope;
- (* Pushes a scope for a procedure body, enters proc depth + 1,
- resets slot counters, pushes return-type context. *)
- PROCEDURE CloseProc;
- (* Pops a procedure body scope, restores the enclosing context. *)
- PROCEDURE EnterParam (name: ARRAY OF CHAR; isVar: BOOLEAN;
- t: TypeIndex): BOOLEAN;
- (* Enters a value (KindParam) or VAR (KindVarPar) parameter in the
- current procedure scope with its frame slot, appends it to the
- define signature. FALSE on duplicate. *)
- PROCEDURE SetProcRet (t: TypeIndex): BOOLEAN;
- (* Sets the return type (InvalidType = proper procedure). TRUE
- unless it mismatches a forward heading (error 231). *)
- PROCEDURE VerifyProc (): BOOLEAN;
- (* TRUE unless the define signature mismatches the forward
- heading (error 231). *)
- PROCEDURE SetForward;
- (* Marks the current procedure forward-declared (body pending). *)
- PROCEDURE AnyForward (): BOOLEAN;
- (* TRUE if some procedure body is still missing (error 231). *)
- PROCEDURE ProcNum (name: ARRAY OF CHAR): INTEGER;
- (* Proc number, or -1 if absent / not a procedure. *)
- PROCEDURE ProcRet (name: ARRAY OF CHAR): TypeIndex;
- (* Return type (InvalidType = proper procedure or unknown). *)
- PROCEDURE ProcNPar (name: ARRAY OF CHAR): CARDINAL;
- (* Arity from the define signature, else the forward one. *)
- PROCEDURE ParamType (name: ARRAY OF CHAR; i: CARDINAL): TypeIndex;
- PROCEDURE ParamIsVar (name: ARRAY OF CHAR; i: CARDINAL): BOOLEAN;
- (* i-th formal parameter (0-based), InvalidType/FALSE if absent. *)
- PROCEDURE ProcValid (num: INTEGER): BOOLEAN;
- (* TRUE if num is a declared procedure number (survives scope pops,
- so module procs stay callable after ExitModule). *)
- PROCEDURE ProcNParByNum (num: INTEGER): CARDINAL;
- PROCEDURE ParamTypeByNum (num: INTEGER; i: CARDINAL): TypeIndex;
- PROCEDURE ParamIsVarByNum (num: INTEGER; i: CARDINAL): BOOLEAN;
- PROCEDURE ProcRetByNum (num: INTEGER): TypeIndex;
- (* Same signature queries as above, keyed by procedure number. *)
- PROCEDURE SymSlot (name: ARRAY OF CHAR): INTEGER;
- (* Frame slot (params >= 3, locals negative). Only meaningful
- for variables at proc depth > 0. *)
- PROCEDURE SymDepth (name: ARRAY OF CHAR): INTEGER;
- (* Proc depth at declaration (0 = module level). *)
- PROCEDURE CurDepth (): INTEGER;
- (* Current proc depth (0 = module body). *)
- PROCEDURE CurProc (): INTEGER;
- (* Current proc number (0 = module body). *)
- PROCEDURE CurNPar (): CARDINAL;
- (* Arity of the current procedure (0 outside). *)
- PROCEDURE CurRet (): TypeIndex;
- (* Current return type (InvalidType = proper or outside). *)
- PROCEDURE InProc (): BOOLEAN;
- (* TRUE inside a procedure body. *)
- PROCEDURE InFunction (): BOOLEAN;
- (* TRUE inside a function (non-InvalidType return) body. *)
- PROCEDURE ProcNLocals (): CARDINAL;
- (* Local slot count of the current procedure (0 outside). *)
- END SymTab.
|