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;
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);
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
- foreach (Argument a in arguments)
- a.Expr.MutateHoistedGenericType (storey);
-
+ arguments.MutateHoistedGenericType (storey);
mg.MutateHoistedGenericType (storey);
}
}
public ParenthesizedExpression (Expression expr)
{
- this.Expr = expr;
- this.loc = expr.Location;
+ Expr = expr;
+ loc = expr.Location;
}
public override Expression CreateExpressionTree (EmitContext ec)
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");
//
// Unary implements unary expressions.
//
- public class Unary : Expression {
+ public class Unary : Expression
+ {
public enum Operator : byte {
UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
AddressOf, TOP
public Expression Expr;
Expression enum_conversion;
- public Unary (Operator op, Expression expr, Location loc)
+ public Unary (Operator op, Expression expr)
{
- this.Oper = op;
- this.Expr = expr;
- this.loc = loc;
+ Oper = op;
+ Expr = expr;
+ loc = expr.Location;
}
// <summary>
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)
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)));
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.
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;
vi.SetAssigned (ec);
}
- is_fixed = vr.IsFixedVariable;
+ is_fixed = vr.IsFixed;
vr.SetHasAddressTaken ();
if (vr.IsHoisted) {
AnonymousMethodExpression.Error_AddressOfCapturedVar (vr, loc);
}
} else {
- //
- // A pointer-indirection is always fixed
- //
- is_fixed = Expr is Indirection;
+ IFixedExpression fe = Expr as IFixedExpression;
+ is_fixed = fe != null && fe.IsFixed;
}
if (!is_fixed && !ec.InFixedInitializer) {
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);
}
// after semantic analysis (this is so we can take the address
// of an indirection).
//
- public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod, IFixedExpression {
Expression expr;
LocalTemporary temporary;
bool prepared;
return this;
}
+ public bool IsFixed {
+ get { return true; }
+ }
+
public override string ToString ()
{
return "*(" + expr + ")";
//
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;
}
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
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;
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;
}
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);
}
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;
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);
}
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;
}
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);
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 {
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);
}
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);
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,
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)
{
//
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)
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);
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)
/// <summary>
/// Binary operators
/// </summary>
- public class Binary : Expression {
+ public class Binary : Expression, IDynamicBinder
+ {
protected class PredefinedOperator {
protected readonly Type left;
}
Type r_type = ReturnType;
+ Expression left_arg, right_arg;
if (r_type == null) {
- if (left == null)
+ if (left == null) {
+ left_arg = b.left;
+ right_arg = b.right;
r_type = b.left.Type;
- else
+ } else {
+ left_arg = b.right;
+ right_arg = b.left;
r_type = b.right.Type;
+ }
+ } else {
+ left_arg = b.left;
+ right_arg = b.right;
}
- return new PointerArithmetic (b.oper, b.left, b.right, r_type, b.loc).Resolve (ec);
+ return new PointerArithmetic (b.oper, left_arg, right_arg, r_type, b.loc).Resolve (ec);
}
}
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);
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;
// 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) {
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);
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;
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) {
return null;
}
- if (l == TypeManager.anonymous_method_type)
+ if (l == InternalType.AnonymousMethod)
return null;
if (TypeManager.IsValueType (l))
return null;
} else if (l.IsInterface) {
l = TypeManager.object_type;
- } else if (l.IsValueType) {
+ } else if (TypeManager.IsStruct (l)) {
return null;
}
return null;
} else if (r.IsInterface) {
r = TypeManager.object_type;
- } else if (r.IsValueType) {
+ } else if (TypeManager.IsStruct (r)) {
return null;
}
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);
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;
}
}
}
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)
{
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) {
// 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)
{
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);
}
//
//
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)
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);
}
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 (
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
- foreach (Argument a in arguments)
- a.Expr.MutateHoistedGenericType (storey);
+ arguments.MutateHoistedGenericType (storey);
}
}
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)
{
//
// Emit and duplicate left argument
//
- ((Argument)arguments [0]).Expr.Emit (ec);
+ arguments [0].Expr.Emit (ec);
ig.Emit (OpCodes.Dup);
arguments.RemoveAt (0);
//
// handle + and - on (pointer op int)
//
+ Constant left_const = left as Constant;
+ if (left_const != null) {
+ //
+ // Optimize ((T*)null) pointer operations
+ //
+ if (left_const.IsDefaultValue) {
+ left = EmptyExpression.Null;
+ } else {
+ left_const = null;
+ }
+ }
+
left.Emit (ec);
Constant right_const = right as Constant;
Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype);
}
- if (rtype == TypeManager.int64_type)
- ig.Emit (OpCodes.Conv_I);
- else if (rtype == TypeManager.uint64_type)
- ig.Emit (OpCodes.Conv_U);
+ if (left_const == null) {
+ if (rtype == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_I);
+ else if (rtype == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Conv_U);
- Binary.EmitOperatorOpcode (ec, op, op_type);
+ Binary.EmitOperatorOpcode (ec, op, op_type);
+ }
}
}
}
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)));
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) {
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;
LocalTemporary temp;
#region Abstract
- public abstract HoistedVariable HoistedVariable { get; }
- public abstract bool IsFixedVariable { get; }
+ public abstract HoistedVariable GetHoistedVariable (EmitContext ec);
+ public abstract bool IsFixed { get; }
public abstract bool IsRef { get; }
public abstract string Name { get; }
public abstract void SetHasAddressTaken ();
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;
}
{
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;
}
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) {
}
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)
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;
}
//
get { return local_info.VariableInfo; }
}
- public override HoistedVariable HoistedVariable {
- get { return local_info.HoistedVariableReference; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return local_info.HoistedVariableReference;
}
//
// A local variable is always fixed
//
- public override bool IsFixedVariable {
+ public override bool IsFixed {
get { return true; }
}
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);
}
}
}
+ resolved |= ec.DoFlowAnalysis;
+ eclass = ExprClass.Variable;
return this;
}
public override Expression DoResolve (EmitContext ec)
{
+ if (resolved)
+ return this;
+
ResolveLocalInfo ();
local_info.Used = true;
return DoResolveBase (ec);
}
- override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
ResolveLocalInfo ();
/// </summary>
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;
}
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;
}
//
// A ref or out parameter is classified as a moveable variable, even
// if the argument given for the parameter is a fixed variable
//
- public override bool IsFixedVariable {
+ public override bool IsFixed {
get { return !IsRef; }
}
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);
}
if (pr == null)
return false;
- return Name == pr.Name && referenced == pr.referenced;
+ return Name == pr.Name;
}
protected override void CloneTo (CloneContext clonectx, Expression target)
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 ();
}
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;
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);
- }
- }
-
- /// <summary>
- /// Used for arguments to New(), Invocation()
- /// </summary>
- 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);
}
}
-
+
/// <summary>
/// Invocation of methods or delegates.
/// </summary>
- public class Invocation : ExpressionStatement {
- protected ArrayList Arguments;
+ public class Invocation : ExpressionStatement
+ {
+ protected Arguments arguments;
protected Expression expr;
protected MethodGroupExpr mg;
bool arguments_resolved;
// 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)
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;
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);
+ Expression instance = mg.IsInstance ?
+ mg.InstanceExpression.CreateExpressionTree (ec) :
+ new NullLiteral (loc);
- if (mg.IsInstance)
- args.Add (new Argument (mg.InstanceExpression.CreateExpressionTree (ec)));
- else
- args.Add (new Argument (new NullLiteral (loc)));
+ args = Arguments.CreateForExpressionTree (ec, arguments,
+ instance,
+ mg.CreateExpressionTree (ec));
- 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));
- }
-
- if (Arguments != null) {
- foreach (Argument a in Arguments) {
- Expression e = a.Expr.CreateExpressionTree (ec);
- if (e != null)
- args.Add (new Argument (e));
- }
- }
-
- if (mg.IsBase)
- MemberExpr.Error_BaseAccessInExpressionTree (loc);
+ if (mg.IsBase)
+ MemberExpr.Error_BaseAccessInExpressionTree (loc);
return CreateExpressionFactoryCall ("Call", args);
}
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;
//
// 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);
return null;
}
} else {
- if (iexpr == null) {
+ if (iexpr == null || iexpr == EmptyExpression.Null) {
SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ());
}
}
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
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)
return true;
}
- /// <summary>
- /// 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.
- /// </summary>
- public static void EmitArguments (EmitContext ec, ArrayList arguments, bool dup_args, LocalTemporary this_arg)
- {
- if (arguments == null)
- return;
-
- int top = arguments.Count;
- LocalTemporary [] temps = null;
-
- 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)
+ static Type[] GetVarargsTypes (MethodBase mb, Arguments 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;
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 ();
/// </remarks>
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);
}
// 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;
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;
//
//
// 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
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;
}
}
}
- 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);
public override void Emit (EmitContext ec)
{
- mg.EmitCall (ec, Arguments);
+ mg.EmitCall (ec, arguments);
}
public override void EmitStatement (EmitContext ec)
{
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);
}
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
//
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
- }
- }
-
/// <summary>
/// Implements the new expression
/// </summary>
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;
- }
-
-
/// <summary>
/// Converts complex core type syntax like 'new int ()' to simple constant
/// </summary>
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;
}
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);
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)) {
eclass = ExprClass.Value;
return this;
}
-#endif
if (type.IsAbstract && type.IsSealed) {
Report.SymbolRelatedToPreviousError (type);
return null;
}
- bool is_struct = type.IsValueType;
+ bool is_struct = TypeManager.IsStruct (type);
eclass = ExprClass.Value;
//
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;
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);
}
//
- // 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:
//
//
// 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 {
}
}
- 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:
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)
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);
}
}
if (method != null) {
method.MutateHoistedGenericType (storey);
if (Arguments != null) {
- foreach (Argument a in Arguments)
- a.Expr.MutateHoistedGenericType (storey);
+ Arguments.MutateHoistedGenericType (storey);
}
}
arguments = new ArrayList (exprs.Count);
foreach (Expression e in exprs) {
- arguments.Add (new Argument (e, Argument.AType.Expression));
+ arguments.Add (e);
num_arguments++;
}
}
expect_initializers = true;
}
- void Error_IncorrectArrayInitializer ()
+ public static void Error_IncorrectArrayInitializer (Location loc)
{
- Error (178, "Invalid rank specifier: expected `,' or `]'");
+ Report.Error (178, loc, "Invalid rank specifier: expected `,' or `]'");
}
protected override void Error_NegativeArrayIndex (Location loc)
{
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 ();
+ 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 ();
- 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 ();
- return false;
- }
-
Expression element = ResolveArrayElement (ec, (Expression) o);
if (element == null)
continue;
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);
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) {
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;
} 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;
if (element == null)
return null;
- if (element is CompoundAssign.Helper) {
+ if (element is CompoundAssign.TargetExpression) {
if (first_emit != null)
throw new InternalErrorException ("Can only handle one mutator at a time");
first_emit = element;
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 ();
if (!ResolveInitializers (ec))
return null;
- if (arguments.Count != dimensions) {
- Error_IncorrectArrayInitializer ();
- }
-
- 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;
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++)
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);
+ }
}
}
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);
// 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);
}
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);
}
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;
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){
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;
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;
}
return this;
}
- public override HoistedVariable HoistedVariable {
- get { return null; }
+ public override HoistedVariable GetHoistedVariable (EmitContext ec)
+ {
+ return null;
}
}
get { return variable_info; }
}
- public override bool IsFixedVariable {
- get { return !TypeManager.IsValueType (type); }
+ public override bool IsFixed {
+ 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;
- public override HoistedVariable HoistedVariable {
- get { return TopToplevelBlock.HoistedThisVariable; }
+ 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;
+ }
+
+ return null;
}
public override bool IsRef {
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)
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 could be optimized
- AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
- if (HoistedVariable == null) {
- TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this);
- }
- }
+ if (am != null && ec.IsVariableCapturingRequired) {
+ am.SetHasThisAccess ();
}
}
//
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");
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);
}
target.block = clonectx.LookupBlock (block);
}
- public void RemoveHoisting ()
- {
- TopToplevelBlock.HoistedThisVariable = null;
- }
-
public override void SetHasAddressTaken ()
{
// Nothing
{
Error (190, "The __arglist construct is valid only within " +
"a variable argument method");
- return null;
+ return this;
}
return this;
/// <summary>
/// Represents the `__arglist (....)' construct
/// </summary>
- 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)
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);
}
}
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);
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);
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
if (alias == GlobalAlias) {
- expr = RootNamespace.Global;
+ expr = GlobalRootNamespace.Instance;
return base.ResolveAsTypeStep (ec, silent);
}
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)
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;
}
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;
}
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;
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
//
// 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;
}
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;
if (silent)
return null;
- Error_IdentifierNotFound (rc, new_expr, LookupIdentifier);
+ Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier);
return null;
}
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));
}
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;
}
if (expr_type == null)
return;
- Namespace.Error_TypeArgumentsCannotBeUsed (expr_type.Type, loc);
+ Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc);
return;
}
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;
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;
/// IndexerAccess, ArrayAccess or a PointerArithmetic.
/// </summary>
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);
}
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);
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);
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);
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 ();
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);
}
}
}
foreach (Argument a in ea.Arguments) {
+ if (a is NamedArgument)
+ ElementAccess.Error_NamedArgument ((NamedArgument) a);
+
a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
}
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
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;
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;
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;
ea.Expr.Emit (ec);
for (int i = 0; i < ea.Arguments.Count; ++i) {
- ((Argument)ea.Arguments [i]).Emit (ec);
+ ea.Arguments [i].Emit (ec);
}
}
}
args [arg_count] = type;
- MethodInfo set = CodeGen.Module.Builder.GetArrayMethod (
+ MethodInfo set = RootContext.ToplevelTypes.Builder.GetArrayMethod (
ea.Expr.Type, "Set",
CallingConventions.HasThis |
CallingConventions.Standard,
}
}
+ 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 ();
{
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)
return ix;
}
- #endif
Type copy = lookup_type;
while (copy != TypeManager.object_type && copy != null){
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)
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);
}
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) {
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);
}
{
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);
}
/// The base indexer operator
/// </summary>
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)
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;
}
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;
private EmptyExpressionStatement ()
{
- type = TypeManager.object_type;
eclass = ExprClass.Value;
loc = Location.Null;
}
public override Expression DoResolve (EmitContext ec)
{
+ type = TypeManager.object_type;
return this;
}
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)));
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;
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);
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);
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 ()));
//
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)
//
// A collection initializer expression
//
- public class CollectionElementInitializer : Invocation
+ class CollectionElementInitializer : Invocation
{
public class ElementInitializerArgument : Argument
{
}
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)));
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)
// TODO: We could call a constructor which takes element count argument,
// for known types like List<T>, Dictionary<T, U>
-
- 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);
public class CollectionOrObjectInitializers : ExpressionStatement
{
ArrayList initializers;
+ bool is_collection_initialization;
public static readonly CollectionOrObjectInitializers Empty =
new CollectionOrObjectInitializers (new ArrayList (0), Location.Null);
public bool IsCollectionInitializer {
get {
- return type == typeof (CollectionOrObjectInitializers);
+ return is_collection_initialization;
}
}
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];
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 (),
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;
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);
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)));
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);
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 {
AnonymousTypeClass CreateAnonymousType (ArrayList parameters)
{
- AnonymousTypeClass type = RootContext.ToplevelTypes.GetAnonymousType (parameters);
+ AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters);
if (type != null)
return type;
if (Report.Errors == 0)
type.CloseType ();
- RootContext.ToplevelTypes.AddAnonymousType (type);
+ parent.Module.AddAnonymousType (type);
return type;
}
}
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);
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);
}
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;
}