//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
+// Copyright 2011 Xamarin Inc
//
using System;
}
}
- public class Unwrap : Expression, IMemoryLocation, IAssignMethod
+ public class Unwrap : Expression, IMemoryLocation
{
Expression expr;
eclass = expr.eclass;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return expr.ContainsEmitWithAwait ();
+ }
+
public static Expression Create (Expression expr)
{
//
public override void Emit (EmitContext ec)
{
Store (ec);
+
+ var call = new CallEmitter ();
+ call.InstanceExpression = this;
+
if (useDefaultValue)
- Invocation.EmitCall (ec, this, NullableInfo.GetGetValueOrDefault (expr.Type), null, loc);
+ call.EmitPredefined (ec, NullableInfo.GetGetValueOrDefault (expr.Type), null);
else
- Invocation.EmitCall (ec, this, NullableInfo.GetValue (expr.Type), null, loc);
+ call.EmitPredefined (ec, NullableInfo.GetValue (expr.Type), null);
}
public void EmitCheck (EmitContext ec)
{
Store (ec);
- Invocation.EmitCall (ec, this, NullableInfo.GetHasValue (expr.Type), null, loc);
+
+ var call = new CallEmitter ();
+ call.InstanceExpression = this;
+
+ call.EmitPredefined (ec, NullableInfo.GetHasValue (expr.Type), null);
}
public override bool Equals (object obj)
void Store (EmitContext ec)
{
- if (expr is VariableReference)
+ if (temp != null)
return;
- if (temp != null)
+ if (expr is VariableReference)
return;
expr.Emit (ec);
return temp;
}
}
-
- public void Emit (EmitContext ec, bool leave_copy)
- {
- if (leave_copy)
- Load (ec);
-
- Emit (ec);
- }
-
- public void EmitAssign (EmitContext ec, Expression source,
- bool leave_copy, bool prepare_for_load)
- {
- InternalWrap wrap = new InternalWrap (source, expr.Type, loc);
- ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false);
- }
-
- class InternalWrap : Expression
- {
- public Expression expr;
-
- public InternalWrap (Expression expr, TypeSpec type, Location loc)
- {
- this.expr = expr;
- this.loc = loc;
- this.type = type;
-
- eclass = ExprClass.Value;
- }
-
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- throw new NotSupportedException ("ET");
- }
-
- protected override Expression DoResolve (ResolveContext ec)
- {
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- expr.Emit (ec);
- ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));
- }
- }
}
//
public override void Emit (EmitContext ec)
{
- Invocation.EmitCall (ec, Child, NullableInfo.GetValue (Child.Type), null, loc);
+ var call = new CallEmitter ();
+ call.InstanceExpression = Child;
+ call.EmitPredefined (ec, NullableInfo.GetValue (Child.Type), null);
}
}
value_target.AddressOf (ec, AddressOp.Store);
ec.Emit (OpCodes.Initobj, type);
value_target.Emit (ec);
+ value_target.Release (ec);
}
public void AddressOf (EmitContext ec, AddressOp Mode)
: this (expr, unwrap as Unwrap, type)
{
}
+
+ public override bool ContainsEmitWithAwait ()
+ {
+ return unwrap.ContainsEmitWithAwait ();
+ }
public override Expression CreateExpressionTree (ResolveContext ec)
{
return null;
null_value = LiftedNull.Create (type, loc);
- } else if (TypeManager.IsValueType (type)) {
+ } else if (TypeSpec.IsValueType (type)) {
null_value = LiftedNull.Create (type, loc);
} else {
null_value = new NullConstant (type, loc);
}
left_unwrap.Emit (ec);
- ec.Emit (OpCodes.Brtrue_S, load_right);
+ ec.Emit (OpCodes.Brtrue, load_right);
// value & null, value | null
if (right_unwrap != null) {
if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) {
left_unwrap.EmitCheck (ec);
if (Oper == Binary.Operator.Equality) {
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
ec.Emit (OpCodes.Ceq);
}
return;
if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) {
right_unwrap.EmitCheck (ec);
if (Oper == Binary.Operator.Equality) {
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
ec.Emit (OpCodes.Ceq);
}
return;
user_operator.Emit (ec);
ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label);
} else {
+ if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) {
+ left = left.EmitToField (ec);
+ right = right.EmitToField (ec);
+ }
+
left.Emit (ec);
right.Emit (ec);
ec.Emit (OpCodes.Ceq);
} else {
if (Oper == Operator.Inequality) {
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
ec.Emit (OpCodes.Ceq);
}
}
ec.MarkLabel (dissimilar_label);
if (Oper == Operator.Inequality)
- ec.Emit (OpCodes.Ldc_I4_1);
+ ec.EmitInt (1);
else
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
ec.MarkLabel (end_label);
}
ec.MarkLabel (is_null_label);
if ((Oper & Operator.ComparisonMask) != 0) {
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
} else {
LiftedNull.Create (type, loc).Emit (ec);
}
return;
}
- if (l.IsNullableType)
- l = TypeManager.GetTypeArguments (l) [0];
+ if (left.Type.IsNullableType) {
+ l = NullableInfo.GetUnderlyingType (left.Type);
+ left = EmptyCast.Create (left, l);
+ }
+
+ if (right.Type.IsNullableType) {
+ right = EmptyCast.Create (right, NullableInfo.GetUnderlyingType (right.Type));
+ }
base.EmitOperator (ec, l);
}
// Lift the result in the case it can be null and predefined or user operator
// result type is of a value type
//
- if (!TypeManager.IsValueType (expr.Type))
+ if (!TypeSpec.IsValueType (expr.Type))
return null;
if (state != orig_state)
this.right = right;
this.loc = loc;
}
+
+ public Expression LeftExpression {
+ get {
+ return left;
+ }
+ }
+
+ public Expression RightExpression {
+ get {
+ return right;
+ }
+ }
public override Expression CreateExpressionTree (ResolveContext ec)
{
type = ltype;
return this;
}
- } else if (TypeManager.IsReferenceType (ltype)) {
+ } else if (TypeSpec.IsReferenceType (ltype)) {
if (Convert.ImplicitConversionExists (ec, right, ltype)) {
//
// If right is a dynamic expression, the result type is dynamic
return this;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ if (unwrap != null)
+ return unwrap.ContainsEmitWithAwait () || right.ContainsEmitWithAwait ();
+
+ return left.ContainsEmitWithAwait () || right.ContainsEmitWithAwait ();
+ }
+
protected override Expression DoResolve (ResolveContext ec)
{
left = left.Resolve (ec);
target.left = left.Clone (clonectx);
target.right = right.Clone (clonectx);
}
- }
-
- public class LiftedUnaryMutator : ExpressionStatement
- {
- public readonly UnaryMutator.Mode Mode;
- Expression expr;
- UnaryMutator underlying;
- Unwrap unwrap;
-
- public LiftedUnaryMutator (UnaryMutator.Mode mode, Expression expr, Location loc)
+
+ public override object Accept (StructuralVisitor visitor)
{
- this.expr = expr;
- this.Mode = mode;
- this.loc = loc;
+ return visitor.Visit (this);
}
+ }
- public override Expression CreateExpressionTree (ResolveContext ec)
+ class LiftedUnaryMutator : UnaryMutator
+ {
+ public LiftedUnaryMutator (Mode mode, Expression expr, Location loc)
+ : base (mode, expr, loc)
{
- return new SimpleAssign (this, this).CreateExpressionTree (ec);
}
protected override Expression DoResolve (ResolveContext ec)
{
- expr = expr.Resolve (ec);
- if (expr == null)
- return null;
+ var orig_expr = expr;
- unwrap = Unwrap.Create (expr, false);
- if (unwrap == null)
- return null;
-
- underlying = (UnaryMutator) new UnaryMutator (Mode, unwrap, loc).Resolve (ec);
- if (underlying == null)
- return null;
+ expr = Unwrap.Create (expr);
+ var res = base.DoResolveOperation (ec);
- eclass = ExprClass.Value;
+ expr = orig_expr;
type = expr.Type;
- return this;
+
+ return res;
}
- void DoEmit (EmitContext ec, bool is_expr)
+ protected override void EmitOperation (EmitContext ec)
{
Label is_null_label = ec.DefineLabel ();
Label end_label = ec.DefineLabel ();
- unwrap.EmitCheck (ec);
+ LocalTemporary lt = new LocalTemporary (type);
+
+ // Value is on the stack
+ lt.Store (ec);
+
+ var call = new CallEmitter ();
+ call.InstanceExpression = lt;
+ call.EmitPredefined (ec, NullableInfo.GetHasValue (expr.Type), null);
+
ec.Emit (OpCodes.Brfalse, is_null_label);
- if (is_expr) {
- underlying.Emit (ec);
- ec.Emit (OpCodes.Br_S, end_label);
- } else {
- underlying.EmitStatement (ec);
- }
+ call = new CallEmitter ();
+ call.InstanceExpression = lt;
+ call.EmitPredefined (ec, NullableInfo.GetValue (expr.Type), null);
- ec.MarkLabel (is_null_label);
- if (is_expr)
- LiftedNull.Create (type, loc).Emit (ec);
+ lt.Release (ec);
- ec.MarkLabel (end_label);
- }
+ base.EmitOperation (ec);
- public override void Emit (EmitContext ec)
- {
- DoEmit (ec, true);
- }
+ ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type));
+ ec.Emit (OpCodes.Br_S, end_label);
- public override void EmitStatement (EmitContext ec)
- {
- DoEmit (ec, false);
+ ec.MarkLabel (is_null_label);
+ LiftedNull.Create (type, loc).Emit (ec);
+
+ ec.MarkLabel (end_label);
}
}
}