public static Block createElementInitializerInternal(TYPE type, Expression indexer, int level, List <Expression> nonConstantDimensions, bool skipFirstLevel, SourceContext sourceContext) { // Generates internal part of array initializer: // either object constructor or, again, array initializer. // Check if the type is ARRAY. if (!(type is ARRAY_TYPE) && !(type is OBJECT_TYPE)) { return(null); } if (type is ARRAY_TYPE) { EXPRESSION_LIST declaredDimensions = ((ARRAY_TYPE)type).dimensions; int Rank = declaredDimensions.Length; List <Expression> dimensions = new List <Expression>(); // Check if all dimensions are constants or there is an expression available. for (int i = 0, n = Rank; i < n; i++) { if (declaredDimensions[i] == null || declaredDimensions[i].calculate() == null) { if (nonConstantDimensions == null) { return(null); } if (nonConstantDimensions.Count > 0) { dimensions.Add(nonConstantDimensions[0]); nonConstantDimensions.RemoveAt(0); } else { ERROR.MissingParameters(Rank, type.sourceContext); return(null); } } else { long d = (long)declaredDimensions[i].calculate(); Literal dim = new Literal((int)d, SystemTypes.Int32); dimensions.Add(dim); } } Block block = new Block(new StatementList()); // Generate array initializer: // x = new object[n]; if (skipFirstLevel && level == 0) { goto Bypass; } AssignmentStatement array_initializer = new AssignmentStatement(); array_initializer.NodeType = NodeType.AssignmentStatement; array_initializer.Operator = NodeType.Nop; // this means "normal" assignment, but not += etc. // Generate 'new object[n]' ConstructArray array_construct = new ConstructArray(); Node elem_type = ((ARRAY_TYPE)type).base_type.convert(); if (elem_type is ArrayTypeExpression) { ArrayTypeExpression arr_type = (elem_type.Clone()) as ArrayTypeExpression; // for ( int i=0, n=arr_type.Rank; i<n; i++ ) // arr_type.Sizes[i] = -1; elem_type = arr_type; } array_construct.ElementType = (TypeNode)elem_type; array_construct.Rank = Rank; array_construct.SourceContext = sourceContext; array_construct.Type = (TypeNode)type.convert(); array_construct.Operands = new ExpressionList(); for (int i = 0; i < Rank; i++) { array_construct.Operands.Add(dimensions[i]); } array_initializer.Source = array_construct; array_initializer.Target = indexer; array_initializer.SourceContext = sourceContext; block.Statements.Add(array_initializer); Bypass: // Generate x[i0,i1,...] for passing to the recursive call. Indexer new_indexer = new Indexer(); new_indexer.Object = indexer; new_indexer.Type = type.convert() as TypeNode; new_indexer.ElementType = ((ARRAY_TYPE)type).base_type.convert() as TypeNode; new_indexer.Operands = new ExpressionList(); for (int i = 0; i < Rank; i++) { Identifier index = Identifier.For("_i" + (level + i).ToString()); new_indexer.Operands.Add(index); } // Generate the last part (see comment, part 4, below). Block elem_initializers = createElementInitializerInternal(((ARRAY_TYPE)type).base_type, new_indexer, level + Rank, nonConstantDimensions, true, sourceContext); if (elem_initializers == null) { return(block); } // We do not need loops to initialize elements... // Return just array initializer. // Otherwise go generate initializers. // Generate // 1) int i0, i1, ...; // 2) for (int i1=0; i1<n; i1++) // for (int i2=0; i2<m; i2++) // ... // // Generate recursively: // 3) Initializers for array elements: x[i1,i2,...] = new object[n]; // 4) Initializers for every element (the similar loop(s)). // Generate int i0, i1, ...; for (int i = 0; i < Rank; i++) { VariableDeclaration locali = new VariableDeclaration(Identifier.For("_i" + (level + i).ToString()), SystemTypes.Int32, null); block.Statements.Add(locali); } // Generate loop headers: // for (int i1=0; i1<n; i1++) // for (int i2=0; i2<m; i2++) // ... Block owner = block; // where to put generated for-node for (int i = 0; i < Rank; i++) { For forStatement = new For(); // forStatement.NodeType; forStatement.SourceContext = sourceContext; // Making for-statement's body forStatement.Body = new Block(); forStatement.Body.Checked = true; forStatement.Body.HasLocals = false; // forStatement.Body.NodeType; // forStatement.Body.Scope; forStatement.Body.SourceContext = sourceContext; forStatement.Body.SuppressCheck = false; forStatement.Body.Statements = new StatementList(); // Now leave the body empty... // Making condition: i<n BinaryExpression condition = new BinaryExpression(); condition.NodeType = NodeType.Lt; condition.Operand1 = Identifier.For("_i" + (level + i).ToString()); condition.Operand2 = dimensions[i]; condition.SourceContext = sourceContext; forStatement.Condition = condition; // Making incrementer: i+=1 forStatement.Incrementer = new StatementList(); AssignmentStatement assignment = new AssignmentStatement(); assignment.NodeType = NodeType.AssignmentStatement; assignment.Operator = NodeType.Add; // Hope this means += // assignment.OperatorOverload assignment.Source = new Literal((int)1, SystemTypes.Int32); assignment.SourceContext = sourceContext; assignment.Target = Identifier.For("_i" + (level + i).ToString()); forStatement.Incrementer.Add(assignment); // Making initializer: i=0 forStatement.Initializer = new StatementList(); AssignmentStatement initializer = new AssignmentStatement(); initializer.NodeType = NodeType.AssignmentStatement; initializer.Operator = NodeType.Nop; // this means "normal" assignment, but not += etc. initializer.Source = new Literal(0, SystemTypes.Int32); initializer.Target = Identifier.For("_i" + (level + i).ToString()); initializer.SourceContext = sourceContext; forStatement.Initializer.Add(initializer); owner.Statements.Add(forStatement); owner = forStatement.Body; // for next iteration } // Adding element initializers generated in advance. owner.Statements.Add(elem_initializers); return(block); } else if (type is OBJECT_TYPE) { // Check if the type is VAL-object. if (!((OBJECT_TYPE)type).ObjectUnit.modifiers.Value) { return(null); } Block block = new Block(new StatementList()); // Generate 'new obj' DECLARATION objct = ((OBJECT_TYPE)type).ObjectUnit; // We do it for only own value types. They have // extra constcutor that takes ont fictive intgere. Might have // Chtck and call it Construct construct = new Construct(); // Strange thing: CCI expects _class_ in Construst.Constructor, // but not a constructor itself!.. // construct.Constructor = new MemberBinding(null,((TypeNode)objct.convert()).GetConstructors()[0]); // NODE.convertTypeName(objct); construct.Constructor = new MemberBinding(null, (TypeNode)objct.convert()); construct.Constructor.Type = SystemTypes.Type; construct.Operands = new ExpressionList(); construct.SourceContext = sourceContext; construct.Type = (TypeNode)objct.convert(); construct.Operands.Add(new Literal(1, SystemTypes.Int32)); // Generate x[i0,i1,...] = new obj; AssignmentStatement main_initializer = new AssignmentStatement(); main_initializer.NodeType = NodeType.AssignmentStatement; main_initializer.Operator = NodeType.Nop; // this means "normal" assignment, but not += etc. main_initializer.Source = construct; main_initializer.Target = indexer; main_initializer.SourceContext = sourceContext; block.Statements.Add(main_initializer); return(block); } else if (type is EXTERNAL_TYPE) { // Only value types might need extra calls Struct str = ((EXTERNAL_TYPE)type).entity as Struct; InstanceInitializer ctr = str.GetConstructor(new TypeNode[] { SystemTypes.Int32 }); bool possibly_was_our_structure = (ctr != null); if (ctr == null) { ctr = str.GetConstructor(new TypeNode[0] { }); } // TO_DO: When metadata is available replace this with // more consistent check Block block = new Block(new StatementList()); // Generate 'new obj' Construct construct = new Construct(); construct.Constructor = new MemberBinding(null, ctr); construct.Operands = new ExpressionList(); construct.Type = str; // We do it for only own value types. They have // extra constcutor that takes ont fictive intgere. Might have // Chtck and call it if (possibly_was_our_structure) { construct.Operands.Add(Literal.Int32MinusOne); } // Generate x[i0,i1,...] = new obj; AssignmentStatement main_initializer = new AssignmentStatement(); main_initializer.NodeType = NodeType.AssignmentStatement; main_initializer.Operator = NodeType.Nop; // this means "normal" assignment, but not += etc. main_initializer.Source = construct; main_initializer.Target = indexer; main_initializer.SourceContext = sourceContext; indexer.Type = construct.Type; block.Statements.Add(main_initializer); return(block); } else { return(null); } }