예제 #1
0
        /// <summary>
        /// 整数と小数の演算を行う
        /// </summary>
        private DynamicMetaObject TryCalcNumeric(DynamicMetaObject left, DynamicMetaObject right)
        {
            Expression leftExpr  = BinderHelper.LimitTypeConvert(left);
            Expression rightExpr = BinderHelper.LimitTypeConvert(right);
            Expression expr      = null;

            foreach (var pattern in BinderHelper.CastPatterns)
            {
                if (leftExpr.Type == pattern.Narrow && rightExpr.Type == pattern.Wide)
                {
                    var upperLeft = Expression.Convert(leftExpr, pattern.Wide);
                    expr = OverflowCheckingCalc(upperLeft, rightExpr);
                    break;
                }
                if (leftExpr.Type == pattern.Wide && rightExpr.Type == pattern.Narrow)
                {
                    var upperRight = Expression.Convert(rightExpr, pattern.Wide);
                    expr = OverflowCheckingCalc(leftExpr, upperRight);
                    break;
                }
            }
            if (expr == null)
            {
                return(null);
            }
            var bindings = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, bindings));
        }
예제 #2
0
        /// <summary>
        /// 左辺、右辺ともに、nullだった場合
        /// </summary>
        private DynamicMetaObject CompareBotheNull(DynamicMetaObject left, DynamicMetaObject right)
        {
            Contract.Requires <ArgumentException>(left.Value == null);
            Contract.Requires <ArgumentException>(right.Value == null);

            Expression value = null;

            switch (this.Operation)
            {
            case ExpressionType.LessThan:
            case ExpressionType.GreaterThan:
                value = Expression.Constant(false);
                break;

            case ExpressionType.LessThanOrEqual:
            case ExpressionType.GreaterThanOrEqual:
                value = Expression.Constant(true);
                break;
            }
            var expr = BinderHelper.Wrap(value, this.ReturnType);
            var rest = BindingRestrictions.GetExpressionRestriction(
                Expression.And(
                    BinderHelper.IsNull(left.Expression),
                    BinderHelper.IsNull(right.Expression)));

            return(new DynamicMetaObject(expr, rest));
        }
예제 #3
0
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject left, DynamicMetaObject right, DynamicMetaObject errorSuggestion)
        {
            Expression          expr;
            BindingRestrictions rest;

            if (left.Value == null)
            {
                expr = BinderHelper.Wrap(right.Expression, this.ReturnType);
                rest = BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(left.Expression));
            }
            else if (left.LimitType == typeof(bool))
            {
                expr = BinderHelper.Wrap(
                    Expression.Condition(BinderHelper.Wrap(left.Expression, typeof(bool)), left.Expression, right.Expression),
                    this.ReturnType);
                rest = BindingRestrictions.GetTypeRestriction(left.Expression, typeof(bool));
            }
            else
            {
                expr = BinderHelper.Wrap(left.Expression, this.ReturnType);
                rest = BindingRestrictions.GetExpressionRestriction(
                    Expression.AndAlso(
                        BinderHelper.IsNotNull(left.Expression),
                        Expression.Not(Expression.TypeIs(left.Expression, typeof(bool)))));
            }
            return(new DynamicMetaObject(expr, rest));
        }
