using System; using System.Text; /// Z# Type Structures: /// A type structure stores the type attributes of a declared type. public class Struct { public enum Kind { None, Int, Char, Arr, Class } public Kind 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 (Kind kind) : this(kind, null) { } public Struct (Kind kind, Struct elemType) { this.kind = kind; // set CLR type of Struct instance switch (kind) { case Kind.None: sysType = typeof(void); break; case Kind.Int: sysType = typeof(int); break; case Kind.Char: sysType = typeof(char); break; case Kind.Arr: sysType = Array.CreateInstance(elemType.sysType, 0).GetType(); break; case Kind.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) { // same object return true; } Struct s = o as Struct; return s != null && kind == Kind.Arr && s.kind == Kind.Arr && elemType.Equals(s.elemType); } public override int GetHashCode() { return (int) kind; } public bool IsRefType () { return kind == Kind.Class || kind == Kind.Arr; } public bool CompatibleWith (Struct other) { return Equals(other) || this == Tab.nullType && other.IsRefType() || other == Tab.nullType && this.IsRefType(); } public bool AssignableTo (Struct dest) { return Equals(dest) || this == Tab.nullType && dest.IsRefType() || // for predefined function len(Array of noType) kind == Kind.Arr && dest.kind == Kind.Arr && dest.elemType == Tab.objType; } public override string ToString () { StringBuilder sb = new StringBuilder(); switch (kind) { case Kind.Int: sb.Append("int"); break; case Kind.Char: sb.Append("char"); break; case Kind.Class: sb.AppendFormat("#{0}", base.GetHashCode()); Symbol field = fields; int i = 0; while (field != null) { sb.AppendFormat("{0}-----field[{1}]={2}", Environment.NewLine, i, field); field = field.next; ++i; } sb.Append(Environment.NewLine); break; case Kind.Arr: sb.AppendFormat("{0}[]", elemType); break; } return sb.ToString(); } }