public class Tab
public static readonly Struct noType = new Struct(Struct.Kinds.None), intType = new Struct(Struct.Kinds.Int), charType = new Struct(Struct.Kinds.Char), nullType = new Struct(Struct.Kinds.Class); /* Symbol to indicate that an error has occurred in the symbol table */ public static readonly Symbol noSym = new Symbol(Symbol.Kinds.Const, "noSymbol", noType); public static Symbol chrSym, ordSym, lenSym; internal static Scope topScope; // current scope |
/* Sets up the "universe" (= predefined names). */ public static void Init () { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } public static void OpenScope () { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } public static void CloseScope () { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } public static Symbol Insert (Symbol.Kinds kind, string name, Struct type) { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } /* Retrieves the Symbol with name from the innermost scope. */ public static Symbol Find (string name) { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } /* Retrieves the field name from the fields of type. */ public static Symbol FindField (string name, Struct type) { /*---------------------------------*/ /*----- insert your code here -----*/ /*---------------------------------*/ } } |
public class Scope { public Scope outer; // reference to enclosing scope public Symbol locals; // symbol table of this scope public int nArgs; // # of arguments in this scope (for address asignment) public int nLocs; // # of local variables in this scope (for address asignment) } |
/* Z# Symbol Table Nodes: * Every named object in a program is stored in an Symbol node. * Every scope has a list of Symbols declared within it. */ public class Symbol { public enum Kinds { Const, Global, Field, Arg, Local, Type, Meth, Prog } public Kinds kind; public string name; public Struct type; public Symbol next; // next Symbol node in this scope public int val; // Const: value; public int adr; // Field, Arg, Local: order of declaration in scope public int nArgs; // Meth: # of arguments public int nLocs; // Meth: # of local variables public Symbol locals; // Meth: arguments, then local variables; Prog: symbol table of program /* these fields are necessary for the building the assembly with System.Reflection.Emit */ internal MethodBuilder meth; // Method: builder for metadata and CIL internal FieldBuilder fld; // Field: builder for metadata internal ConstructorBuilder ctor; // Type: builder for metadata and CIL public Symbol (Kinds kind, string name, Struct type) { this.kind = kind; this.name = name; this.type = type; } public override bool Equals (object o) { if (this == o) return true; // same object Symbol sym = o as Symbol; if (sym == null) return false; return Equals(sym); } public bool Equals (Symbol sym) { if (kind != sym.kind || name != sym.name || !type.Equals(sym.type)) return false; switch (kind) { case Kinds.Const: return val == sym.val; case Kinds.Arg: case Kinds.Local: return adr == sym.adr; case Kinds.Meth: return nArgs == sym.nArgs && nLocs == sym.nLocs && EqualsCompleteList(locals, sym.locals); } return true; } public override string ToString () { StringBuilder sb = new StringBuilder(); sb.AppendFormat("{0}: {1}, {2}", name, kind, type); switch (kind) { case Kinds.Const: sb.AppendFormat(" ={0}", val); break; case Kinds.Arg: case Kinds.Local: sb.AppendFormat(", {0}", adr); break; case Kinds.Meth: sb.AppendFormat(", {0}, {1}", nArgs, nLocs); Symbol sym; int i; for (sym = locals, i = 0; sym != null; sym = sym.next, i++) sb.AppendFormat("{0}-----{3}[{1}]={2}", Environment.NewLine, i, sym, (sym.kind == Symbol.Kinds.Arg) ? "arg" : "loc"); if (nArgs + nLocs > 0) sb.AppendFormat("{0}", Environment.NewLine); break; } return sb.ToString(); } /* Compare complete Symbol node lists. */ public static bool EqualsCompleteList (Symbol sym1, Symbol sym2) { if (sym1 == sym2) return true; // same object while (sym1 != null && sym1.Equals(sym2)) { sym1 = sym1.next; sym2 = sym2.next; } if (sym1 != null || sym2 != null) return false; return true; } } |
/* Z# Type Structures: * A type structure stores the type attributes of a declared type. */ public class Struct { public enum Kinds { None, Int, Char, Arr, Class } public Kinds kind; // None, Int, Char, Arr, Class public Struct elemType; // Arr: type of array elements public Symbol fields; // Class: reference to list of local variables /* this field is necessary for the building the assembly with System.Reflection.Emit */ internal Type sysType; // CLR runtime type object public Struct (Kinds kind) : this(kind, null) {} public Struct (Kinds kind, Struct elemType) { this.kind = kind; // set CLR type of Struct instance switch (kind) { case Struct.Kinds.None: sysType = typeof(void); break; case Struct.Kinds.Int: sysType = typeof(int); break; case Struct.Kinds.Char: sysType = typeof(char); break; case Struct.Kinds.Arr: sysType = Array.CreateInstance(elemType.sysType, 0).GetType(); this.elemType = elemType; break; case Struct.Kinds.Class: // do nothing here, type must first be defined // sysType is set in Code.CreateMetadata before first use break; } this.elemType = elemType; } public override bool Equals (object o) { if (this == o) return true; // same object Struct s = o as Struct; if (s == null) return false; return Equals(s); } public bool Equals (Struct other) { if (kind == Kinds.Arr) return other.kind == Kinds.Arr && elemType.Equals(other.elemType); return this == other; // must be same type node } public bool IsRefType () { return kind == Kinds.Class || kind == Kinds.Arr; } public bool CompatibleWith (Struct other) { return this.Equals(other) || this == Tab.nullType && other.IsRefType() || other == Tab.nullType && this.IsRefType(); } public bool AssignableTo (Struct dest) { return this.Equals(dest) || this == Tab.nullType && dest.IsRefType() || // for predefined function len(Array of noType) kind == Kinds.Arr && dest.kind == Kinds.Arr && dest.elemType == Tab.noType; } public override string ToString () { StringBuilder sb = new StringBuilder(); switch (kind) { case Struct.Kinds.Int: sb.Append("int"); break; case Struct.Kinds.Char: sb.Append("char"); break; case Struct.Kinds.Class: sb.AppendFormat("#{0}", GetHashCode()); Symbol field; int i; for (field = fields, i = 0; field != null; field = field.next, i++) sb.AppendFormat("{0}-----field[{1}]={2}", Environment.NewLine, i, field); sb.AppendFormat("{0}", Environment.NewLine); break; case Struct.Kinds.Arr: sb.AppendFormat("{0}[]", elemType); break; } return sb.ToString(); } } |