예제 #4
0
        /// <summary>
        /// 暗黙の型変換が存在する場合,それを利用する。
        /// </summary>
        private DynamicMetaObject TryImplicitCast(DynamicMetaObject left, DynamicMetaObject right)
        {
            Expression cmpExpr = null;

            if (BinderHelper.GetImplicitCast(left.LimitType, right.LimitType) != null)
            {
                try {
                    cmpExpr = Expression.MakeBinary(this.Operation,
                                                    BinderHelper.Wrap(left.Expression, left.LimitType, right.LimitType),
                                                    BinderHelper.Wrap(right.Expression, right.LimitType));
                }
                catch (InvalidCastException) { }
            }
            if (BinderHelper.GetImplicitCast(right.LimitType, left.LimitType) != null)
            {
                try {
                    cmpExpr = Expression.MakeBinary(this.Operation,
                                                    BinderHelper.Wrap(left.Expression, left.LimitType),
                                                    BinderHelper.Wrap(right.Expression, right.LimitType, left.LimitType));
                }
                catch (InvalidCastException) { }
            }
            if (cmpExpr == null)
            {
                return(null);
            }
            var expr = BinderHelper.Wrap(cmpExpr, this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #5
0
        public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            Expression          boolExpr;
            BindingRestrictions rest;

            if (target.Value == null)
            {
                boolExpr = Expression.Constant(true);
                rest     = BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(target.Expression));
            }
            else if (target.LimitType == typeof(bool))
            {
                boolExpr = Expression.Not(BinderHelper.Wrap(target.Expression, typeof(bool)));
                rest     = BindingRestrictions.GetTypeRestriction(target.Expression, typeof(bool));
            }
            else
            {
                boolExpr = Expression.Constant(false);
                rest     = BindingRestrictions.GetExpressionRestriction(
                    Expression.AndAlso(
                        BinderHelper.IsNotNull(target.Expression),
                        Expression.Not(Expression.TypeIs(target.Expression, typeof(bool)))));
            }
            var expr = BinderHelper.Wrap(boolExpr, this.ReturnType);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #6
0
        /// <summary>
        /// 左辺か右辺のいずれかがnullの場合の比較
        /// </summary>
        private DynamicMetaObject FallbackOnNull(DynamicMetaObject left, DynamicMetaObject right)
        {
            bool       value    = this.Operation == ExpressionType.Equal;
            Expression restExpr = null;

            if (left.Value == null && right.Value == null)
            {
                restExpr = Expression.And(
                    BinderHelper.IsNull(left.Expression),
                    BinderHelper.IsNull(right.Expression));
            }
            else if (left.Value == null)
            {
                value   ^= true;
                restExpr = Expression.AndAlso(
                    BinderHelper.IsNull(left.Expression),
                    BinderHelper.IsNotNull(right.Expression));
            }
            else
            {
                value   ^= true;
                restExpr = Expression.AndAlso(
                    BinderHelper.IsNull(right.Expression),
                    BinderHelper.IsNotNull(left.Expression));
            }
            var expr = BinderHelper.Wrap(Expression.Constant(value), this.ReturnType);
            var rest = BindingRestrictions.GetExpressionRestriction(restExpr);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #7
0
        public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            const string errorMsg = "{0}を符号反転出来ません。";

            if (target.Value == null)
            {
                var msg      = String.Format(errorMsg, ConstantNames.NullText);
                var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });
                var expr     = Expression.Throw(Expression.New(ctorInfo, Expression.Constant(errorMsg)), this.ReturnType);
                var rest     = BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(target.Expression));
                return(new DynamicMetaObject(expr, rest));
            }
            try {
                var expr = BinderHelper.Wrap(Expression.Negate(Expression.Convert(target.Expression, target.LimitType)), this.ReturnType);
                var rest = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);
                return(new DynamicMetaObject(expr, rest));
            }
            catch (InvalidOperationException) {
                var msgExpr = ExpressionHelper.BetaReduction <string, object, string>(
                    (format, obj) => String.Format(format, obj),
                    Expression.Constant(errorMsg), target.Expression);
                var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });
                var expr     = Expression.Throw(Expression.New(ctorInfo, msgExpr), this.ReturnType);
                var rest     = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);
                return(new DynamicMetaObject(expr, rest));
            }
        }
예제 #8
0
        /// <summary>
        /// 暗黙のキャストを探す。
        /// </summary>
        private DynamicMetaObject DefferentType(DynamicMetaObject left, DynamicMetaObject right)
        {
            var val = TryCalcNumeric(left, right);

            if (val != null)
            {
                return(val);
            }
            // 左辺のキャスト
            var mInfo = BinderHelper.GetImplicitCast(left.LimitType, right.LimitType);

            if (mInfo != null)
            {
                Expression expr = Expression.MakeBinary(this.Operation,
                                                        BinderHelper.Wrap(left.Expression, left.LimitType, right.LimitType),
                                                        Expression.Convert(right.Expression, right.LimitType));
                return(new DynamicMetaObject(
                           BinderHelper.Wrap(expr, this.ReturnType),
                           BinderHelper.GetTypeRestriction(left, right)));
            }
            // 右辺のキャスト
            mInfo = BinderHelper.GetImplicitCast(right.LimitType, left.LimitType);
            if (mInfo != null)
            {
                Expression expr = Expression.MakeBinary(this.Operation,
                                                        Expression.Convert(left.Expression, left.LimitType),
                                                        BinderHelper.Wrap(right.Expression, right.LimitType, left.LimitType));
                return(new DynamicMetaObject(
                           BinderHelper.Wrap(expr, this.ReturnType),
                           BinderHelper.GetTypeRestriction(left, right)));
            }
            return(BinderHelper.NoResult(_name, this.ReturnType, left, right));
        }
