// Copyright 2004-2008 Novell, Inc
//
using System;
-using System.Reflection;
+
+#if STATIC
+using IKVM.Reflection.Emit;
+#else
using System.Reflection.Emit;
+#endif
namespace Mono.CSharp {
// be data on the stack that it can use to compuatate its value. This is
// for expressions like a [f ()] ++, where you can't call `f ()' twice.
//
- void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
+ void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound);
/*
For simple assignments, this interface is very simple, EmitAssign is called with source
builder = null;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return false;
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
Arguments args = new Arguments (1);
Emit (ec);
}
- public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
{
- if (prepare_for_load)
+ if (isCompound)
throw new NotImplementedException ();
source.Emit (ec);
this.loc = loc;
}
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator");
- return null;
- }
-
public Expression Target {
get { return target; }
}
}
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return target.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ();
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator");
+ return null;
+ }
+
protected override Expression DoResolve (ResolveContext ec)
{
bool ok = true;
if (target_object.NodeType == System.Linq.Expressions.ExpressionType.Block)
return target_object;
- var source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type);
+ System.Linq.Expressions.UnaryExpression source_object;
+ if (ctx.HasSet (BuilderContext.Options.CheckedScope)) {
+ source_object = System.Linq.Expressions.Expression.ConvertChecked (source.MakeExpression (ctx), target_object.Type);
+ } else {
+ source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type);
+ }
+
return System.Linq.Expressions.Expression.Assign (target_object, source_object);
}
#endif
protected virtual Expression ResolveConversions (ResolveContext ec)
{
- source = Convert.ImplicitConversionRequired (ec, source, target.Type, loc);
+ source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location);
if (source == null)
return null;
protected override Expression ResolveConversions (ResolveContext ec)
{
- source = Convert.ExplicitConversion (ec, source, target.Type, loc);
- if (source != null)
- return this;
-
- return base.ResolveConversions (ec);
+ source = EmptyCast.Create (source, target.Type);
+ return this;
}
}
{
this.mc = mc;
if (!spec.IsStatic)
- ((FieldExpr)target).InstanceExpression = CompilerGeneratedThis.Instance;
+ ((FieldExpr)target).InstanceExpression = new CompilerGeneratedThis (mc.CurrentType, expression.Location);
}
protected override Expression DoResolve (ResolveContext ec)
base.EmitStatement (ec);
}
- public bool IsComplexInitializer {
- get { return !(source is Constant); }
- }
-
public bool IsDefaultInitializer {
get {
Constant c = source as Constant;
return c.IsDefaultInitializer (fe.Type);
}
}
+
+ public override bool IsSideEffectFree {
+ get {
+ return source.IsSideEffectFree;
+ }
+ }
}
//
// This is just a hack implemented for arrays only
public sealed class TargetExpression : Expression
{
- Expression child;
+ readonly Expression child;
+
public TargetExpression (Expression child)
{
this.child = child;
this.loc = child.Location;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return child.ContainsEmitWithAwait ();
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotSupportedException ("ET");
{
child.Emit (ec);
}
+
+ public override Expression EmitToField (EmitContext ec)
+ {
+ return child.EmitToField (ec);
+ }
}
// Used for underlying binary operator
Arguments args = new Arguments (targs.Count + 1);
args.AddRange (targs);
args.Add (new Argument (source));
+
+ var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment;
+
+ //
+ // Compound assignment does target conversion using additional method
+ // call, set checked context as the binary operation can overflow
+ //
+ if (ec.HasSet (ResolveContext.Options.CheckedScope))
+ binder_flags |= CSharpBinderFlags.CheckedContext;
+
if (target is DynamicMemberBinder) {
- source = new DynamicMemberBinder (ma.Name, CSharpBinderFlags.ValueFromCompoundAssignment, args, loc).Resolve (ec);
+ source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec);
// Handles possible event addition/subtraction
if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) {
- args = new Arguments (2);
+ args = new Arguments (targs.Count + 1);
args.AddRange (targs);
args.Add (new Argument (right));
string method_prefix = op == Binary.Operator.Addition ?
var invoke = DynamicInvocation.CreateSpecialNameInvoke (
new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec);
- args = new Arguments (1);
+ args = new Arguments (targs.Count);
args.AddRange (targs);
source = new DynamicEventCompoundAssign (ma.Name, args,
(ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec);
}
} else {
- source = new DynamicIndexBinder (CSharpBinderFlags.ValueFromCompoundAssignment, args, loc).Resolve (ec);
+ source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec);
}
return source;
}
}
- if (source.Type == InternalType.Dynamic) {
+ if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
Arguments arg = new Arguments (1);
arg.Add (new Argument (source));
return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec);