public override AstNode Visit(NewArrayExpression node) { // Begin the node. builder.BeginNode(node); // Visit each size expresion. Expression sizeExpr = node.GetSize(); IChelaType coercionType = node.GetCoercionType(); while(sizeExpr != null) { // Visit the size expression. sizeExpr.Accept(this); // Coerce the size. IChelaType sizeType = sizeExpr.GetNodeType(); if(sizeType != coercionType) Cast(node, sizeExpr.GetNodeValue(), sizeType, coercionType); // Process the next size. sizeExpr = (Expression)sizeExpr.GetNext(); } // Create the array IChelaType arrayType = node.GetArrayType(); builder.CreateNewArray(arrayType); // Initialize elements. Expression init = (Expression)node.GetInitializers(); if(init != null) InitializeArrayElements(init, node.GetDimensions(), 0, arrayType, node.GetInitCoercionType(), init); return builder.EndNode(); }
public override AstNode Visit(NewArrayExpression node) { // Visit the type expression. Expression typeExpression = node.GetTypeExpression(); typeExpression.SetHints(Expression.TypeHint); typeExpression.Accept(this); // Get the size expression. Expression sizeExpression = node.GetSize(); int dimensions = node.GetDimensions(); // Count the dimensions- if(sizeExpression != null) { dimensions = 0; AstNode currentSize = sizeExpression; while(currentSize != null) { ++dimensions; currentSize = currentSize.GetNext(); } node.SetDimensions(dimensions); } // Get the type. IChelaType objectType = typeExpression.GetNodeType(); objectType = ExtractActualType(typeExpression, objectType); // Check the object type. if(objectType.IsConstant()) Error(node, "cannot create array of constants."); // Compute the init coercion type. IChelaType initCoercionType = objectType; if(initCoercionType.IsPassedByReference()) initCoercionType = ReferenceType.Create(initCoercionType); node.SetInitCoercionType(initCoercionType); // Create the array type. ArrayType arrayType = ArrayType.Create(objectType, dimensions, false); node.SetArrayType(arrayType); node.SetObjectType(objectType); node.SetNodeType(ReferenceType.Create(arrayType)); // Read or guess the sizes int[] arraySizes = new int[dimensions]; bool canInit = true; IChelaType sizeCoercionType = null; if(sizeExpression != null) { // Load the sizes. int currentSizeIndex = 0; while(sizeExpression != null) { // Visit the size expression. sizeExpression.Accept(this); // Get the size type. IChelaType sizeType = sizeExpression.GetNodeType(); if(sizeType.IsConstant() && canInit) { sizeType = DeConstType(sizeType); if(sizeType.IsInteger() && sizeType.IsPrimitive()) { // Read the size constant. ConstantValue sizeConst = sizeExpression.GetNodeValue() as ConstantValue; if(sizeConst != null) { sizeConst = sizeConst.Cast(ConstantValue.ValueType.Int); arraySizes[currentSizeIndex] = sizeConst.GetIntValue(); } else { // Cannot initialize here. canInit = false; } } else { // Cannot initialize here. canInit = false; } } else { // Cannot initialize here. canInit = false; } // Coerce the size type. if(sizeCoercionType == null) { if(sizeType.IsReference()) sizeType = DeReferenceType(sizeType); if(sizeType.IsConstant()) sizeType = DeReferenceType(sizeType); if(sizeType.IsStructure()) { IChelaType assoc = currentModule.GetAssociatedClassPrimitive((Structure)sizeType); if(assoc != null) sizeType = assoc; } if(!sizeType.IsInteger() || !sizeType.IsPrimitive()) Error(sizeExpression, "expected a size of integer type instead of '{0}'.", sizeType); sizeCoercionType = sizeType; } else if(sizeType != sizeCoercionType) { // Try to get a common coercion type. IChelaType newSizeCoercion = Coerce(sizeExpression, sizeCoercionType, sizeType, sizeExpression.GetNodeValue()); if(!newSizeCoercion.IsInteger() || !newSizeCoercion.IsPrimitive()) Error(sizeExpression, "expected a size of integer type instead of '{0}'.", sizeType); sizeCoercionType = newSizeCoercion; } // Process the next size. ++currentSizeIndex; sizeExpression = (Expression)sizeExpression.GetNext(); } } else { // Guess the sizes. for(int i = 0; i < dimensions; ++i) arraySizes[i] = -1; } // Use a coercion type. if(sizeCoercionType == null) // For implicit sizes. sizeCoercionType = ChelaType.GetIntType(); node.SetCoercionType(sizeCoercionType); // Check the initializer. AstNode init = node.GetInitializers(); if(init != null) { if(!canInit) Error(node, "cannot have variable size arrays with initializers."); CheckArrayInitializers(init, arraySizes, 0, initCoercionType, init); } // Create implicit size expressions. sizeExpression = node.GetSize(); if(sizeExpression == null) { Expression lastSize = null; for(int i = 0; i < dimensions; ++i) { Expression nextSize = new IntegerConstant(arraySizes[i], node.GetPosition()); if(i == 0) node.SetSize(nextSize); else lastSize.SetNext(nextSize); lastSize = nextSize; } } return node; }