예제 #9
0
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            if (target.Value == null || arg.Value == null)
            {
                return(BinderHelper.NullErrorOnOperation(_name, this.ReturnType, target, arg));
            }

            try {
                if (target.LimitType == arg.LimitType)
                {
                    var type        = target.LimitType;
                    var leftExpr    = BinderHelper.Wrap(target.Expression, type);
                    var rightExpr   = BinderHelper.Wrap(arg.Expression, type);
                    var checkedExpr = OverflowCheckingCalc(leftExpr, rightExpr);
                    if (checkedExpr != null)
                    {
                        var bindings = BinderHelper.GetTypeRestriction(target, arg);
                        return(new DynamicMetaObject(checkedExpr, bindings));
                    }
                }
                Expression expr = Expression.MakeBinary(
                    this.Operation,
                    BinderHelper.Wrap(target.Expression, target.LimitType),
                    BinderHelper.Wrap(arg.Expression, arg.LimitType));
                return(new DynamicMetaObject(
                           BinderHelper.Wrap(expr, this.ReturnType),
                           BinderHelper.GetTypeRestriction(target, arg)));
            }
            catch (InvalidOperationException) {
                return(DefferentType(target, arg));
            }
        }
예제 #10
0
        /// <summary>
        /// Map関数を呼び出す。
        /// </summary>
        /// <param name="target">関数</param>
        /// <param name="arg">リスト</param>
        /// <param name="errorSuggestion"></param>
        /// <returns>リスト</returns>
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            Expression expr     = null;
            Expression rest     = null;
            var        funcType = typeof(Func <object, object>);

            if (target.LimitType == funcType)
            {
                var funcExpr = BinderHelper.Wrap(target.Expression, funcType);
                expr = ExpressionHelper.BetaReduction <Func <object, object>, object, object>(
                    (func, lst) => ListLib.Map(func, lst), funcExpr, arg.Expression);
                rest = Expression.TypeIs(target.Expression, funcType);
            }
            funcType = typeof(SuffixFunc <Func <object, object> >);
            if (target.LimitType == funcType)
            {
                expr = ExpressionHelper.BetaReduction <SuffixFunc <Func <object, object> >, object, object>(
                    (sfxFunc, lst) => ListLib.Map(sfxFunc.Func, lst),
                    BinderHelper.Wrap(target.Expression, funcType), arg.Expression);
                rest = Expression.TypeIs(target.Expression, funcType);
            }
            // ----- ----- ----- return ----- ----- -----
            if (expr != null && rest != null)
            {
                return(new DynamicMetaObject(
                           BinderHelper.Wrap(expr, this.ReturnType),
                           BindingRestrictions.GetExpressionRestriction(rest)));
            }
            else
            {
                return(ThrowArgumentException(
                           target.LimitType + "を用いて射影(それぞれ)できません。",
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
        }
예제 #11
0
        /// <summary>
        /// 整数と小数の比較
        /// </summary>
        private DynamicMetaObject TryCalcOnDefferentNumericType(DynamicMetaObject left, DynamicMetaObject right)
        {
            Expression leftExpr  = BinderHelper.LimitTypeConvert(left);
            Expression rightExpr = BinderHelper.LimitTypeConvert(right);
            Expression expr      = null;

            foreach (var pattern in BinderHelper.CastPatterns)
            {
                if (leftExpr.Type == pattern.Narrow && rightExpr.Type == pattern.Wide)
                {
                    var upperLeft = Expression.Convert(leftExpr, pattern.Wide);
                    expr = Expression.MakeBinary(this.Operation, upperLeft, rightExpr);
                    break;
                }
                if (leftExpr.Type == pattern.Wide && rightExpr.Type == pattern.Narrow)
                {
                    var upperRight = Expression.Convert(rightExpr, pattern.Wide);
                    expr = Expression.MakeBinary(this.Operation, leftExpr, upperRight);
                    break;
                }
            }
            if (expr == null)
            {
                return(null);
            }
            return(new DynamicMetaObject(
                       BinderHelper.Wrap(expr, this.ReturnType),
                       BinderHelper.GetTypeRestriction(left, right)));
        }
예제 #12
0
 /// <summary>
 /// 比較方法を検索し、見つからなかったら例外を投げるMetaObjectを返す。
 /// </summary>
 private DynamicMetaObject Search(DynamicMetaObject left, DynamicMetaObject right)
 {
     return
         (TryCalcDefferentNumberType(left, right) ??
          TryImplicitCast(left, right) ??
          TryUseIComparableT(left, right) ??
          BinderHelper.NoResult("比較", this.ReturnType, left, right));
 }
예제 #13
0
        private DynamicMetaObject MakeDynamicMetaObject(DynamicMetaObject target, PropertyInfo propInfo)
        {
            var targetExpr = BinderHelper.Wrap(target.Expression, target.LimitType);
            var propAccess = Expression.Property(targetExpr, propInfo);
            var expr       = BinderHelper.Wrap(propAccess, this.ReturnType);
            var rest       = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #14
0
        private Expression[] ConvertArguments(DynamicMetaObject[] args, Type[] typeArgs)
        {
            var argsExpr = new Expression[args.Length];

            for (int i = 0; i < argsExpr.Length; i++)
            {
                argsExpr[i] = BinderHelper.Wrap(args[i].Expression, typeArgs[i]);
            }
            return(argsExpr);
        }
예제 #15
0
        /// <summary>
        /// 適切な計算方法が見つからなかった場合、RuntimeBinderExceptionを投げる。
        /// </summary>
        public static DynamicMetaObject NoResult(string name, Type type, DynamicMetaObject left, DynamicMetaObject right)
        {
            var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });
            var errorMsg = "{0}と{1}を" + name + "出来ません。";
            var mInfo    = typeof(String).GetMethod("Format", new[] { typeof(string), typeof(object), typeof(object) });
            var msgExpr  = Expression.Call(mInfo,
                                           Expression.Constant(errorMsg),
                                           Expression.Convert(left.Expression, typeof(object)),
                                           Expression.Convert(right.Expression, typeof(object)));
            var expr = Expression.Throw(Expression.New(ctorInfo, msgExpr), typeof(object));

            return(new DynamicMetaObject(expr, BinderHelper.GetTypeRestriction(left, right)));
        }
예제 #16
0
        private DynamicMetaObject InvokeDelegate(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            var  funcType = target.LimitType;
            var  typeArgs = funcType.GetGenericArguments();
            Type type     = null;

            if (Expression.TryGetFuncType(typeArgs, out type))
            {
                Expression[] argExprs = null;
                if (typeArgs.Length == args.Length + 1)
                {
                    argExprs = ConvertArguments(args, typeArgs);
                }
                else if (typeArgs.Length == (2 + 1) && args.Length == 1)
                {
                    // try inline tuple
                    if (args[0].LimitType == typeof(Tuple <object, object>))
                    {
                        var tupleExpr = BinderHelper.Wrap(args[0].Expression, typeof(Tuple <object, object>));
                        var fst       = ExpressionHelper.BetaReduction <Tuple <object, object>, object>(t => t.Item1, tupleExpr);
                        var snd       = ExpressionHelper.BetaReduction <Tuple <object, object>, object>(t => t.Item2, tupleExpr);
                        argExprs = new Expression[] {
                            BinderHelper.Wrap(fst, typeArgs[0]),
                            BinderHelper.Wrap(snd, typeArgs[1])
                        };
                    }
                }
                if (argExprs != null)
                {
                    return(new DynamicMetaObject(
                               Expression.Invoke(Expression.Convert(target.Expression, target.LimitType), argExprs),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }
            }
            if (Expression.TryGetActionType(typeArgs, out type))
            {
                if (typeArgs.Length == args.Length)
                {
                    return(new DynamicMetaObject(
                               Expression.Block(
                                   Expression.Invoke(
                                       Expression.Convert(target.Expression, target.LimitType),
                                       ConvertArguments(args, typeArgs)),
                                   Expression.Constant(null)),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }
            }
            return(ThrowArgumentException(
                       "引数の数が一致していません。",
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
        }
예제 #17
0
        /// <summary>
        /// 左辺と右辺を参照比較する。
        /// </summary>
        private DynamicMetaObject TryReferenceEqual(DynamicMetaObject left, DynamicMetaObject right)
        {
            if (left.LimitType.IsValueType || right.LimitType.IsValueType)
            {
                return(null);
            }
            var        boolResult = Expression.Constant(this.Operation == ExpressionType.Equal);
            Expression expr       = ExpressionHelper.BetaReduction(
                (object objA, object objB, bool result) => (object)(Object.ReferenceEquals(objA, objB) == result),
                left.Expression, right.Expression, boolResult);

            expr = BinderHelper.Wrap(expr, this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #18
0
        /// <summary>
        /// 標準の比較を用いる。
        /// 失敗した場合,右辺と左辺は等しくないものとする。
        /// </summary>
        private DynamicMetaObject Default(DynamicMetaObject left, DynamicMetaObject right)
        {
            Expression eqExpr = null;

            try {
                eqExpr = Expression.MakeBinary(this.Operation,
                                               BinderHelper.Wrap(left.Expression, left.LimitType),
                                               BinderHelper.Wrap(right.Expression, right.LimitType));
            }
            catch (InvalidOperationException) {
                eqExpr = Expression.Constant(this.Operation != ExpressionType.Equal);
            }
            var expr = BinderHelper.Wrap(eqExpr, this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #19
0
 public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
 {
     if (target.Value == null)
     {
         return(new DynamicMetaObject(
                    BinderHelper.Wrap(Expression.Constant(true), this.ReturnType),
                    BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(target.Expression))));
     }
     if (target.LimitType == typeof(bool))
     {
         return(new DynamicMetaObject(
                    BinderHelper.Wrap(Expression.Not(target.Expression), this.ReturnType),
                    BindingRestrictions.GetTypeRestriction(target.Expression, typeof(bool))));
     }
     return(new DynamicMetaObject(
                BinderHelper.Wrap(Expression.Constant(false), this.ReturnType),
                BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
 }
예제 #20
0
        /// <summary>
        /// 左辺がIComparable<T>を実装している場合、CompareToメソッドを呼ぶことで比較する。
        /// </summary>
        private DynamicMetaObject TryUseIComparableT(DynamicMetaObject left, DynamicMetaObject right)
        {
            var types      = left.LimitType.GetInterfaces();
            var cmpType    = typeof(IComparable <>).MakeGenericType(right.LimitType);
            var hasGeneric = Array.IndexOf(types, cmpType) != -1;

            if (hasGeneric == false)
            {
                return(null);
            }
            var callExpr = Expression.Call(
                Expression.Convert(left.Expression, cmpType),
                cmpType.GetMethod("CompareTo", new[] { right.LimitType }),
                Expression.Convert(right.Expression, right.LimitType));
            var expr = BinderHelper.Wrap(ExpressionHelper.BetaReduction(_compareExpr, callExpr), this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #21
0
        /// <summary>
        /// 左辺がIEquatable<T>を継承している場合,それを利用する。
        /// </summary>
        private DynamicMetaObject TryUseIEquatableT(DynamicMetaObject left, DynamicMetaObject right)
        {
            var types      = left.LimitType.GetInterfaces();
            var cmpType    = typeof(IEquatable <>).MakeGenericType(right.LimitType);
            var hasGeneric = Array.IndexOf(types, cmpType) != -1;

            if (hasGeneric == false)
            {
                return(null);
            }
            var callExpr = Expression.Call(
                Expression.Convert(left.Expression, cmpType),
                cmpType.GetMethod("Equals", new[] { right.LimitType }),
                Expression.Convert(right.Expression, right.LimitType));
            var result = Expression.Constant(this.Operation == ExpressionType.Equal);
            var expr   = BinderHelper.Wrap(Expression.Equal(callExpr, result), this.ReturnType);
            var rest   = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
예제 #22
0
        /// <summary>
        /// 左辺、右辺のいずれかがnullで、もう一方はそうでない場合
        /// </summary>
        private DynamicMetaObject CompareEatherNull(DynamicMetaObject left, DynamicMetaObject right)
        {
            Contract.Requires <ArgumentException>(
                left.Value == null && right.Value != null ||
                left.Value != null && right.Value == null);

            bool?value = null;

            switch (this.Operation)
            {
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
                value = false;
                break;

            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
                value = true;
                break;
            }
            Expression rest;
            bool       order;

            if (left.Value == null)
            {
                rest = Expression.AndAlso(
                    BinderHelper.IsNull(left.Expression),
                    BinderHelper.IsNotNull(right.Expression));
                order = true;
            }
            else
            {
                rest = Expression.AndAlso(
                    BinderHelper.IsNull(right.Expression),
                    BinderHelper.IsNotNull(left.Expression));
                order = false;
            }
            var expr = BinderHelper.Wrap(Expression.Constant(value ^ order), this.ReturnType);

            return(new DynamicMetaObject(expr, BindingRestrictions.GetExpressionRestriction(rest)));
        }
예제 #23
0
 public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
 {
     if (target.Value == null && arg.Value == null)
     {
         return(CompareBotheNull(target, arg));
     }
     if (target.Value == null || arg.Value == null)
     {
         return(CompareEatherNull(target, arg));
     }
     try {
         var expr = Expression.MakeBinary(
             this.Operation,
             BinderHelper.Wrap(target.Expression, target.LimitType),
             BinderHelper.Wrap(arg.Expression, arg.LimitType));
         return(new DynamicMetaObject(
                    BinderHelper.Wrap(expr, this.ReturnType),
                    BinderHelper.GetTypeRestriction(target, arg)));
     }
     catch (InvalidOperationException) {
         return(Search(target, arg));
     }
 }