public static DynamicMetaObject Operation(BinaryOperationBinder operation, DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback BinaryOperator " + target.LimitType.FullName + " " + operation.Operation + " " + arg.LimitType.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString());

            DynamicMetaObject[] args = new[] { target, arg };
            if (BindingHelpers.NeedsDeferal(args))
                return operation.Defer(args);

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args);

            TotemOperationKind? toOperator = null;
            switch (operation.Operation)
            {
                case ExpressionType.Add: toOperator = TotemOperationKind.Add; break;
                case ExpressionType.And: toOperator = TotemOperationKind.BitwiseAnd; break;
                case ExpressionType.Divide: toOperator = TotemOperationKind.Divide; break;
                case ExpressionType.ExclusiveOr: toOperator = TotemOperationKind.ExclusiveOr; break;
                case ExpressionType.Modulo: toOperator = TotemOperationKind.Mod; break;
                case ExpressionType.Multiply: toOperator = TotemOperationKind.Multiply; break;
                case ExpressionType.Or: toOperator = TotemOperationKind.BitwiseOr; break;
                case ExpressionType.Power: toOperator = TotemOperationKind.Power; break;
                case ExpressionType.RightShift: toOperator = TotemOperationKind.RightShift; break;
                case ExpressionType.LeftShift: toOperator = TotemOperationKind.LeftShift; break;
                case ExpressionType.Subtract: toOperator = TotemOperationKind.Subtract; break;

                case ExpressionType.AddAssign: toOperator = TotemOperationKind.InPlaceAdd; break;
                case ExpressionType.AndAssign: toOperator = TotemOperationKind.InPlaceBitwiseAnd; break;
                case ExpressionType.DivideAssign: toOperator = TotemOperationKind.InPlaceDivide; break;
                case ExpressionType.ExclusiveOrAssign: toOperator = TotemOperationKind.InPlaceExclusiveOr; break;
                case ExpressionType.ModuloAssign: toOperator = TotemOperationKind.InPlaceMod; break;
                case ExpressionType.MultiplyAssign: toOperator = TotemOperationKind.InPlaceMultiply; break;
                case ExpressionType.OrAssign: toOperator = TotemOperationKind.InPlaceBitwiseOr; break;
                case ExpressionType.PowerAssign: toOperator = TotemOperationKind.InPlacePower; break;
                case ExpressionType.RightShiftAssign: toOperator = TotemOperationKind.InPlaceRightShift; break;
                case ExpressionType.LeftShiftAssign: toOperator = TotemOperationKind.InPlaceLeftShift; break;
                case ExpressionType.SubtractAssign: toOperator = TotemOperationKind.InPlaceSubtract; break;

                case ExpressionType.Equal: toOperator = TotemOperationKind.Equal; break;
                case ExpressionType.GreaterThan: toOperator = TotemOperationKind.GreaterThan; break;
                case ExpressionType.GreaterThanOrEqual: toOperator = TotemOperationKind.GreaterThanOrEqual; break;
                case ExpressionType.LessThan: toOperator = TotemOperationKind.LessThan; break;
                case ExpressionType.LessThanOrEqual: toOperator = TotemOperationKind.LessThanOrEqual; break;
                case ExpressionType.NotEqual: toOperator = TotemOperationKind.NotEqual; break;
            }

            DynamicMetaObject res = null;
            if (toOperator != null)
                res = MakeBinaryOperation(operation, args, toOperator.Value, errorSuggestion);
            else
                res = operation.FallbackBinaryOperation(target, arg);

            return BindingHelpers.AddDynamicTestAndDefer(operation, BindingHelpers.AddTotemBoxing(res), args, valInfo);
        }
        public static DynamicMetaObject Operation(UnaryOperationBinder operation, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback UnaryOperator " + " " + operation.Operation + " " + arg.LimitType.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString());

            DynamicMetaObject[] args = new[] { arg };
            if (arg.NeedsDeferral())
                return operation.Defer(arg);

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args);

            TotemOperationKind? toOperator = null;
            Type retType = typeof(object);
            bool box = true;
            bool inverse = false;
            switch (operation.Operation)
            {
                case ExpressionType.UnaryPlus: toOperator = TotemOperationKind.Positive; break;
                case ExpressionType.Negate: toOperator = TotemOperationKind.Negate; break;
                case ExpressionType.OnesComplement: toOperator = TotemOperationKind.OnesComplement; break;
                case ExpressionType.Not: toOperator = TotemOperationKind.Not; box = false; break;
                case ExpressionType.IsFalse: toOperator = TotemOperationKind.IsFalse; box = false; retType = typeof(bool); break;
                case ExpressionType.IsTrue: toOperator = TotemOperationKind.IsFalse; box = false; retType = typeof(bool); inverse = true; break;
            }

            DynamicMetaObject res = null;
            if (toOperator != null)
                res = MakeUnaryOperation(operation, args[0], toOperator.Value, errorSuggestion, retType);
            else
                res = operation.FallbackUnaryOperation(arg);

            if (inverse)
            {
                res = new DynamicMetaObject(
                    Expression.Condition(
                        res.Expression,
                        Utils.Constant(ScriptingRuntimeHelpers.False),
                        Utils.Constant(ScriptingRuntimeHelpers.True)
                    ),
                    res.Restrictions
                );
            }

            if (box)
            {
                res = BindingHelpers.AddTotemBoxing(res);
            }

            return BindingHelpers.AddDynamicTestAndDefer(operation, res, args, valInfo, retType);
        }