X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=c9a7ab18eb6db7423553acbd0d87adef93c3291c;hb=54333f197275415e2c2fbdddc046e0f32c44bc87;hp=b48fd1358c860f5b031fae69e740aacbed6b3e12;hpb=1c21e088c10b34217797359553183d7a1a6f4fda;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index b48fd1358c8..c9a7ab18eb6 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -24,11 +24,11 @@ namespace Mono.CSharp { public class UserOperatorCall : Expression { public delegate Expression ExpressionTreeExpression (EmitContext ec, MethodGroupExpr mg); - protected readonly ArrayList arguments; + protected readonly Arguments arguments; protected readonly MethodGroupExpr mg; readonly ExpressionTreeExpression expr_tree; - public UserOperatorCall (MethodGroupExpr mg, ArrayList args, ExpressionTreeExpression expr_tree, Location loc) + public UserOperatorCall (MethodGroupExpr mg, Arguments args, ExpressionTreeExpression expr_tree, Location loc) { this.mg = mg; this.arguments = args; @@ -44,12 +44,9 @@ namespace Mono.CSharp { if (expr_tree != null) return expr_tree (ec, mg); - ArrayList args = new ArrayList (arguments.Count + 1); - args.Add (new Argument (new NullLiteral (loc))); - args.Add (new Argument (mg.CreateExpressionTree (ec))); - foreach (Argument a in arguments) { - args.Add (new Argument (a.Expr.CreateExpressionTree (ec))); - } + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + new NullLiteral (loc), + mg.CreateExpressionTree (ec)); return CreateExpressionFactoryCall ("Call", args); } @@ -78,9 +75,7 @@ namespace Mono.CSharp { public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - foreach (Argument a in arguments) - a.Expr.MutateHoistedGenericType (storey); - + arguments.MutateHoistedGenericType (storey); mg.MutateHoistedGenericType (storey); } } @@ -106,6 +101,11 @@ namespace Mono.CSharp { return Expr; } + public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + { + return Expr.DoResolveLValue (ec, right_side); + } + public override void Emit (EmitContext ec) { throw new Exception ("Should not happen"); @@ -122,7 +122,8 @@ namespace Mono.CSharp { // // Unary implements unary expressions. // - public class Unary : Expression { + public class Unary : Expression + { public enum Operator : byte { UnaryPlus, UnaryNegation, LogicalNot, OnesComplement, AddressOf, TOP @@ -134,11 +135,11 @@ namespace Mono.CSharp { public Expression Expr; Expression enum_conversion; - public Unary (Operator op, Expression expr, Location loc) + public Unary (Operator op, Expression expr) { Oper = op; Expr = expr; - this.loc = loc; + loc = expr.Location; } // @@ -238,20 +239,17 @@ namespace Mono.CSharp { if (expr_type == TypeManager.float_type) { FloatLiteral fl = e as FloatLiteral; // For better error reporting - if (fl != null) { - fl.Value = -fl.Value; - return fl; - } + if (fl != null) + return new FloatLiteral (-fl.Value, e.Location); + return new FloatConstant (-((FloatConstant)e).Value, e.Location); } if (expr_type == TypeManager.double_type) { DoubleLiteral dl = e as DoubleLiteral; // For better error reporting - if (dl != null) { - dl.Value = -dl.Value; - return dl; - } - + if (dl != null) + return new DoubleLiteral (-dl.Value, e.Location); + return new DoubleConstant (-((DoubleConstant)e).Value, e.Location); } if (expr_type == TypeManager.decimal_type) @@ -374,7 +372,7 @@ namespace Mono.CSharp { throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ()); } - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (Expr.CreateExpressionTree (ec))); if (user_op != null) args.Add (new Argument (user_op.CreateExpressionTree (ec))); @@ -449,8 +447,14 @@ namespace Mono.CSharp { if (Expr == null) return null; - if (TypeManager.IsNullableValueType (Expr.Type)) - return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec); + if (Expr.Type == InternalType.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (Expr)); + return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).DoResolve (ec); + } + + if (TypeManager.IsNullableType (Expr.Type)) + return new Nullable.LiftedUnaryOperator (Oper, Expr).Resolve (ec); // // Attempt to use a constant folding operation. @@ -554,6 +558,19 @@ namespace Mono.CSharp { oper, TypeManager.CSharpName (t)); } + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + switch (Oper) { + case Operator.UnaryPlus: + return "UnaryPlus"; + default: + throw new NotImplementedException ("Unknown express type operator " + Oper.ToString ()); + } + } + static bool IsFloat (Type t) { return t == TypeManager.float_type || t == TypeManager.double_type; @@ -671,14 +688,14 @@ namespace Mono.CSharp { if (user_op == null) return null; - ArrayList args = new ArrayList (1); + Arguments args = new Arguments (1); args.Add (new Argument (expr)); user_op = user_op.OverloadResolve (ec, ref args, false, expr.Location); if (user_op == null) return null; - Expr = ((Argument) args [0]).Expr; + Expr = args [0].Expr; return new UserOperatorCall (user_op, args, CreateExpressionTree, expr.Location); } @@ -899,10 +916,10 @@ namespace Mono.CSharp { // UserOperatorCall method; - public UnaryMutator (Mode m, Expression e, Location l) + public UnaryMutator (Mode m, Expression e) { mode = m; - loc = l; + loc = e.Location; expr = e; } @@ -938,6 +955,17 @@ namespace Mono.CSharp { Expression ResolveOperator (EmitContext ec) { type = expr.Type; + + // + // The operand of the prefix/postfix increment decrement operators + // should be an expression that is classified as a variable, + // a property access or an indexer access + // + if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) { + expr = expr.ResolveLValue (ec, expr); + } else { + Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); + } // // Step 1: Perform Operator Overload location @@ -953,8 +981,8 @@ namespace Mono.CSharp { mg = MemberLookup (ec.ContainerType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr; if (mg != null) { - ArrayList args = new ArrayList (1); - args.Add (new Argument (expr, Argument.AType.Expression)); + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); mg = mg.OverloadResolve (ec, ref args, false, loc); if (mg == null) return null; @@ -970,17 +998,6 @@ namespace Mono.CSharp { return null; } - // - // The operand of the prefix/postfix increment decrement operators - // should be an expression that is classified as a variable, - // a property access or an indexer access - // - if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) { - expr = expr.ResolveLValue (ec, expr, Location); - } else { - Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); - } - return this; } @@ -998,10 +1015,8 @@ namespace Mono.CSharp { eclass = ExprClass.Value; -#if GMCS_SOURCE - if (TypeManager.IsNullableValueType (expr.Type)) + if (TypeManager.IsNullableType (expr.Type)) return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec); -#endif return ResolveOperator (ec); } @@ -1155,7 +1170,7 @@ namespace Mono.CSharp { return null; } - if (expr.Type == TypeManager.anonymous_method_type) { + if (expr.Type == InternalType.AnonymousMethod) { Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression or anonymous method", OperatorName); return null; @@ -1195,9 +1210,10 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); - args.Add (new Argument (expr.CreateExpressionTree (ec))); - args.Add (new Argument (new TypeOf (probe_type_expr, loc))); + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + return CreateExpressionFactoryCall ("TypeIs", args); } @@ -1268,13 +1284,13 @@ namespace Mono.CSharp { t_is_nullable = true; } - if (t.IsValueType) { + if (TypeManager.IsStruct (t)) { if (d == t) { // // D and T are the same value types but D can be null // if (d_is_nullable && !t_is_nullable) { - expr_unwrap = Nullable.Unwrap.Create (expr, ec); + expr_unwrap = Nullable.Unwrap.Create (expr, false); return this; } @@ -1296,7 +1312,7 @@ namespace Mono.CSharp { if (TypeManager.IsGenericParameter (t)) return ResolveGenericParameter (d, t); - if (d.IsValueType) { + if (TypeManager.IsStruct (d)) { bool temp; if (Convert.ImplicitBoxingConversionExists (expr, t, out temp)) return CreateConstantResult (true); @@ -1319,23 +1335,19 @@ namespace Mono.CSharp { Expression ResolveGenericParameter (Type d, Type t) { -#if GMCS_SOURCE GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t); if (constraints != null) { - if (constraints.IsReferenceType && d.IsValueType) + if (constraints.IsReferenceType && TypeManager.IsStruct (d)) return CreateConstantResult (false); - if (constraints.IsValueType && !d.IsValueType) + if (constraints.IsValueType && !TypeManager.IsStruct (d)) return CreateConstantResult (TypeManager.IsEqual (d, t)); } - if (!TypeManager.IsReferenceType (expr.Type)) + if (TypeManager.IsGenericParameter (expr.Type)) expr = new BoxedCast (expr, d); return this; -#else - return null; -#endif } protected override string OperatorName { @@ -1357,9 +1369,10 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); - args.Add (new Argument (expr.CreateExpressionTree (ec))); - args.Add (new Argument (new TypeOf (probe_type_expr, loc))); + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + return CreateExpressionFactoryCall ("TypeAs", args); } @@ -1370,16 +1383,20 @@ namespace Mono.CSharp { expr.Emit (ec); if (do_isinst) - ig.Emit (OpCodes.Isinst, probe_type_expr.Type); + ig.Emit (OpCodes.Isinst, type); #if GMCS_SOURCE - if (TypeManager.IsNullableType (type)) + if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type)) ig.Emit (OpCodes.Unbox_Any, type); #endif } public override Expression DoResolve (EmitContext ec) { + // Because expr is modified + if (eclass != ExprClass.Invalid) + return this; + if (resolved_type == null) { resolved_type = base.DoResolve (ec); @@ -1394,7 +1411,7 @@ namespace Mono.CSharp { if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) { if (probe_type_expr is TypeParameterExpr) { Report.Error (413, loc, - "The `as' operator cannot be used with a non-reference type parameter `{0}'", + "The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint", probe_type_expr.GetSignatureForError ()); } else { Report.Error (77, loc, @@ -1439,6 +1456,12 @@ namespace Mono.CSharp { protected override string OperatorName { get { return "as"; } } + + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + type = storey.MutateType (type); + base.MutateHoistedGenericType (storey); + } public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value) { @@ -1534,6 +1557,20 @@ namespace Mono.CSharp { // public class DefaultValueExpression : Expression { + sealed class DefaultValueNullLiteral : NullLiteral + { + public DefaultValueNullLiteral (DefaultValueExpression expr) + : base (expr.type, expr.loc) + { + } + + public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type t, bool expl) + { + Error_ValueCannotBeConvertedCore (ec, loc, t, expl); + } + } + + Expression expr; public DefaultValueExpression (Expression expr, Location loc) @@ -1544,7 +1581,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (this)); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); return CreateExpressionFactoryCall ("Constant", args); @@ -1565,12 +1602,8 @@ namespace Mono.CSharp { if (type.IsPointer) return new NullLiteral (Location).ConvertImplicitly (type); - if (TypeManager.IsReferenceType (type)) { - return new EmptyConstantCast (new NullLiteral (Location), type); - - // TODO: ET needs - // return ReducedExpression.Create (new NullLiteral (Location), this); - } + if (TypeManager.IsReferenceType (type)) + return new DefaultValueNullLiteral (this); Constant c = New.Constantify (type); if (c != null) @@ -1605,7 +1638,8 @@ namespace Mono.CSharp { /// /// Binary operators /// - public class Binary : Expression { + public class Binary : Expression, IDynamicBinder + { protected class PredefinedOperator { protected readonly Type left; @@ -1975,16 +2009,8 @@ namespace Mono.CSharp { public static void Error_OperatorCannotBeApplied (Expression left, Expression right, string oper, Location loc) { string l, r; - // TODO: This should be handled as Type of method group in CSharpName - if (left.eclass == ExprClass.MethodGroup) - l = left.ExprClassName; - else - l = TypeManager.CSharpName (left.Type); - - if (right.eclass == ExprClass.MethodGroup) - r = right.ExprClassName; - else - r = TypeManager.CSharpName (right.Type); + l = TypeManager.CSharpName (left.Type); + r = TypeManager.CSharpName (right.Type); Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'", oper, l, r); @@ -1995,6 +2021,23 @@ namespace Mono.CSharp { Error_OperatorCannotBeApplied (left, right, OperName (oper), loc); } + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + switch (oper) { + case Operator.Addition: + return is_compound ? "AddAssign" : "Add"; + case Operator.Equality: + return "Equal"; + case Operator.Multiply: + return is_compound ? "MultiplyAssign" : "Multiply"; + default: + throw new NotImplementedException ("Unknown expression type operator " + oper.ToString ()); + } + } + static string GetOperatorMetadataName (Operator op) { CSharp.Operator.OpType op_type; @@ -2526,13 +2569,9 @@ namespace Mono.CSharp { // The conversion rules are ignored in enum context but why if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) { - left = lc = EnumLiftUp (ec, lc, rc, loc); - if (lc == null) - return null; - - right = rc = EnumLiftUp (ec, rc, lc, loc); - if (rc == null) - return null; + lc = EnumLiftUp (ec, lc, rc, loc); + if (lc != null) + rc = EnumLiftUp (ec, rc, lc, loc); } if (rc != null && lc != null) { @@ -2570,9 +2609,18 @@ namespace Mono.CSharp { CheckUselessComparison (rc, left.Type); } + if (left.Type == InternalType.Dynamic || right.Type == InternalType.Dynamic) { + Arguments args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); + return new DynamicExpressionStatement (this, args, loc).Resolve (ec); + } + if (RootContext.Version >= LanguageVersion.ISO_2 && - (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type) || - (left is NullLiteral && right.Type.IsValueType) || (right is NullLiteral && left.Type.IsValueType))) + ((TypeManager.IsNullableType (left.Type) && (right is NullLiteral || TypeManager.IsNullableType (right.Type) || TypeManager.IsValueType (right.Type))) || + (TypeManager.IsValueType (left.Type) && right is NullLiteral) || + (TypeManager.IsNullableType (right.Type) && (left is NullLiteral || TypeManager.IsNullableType (left.Type) || TypeManager.IsValueType (left.Type))) || + (TypeManager.IsValueType (right.Type) && left is NullLiteral))) return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); return DoResolveCore (ec, left, right); @@ -2608,15 +2656,15 @@ namespace Mono.CSharp { Expression ResolveOperatorDelegate (EmitContext ec, Type l, Type r) { bool is_equality = (oper & Operator.EqualityMask) != 0; - if (!TypeManager.IsEqual (l, r)) { + if (!TypeManager.IsEqual (l, r) && !TypeManager.IsVariantOf (r, l)) { Expression tmp; - if (right.eclass == ExprClass.MethodGroup || (r == TypeManager.anonymous_method_type && !is_equality)) { + if (right.eclass == ExprClass.MethodGroup || (r == InternalType.AnonymousMethod && !is_equality)) { tmp = Convert.ImplicitConversionRequired (ec, right, l, loc); if (tmp == null) return null; right = tmp; r = right.Type; - } else if (left.eclass == ExprClass.MethodGroup || (l == TypeManager.anonymous_method_type && !is_equality)) { + } else if (left.eclass == ExprClass.MethodGroup || (l == InternalType.AnonymousMethod && !is_equality)) { tmp = Convert.ImplicitConversionRequired (ec, left, r, loc); if (tmp == null) return null; @@ -2634,9 +2682,9 @@ namespace Mono.CSharp { return ResolveUserOperator (ec, l, r); MethodInfo method; - ArrayList args = new ArrayList (2); - args.Add (new Argument (left, Argument.AType.Expression)); - args.Add (new Argument (right, Argument.AType.Expression)); + Arguments args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); if (oper == Operator.Addition) { if (TypeManager.delegate_combine_delegate_delegate == null) { @@ -2836,7 +2884,7 @@ namespace Mono.CSharp { return null; } - if (l == TypeManager.anonymous_method_type) + if (l == InternalType.AnonymousMethod) return null; if (TypeManager.IsValueType (l)) @@ -2884,7 +2932,7 @@ namespace Mono.CSharp { return null; } else if (l.IsInterface) { l = TypeManager.object_type; - } else if (l.IsValueType) { + } else if (TypeManager.IsStruct (l)) { return null; } @@ -2894,7 +2942,7 @@ namespace Mono.CSharp { return null; } else if (r.IsInterface) { r = TypeManager.object_type; - } else if (r.IsValueType) { + } else if (TypeManager.IsStruct (r)) { return null; } @@ -3041,7 +3089,7 @@ namespace Mono.CSharp { return null; } - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); Argument larg = new Argument (left); args.Add (larg); Argument rarg = new Argument (right); @@ -3094,11 +3142,14 @@ namespace Mono.CSharp { type = TypeManager.bool_type; if (left is NullLiteral || right is NullLiteral) oper_expr = ReducedExpression.Create (this, oper_expr).Resolve (ec); - } else if (union.DeclaringType == TypeManager.delegate_type && l != r) { + } else if (l != r) { + MethodInfo mi = (MethodInfo) union; + // // Two System.Delegate(s) are never equal // - return null; + if (mi.DeclaringType == TypeManager.multicast_delegate_type) + return null; } } } @@ -3453,6 +3504,25 @@ namespace Mono.CSharp { target.left = left.Clone (clonectx); target.right = right.Clone (clonectx); } + + public Expression CreateCallSiteBinder (EmitContext ec, Arguments args) + { + Arguments binder_args = new Arguments (4); + + MemberAccess sle = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); + + MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc); + + binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc))); + binder_args.Add (new Argument (new BoolLiteral (ec.CheckState, loc))); + + bool member_access = left is DynamicMemberBinder || right is DynamicMemberBinder; + binder_args.Add (new Argument (new BoolLiteral (member_access, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (), loc))); + + return new New (new MemberAccess (binder, "CSharpBinaryOperationBinder", loc), binder_args, loc); + } public override Expression CreateExpressionTree (EmitContext ec) { @@ -3539,7 +3609,7 @@ namespace Mono.CSharp { throw new InternalErrorException ("Unknown expression tree binary operator " + oper); } - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (left.CreateExpressionTree (ec))); args.Add (new Argument (right.CreateExpressionTree (ec))); if (method != null) { @@ -3558,7 +3628,7 @@ namespace Mono.CSharp { // b, c, d... may be strings or objects. // public class StringConcat : Expression { - ArrayList arguments; + Arguments arguments; public StringConcat (EmitContext ec, Location loc, Expression left, Expression right) { @@ -3566,15 +3636,15 @@ namespace Mono.CSharp { type = TypeManager.string_type; eclass = ExprClass.Value; - arguments = new ArrayList (2); + arguments = new Arguments (2); Append (ec, left); Append (ec, right); } public override Expression CreateExpressionTree (EmitContext ec) { - Argument arg = (Argument) arguments [0]; - return CreateExpressionAddCall (ec, arg, arg.Expr.CreateExpressionTree (ec), 1); + Argument arg = arguments [0]; + return CreateExpressionAddCall (ec, arg, arg.CreateExpressionTree (ec), 1); } // @@ -3582,14 +3652,14 @@ namespace Mono.CSharp { // Expression CreateExpressionAddCall (EmitContext ec, Argument left, Expression left_etree, int pos) { - ArrayList concat_args = new ArrayList (2); - ArrayList add_args = new ArrayList (3); + Arguments concat_args = new Arguments (2); + Arguments add_args = new Arguments (3); concat_args.Add (left); add_args.Add (new Argument (left_etree)); concat_args.Add (arguments [pos]); - add_args.Add (new Argument (((Argument) arguments [pos]).Expr.CreateExpressionTree (ec))); + add_args.Add (new Argument (arguments [pos].CreateExpressionTree (ec))); MethodGroupExpr method = CreateConcatMemberExpression ().Resolve (ec) as MethodGroupExpr; if (method == null) @@ -3605,7 +3675,7 @@ namespace Mono.CSharp { if (++pos == arguments.Count) return expr; - left = new Argument (new EmptyExpression (method.Type)); + left = new Argument (new EmptyExpression (((MethodInfo)method).ReturnType)); return CreateExpressionAddCall (ec, left, expr, pos); } @@ -3622,7 +3692,7 @@ namespace Mono.CSharp { StringConstant sc = operand as StringConstant; if (sc != null) { if (arguments.Count != 0) { - Argument last_argument = (Argument) arguments [arguments.Count - 1]; + Argument last_argument = arguments [arguments.Count - 1]; StringConstant last_expr_constant = last_argument.Expr as StringConstant; if (last_expr_constant != null) { last_argument.Expr = new StringConstant ( @@ -3659,8 +3729,7 @@ namespace Mono.CSharp { public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - foreach (Argument a in arguments) - a.Expr.MutateHoistedGenericType (storey); + arguments.MutateHoistedGenericType (storey); } } @@ -3671,7 +3740,7 @@ namespace Mono.CSharp { readonly bool is_and; Expression oper; - public ConditionalLogicalOperator (MethodGroupExpr oper_method, ArrayList arguments, + public ConditionalLogicalOperator (MethodGroupExpr oper_method, Arguments arguments, ExpressionTreeExpression expr_tree, bool is_and, Location loc) : base (oper_method, arguments, expr_tree, loc) { @@ -3713,7 +3782,7 @@ namespace Mono.CSharp { // // Emit and duplicate left argument // - ((Argument)arguments [0]).Expr.Emit (ec); + arguments [0].Expr.Emit (ec); ig.Emit (OpCodes.Dup); arguments.RemoveAt (0); @@ -3894,7 +3963,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (3); + Arguments args = new Arguments (3); args.Add (new Argument (expr.CreateExpressionTree (ec))); args.Add (new Argument (true_expr.CreateExpressionTree (ec))); args.Add (new Argument (false_expr.CreateExpressionTree (ec))); @@ -3903,18 +3972,7 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - expr = expr.Resolve (ec); - - if (expr == null) - return null; - - if (expr.Type != TypeManager.bool_type){ - expr = Expression.ResolveBoolean ( - ec, expr, loc); - - if (expr == null) - return null; - } + expr = Expression.ResolveBoolean (ec, expr, loc); Assign ass = expr as Assign; if (ass != null && ass.Source is Constant) { @@ -3924,7 +3982,7 @@ namespace Mono.CSharp { true_expr = true_expr.Resolve (ec); false_expr = false_expr.Resolve (ec); - if (true_expr == null || false_expr == null) + if (true_expr == null || false_expr == null || expr == null) return null; eclass = ExprClass.Value; @@ -4022,7 +4080,7 @@ namespace Mono.CSharp { LocalTemporary temp; #region Abstract - public abstract HoistedVariable HoistedVariable { get; } + public abstract HoistedVariable GetHoistedVariable (EmitContext ec); public abstract bool IsFixed { get; } public abstract bool IsRef { get; } public abstract string Name { get; } @@ -4041,8 +4099,9 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { - if (IsHoistedEmitRequired (ec)) { - HoistedVariable.AddressOf (ec, mode); + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.AddressOf (ec, mode); return; } @@ -4074,8 +4133,9 @@ namespace Mono.CSharp { { Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc); - if (IsHoistedEmitRequired (ec)) { - HoistedVariable.Emit (ec, leave_copy); + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.Emit (ec, leave_copy); return; } @@ -4102,25 +4162,24 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { - Report.Debug (64, "VARIABLE EMIT ASSIGN", this, Variable, type, IsRef, - source, loc); - - if (IsHoistedEmitRequired (ec)) { - HoistedVariable.EmitAssign (ec, source, leave_copy, prepare_for_load); + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.EmitAssign (ec, source, leave_copy, prepare_for_load); return; } - if (IsRef) - Variable.Emit (ec); - - source.Emit (ec); - - // HACK: variable is already emitted when source is an initializer - if (source is NewInitialize) { - if (leave_copy) { - Variable.Emit (ec); + New n_source = source as New; + if (n_source != null) { + if (!n_source.Emit (ec, this)) { + if (leave_copy) + EmitLoad (ec); + return; } - return; + } else { + if (IsRef) + EmitLoad (ec); + + source.Emit (ec); } if (leave_copy) { @@ -4143,15 +4202,7 @@ namespace Mono.CSharp { } public bool IsHoisted { - get { return HoistedVariable != null; } - } - - protected virtual bool IsHoistedEmitRequired (EmitContext ec) - { - // - // Default implementation return true when there is a hosted variable - // - return HoistedVariable != null; + get { return GetHoistedVariable (null) != null; } } public override void MutateHoistedGenericType (AnonymousMethodStorey storey) @@ -4168,13 +4219,13 @@ namespace Mono.CSharp { public Block Block; public LocalInfo local_info; bool is_readonly; + bool resolved; // TODO: merge with eclass public LocalVariableReference (Block block, string name, Location l) { Block = block; this.name = name; loc = l; - eclass = ExprClass.Variable; } // @@ -4193,8 +4244,9 @@ namespace Mono.CSharp { get { return local_info.VariableInfo; } } - public override HoistedVariable HoistedVariable { - get { return local_info.HoistedVariableReference; } + public override HoistedVariable GetHoistedVariable (EmitContext ec) + { + return local_info.HoistedVariableReference; } // @@ -4238,7 +4290,11 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList arg = new ArrayList (1); + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (ec); + + Arguments arg = new Arguments (1); arg.Add (new Argument (this)); return CreateExpressionFactoryCall ("Constant", arg); } @@ -4267,11 +4323,16 @@ namespace Mono.CSharp { } } + resolved |= ec.DoFlowAnalysis; + eclass = ExprClass.Variable; return this; } public override Expression DoResolve (EmitContext ec) { + if (resolved) + return this; + ResolveLocalInfo (); local_info.Used = true; @@ -4284,7 +4345,7 @@ namespace Mono.CSharp { return DoResolveBase (ec); } - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) + public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { ResolveLocalInfo (); @@ -4363,12 +4424,10 @@ namespace Mono.CSharp { /// public class ParameterReference : VariableReference { readonly ToplevelParameterInfo pi; - readonly ToplevelBlock referenced; - public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc) + public ParameterReference (ToplevelParameterInfo pi, Location loc) { this.pi = pi; - this.referenced = referenced; this.loc = loc; } @@ -4380,8 +4439,9 @@ namespace Mono.CSharp { get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; } } - public override HoistedVariable HoistedVariable { - get { return pi.Parameter.HoistedVariableReference; } + public override HoistedVariable GetHoistedVariable (EmitContext ec) + { + return pi.Parameter.HoistedVariableReference; } // @@ -4441,24 +4501,38 @@ namespace Mono.CSharp { if (am == null) return true; - ToplevelBlock declared = pi.Block; - if (declared != referenced) { - if (IsRef) { - Report.Error (1628, loc, - "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier", - Name, am.ContainerType); - return false; + Block b = ec.CurrentBlock; + while (b != null) { + IParameterData[] p = b.Toplevel.Parameters.FixedParameters; + for (int i = 0; i < p.Length; ++i) { + if (p [i] != Parameter) + continue; + + // + // Skip closest anonymous method parameters + // + if (b == ec.CurrentBlock && !am.IsIterator) + return true; + + if (IsRef) { + Report.Error (1628, loc, + "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier", + Name, am.ContainerType); + } + + b = null; + break; } - } else { - if (!am.IsIterator) - return true; + + if (b != null) + b = b.Toplevel.Parent; } - if (ec.IsVariableCapturingRequired) { - if (pi.Parameter.HasAddressTaken) - AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc); + if (pi.Parameter.HasAddressTaken) + AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc); - AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec); + if (ec.IsVariableCapturingRequired) { + AnonymousMethodStorey storey = pi.Block.CreateAnonymousMethodStorey (ec); storey.CaptureParameter (ec, this); } @@ -4476,7 +4550,7 @@ namespace Mono.CSharp { if (pr == null) return false; - return Name == pr.Name && referenced == pr.referenced; + return Name == pr.Name; } protected override void CloneTo (CloneContext clonectx, Expression target) @@ -4486,8 +4560,9 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - if (IsHoistedEmitRequired (ec)) - return HoistedVariable.CreateExpressionTree (ec); + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (ec); return Parameter.ExpressionTreeVariableReference (); } @@ -4509,6 +4584,10 @@ namespace Mono.CSharp { if (!DoResolveBase (ec)) return null; + // HACK: Variables are not captured in probing mode + if (ec.IsInProbingMode) + return this; + if (HasOutModifier && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc)) return null; @@ -4530,143 +4609,27 @@ namespace Mono.CSharp { static public void EmitLdArg (ILGenerator ig, int x) { - if (x <= 255){ - switch (x){ - case 0: ig.Emit (OpCodes.Ldarg_0); break; - case 1: ig.Emit (OpCodes.Ldarg_1); break; - case 2: ig.Emit (OpCodes.Ldarg_2); break; - case 3: ig.Emit (OpCodes.Ldarg_3); break; - default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break; - } - } else - ig.Emit (OpCodes.Ldarg, x); - } - } - - /// - /// Used for arguments to New(), Invocation() - /// - public class Argument { - public enum AType : byte { - Expression, - Ref, - Out, - ArgList - }; - - public static readonly Argument[] Empty = new Argument [0]; - - public readonly AType ArgType; - public Expression Expr; - - public Argument (Expression expr, AType type) - { - this.Expr = expr; - this.ArgType = type; - } - - public Argument (Expression expr) - { - this.Expr = expr; - this.ArgType = AType.Expression; - } - - public Type Type { - get { return Expr.Type; } - } - - public Parameter.Modifier Modifier - { - get { - switch (ArgType) { - case AType.Out: - return Parameter.Modifier.OUT; - - case AType.Ref: - return Parameter.Modifier.REF; - - default: - return Parameter.Modifier.NONE; - } - } - } - - public string GetSignatureForError () - { - if (Expr.eclass == ExprClass.MethodGroup) - return Expr.ExprClassName; - - return TypeManager.CSharpName (Expr.Type); - } - - public bool ResolveMethodGroup (EmitContext ec) - { - SimpleName sn = Expr as SimpleName; - if (sn != null) - Expr = sn.GetMethodGroup (); - - // FIXME: csc doesn't report any error if you try to use `ref' or - // `out' in a delegate creation expression. - Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); - if (Expr == null) - return false; - - return true; - } - - public bool Resolve (EmitContext ec, Location loc) - { - if (Expr == null) - return false; - - using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) { - // Verify that the argument is readable - if (ArgType != AType.Out) - Expr = Expr.Resolve (ec); - - // Verify that the argument is writeable - if (Expr != null && (ArgType == AType.Out || ArgType == AType.Ref)) - Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess, loc); - - return Expr != null; - } - } - - public void Emit (EmitContext ec) - { - if (ArgType != AType.Ref && ArgType != AType.Out) { - Expr.Emit (ec); - return; + switch (x) { + case 0: ig.Emit (OpCodes.Ldarg_0); break; + case 1: ig.Emit (OpCodes.Ldarg_1); break; + case 2: ig.Emit (OpCodes.Ldarg_2); break; + case 3: ig.Emit (OpCodes.Ldarg_3); break; + default: + if (x > byte.MaxValue) + ig.Emit (OpCodes.Ldarg, x); + else + ig.Emit (OpCodes.Ldarg_S, (byte) x); + break; } - - AddressOp mode = AddressOp.Store; - if (ArgType == AType.Ref) - mode |= AddressOp.Load; - - IMemoryLocation ml = (IMemoryLocation) Expr; - ParameterReference pr = ml as ParameterReference; - - // - // ParameterReferences might already be references, so we want - // to pass just the value - // - if (pr != null && pr.IsRef) - pr.EmitLoad (ec); - else - ml.AddressOf (ec, mode); - } - - public Argument Clone (CloneContext clonectx) - { - return new Argument (Expr.Clone (clonectx), ArgType); } } - + /// /// Invocation of methods or delegates. /// - public class Invocation : ExpressionStatement { - protected ArrayList Arguments; + public class Invocation : ExpressionStatement + { + protected Arguments arguments; protected Expression expr; protected MethodGroupExpr mg; bool arguments_resolved; @@ -4675,7 +4638,7 @@ namespace Mono.CSharp { // arguments is an ArrayList, but we do not want to typecast, // as it might be null. // - public Invocation (Expression expr, ArrayList arguments) + public Invocation (Expression expr, Arguments arguments) { SimpleName sn = expr as SimpleName; if (sn != null) @@ -4683,12 +4646,12 @@ namespace Mono.CSharp { else this.expr = expr; - Arguments = arguments; + this.arguments = arguments; if (expr != null) loc = expr.Location; } - public Invocation (Expression expr, ArrayList arguments, bool arguments_resolved) + public Invocation (Expression expr, Arguments arguments, bool arguments_resolved) : this (expr, arguments) { this.arguments_resolved = arguments_resolved; @@ -4696,47 +4659,24 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args; + Arguments args; // // Special conversion for nested expression trees // if (TypeManager.DropGenericTypeArguments (type) == TypeManager.expression_type) { - args = new ArrayList (1); + args = new Arguments (1); args.Add (new Argument (this)); return CreateExpressionFactoryCall ("Quote", args); } - ExtensionMethodGroupExpr emg = mg as ExtensionMethodGroupExpr; - - int arg_count = Arguments == null ? 2 : Arguments.Count + 2; - if (emg != null) - ++arg_count; - args = new ArrayList (arg_count); - - if (mg.IsInstance) - args.Add (new Argument (mg.InstanceExpression.CreateExpressionTree (ec))); - else - args.Add (new Argument (new NullLiteral (loc))); - - args.Add (new Argument (mg.CreateExpressionTree (ec))); - - // - // Use extension argument when exists - // - if (emg != null) { - Expression e = emg.ExtensionExpression.CreateExpressionTree (ec); - if (e != null) - args.Add (new Argument (e)); - } + Expression instance = mg.IsInstance ? + mg.InstanceExpression.CreateExpressionTree (ec) : + new NullLiteral (loc); - if (Arguments != null) { - foreach (Argument a in Arguments) { - Expression e = a.Expr.CreateExpressionTree (ec); - if (e != null) - args.Add (new Argument (e)); - } - } + args = Arguments.CreateForExpressionTree (ec, arguments, + instance, + mg.CreateExpressionTree (ec)); if (mg.IsBase) MemberExpr.Error_BaseAccessInExpressionTree (loc); @@ -4758,9 +4698,14 @@ namespace Mono.CSharp { if (mg == null) { Type expr_type = expr_resolved.Type; + if (expr_type == InternalType.Dynamic) { + Arguments args = ((DynamicMemberBinder) expr_resolved).Arguments; + return new DynamicInvocation (expr as MemberAccess, args, loc).Resolve (ec); + } + if (expr_type != null && TypeManager.IsDelegateType (expr_type)){ return (new DelegateInvocation ( - expr_resolved, Arguments, loc)).Resolve (ec); + expr_resolved, arguments, loc)).Resolve (ec); } MemberExpr me = expr_resolved as MemberExpr; @@ -4782,12 +4727,8 @@ namespace Mono.CSharp { // // Next, evaluate all the expressions in the argument list // - if (Arguments != null && !arguments_resolved) { - for (int i = 0; i < Arguments.Count; ++i) - { - if (!((Argument)Arguments[i]).Resolve(ec, loc)) - return null; - } + if (arguments != null && !arguments_resolved) { + arguments.Resolve (ec); } mg = DoResolveOverload (ec); @@ -4810,7 +4751,7 @@ namespace Mono.CSharp { return null; } } else { - if (iexpr == null) { + if (iexpr == null || iexpr == EmptyExpression.Null) { SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ()); } } @@ -4831,7 +4772,7 @@ namespace Mono.CSharp { return null; } - if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == "Finalize") { + if (arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == Destructor.MetadataName) { if (mg.IsBase) Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor"); else @@ -4850,7 +4791,7 @@ namespace Mono.CSharp { protected virtual MethodGroupExpr DoResolveOverload (EmitContext ec) { - return mg.OverloadResolve (ec, ref Arguments, false, loc); + return mg.OverloadResolve (ec, ref arguments, false, loc); } public static bool IsSpecialMethodInvocation (MethodBase method, Location loc) @@ -4865,58 +4806,11 @@ namespace Mono.CSharp { return true; } - /// - /// Emits a list of resolved Arguments that are in the arguments - /// ArrayList. - /// - /// The MethodBase argument might be null if the - /// emission of the arguments is known not to contain - /// a `params' field (for example in constructors or other routines - /// that keep their arguments in this structure) - /// - /// if `dup_args' is true, a copy of the arguments will be left - /// on the stack. If `dup_args' is true, you can specify `this_arg' - /// which will be duplicated before any other args. Only EmitCall - /// should be using this interface. - /// - public static void EmitArguments (EmitContext ec, ArrayList arguments, bool dup_args, LocalTemporary this_arg) + static Type[] GetVarargsTypes (MethodBase mb, Arguments arguments) { - if (arguments == null) - return; - - int top = arguments.Count; - LocalTemporary [] temps = null; + AParametersCollection pd = TypeManager.GetParameterData (mb); - if (dup_args && top != 0) - temps = new LocalTemporary [top]; - - int argument_index = 0; - Argument a; - for (int i = 0; i < top; i++) { - a = (Argument) arguments [argument_index++]; - a.Emit (ec); - if (dup_args) { - ec.ig.Emit (OpCodes.Dup); - (temps [i] = new LocalTemporary (a.Type)).Store (ec); - } - } - - if (dup_args) { - if (this_arg != null) - this_arg.Emit (ec); - - for (int i = 0; i < top; i ++) { - temps [i].Emit (ec); - temps [i].Release (ec); - } - } - } - - static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments) - { - AParametersCollection pd = TypeManager.GetParameterData (mb); - - Argument a = (Argument) arguments [pd.Count - 1]; + Argument a = arguments [pd.Count - 1]; Arglist list = (Arglist) a.Expr; return list.ArgumentTypes; @@ -4931,7 +4825,7 @@ namespace Mono.CSharp { return false; method = TypeManager.DropGenericMethodArguments (method); - if (method.DeclaringType.Module == CodeGen.Module.Builder) { + if (method.DeclaringType.Module == RootContext.ToplevelTypes.Builder) { IMethodData md = TypeManager.GetMethod (method); if (md != null) return md.IsExcluded (); @@ -4961,7 +4855,7 @@ namespace Mono.CSharp { /// public static void EmitCall (EmitContext ec, bool is_base, Expression instance_expr, - MethodBase method, ArrayList Arguments, Location loc) + MethodBase method, Arguments Arguments, Location loc) { EmitCall (ec, is_base, instance_expr, method, Arguments, loc, false, false); } @@ -4974,7 +4868,7 @@ namespace Mono.CSharp { // only have been evaluated once. public static void EmitCall (EmitContext ec, bool is_base, Expression instance_expr, - MethodBase method, ArrayList Arguments, Location loc, + MethodBase method, Arguments Arguments, Location loc, bool dup_args, bool omit_args) { ILGenerator ig = ec.ig; @@ -4990,7 +4884,7 @@ namespace Mono.CSharp { bool is_static = method.IsStatic; if (!is_static){ this_call = instance_expr is This; - if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType)) + if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type)) struct_call = true; // @@ -5003,12 +4897,12 @@ namespace Mono.CSharp { // // Push the instance expression // - if (TypeManager.IsValueType (iexpr_type)) { + if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) { // // Special case: calls to a function declared in a // reference-type with a value-type argument need // to have their value boxed. - if (decl_type.IsValueType || + if (TypeManager.IsStruct (decl_type) || TypeManager.IsGenericParameter (iexpr_type)) { // // If the expression implements IMemoryLocation, then @@ -5032,6 +4926,9 @@ namespace Mono.CSharp { t = TypeManager.GetReferenceType (iexpr_type); } else { instance_expr.Emit (ec); + + // FIXME: should use instance_expr is IMemoryLocation + constraint. + // to help JIT to produce better code ig.Emit (OpCodes.Box, instance_expr.Type); t = TypeManager.object_type; } @@ -5050,19 +4947,20 @@ namespace Mono.CSharp { } } - if (!omit_args) - EmitArguments (ec, Arguments, dup_args, this_arg); - -#if GMCS_SOURCE - if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter)) - ig.Emit (OpCodes.Constrained, instance_expr.Type); -#endif + if (!omit_args && Arguments != null) + Arguments.Emit (ec, dup_args, this_arg); OpCode call_op; - if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) + if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) { call_op = OpCodes.Call; - else + } else { call_op = OpCodes.Callvirt; + +#if GMCS_SOURCE + if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter)) + ig.Emit (OpCodes.Constrained, instance_expr.Type); +#endif + } if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { Type[] varargs_types = GetVarargsTypes (method, Arguments); @@ -5084,7 +4982,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - mg.EmitCall (ec, Arguments); + mg.EmitCall (ec, arguments); } public override void EmitStatement (EmitContext ec) @@ -5102,11 +5000,8 @@ namespace Mono.CSharp { { Invocation target = (Invocation) t; - if (Arguments != null) { - target.Arguments = new ArrayList (Arguments.Count); - foreach (Argument a in Arguments) - target.Arguments.Add (a.Clone (clonectx)); - } + if (arguments != null) + target.arguments = arguments.Clone (clonectx); target.expr = expr.Clone (clonectx); } @@ -5114,13 +5009,13 @@ namespace Mono.CSharp { public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { mg.MutateHoistedGenericType (storey); - if (Arguments != null) { - foreach (Argument a in Arguments) - a.Expr.MutateHoistedGenericType (storey); + type = storey.MutateType (type); + if (arguments != null) { + arguments.MutateHoistedGenericType (storey); } } } - +/* // // It's either a cast or delegate invocation // @@ -5226,87 +5121,32 @@ namespace Mono.CSharp { target.argument = argument.Clone (clonectx); } } +*/ - // - // This class is used to "disable" the code generation for the - // temporary variable when initializing value types. - // - sealed class EmptyAddressOf : EmptyExpression, IMemoryLocation { - public void AddressOf (EmitContext ec, AddressOp Mode) - { - // nothing - } - } - /// /// Implements the new expression /// public class New : ExpressionStatement, IMemoryLocation { - ArrayList Arguments; + Arguments Arguments; // // During bootstrap, it contains the RequestedType, // but if `type' is not null, it *might* contain a NewDelegate // (because of field multi-initialization) // - public Expression RequestedType; + Expression RequestedType; MethodGroupExpr method; - // - // If set, the new expression is for a value_target, and - // we will not leave anything on the stack. - // - protected Expression value_target; - protected bool value_target_set; - bool is_type_parameter = false; - - public New (Expression requested_type, ArrayList arguments, Location l) + bool is_type_parameter; + + public New (Expression requested_type, Arguments arguments, Location l) { RequestedType = requested_type; Arguments = arguments; loc = l; } - public bool SetTargetVariable (Expression value) - { - value_target = value; - value_target_set = true; - if (!(value_target is IMemoryLocation)){ - Error_UnexpectedKind (null, "variable", loc); - return false; - } - return true; - } - - // - // This function is used to disable the following code sequence for - // value type initialization: - // - // AddressOf (temporary) - // Construct/Init - // LoadTemporary - // - // Instead the provide will have provided us with the address on the - // stack to store the results. - // - static Expression MyEmptyExpression; - - public void DisableTemporaryValueType () - { - if (MyEmptyExpression == null) - MyEmptyExpression = new EmptyAddressOf (); - - // - // To enable this, look into: - // test-34 and test-89 and self bootstrapping. - // - // For instance, we can avoid a copy by using `newobj' - // instead of Call + Push-temp on value types. -// value_target = MyEmptyExpression; - } - - /// /// Converts complex core type syntax like 'new int ()' to simple constant /// @@ -5340,6 +5180,8 @@ namespace Mono.CSharp { return new DecimalConstant (0, Location.Null); if (TypeManager.IsEnumType (t)) return new EnumConstant (Constantify (TypeManager.GetEnumUnderlyingType (t)), t); + if (TypeManager.IsNullableType (t)) + return Nullable.LiftedNull.Create (t, Location.Null); return null; } @@ -5369,21 +5211,13 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = Arguments == null ? - new ArrayList (1) : new ArrayList (Arguments.Count + 1); - + Arguments args; if (method == null) { + args = new Arguments (1); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); } else { - args.Add (new Argument (method.CreateExpressionTree (ec))); - if (Arguments != null) { - Expression expr; - foreach (Argument a in Arguments) { - expr = a.Expr.CreateExpressionTree (ec); - if (expr != null) - args.Add (new Argument (expr)); - } - } + args = Arguments.CreateForExpressionTree (ec, Arguments, + method.CreateExpressionTree (ec)); } return CreateExpressionFactoryCall ("New", args); @@ -5427,8 +5261,7 @@ namespace Mono.CSharp { return (new NewDelegate (type, Arguments, loc)).Resolve (ec); } -#if GMCS_SOURCE - if (type.IsGenericParameter) { + if (TypeManager.IsGenericParameter (type)) { GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type); if ((gc == null) || (!gc.HasConstructorConstraint && !gc.IsValueType)) { @@ -5460,7 +5293,6 @@ namespace Mono.CSharp { eclass = ExprClass.Value; return this; } -#endif if (type.IsAbstract && type.IsSealed) { Report.SymbolRelatedToPreviousError (type); @@ -5480,7 +5312,7 @@ namespace Mono.CSharp { return null; } - bool is_struct = type.IsValueType; + bool is_struct = TypeManager.IsStruct (type); eclass = ExprClass.Value; // @@ -5494,12 +5326,8 @@ namespace Mono.CSharp { Expression ml = MemberLookupFinal (ec, type, type, ".ctor", MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc); - if (Arguments != null){ - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return null; - } - } + if (Arguments != null) + Arguments.Resolve (ec); if (ml == null) return null; @@ -5550,7 +5378,7 @@ namespace Mono.CSharp { temp.AddressOf (ec, AddressOp.Store); ig.Emit (OpCodes.Initobj, type); temp.Emit (ec); - ig.Emit (OpCodes.Br, label_end); + ig.Emit (OpCodes.Br_S, label_end); ig.MarkLabel (label_activator); @@ -5563,14 +5391,10 @@ namespace Mono.CSharp { } // - // This DoEmit can be invoked in two contexts: + // This Emit can be invoked in two contexts: // * As a mechanism that will leave a value on the stack (new object) // * As one that wont (init struct) // - // You can control whether a value is required on the stack by passing - // need_value_on_stack. The code *might* leave a value on the stack - // so it must be popped manually - // // If we are dealing with a ValueType, we have a few // situations to deal with: // @@ -5586,68 +5410,81 @@ namespace Mono.CSharp { // // Returns whether a value is left on the stack // - bool DoEmit (EmitContext ec, bool need_value_on_stack) + // *** Implementation note *** + // + // To benefit from this optimization, each assignable expression + // has to manually cast to New and call this Emit. + // + // TODO: It's worth to implement it for arrays and fields + // + public virtual bool Emit (EmitContext ec, IMemoryLocation target) { bool is_value_type = TypeManager.IsValueType (type); ILGenerator ig = ec.ig; + VariableReference vr = target as VariableReference; - if (is_value_type){ - IMemoryLocation ml; - - // Allow DoEmit() to be called multiple times. - // We need to create a new LocalTemporary each time since - // you can't share LocalBuilders among ILGeneators. - if (!value_target_set) - value_target = new LocalTemporary (type); - - ml = (IMemoryLocation) value_target; - ml.AddressOf (ec, AddressOp.Store); + if (target != null && is_value_type && (vr != null || method == null)) { + target.AddressOf (ec, AddressOp.Store); + } else if (vr != null && vr.IsRef) { + vr.EmitLoad (ec); } + + if (Arguments != null) + Arguments.Emit (ec); - if (method != null) - method.EmitArguments (ec, Arguments); - - if (is_value_type){ - if (method == null) + if (is_value_type) { + if (method == null) { ig.Emit (OpCodes.Initobj, type); - else + return false; + } + + if (vr != null) { ig.Emit (OpCodes.Call, (ConstructorInfo) method); - if (need_value_on_stack){ - value_target.Emit (ec); - return true; - } - return false; - } else { - ConstructorInfo ci = (ConstructorInfo) method; + return false; + } + } + + if (is_type_parameter) + return DoEmitTypeParameter (ec); + + ConstructorInfo ci = (ConstructorInfo) method; #if MS_COMPATIBLE - if (TypeManager.IsGenericType (type)) - ci = TypeBuilder.GetConstructor (type, ci); + if (TypeManager.IsGenericType (type)) + ci = TypeBuilder.GetConstructor (type, ci); #endif - ig.Emit (OpCodes.Newobj, ci); - return true; - } + + ig.Emit (OpCodes.Newobj, ci); + return true; } public override void Emit (EmitContext ec) { - if (is_type_parameter) - DoEmitTypeParameter (ec); - else - DoEmit (ec, true); + LocalTemporary v = null; + if (method == null && TypeManager.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } + + if (!Emit (ec, v)) + v.Emit (ec); } public override void EmitStatement (EmitContext ec) { - bool value_on_stack; - - if (is_type_parameter) - value_on_stack = DoEmitTypeParameter (ec); - else - value_on_stack = DoEmit (ec, false); + LocalTemporary v = null; + if (method == null && TypeManager.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } - if (value_on_stack) + if (Emit (ec, v)) ec.ig.Emit (OpCodes.Pop); + } + public bool IsDefaultValueType { + get { + return TypeManager.IsValueType (type) && !HasInitializer && Arguments == null; + } } public virtual bool HasInitializer { @@ -5656,17 +5493,23 @@ namespace Mono.CSharp { } } - public void AddressOf (EmitContext ec, AddressOp Mode) + public void AddressOf (EmitContext ec, AddressOp mode) { + EmitAddressOf (ec, mode); + } + + protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode) + { + LocalTemporary value_target = new LocalTemporary (type); + if (is_type_parameter) { - LocalTemporary temp = new LocalTemporary (type); DoEmitTypeParameter (ec); - temp.Store (ec); - temp.AddressOf (ec, Mode); - return; + value_target.Store (ec); + value_target.AddressOf (ec, mode); + return value_target; } - if (!type.IsValueType){ + if (!TypeManager.IsStruct (type)){ // // We throw an exception. So far, I believe we only need to support // value types: @@ -5676,19 +5519,19 @@ namespace Mono.CSharp { throw new Exception ("AddressOf should not be used for classes"); } - if (!value_target_set) - value_target = new LocalTemporary (type); - IMemoryLocation ml = (IMemoryLocation) value_target; + value_target.AddressOf (ec, AddressOp.Store); - ml.AddressOf (ec, AddressOp.Store); if (method == null) { ec.ig.Emit (OpCodes.Initobj, type); } else { - method.EmitArguments (ec, Arguments); + if (Arguments != null) + Arguments.Emit (ec); + ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method); } - ((IMemoryLocation) value_target).AddressOf (ec, Mode); + value_target.AddressOf (ec, mode); + return value_target; } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -5697,10 +5540,7 @@ namespace Mono.CSharp { target.RequestedType = RequestedType.Clone (clonectx); if (Arguments != null){ - target.Arguments = new ArrayList (); - foreach (Argument a in Arguments){ - target.Arguments.Add (a.Clone (clonectx)); - } + target.Arguments = Arguments.Clone (clonectx); } } @@ -5709,8 +5549,7 @@ namespace Mono.CSharp { if (method != null) { method.MutateHoistedGenericType (storey); if (Arguments != null) { - foreach (Argument a in Arguments) - a.Expr.MutateHoistedGenericType (storey); + Arguments.MutateHoistedGenericType (storey); } } @@ -5762,7 +5601,7 @@ namespace Mono.CSharp { arguments = new ArrayList (exprs.Count); foreach (Expression e in exprs) { - arguments.Add (new Argument (e, Argument.AType.Expression)); + arguments.Add (e); num_arguments++; } } @@ -5791,64 +5630,51 @@ namespace Mono.CSharp { { Report.Error (248, loc, "Cannot create an array with a negative size"); } - - bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) + + bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims, int child_bounds) { if (specified_dims) { - Argument a = (Argument) arguments [idx]; - - if (!a.Resolve (ec, loc)) + Expression a = (Expression) arguments [idx]; + a = a.Resolve (ec); + if (a == null) return false; - Constant c = a.Expr as Constant; + Constant c = a as Constant; if (c != null) { - c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Expr.Location); + c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Location); } if (c == null) { - Report.Error (150, a.Expr.Location, "A constant value is expected"); + Report.Error (150, a.Location, "A constant value is expected"); return false; } int value = (int) c.GetValue (); if (value != probe.Count) { - Error_IncorrectArrayInitializer (loc); + Report.Error (847, loc, "An array initializer of length `{0}' was expected", value); return false; } bounds [idx] = value; } - int child_bounds = -1; only_constant_initializers = true; for (int i = 0; i < probe.Count; ++i) { object o = probe [i]; if (o is ArrayList) { ArrayList sub_probe = o as ArrayList; - int current_bounds = sub_probe.Count; - - if (child_bounds == -1) - child_bounds = current_bounds; - - else if (child_bounds != current_bounds){ - Error_IncorrectArrayInitializer (loc); - return false; - } if (idx + 1 >= dimensions){ Error (623, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); return false; } - bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims); + bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); if (!ret) return false; + } else if (child_bounds > 1) { + Report.Error (846, ((Expression) o).Location, "A nested array initializer was expected"); } else { - if (child_bounds != -1){ - Error_IncorrectArrayInitializer (loc); - return false; - } - Expression element = ResolveArrayElement (ec, (Expression) o); if (element == null) continue; @@ -5875,18 +5701,18 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args; + Arguments args; if (array_data == null) { - args = new ArrayList (arguments.Count + 1); + args = new Arguments (arguments.Count + 1); args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc))); - foreach (Argument a in arguments) { + foreach (Expression a in arguments) { if (arguments.Count == 1) { - Constant c = a.Expr as Constant; + Constant c = a as Constant; if (c.IsDefaultValue) return CreateExpressionFactoryCall ("NewArrayInit", args); } - args.Add (new Argument (a.Expr.CreateExpressionTree (ec))); + args.Add (new Argument (a.CreateExpressionTree (ec))); } return CreateExpressionFactoryCall ("NewArrayBounds", args); @@ -5897,7 +5723,7 @@ namespace Mono.CSharp { return null; } - args = new ArrayList (array_data == null ? 1 : array_data.Count + 1); + args = new Arguments (array_data == null ? 1 : array_data.Count + 1); args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc))); if (array_data != null) { for (int i = 0; i < array_data.Count; ++i) { @@ -5918,7 +5744,7 @@ namespace Mono.CSharp { for (ArrayList probe = initializers; probe != null;) { if (probe.Count > 0 && probe [0] is ArrayList) { Expression e = new IntConstant (probe.Count, Location.Null); - arguments.Add (new Argument (e, Argument.AType.Expression)); + arguments.Add (e); bounds [i++] = probe.Count; @@ -5926,7 +5752,7 @@ namespace Mono.CSharp { } else { Expression e = new IntConstant (probe.Count, Location.Null); - arguments.Add (new Argument (e, Argument.AType.Expression)); + arguments.Add (e); bounds [i++] = probe.Count; return; @@ -5969,11 +5795,11 @@ namespace Mono.CSharp { bounds = new System.Collections.Specialized.HybridDictionary (); if (arguments != null) - return CheckIndices (ec, initializers, 0, true); + return CheckIndices (ec, initializers, 0, true, dimensions); arguments = new ArrayList (); - if (!CheckIndices (ec, initializers, 0, false)) + if (!CheckIndices (ec, initializers, 0, false, dimensions)) return false; UpdateIndices (); @@ -6040,15 +5866,12 @@ namespace Mono.CSharp { if (!ResolveInitializers (ec)) return null; - if (arguments.Count != dimensions) { - Error_IncorrectArrayInitializer (loc); - } - - foreach (Argument a in arguments){ - if (!a.Resolve (ec, loc)) + for (int i = 0; i < arguments.Count; ++i) { + Expression e = ((Expression) arguments[i]).Resolve (ec); + if (e == null) continue; - a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr); + arguments [i] = ConvertExpressionToArrayIndex (ec, e); } eclass = ExprClass.Value; @@ -6057,7 +5880,7 @@ namespace Mono.CSharp { MethodInfo GetArrayMethod (int arguments) { - ModuleBuilder mb = CodeGen.Module.Builder; + ModuleBuilder mb = RootContext.ToplevelTypes.Builder; Type[] arg_types = new Type[arguments]; for (int i = 0; i < arguments; i++) @@ -6230,13 +6053,18 @@ namespace Mono.CSharp { array_element_type = storey.MutateType (array_element_type); type = storey.MutateType (type); if (arguments != null) { - foreach (Argument a in arguments) - a.Expr.MutateHoistedGenericType (storey); + foreach (Expression e in arguments) + e.MutateHoistedGenericType (storey); } if (array_data != null) { - foreach (Expression e in array_data) + foreach (Expression e in array_data) { + // Don't mutate values optimized away + if (e == null) + continue; + e.MutateHoistedGenericType (storey); + } } } @@ -6290,8 +6118,8 @@ namespace Mono.CSharp { for (int j = 0; j < dims; j++) args [j] = TypeManager.int32_type; args [dims] = array_element_type; - - set = CodeGen.Module.Builder.GetArrayMethod ( + + set = RootContext.ToplevelTypes.Builder.GetArrayMethod ( type, "Set", CallingConventions.HasThis | CallingConventions.Standard, TypeManager.void_type, args); @@ -6314,18 +6142,9 @@ namespace Mono.CSharp { // If we are dealing with a struct, get the // address of it, so we can store it. // - if ((dims == 1) && etype.IsValueType && + if ((dims == 1) && TypeManager.IsStruct (etype) && (!TypeManager.IsBuiltinOrEnum (etype) || etype == TypeManager.decimal_type)) { - if (e is New){ - New n = (New) e; - - // - // Let new know that we are providing - // the address where to store the results - // - n.DisableTemporaryValueType (); - } ig.Emit (OpCodes.Ldelema, etype); } @@ -6367,8 +6186,8 @@ namespace Mono.CSharp { first_emit_temp.Store (ec); } - foreach (Argument a in arguments) - a.Emit (ec); + foreach (Expression e in arguments) + e.Emit (ec); if (arguments.Count == 1) ig.Emit (OpCodes.Newarr, array_element_type); @@ -6404,7 +6223,7 @@ namespace Mono.CSharp { } if (array_data == null) { - Constant c = (Constant)((Argument)arguments [0]).Expr; + Constant c = (Constant) arguments [0]; if (c.IsDefaultValue) { value = Array.CreateInstance (array_element_type, 0); return true; @@ -6442,8 +6261,8 @@ namespace Mono.CSharp { if (arguments != null){ target.arguments = new ArrayList (arguments.Count); - foreach (Argument a in arguments) - target.arguments.Add (a.Clone (clonectx)); + foreach (Expression e in arguments) + target.arguments.Add (e.Clone (clonectx)); } if (initializers != null){ @@ -6489,7 +6308,7 @@ namespace Mono.CSharp { return null; if (array_element_type == null || array_element_type == TypeManager.null_type || - array_element_type == TypeManager.void_type || array_element_type == TypeManager.anonymous_method_type || + array_element_type == TypeManager.void_type || array_element_type == InternalType.AnonymousMethod || arguments.Count != dimensions) { Error_NoBestType (); return null; @@ -6532,7 +6351,9 @@ namespace Mono.CSharp { return null; if (array_element_type == null) { - array_element_type = element.Type; + if (element.Type != TypeManager.null_type) + array_element_type = element.Type; + return element; } @@ -6573,8 +6394,9 @@ namespace Mono.CSharp { return this; } - public override HoistedVariable HoistedVariable { - get { return null; } + public override HoistedVariable GetHoistedVariable (EmitContext ec) + { + return null; } } @@ -6627,17 +6449,25 @@ namespace Mono.CSharp { get { return false; } } - protected override bool IsHoistedEmitRequired (EmitContext ec) + public override HoistedVariable GetHoistedVariable (EmitContext ec) { - // - // Handle 'this' differently, it cannot be assigned hence - // when we are not inside anonymous method we can emit direct access - // - return ec.CurrentAnonymousMethod != null && base.IsHoistedEmitRequired (ec); - } + // Is null when probing IsHoisted + if (ec == null) + return null; + + if (ec.CurrentAnonymousMethod == null) + return null; + + AnonymousMethodStorey storey = ec.CurrentAnonymousMethod.Storey; + while (storey != null) { + AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey; + if (temp == null) + return storey.HoistedThis; + + storey = temp; + } - public override HoistedVariable HoistedVariable { - get { return TopToplevelBlock.HoistedThisVariable; } + return null; } public override bool IsRef { @@ -6648,15 +6478,6 @@ namespace Mono.CSharp { get { return ThisVariable.Instance; } } - // TODO: Move to ToplevelBlock - ToplevelBlock TopToplevelBlock { - get { - ToplevelBlock tl = block.Toplevel; - while (tl.Parent != null) tl = tl.Parent.Toplevel; - return tl; - } - } - public static bool IsThisAvailable (EmitContext ec) { if (ec.IsStatic || ec.IsInFieldInitializer) @@ -6700,24 +6521,8 @@ namespace Mono.CSharp { variable_info = block.Toplevel.ThisVariable.VariableInfo; AnonymousExpression am = ec.CurrentAnonymousMethod; - if (am != null) { - // - // this is hoisted to very top level block - // - if (ec.IsVariableCapturingRequired) { - // - // TODO: it should be optimized, see test-anon-75.cs - // - // `this' variable has its own scope which is mostly empty - // and causes creation of extraneous storey references. - // Also it's hard to remove `this' dependencies when we Undo - // this access. - // - AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec); - if (HoistedVariable == null) { - TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this); - } - } + if (am != null && ec.IsVariableCapturingRequired) { + am.SetHasThisAccess (); } } @@ -6729,7 +6534,7 @@ namespace Mono.CSharp { // public override void CheckMarshalByRefAccess (EmitContext ec) { - if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) && + if ((variable_info != null) && !(TypeManager.IsStruct (type) && ec.OmitStructFlowAnalysis) && !variable_info.IsAssigned (ec)) { Error (188, "The `this' object cannot be used before all of its " + "fields are assigned to"); @@ -6739,9 +6544,11 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (1); args.Add (new Argument (this)); - args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + + // Use typeless constant for ldarg.0 to save some + // space and avoid problems with anonymous stories return CreateExpressionFactoryCall ("Constant", args); } @@ -6804,11 +6611,6 @@ namespace Mono.CSharp { target.block = clonectx.LookupBlock (block); } - public void RemoveHoisting () - { - TopToplevelBlock.HoistedThisVariable = null; - } - public override void SetHasAddressTaken () { // Nothing @@ -6839,7 +6641,7 @@ namespace Mono.CSharp { { Error (190, "The __arglist construct is valid only within " + "a variable argument method"); - return null; + return this; } return this; @@ -6859,28 +6661,32 @@ namespace Mono.CSharp { /// /// Represents the `__arglist (....)' construct /// - public class Arglist : Expression + class Arglist : Expression { - Argument[] Arguments; + Arguments Arguments; public Arglist (Location loc) - : this (Argument.Empty, loc) + : this (null, loc) { } - public Arglist (Argument[] args, Location l) + public Arglist (Arguments args, Location l) { Arguments = args; loc = l; } public Type[] ArgumentTypes { - get { - Type[] retval = new Type [Arguments.Length]; - for (int i = 0; i < Arguments.Length; i++) - retval [i] = Arguments [i].Type; - return retval; - } + get { + if (Arguments == null) + return Type.EmptyTypes; + + Type[] retval = new Type [Arguments.Count]; + for (int i = 0; i < retval.Length; i++) + retval [i] = Arguments [i].Expr.Type; + + return retval; + } } public override Expression CreateExpressionTree (EmitContext ec) @@ -6892,35 +6698,31 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { eclass = ExprClass.Variable; - type = TypeManager.runtime_argument_handle_type; - - foreach (Argument arg in Arguments) { - if (!arg.Resolve (ec, loc)) - return null; - } + type = InternalType.Arglist; + if (Arguments != null) + Arguments.Resolve (ec); return this; } public override void Emit (EmitContext ec) { - foreach (Argument arg in Arguments) - arg.Emit (ec); + if (Arguments != null) + Arguments.Emit (ec); } public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - foreach (Argument arg in Arguments) - arg.Expr.MutateHoistedGenericType (storey); + if (Arguments != null) + Arguments.MutateHoistedGenericType (storey); } protected override void CloneTo (CloneContext clonectx, Expression t) { Arglist target = (Arglist) t; - target.Arguments = new Argument [Arguments.Length]; - for (int i = 0; i < Arguments.Length; i++) - target.Arguments [i] = Arguments [i].Clone (clonectx); + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); } } @@ -6939,7 +6741,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (this)); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); return CreateExpressionFactoryCall ("Constant", args); @@ -7100,7 +6902,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (this)); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); return CreateExpressionFactoryCall ("Constant", args); @@ -7275,7 +7077,7 @@ namespace Mono.CSharp { public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { if (alias == GlobalAlias) { - expr = RootNamespace.Global; + expr = GlobalRootNamespace.Instance; return base.ResolveAsTypeStep (ec, silent); } @@ -7355,8 +7157,6 @@ namespace Mono.CSharp { this.expr = expr; } - // TODO: this method has very poor performace for Enum fields and - // probably for other constants as well Expression DoResolve (EmitContext ec, Expression right_side) { if (type != null) @@ -7379,22 +7179,30 @@ namespace Mono.CSharp { string LookupIdentifier = MemberName.MakeName (Name, targs); - if (expr_resolved is Namespace) { - Namespace ns = (Namespace) expr_resolved; + Namespace ns = expr_resolved as Namespace; + if (ns != null) { FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc); -#if GMCS_SOURCE - if ((retval != null) && (targs != null)) - retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (ec, false); -#endif if (retval == null) - ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Name); + ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, LookupIdentifier); + else if (targs != null) + retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false); + return retval; } Type expr_type = expr_resolved.Type; + if (expr_type == InternalType.Dynamic) { + Arguments args = new Arguments (2); + args.Add (new Argument (expr_resolved.Resolve (ec))); + if (right_side != null) + args.Add (new Argument (right_side)); + + return new DynamicMemberBinder (right_side != null, Name, args, loc).Resolve (ec); + } + if (expr_type.IsPointer || expr_type == TypeManager.void_type || - expr_resolved is NullLiteral || expr_type == TypeManager.anonymous_method_type) { + expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) { Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type); return null; } @@ -7413,12 +7221,12 @@ namespace Mono.CSharp { Expression member_lookup; member_lookup = MemberLookup ( ec.ContainerType, expr_type, expr_type, Name, loc); -#if GMCS_SOURCE - if ((member_lookup == null) && (targs != null)) { + + if (member_lookup == null && targs != null) { member_lookup = MemberLookup ( ec.ContainerType, expr_type, expr_type, LookupIdentifier, loc); } -#endif + if (member_lookup == null) { ExprClass expr_eclass = expr_resolved.eclass; @@ -7441,10 +7249,11 @@ namespace Mono.CSharp { } expr = expr_resolved; - Error_MemberLookupFailed ( + member_lookup = Error_MemberLookupFailed ( ec.ContainerType, expr_type, expr_type, Name, null, AllMemberTypes, AllBindingFlags); - return null; + if (member_lookup == null) + return null; } TypeExpr texpr = member_lookup as TypeExpr; @@ -7462,8 +7271,7 @@ namespace Mono.CSharp { return null; } -#if GMCS_SOURCE - ConstructedType ct = expr_resolved as ConstructedType; + GenericTypeExpr ct = expr_resolved as GenericTypeExpr; if (ct != null) { // // When looking up a nested type in a generic instance @@ -7472,12 +7280,12 @@ namespace Mono.CSharp { // // See gtest-172-lib.cs and gtest-172.cs for an example. // - ct = new ConstructedType ( + ct = new GenericTypeExpr ( member_lookup.Type, ct.TypeArguments, loc); return ct.ResolveAsTypeStep (ec, false); } -#endif + return member_lookup; } @@ -7524,26 +7332,26 @@ namespace Mono.CSharp { public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent) { - FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent); + FullNamedExpression expr_resolved = expr.ResolveAsTypeStep (rc, silent); - if (new_expr == null) + if (expr_resolved == null) return null; string LookupIdentifier = MemberName.MakeName (Name, targs); - if (new_expr is Namespace) { - Namespace ns = (Namespace) new_expr; + Namespace ns = expr_resolved as Namespace; + if (ns != null) { FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc); -#if GMCS_SOURCE - if ((retval != null) && (targs != null)) - retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (rc, false); -#endif - if (!silent && retval == null) + + if (retval == null && !silent) ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier); + else if (targs != null) + retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent); + return retval; } - TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (rc, false); + TypeExpr tnew_expr = expr_resolved.ResolveAsTypeTerminal (rc, false); if (tnew_expr == null) return null; @@ -7561,7 +7369,7 @@ namespace Mono.CSharp { if (silent) return null; - Error_IdentifierNotFound (rc, new_expr, LookupIdentifier); + Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier); return null; } @@ -7569,15 +7377,14 @@ namespace Mono.CSharp { if (texpr == null) return null; -#if GMCS_SOURCE TypeArguments the_args = targs; Type declaring_type = texpr.Type.DeclaringType; - if (TypeManager.HasGenericArguments (declaring_type)) { + if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) { while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) { expr_type = expr_type.BaseType; } - TypeArguments new_args = new TypeArguments (loc); + TypeArguments new_args = new TypeArguments (); foreach (Type decl in TypeManager.GetTypeArguments (expr_type)) new_args.Add (new TypeExpression (decl, loc)); @@ -7588,10 +7395,9 @@ namespace Mono.CSharp { } if (the_args != null) { - ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc); + GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc); return ctype.ResolveAsTypeStep (rc, false); } -#endif return texpr; } @@ -7607,7 +7413,7 @@ namespace Mono.CSharp { if (expr_type == null) return; - Namespace.Error_TypeArgumentsCannotBeUsed (expr_type.Type, loc); + Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc); return; } @@ -7678,7 +7484,7 @@ namespace Mono.CSharp { if (Expr == null) return null; - if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression) + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) return Expr; eclass = Expr.eclass; @@ -7738,7 +7544,7 @@ namespace Mono.CSharp { if (Expr == null) return null; - if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression) + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) return Expr; eclass = Expr.eclass; @@ -7778,43 +7584,30 @@ namespace Mono.CSharp { /// IndexerAccess, ArrayAccess or a PointerArithmetic. /// public class ElementAccess : Expression { - public ArrayList Arguments; + public Arguments Arguments; public Expression Expr; - - public ElementAccess (Expression e, ArrayList e_list) + + public ElementAccess (Expression e, Arguments args) { Expr = e; loc = e.Location; - - if (e_list == null) - return; - - Arguments = new ArrayList (e_list.Count); - foreach (Expression tmp in e_list) - Arguments.Add (new Argument (tmp, Argument.AType.Expression)); + this.Arguments = args; } bool CommonResolve (EmitContext ec) { Expr = Expr.Resolve (ec); - if (Arguments == null) - return false; - - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return false; - } + if (Arguments != null) + Arguments.Resolve (ec); return Expr != null; } public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (Arguments.Count + 1); - args.Add (new Argument (Expr.CreateExpressionTree (ec))); - foreach (Argument a in Arguments) - args.Add (new Argument (a.Expr.CreateExpressionTree (ec))); + Arguments args = Arguments.CreateForExpressionTree (ec, Arguments, + Expr.CreateExpressionTree (ec)); return CreateExpressionFactoryCall ("ArrayIndex", args); } @@ -7826,7 +7619,10 @@ namespace Mono.CSharp { return null; } - Expression p = new PointerArithmetic (Binary.Operator.Addition, Expr, ((Argument) Arguments [0]).Expr, t, loc).Resolve (ec); + if (Arguments [0] is NamedArgument) + Error_NamedArgument ((NamedArgument) Arguments[0]); + + Expression p = new PointerArithmetic (Binary.Operator.Addition, Expr, Arguments [0].Expr, t, loc).Resolve (ec); if (p == null) return null; return new Indirection (p, loc).Resolve (ec); @@ -7855,6 +7651,13 @@ namespace Mono.CSharp { if (t.IsPointer) return MakePointerAccess (ec, t); + if (t == InternalType.Dynamic) { + Arguments args = new Arguments (Arguments.Count + 1); + args.Add (new Argument (Expr)); + args.AddRange (Arguments); + return new DynamicIndexBinder (false, args, loc).Resolve (ec); + } + FieldExpr fe = Expr as FieldExpr; if (fe != null) { IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo); @@ -7877,7 +7680,15 @@ namespace Mono.CSharp { if (type.IsPointer) return MakePointerAccess (ec, type); - if (Expr.eclass != ExprClass.Variable && type.IsValueType) + if (type == InternalType.Dynamic) { + Arguments args = new Arguments (Arguments.Count + 2); + args.Add (new Argument (Expr)); + args.AddRange (Arguments); + args.Add (new Argument (right_side)); + return new DynamicIndexBinder (true, args, loc).Resolve (ec); + } + + if (Expr.eclass != ExprClass.Variable && TypeManager.IsStruct (type)) Error_CannotModifyIntermediateExpressionValue (ec); return (new IndexerAccess (this, loc)).DoResolveLValue (ec, right_side); @@ -7888,6 +7699,11 @@ namespace Mono.CSharp { throw new Exception ("Should never be reached"); } + public static void Error_NamedArgument (NamedArgument na) + { + Report.Error (1742, na.Name.Location, "An element access expression cannot use named argument"); + } + public override string GetSignatureForError () { return Expr.GetSignatureForError (); @@ -7898,9 +7714,8 @@ namespace Mono.CSharp { ElementAccess target = (ElementAccess) t; target.Expr = Expr.Clone (clonectx); - target.Arguments = new ArrayList (Arguments.Count); - foreach (Argument a in Arguments) - target.Arguments.Add (a.Clone (clonectx)); + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); } } @@ -7964,6 +7779,9 @@ namespace Mono.CSharp { } foreach (Argument a in ea.Arguments) { + if (a is NamedArgument) + ElementAccess.Error_NamedArgument ((NamedArgument) a); + a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr); } @@ -8008,7 +7826,7 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldelem_I); else if (TypeManager.IsEnumType (type)){ EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank); - } else if (type.IsValueType){ + } else if (TypeManager.IsStruct (type)){ ig.Emit (OpCodes.Ldelema, type); ig.Emit (OpCodes.Ldobj, type); #if GMCS_SOURCE @@ -8055,7 +7873,7 @@ namespace Mono.CSharp { has_type_arg = true; is_stobj = true; return OpCodes.Stobj; - } else if (t.IsValueType) { + } else if (TypeManager.IsStruct (t)) { has_type_arg = true; is_stobj = true; return OpCodes.Stobj; @@ -8073,7 +7891,7 @@ namespace Mono.CSharp { MethodInfo FetchGetMethod () { - ModuleBuilder mb = CodeGen.Module.Builder; + ModuleBuilder mb = RootContext.ToplevelTypes.Builder; int arg_count = ea.Arguments.Count; Type [] args = new Type [arg_count]; MethodInfo get; @@ -8094,7 +7912,7 @@ namespace Mono.CSharp { MethodInfo FetchAddressMethod () { - ModuleBuilder mb = CodeGen.Module.Builder; + ModuleBuilder mb = RootContext.ToplevelTypes.Builder; int arg_count = ea.Arguments.Count; Type [] args = new Type [arg_count]; MethodInfo address; @@ -8124,7 +7942,7 @@ namespace Mono.CSharp { ea.Expr.Emit (ec); for (int i = 0; i < ea.Arguments.Count; ++i) { - ((Argument)ea.Arguments [i]).Emit (ec); + ea.Arguments [i].Emit (ec); } } @@ -8214,7 +8032,7 @@ namespace Mono.CSharp { } args [arg_count] = type; - MethodInfo set = CodeGen.Module.Builder.GetArrayMethod ( + MethodInfo set = RootContext.ToplevelTypes.Builder.GetArrayMethod ( ea.Expr.Type, "Set", CallingConventions.HasThis | CallingConventions.Standard, @@ -8230,6 +8048,18 @@ namespace Mono.CSharp { } } + public void EmitNew (EmitContext ec, New source, bool leave_copy) + { + if (!source.Emit (ec, this)) { + if (leave_copy) + throw new NotImplementedException (); + + return; + } + + throw new NotImplementedException (); + } + public void AddressOf (EmitContext ec, AddressOp mode) { int rank = ea.Expr.Type.GetArrayRank (); @@ -8330,14 +8160,18 @@ namespace Mono.CSharp { { Indexers ix = new Indexers (); - #if GMCS_SOURCE - if (lookup_type.IsGenericParameter) { + if (TypeManager.IsGenericParameter (lookup_type)) { GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type); if (gc == null) return ix; - if (gc.HasClassConstraint) - ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, gc.ClassConstraint)); + if (gc.HasClassConstraint) { + Type class_contraint = gc.ClassConstraint; + while (class_contraint != TypeManager.object_type && class_contraint != null) { + ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, class_contraint)); + class_contraint = class_contraint.BaseType; + } + } Type[] ifaces = gc.InterfaceConstraints; foreach (Type itype in ifaces) @@ -8345,7 +8179,6 @@ namespace Mono.CSharp { return ix; } - #endif Type copy = lookup_type; while (copy != TypeManager.object_type && copy != null){ @@ -8384,7 +8217,7 @@ namespace Mono.CSharp { protected Type indexer_type; protected Type current_type; protected Expression instance_expr; - protected ArrayList arguments; + protected Arguments arguments; public IndexerAccess (ElementAccess ea, Location loc) : this (ea.Expr, false, loc) @@ -8414,11 +8247,9 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (arguments.Count + 2); - args.Add (new Argument (instance_expr.CreateExpressionTree (ec))); - args.Add (new Argument (new TypeOfMethodInfo (get, loc))); - foreach (Argument a in arguments) - args.Add (new Argument (a.Expr.CreateExpressionTree (ec))); + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + instance_expr.CreateExpressionTree (ec), + new TypeOfMethodInfo (get, loc)); return CreateExpressionFactoryCall ("Call", args); } @@ -8584,7 +8415,9 @@ namespace Mono.CSharp { value = temp; } - arguments.Add (new Argument (value, Argument.AType.Expression)); + if (!prepared) + arguments.Add (new Argument (value)); + Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared); if (temp != null) { @@ -8611,8 +8444,8 @@ namespace Mono.CSharp { set = storey.MutateGenericMethod (set); instance_expr.MutateHoistedGenericType (storey); - foreach (Argument a in arguments) - a.Expr.MutateHoistedGenericType (storey); + if (arguments != null) + arguments.MutateHoistedGenericType (storey); type = storey.MutateType (type); } @@ -8621,11 +8454,9 @@ namespace Mono.CSharp { { IndexerAccess target = (IndexerAccess) t; - if (arguments != null){ - target.arguments = new ArrayList (); - foreach (Argument a in arguments) - target.arguments.Add (a.Clone (clonectx)); - } + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + if (instance_expr != null) target.instance_expr = instance_expr.Clone (clonectx); } @@ -8748,12 +8579,10 @@ namespace Mono.CSharp { /// The base indexer operator /// public class BaseIndexerAccess : IndexerAccess { - public BaseIndexerAccess (ArrayList args, Location loc) + public BaseIndexerAccess (Arguments args, Location loc) : base (null, true, loc) { - arguments = new ArrayList (); - foreach (Expression tmp in args) - arguments.Add (new Argument (tmp, Argument.AType.Expression)); + this.arguments = args; } protected override bool CommonResolve (EmitContext ec) @@ -8763,10 +8592,7 @@ namespace Mono.CSharp { current_type = ec.ContainerType.BaseType; indexer_type = current_type; - foreach (Argument a in arguments){ - if (!a.Resolve (ec, loc)) - return false; - } + arguments.Resolve (ec); return true; } @@ -8809,9 +8635,9 @@ namespace Mono.CSharp { temp = e; } - // TODO: should be protected - public EmptyExpression () + EmptyExpression () { + // FIXME: Don't set to object type = TypeManager.object_type; eclass = ExprClass.Value; loc = Location.Null; @@ -8863,7 +8689,6 @@ namespace Mono.CSharp { private EmptyExpressionStatement () { - type = TypeManager.object_type; eclass = ExprClass.Value; loc = Location.Null; } @@ -8880,6 +8705,7 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { + type = TypeManager.object_type; return this; } @@ -8909,7 +8735,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (3); + Arguments args = new Arguments (3); args.Add (new Argument (source.CreateExpressionTree (ec))); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); args.Add (new Argument (new TypeOfMethodInfo (method, loc))); @@ -8973,14 +8799,12 @@ namespace Mono.CSharp { return null; Type ltype = lexpr.Type; -#if GMCS_SOURCE if ((dim.Length > 0) && (dim [0] == '?')) { - TypeExpr nullable = new Nullable.NullableType (left, loc); + TypeExpr nullable = new Nullable.NullableType (lexpr, loc); if (dim.Length > 1) nullable = new ComposedCast (nullable, dim.Substring (1), loc); return nullable.ResolveAsTypeTerminal (ec, false); } -#endif if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc)) return null; @@ -9019,13 +8843,6 @@ namespace Mono.CSharp { return left.GetSignatureForError () + dim; } - protected override void CloneTo (CloneContext clonectx, Expression t) - { - ComposedCast target = (ComposedCast) t; - - target.left = (FullNamedExpression)left.Clone (clonectx); - } - public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) { return ResolveAsBaseTerminal (ec, silent); @@ -9101,7 +8918,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (child.CreateExpressionTree (ec))); args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc))); return CreateExpressionFactoryCall ("ConvertChecked", args); @@ -9228,7 +9045,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); FieldExpr fe = target as FieldExpr; if (fe != null) args.Add (new Argument (fe.CreateTypeOfExpression ())); @@ -9277,12 +9094,12 @@ namespace Mono.CSharp { // Constant c = source as Constant; if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable) - return EmptyExpressionStatement.Instance; + return EmptyExpressionStatement.Instance.DoResolve (ec); return expr; } - protected override Expression Error_MemberLookupFailed (MemberInfo[] members) + protected override Expression Error_MemberLookupFailed (Type type, MemberInfo[] members) { MemberInfo member = members [0]; if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field) @@ -9307,7 +9124,7 @@ namespace Mono.CSharp { // // A collection initializer expression // - public class CollectionElementInitializer : Invocation + class CollectionElementInitializer : Invocation { public class ElementInitializerArgument : Argument { @@ -9334,26 +9151,29 @@ namespace Mono.CSharp { } public CollectionElementInitializer (Expression argument) - : base (null, new ArrayList (1), true) + : base (null, new Arguments (1), true) { - Arguments.Add (argument); + base.arguments.Add (new ElementInitializerArgument (argument)); this.loc = argument.Location; } public CollectionElementInitializer (ArrayList arguments, Location loc) - : base (null, arguments, true) + : base (null, new Arguments (arguments.Count), true) { + foreach (Expression e in arguments) + base.arguments.Add (new ElementInitializerArgument (e)); + this.loc = loc; } public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (mg.CreateExpressionTree (ec))); - ArrayList expr_initializers = new ArrayList (Arguments.Count); - foreach (Argument a in Arguments) - expr_initializers.Add (a.Expr.CreateExpressionTree (ec)); + ArrayList expr_initializers = new ArrayList (arguments.Count); + foreach (Argument a in arguments) + expr_initializers.Add (a.CreateExpressionTree (ec)); args.Add (new Argument (new ArrayCreation ( CreateExpressionTypeExpression (loc), "[]", expr_initializers, loc))); @@ -9363,10 +9183,8 @@ namespace Mono.CSharp { protected override void CloneTo (CloneContext clonectx, Expression t) { CollectionElementInitializer target = (CollectionElementInitializer) t; - - target.Arguments = new ArrayList (Arguments.Count); - foreach (Expression e in Arguments) - target.Arguments.Add (e.Clone (clonectx)); + if (arguments != null) + target.arguments = arguments.Clone (clonectx); } public override Expression DoResolve (EmitContext ec) @@ -9376,18 +9194,8 @@ namespace Mono.CSharp { // TODO: We could call a constructor which takes element count argument, // for known types like List, Dictionary - - for (int i = 0; i < Arguments.Count; ++i) { - Expression expr = Arguments [i] as Expression; - if (expr == null) - return null; - expr = expr.Resolve (ec); - if (expr == null) - return null; - - Arguments [i] = new ElementInitializerArgument (expr); - } + arguments.Resolve (ec); base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc); @@ -9401,6 +9209,7 @@ namespace Mono.CSharp { public class CollectionOrObjectInitializers : ExpressionStatement { ArrayList initializers; + bool is_collection_initialization; public static readonly CollectionOrObjectInitializers Empty = new CollectionOrObjectInitializers (new ArrayList (0), Location.Null); @@ -9419,7 +9228,7 @@ namespace Mono.CSharp { public bool IsCollectionInitializer { get { - return type == typeof (CollectionOrObjectInitializers); + return is_collection_initialization; } } @@ -9449,7 +9258,6 @@ namespace Mono.CSharp { if (eclass != ExprClass.Invalid) return this; - bool is_collection_initialization = false; ArrayList element_names = null; for (int i = 0; i < initializers.Count; ++i) { Expression initializer = (Expression) initializers [i]; @@ -9459,9 +9267,11 @@ namespace Mono.CSharp { if (element_initializer != null) { element_names = new ArrayList (initializers.Count); element_names.Add (element_initializer.Name); + } else if (initializer is CompletingExpression){ + initializer.Resolve (ec); + throw new InternalErrorException ("This line should never be reached"); } else { - if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type, - TypeManager.ienumerable_type)) { + if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type, TypeManager.ienumerable_type)) { Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " + "object initializer because type `{1}' does not implement `{2}' interface", ec.CurrentInitializerVariable.GetSignatureForError (), @@ -9496,15 +9306,12 @@ namespace Mono.CSharp { initializers [i] = e; } + type = ec.CurrentInitializerVariable.Type; if (is_collection_initialization) { - if (TypeManager.HasElementType (ec.CurrentInitializerVariable.Type)) { + if (TypeManager.HasElementType (type)) { Report.Error (1925, loc, "Cannot initialize object of type `{0}' with a collection initializer", - TypeManager.CSharpName (ec.CurrentInitializerVariable.Type)); + TypeManager.CSharpName (type)); } - - type = typeof (CollectionOrObjectInitializers); - } else { - type = typeof (ElementInitializer); } eclass = ExprClass.Variable; @@ -9569,27 +9376,39 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - new_instance.value_target.Emit (ec); + Expression e = (Expression) new_instance.instance; + e.Emit (ec); } #region IMemoryLocation Members public void AddressOf (EmitContext ec, AddressOp mode) { - ((IMemoryLocation)new_instance.value_target).AddressOf (ec, mode); + new_instance.instance.AddressOf (ec, mode); } #endregion } CollectionOrObjectInitializers initializers; + IMemoryLocation instance; - public NewInitialize (Expression requested_type, ArrayList arguments, CollectionOrObjectInitializers initializers, Location l) + public NewInitialize (Expression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) : base (requested_type, arguments, l) { this.initializers = initializers; } + protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) + { + instance = base.EmitAddressOf (ec, Mode); + + if (!initializers.IsEmpty) + initializers.Emit (ec); + + return instance; + } + protected override void CloneTo (CloneContext clonectx, Expression t) { base.CloneTo (clonectx, t); @@ -9600,7 +9419,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (EmitContext ec) { - ArrayList args = new ArrayList (2); + Arguments args = new Arguments (2); args.Add (new Argument (base.CreateExpressionTree (ec))); if (!initializers.IsEmpty) args.Add (new Argument (initializers.CreateExpressionTree (ec))); @@ -9619,12 +9438,6 @@ namespace Mono.CSharp { if (type == null) return null; - // Empty initializer can be optimized to simple new - if (initializers.IsEmpty) { - initializers.Resolve (ec); - return ReducedExpression.Create (e, this).Resolve (ec); - } - Expression previous = ec.CurrentInitializerVariable; ec.CurrentInitializerVariable = new InitializerTargetExpression (this); initializers.Resolve (ec); @@ -9632,51 +9445,41 @@ namespace Mono.CSharp { return e; } - public override void Emit (EmitContext ec) + public override bool Emit (EmitContext ec, IMemoryLocation target) { - base.Emit (ec); + bool left_on_stack = base.Emit (ec, target); - // - // If target is non-hoisted variable, let's use it - // - VariableReference variable = value_target as VariableReference; - if (variable != null && variable.HoistedVariable == null) { - if (variable.IsRef) - StoreFromPtr (ec.ig, type); - else - variable.EmitAssign (ec, EmptyExpression.Null, false, false); - } else { - variable = null; - if (value_target == null || value_target_set) - value_target = new LocalTemporary (type); + if (initializers.IsEmpty) + return left_on_stack; - ((LocalTemporary) value_target).Store (ec); - } + LocalTemporary temp = target as LocalTemporary; + if (temp == null) { + if (!left_on_stack) { + VariableReference vr = target as VariableReference; + + // FIXME: This still does not work correctly for pre-set variables + if (vr != null && vr.IsRef) + target.AddressOf (ec, AddressOp.Load); - initializers.Emit (ec); + ((Expression) target).Emit (ec); + left_on_stack = true; + } - if (variable == null) { - value_target.Emit (ec); - value_target = null; + temp = new LocalTemporary (type); } - } - public override void EmitStatement (EmitContext ec) - { - if (initializers.IsEmpty) { - base.EmitStatement (ec); - return; - } + instance = temp; + if (left_on_stack) + temp.Store (ec); - base.Emit (ec); + initializers.Emit (ec); - if (value_target == null) { - LocalTemporary variable = new LocalTemporary (type); - variable.Store (ec); - value_target = variable; + if (left_on_stack) { + temp.Emit (ec); + temp.Release (ec); } - initializers.EmitStatement (ec); + return left_on_stack; } public override bool HasInitializer { @@ -9718,7 +9521,7 @@ namespace Mono.CSharp { AnonymousTypeClass CreateAnonymousType (ArrayList parameters) { - AnonymousTypeClass type = RootContext.ToplevelTypes.GetAnonymousType (parameters); + AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters); if (type != null) return type; @@ -9732,7 +9535,7 @@ namespace Mono.CSharp { if (Report.Errors == 0) type.CloseType (); - RootContext.ToplevelTypes.AddAnonymousType (type); + parent.Module.AddAnonymousType (type); return type; } @@ -9757,7 +9560,7 @@ namespace Mono.CSharp { } bool error = false; - ArrayList arguments = new ArrayList (parameters.Count); + Arguments arguments = new Arguments (parameters.Count); TypeExpression [] t_args = new TypeExpression [parameters.Count]; for (int i = 0; i < parameters.Count; ++i) { Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec); @@ -9777,8 +9580,8 @@ namespace Mono.CSharp { if (anonymous_type == null) return null; - ConstructedType te = new ConstructedType (anonymous_type.TypeBuilder, - new TypeArguments (loc, t_args), loc); + GenericTypeExpr te = new GenericTypeExpr (anonymous_type.TypeBuilder, + new TypeArguments (t_args), loc); return new New (te, arguments, loc).Resolve (ec); } @@ -9843,7 +9646,7 @@ namespace Mono.CSharp { type = e.Type; if (type == TypeManager.void_type || type == TypeManager.null_type || - type == TypeManager.anonymous_method_type || type.IsPointer) { + type == InternalType.AnonymousMethod || type.IsPointer) { Error_InvalidInitializer (e.GetSignatureForError ()); return null; }