public override AstNode ShallowClone() { var res = new AstNew(Source, Start, End, Expression); res.Args.AddRange(Args.AsReadOnlySpan()); return(res); }
public void WriteNew(AstNew a) { Write(a.Source); Write(a.OptionalType); Write(a.OptionalArraySize); WriteArguments(a.OptionalArguments); WriteExpressions(a.OptionalCollectionInitializer); }
public Expression CompileNewExpression(AstNew e) { // Implicitly typed arrays if (e.OptionalType == null) { if (e.OptionalArguments != null) { return(Error(e.Source, ErrorCode.E2001, "Array constructors cannot have argument list")); } if (e.OptionalArraySize != null) { return(Error(e.Source, ErrorCode.E2002, "Cannot specify size on implicitly typed arrays")); } if (e.OptionalCollectionInitializer == null || e.OptionalCollectionInitializer.Count == 0) { return(Error(e.Source, ErrorCode.E2003, "Must provide non-empty initializer list for implicitly typed arrays")); } var values = new Expression[e.OptionalCollectionInitializer.Count]; for (int i = 0; i < values.Length; i++) { values[i] = CompileExpression(e.OptionalCollectionInitializer[i]); } var et = TryGetImplicitElementType(values); if (et == null) { return(Error(e.Source, ErrorCode.E2004, "No best type found for implicitly typed array")); } for (int i = 0; i < values.Length; i++) { values[i] = CompileImplicitCast(e.Source, et, values[i]); } return(et.IsValueType || et.IsReferenceType ? new NewArray(e.Source, TypeBuilder.GetArray(et), values) : et != DataType.Invalid ? Error(e.Source, ErrorCode.E2080, "Cannot create an implicitly typed array of type " + et.Quote()) : Expression.Invalid); } var dt = NameResolver.GetType(Namescope, e.OptionalType); switch (dt.TypeType) { case TypeType.RefArray: { if (e.OptionalArguments != null) { return(Error(e.Source, ErrorCode.E2005, "Array constructors cannot have argument list")); } var at = dt as RefArrayType; Expression size = null; if (e.OptionalArraySize != null) { size = CompileImplicitCast(e.Source, Essentials.Int, CompileExpression(e.OptionalArraySize)); if (size.IsInvalid) { return(Expression.Invalid); } } if (e.OptionalCollectionInitializer != null) { var values = new Expression[e.OptionalCollectionInitializer.Count]; for (int i = 0; i < values.Length; i++) { values[i] = CompileExpression(e.OptionalCollectionInitializer[i]); } if (size != null) { var c = Compiler.ConstantFolder.TryMakeConstant(size); if (c == null || !c.Value.Equals(values.Length)) { return(Error(size.Source, ErrorCode.E2006, "Inconsistent array size and initializer list length")); } } switch (at.ElementType.BuiltinType) { case BuiltinType.Bool: case BuiltinType.Byte: case BuiltinType.Char: case BuiltinType.Double: case BuiltinType.Int: case BuiltinType.Float: case BuiltinType.Long: case BuiltinType.SByte: case BuiltinType.Short: case BuiltinType.UInt: case BuiltinType.ULong: case BuiltinType.UShort: // Disable warning on primitive types break; default: if (TryGetImplicitElementType(values) == at.ElementType) { Log.Warning3(e.Source, ErrorCode.W2007, "Array can be instantiated as implicitly typed array (new[] { ... })"); } break; } for (int i = 0; i < values.Length; i++) { values[i] = CompileImplicitCast(values[i].Source, at.ElementType, values[i]); } return(new NewArray(e.Source, at, values)); } return(new NewArray(e.Source, at, size)); } case TypeType.Class: case TypeType.Struct: case TypeType.GenericParameter: { if (dt.IsStatic) { return(Error(e.Source, ErrorCode.E2090, "Cannot instantiate static class")); } if (e.OptionalArguments != null || e.OptionalCollectionInitializer != null) { if (e.OptionalArraySize != null) { return(Error(e.Source, ErrorCode.E2008, "Object constructors cannot have array size")); } Expression newObject; if (dt.IsStruct && (e.OptionalArguments == null || e.OptionalArguments.Count == 0)) { newObject = new Default(e.Source, dt); } else { dt.PopulateMembers(); Constructor ctor; Expression[] args; if (!TryResolveConstructorOverload(e.Source, dt.Constructors, e.OptionalArguments ?? AstArgument.Empty, out ctor, out args)) { return(e.OptionalArguments != null && e.OptionalArguments.Count > 0 ? (dt.Constructors.Count == 1 ? Error(e.Source, ErrorCode.E2009, "Call to " + (dt + PrintableParameterList(dt.Constructors[0].Parameters)).Quote() + " has some invalid arguments " + PrintableArgumentList(e.OptionalArguments)) : Error(e.Source, ErrorCode.E2009, dt.Quote() + " has no constructors matching the argument list " + PrintableArgumentList(e.OptionalArguments) + NameResolver.SuggestCandidates(dt.Constructors))) : Error(e.Source, ErrorCode.E0000, dt.Quote() + " has no default constructor")); } newObject = new NewObject(e.Source, ctor, args); } if (e.OptionalCollectionInitializer != null && e.OptionalCollectionInitializer.Count > 0) { var var = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("collection"), newObject.ReturnType); CurrentVariableScope.Variables.Add(var.Name, var); Expression root = new StoreLocal(e.Source, var, newObject); // See if it is a member initializer or collection initializer var containsAssignOp = false; foreach (var i in e.OptionalCollectionInitializer) { if (i is AstBinary && (i as AstBinary).IsAssign) { containsAssignOp = true; break; } } if (containsAssignOp) { var initedMembers = new List <string>(); // Assign members foreach (var i in e.OptionalCollectionInitializer) { var binOp = i as AstBinary; if (binOp == null || binOp.Type != AstBinaryType.Assign || !(binOp.Left is AstIdentifier)) { Log.Error(i.Source, ErrorCode.E2077, "Invalid initalizer member declarator"); continue; } var id = (AstIdentifier)binOp.Left; var member = new AstMember(new AstIdentifier(i.Source, var.Name), id); if (binOp.Right is AstArrayInitializer) { var ai = binOp.Right as AstArrayInitializer; var collection = CompileExpression(member); var cvar = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("array"), collection.ReturnType); CurrentVariableScope.Variables.Add(cvar.Name, cvar); root = new SequenceOp(root, new StoreLocal(collection.Source, cvar, collection)); if (collection.IsInvalid) { continue; } foreach (var ci in ai.Values) { root = new SequenceOp(root, CompileAddToCollection(cvar.Name, ci)); } } else { var assign = CompileAssign(new AstBinary(AstBinaryType.Assign, member, i.Source, binOp.Right)); root = new SequenceOp(root, assign); if (assign.IsInvalid) { continue; } } foreach (var m in initedMembers) { if (m == id.Symbol) { Log.Error(i.Source, ErrorCode.E2078, "Duplicate initialization of member " + id.Symbol.Quote()); break; } } initedMembers.Add(id.Symbol); } } else { // Add to collection foreach (var i in e.OptionalCollectionInitializer) { root = new SequenceOp(root, CompileAddToCollection(var.Name, i)); } } return(new SequenceOp(root, new LoadLocal(e.Source, var))); } if (e.OptionalType is AstBuiltinType && dt.IsStruct) { Log.Warning(e.Source, ErrorCode.W0000, "Redundant 'new' operator on builtin struct initialization"); } return(newObject); } return(Error(e.Source, ErrorCode.E2011, "Must provide argument list for object constructor")); } case TypeType.Delegate: { if (e.OptionalArguments == null) { return(Error(e.Source, ErrorCode.E0000, "Must provide argument list for delegate constructor")); } var args = CompileArgumentList(e.OptionalArguments); if (e.OptionalCollectionInitializer != null) { return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have collection initializer")); } if (e.OptionalArraySize != null) { return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have array size")); } if (args.Length != 1 || args[0].ExpressionType != ExpressionType.MethodGroup) { return(Error(e.Source, ErrorCode.E0000, "Delegate construction requires one method argument")); } return(CompileImplicitCast(e.Source, dt, args[0])); } case TypeType.Invalid: return(Expression.Invalid); default: return(Error(e.Source, ErrorCode.E2012, "Instances of type " + dt.Quote() + " cannot be created using 'new' because it is not a class, struct or array type")); } }