using System; using System.Text; using System.Reflection.Emit; /* 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 Kind { Const, Global, Field, Arg, Local, Type, Meth, Prog } public Kind 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 (Kind kind, string name, Struct type) { this.kind = kind; this.name = name; this.type = type; } public override string ToString () { Symbol cur; StringBuilder sb = new StringBuilder(); sb.AppendFormat("{0}: {1}, {2}", name, kind, type); switch (kind) { case Kind.Const: sb.AppendFormat(" ={0}", val); break; case Kind.Arg: case Kind.Local: sb.AppendFormat(", {0}", adr); break; case Kind.Meth: sb.AppendFormat(", {0}, {1}", nArgs, nLocs); cur = locals; int i = 0; while (cur != null) { sb.AppendFormat("{0}-----{3}[{1}]={2}", Environment.NewLine, i, cur, (cur.kind == Kind.Arg) ? "arg" : "loc"); cur = cur.next; ++i; } if (nArgs + nLocs > 0) { sb.AppendFormat("{0}", Environment.NewLine); } break; case Kind.Prog: sb.AppendFormat("{0}Declarations in program:{0}", Environment.NewLine); cur = locals; while (cur != null) { sb.AppendFormat("{1}{0}", Environment.NewLine, cur.ToString()); cur = cur.next; } sb.AppendFormat("End of program.{0}", Environment.NewLine); break; } return sb.ToString(); } }