//----------------------------------------------------------------------------- // Resolve a CLR type to a Blue Type // How to handle array types? //----------------------------------------------------------------------------- public TypeEntry ResolveCLRTypeToBlueType(System.Type t) { Debug.Assert(t != null); Debug.Assert(!IsGenericType(t), "Can't resolve CLR generic type:" + t.FullName); if (t.IsArray) { ArrayTypeEntry a = new ArrayTypeEntry(t, this); return a; } if (t.IsByRef) { System.Type clrElem = t.GetElementType(); TypeEntry blueElem = ResolveCLRTypeToBlueType(clrElem); return new RefTypeEntry(blueElem, this); } TypeEntry type = (TypeEntry) m_hashClrType[t]; Debug.Assert(type != null, "type '" + t.ToString() + "' is unresolve in blue"); if (type == null) { Console.WriteLine("Dump: ["); IDictionaryEnumerator e = m_hashClrType.GetEnumerator(); while(e.MoveNext()) { Console.WriteLine("{0}\t\t{1}", e.Key, e.Value); } Console.WriteLine("] End Dump"); } return type; }
// Semantic resolution public override void ResolveType(ISemanticResolver s) { if (m_ArrayTypeRec != null) return; m_sigBase.ResolveType(s); m_ArrayTypeRec = new ArrayTypeEntry(this, s); }
// Given a symbol for an array type, get the corresponding CLR type. public System.Type GetArrayType(ArrayTypeEntry sym) { System.Type t = m_provider.CreateCLRArrayType(sym); Debug.Assert(t != null); return t; }
// Resolve protected override Exp ResolveExpAsRight(ISemanticResolver s) { if (m_symbol != null) return this; // Resolve the type we're allocating m_tFullType.ResolveType(s); Debug.Assert(this.ElemType != null); // Resolve the initializer list if (HasInitializerList) { // If we specified a length, it'd better match the intializer list length. if (DimensionExpList != null) { Debug.Assert(this.DimensionExpList.Length == 1, "@todo -multidimensional arrays"); Exp e = DimensionExpList[0]; // e must be a compile time constant who's value matches the ArrayInit length IntExp eInt = e as IntExp; if (eInt == null) ThrowError(SymbolError.MustBeCompileTimeConstant(e)); if (eInt.Value != m_ArrayInit.Length) ThrowError(SymbolError.NewArrayBoundsMismatch(this)); } m_ArrayInit.Resolve(s, this.ElemType); // The ability to not specifiy a dimension list is just syntactic sugar. // So if we still don't have it, we'd better fill it in based of the array-init list. if (DimensionExpList == null) { m_arExpList = new Exp[] { new IntExp(m_ArrayInit.Length, this.Location) }; } } Debug.Assert(DimensionExpList != null); for(int i = 0; i < this.m_arExpList.Length; i++) { ResolveExpAsRight(ref m_arExpList[i], s); } m_symbol = new ArrayTypeEntry(m_tFullType, s); CalcCLRType(s); // Transform an initializer list into an CompoundExpression: // new T[] { e0, e1, ... en} // <DeclareTemp(x), x = new T[], x[0]=e0, ... x[n]=en, x> if (HasInitializerList) { DeclareLocalStmtExp declare_x = new DeclareLocalStmtExp(this.ArraySymbol); LocalExp x = declare_x.GetLocal(); StatementExp [] list = new StatementExp[m_ArrayInit.Length + 2]; list[0] = declare_x; list[1] = new AssignStmtExp(x, this); for(int i = 0; i < m_ArrayInit.Length; i++) list[i + 2] = new AssignStmtExp( new ArrayAccessExp( x, new IntExp(i, null) ), m_ArrayInit.GetExpAt(i) ); // Strip the ArrayInitializer off this node. m_ArrayInit = null; StatementExp c = new CompoundStmtExp(list, x); StatementExp.ResolveExpAsRight(ref c, s); return c; } // end has Initializer return this; }