// Resolve this array initializer list. // Provide with the type that we expect each element in the list to be public void Resolve(ISemanticResolver s, TypeEntry tExpected) { // Each node must either be an expression or a nested array initializer list //foreach(Node n in List) for(int i = 0; i < m_list.Length; i++) { Node n = m_list[i]; if (n is Exp) { Exp e = (Exp) n; Exp.ResolveExpAsRight(ref e, s); m_list[i] = e; s.EnsureAssignable(e, tExpected.CLRType); } else if (n is ArrayInitializer) { Debug.Assert(tExpected.IsArray); // @todo -legit ArrayInitializer a = (ArrayInitializer) n; TypeEntry tNested = tExpected.AsArrayType.ElemType; a.Resolve(s, tNested); } else { // Error Debug.Assert(false); // @todo - legit } } }
public NewArrayObjExp( ArrayTypeSig tArrayType, // full array type (includes rank) Exp [] arExpSize, // rank to allocate, eval at runtime ArrayInitializer aInit // optional initilizer list ) { Debug.Assert(tArrayType != null); Debug.Assert(arExpSize != null); m_tFullType = tArrayType; this.m_arExpList = arExpSize; this.m_ArrayInit = aInit; // @todo - this is wrong m_filerange = tArrayType.Location; }
// 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; }
// Implicit size from init list public NewArrayObjExp( ArrayTypeSig tArrayType, // includes rank specifiers ArrayInitializer aInit // mandatory ) { Debug.Assert(tArrayType != null); Debug.Assert(aInit != null); m_tFullType = tArrayType; this.m_arExpList = null; this.m_ArrayInit = aInit; // @todo - this is wrong m_filerange = tArrayType.Location; }