using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
+using Compiler = Mono.CSharp;
namespace Microsoft.CSharp.RuntimeBinder
{
- public class CSharpBinaryOperationBinder : BinaryOperationBinder
+ class CSharpBinaryOperationBinder : BinaryOperationBinder
{
IList<CSharpArgumentInfo> argumentInfo;
- bool is_checked, is_member_access;
+ readonly CSharpBinderFlags flags;
+ readonly Type context;
- public CSharpBinaryOperationBinder (ExpressionType operation, bool isChecked, bool isMemberAccess, IEnumerable<CSharpArgumentInfo> argumentInfo)
+ public CSharpBinaryOperationBinder (ExpressionType operation, CSharpBinderFlags flags, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo)
: base (operation)
{
this.argumentInfo = new ReadOnlyCollectionBuilder<CSharpArgumentInfo> (argumentInfo);
- this.is_checked = isChecked;
- this.is_member_access = isMemberAccess;
- }
-
- public IList<CSharpArgumentInfo> ArgumentInfo {
- get {
- return argumentInfo;
- }
- }
+ if (this.argumentInfo.Count != 2)
+ throw new ArgumentException ("Binary operation requires 2 arguments");
- public bool IsChecked {
- get {
- return is_checked;
- }
- }
-
- public bool IsMemberAccess {
- get {
- return is_member_access;
- }
+ this.flags = flags;
+ this.context = context;
}
-
- public override int GetHashCode ()
+
+ Compiler.Binary.Operator GetOperator (out bool isCompound)
{
- return base.GetHashCode ();
+ isCompound = false;
+ switch (Operation) {
+ case ExpressionType.Add:
+ return Compiler.Binary.Operator.Addition;
+ case ExpressionType.AddAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.Addition;
+ case ExpressionType.And:
+ return (flags & CSharpBinderFlags.BinaryOperationLogical) != 0 ?
+ Compiler.Binary.Operator.LogicalAnd : Compiler.Binary.Operator.BitwiseAnd;
+ case ExpressionType.AndAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.BitwiseAnd;
+ case ExpressionType.Divide:
+ return Compiler.Binary.Operator.Division;
+ case ExpressionType.DivideAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.Division;
+ case ExpressionType.Equal:
+ return Compiler.Binary.Operator.Equality;
+ case ExpressionType.ExclusiveOr:
+ return Compiler.Binary.Operator.ExclusiveOr;
+ case ExpressionType.ExclusiveOrAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.ExclusiveOr;
+ case ExpressionType.GreaterThan:
+ return Compiler.Binary.Operator.GreaterThan;
+ case ExpressionType.GreaterThanOrEqual:
+ return Compiler.Binary.Operator.GreaterThanOrEqual;
+ case ExpressionType.LeftShift:
+ return Compiler.Binary.Operator.LeftShift;
+ case ExpressionType.LeftShiftAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.LeftShift;
+ case ExpressionType.LessThan:
+ return Compiler.Binary.Operator.LessThan;
+ case ExpressionType.LessThanOrEqual:
+ return Compiler.Binary.Operator.LessThanOrEqual;
+ case ExpressionType.Modulo:
+ return Compiler.Binary.Operator.Modulus;
+ case ExpressionType.ModuloAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.Modulus;
+ case ExpressionType.Multiply:
+ return Compiler.Binary.Operator.Multiply;
+ case ExpressionType.MultiplyAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.Multiply;
+ case ExpressionType.NotEqual:
+ return Compiler.Binary.Operator.Inequality;
+ case ExpressionType.Or:
+ return (flags & CSharpBinderFlags.BinaryOperationLogical) != 0 ?
+ Compiler.Binary.Operator.LogicalOr : Compiler.Binary.Operator.BitwiseOr;
+ case ExpressionType.OrAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.BitwiseOr;
+ case ExpressionType.OrElse:
+ return Compiler.Binary.Operator.LogicalOr;
+ case ExpressionType.RightShift:
+ return Compiler.Binary.Operator.RightShift;
+ case ExpressionType.RightShiftAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.RightShift;
+ case ExpressionType.Subtract:
+ return Compiler.Binary.Operator.Subtraction;
+ case ExpressionType.SubtractAssign:
+ isCompound = true;
+ return Compiler.Binary.Operator.Subtraction;
+ default:
+ throw new NotImplementedException (Operation.ToString ());
+ }
}
- [MonoTODO]
public override DynamicMetaObject FallbackBinaryOperation (DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
{
- throw new NotImplementedException ();
+ var ctx = DynamicContext.Create ();
+ var left = ctx.CreateCompilerExpression (argumentInfo [0], target);
+ var right = ctx.CreateCompilerExpression (argumentInfo [1], arg);
+
+ bool is_compound;
+ var oper = GetOperator (out is_compound);
+ Compiler.Expression expr;
+
+ if (is_compound) {
+ var target_expr = new Compiler.RuntimeValueExpression (target, ctx.ImportType (target.LimitType));
+ expr = new Compiler.CompoundAssign (oper, target_expr, right, left);
+ } else {
+ expr = new Compiler.Binary (oper, left, right);
+ }
+
+ expr = new Compiler.Cast (new Compiler.TypeExpression (ctx.ImportType (ReturnType), Compiler.Location.Null), expr, Compiler.Location.Null);
+
+ if ((flags & CSharpBinderFlags.CheckedContext) != 0)
+ expr = new Compiler.CheckedExpr (expr, Compiler.Location.Null);
+
+ var binder = new CSharpBinder (this, expr, errorSuggestion);
+ binder.AddRestrictions (target);
+ binder.AddRestrictions (arg);
+
+ return binder.Bind (ctx, context);
}
}
}