示例#1
0
        private static bool TryBindToMethod(SyntaxTreeNode node, object methodName, ArgumentsTree arguments, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            boundExpression = null;
            bindingError    = null;

            var constructorDescription = default(MemberDescription);

            if (bindingContext.TryResolveMember(methodName, out constructorDescription) == false || constructorDescription.IsConstructor == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCONSTRUCTOR, methodName), node);
                return(false);
            }

            var typeDescription = TypeDescription.GetTypeDescription(constructorDescription.DeclaringType);

            // feature: lambda building via new Func()
            var lambdaArgument = default(SyntaxTreeNode);

            if (typeDescription.IsDelegate && arguments.Count == 1 && (lambdaArgument = arguments.Values.Single()).GetExpressionType(throwOnError: true) == Constants.EXPRESSION_TYPE_LAMBDA)
            {
                return(LambdaBinder.TryBind(lambdaArgument, bindingContext, typeDescription, out boundExpression, out bindingError));
            }

            var constructorQuality = MemberDescription.QUALITY_INCOMPATIBLE;

            if (constructorDescription.TryMakeCall(null, arguments, bindingContext, out boundExpression, out constructorQuality))
            {
                return(true);
            }

            bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCONSTRUCTOR, constructorDescription.DeclaringType), node);
            return(false);
        }
示例#2
0
        internal static bool TryGetListInitializers(SyntaxTreeNode listNode, BindingContext bindingContext, out ElementInit[] initializers, out Exception bindingError)
        {
            if (listNode == null)
            {
                throw new ArgumentNullException("listNode");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }

            bindingError = null;
            var initializerNodes = listNode.GetInitializers(throwOnError: true);

            initializers = new ElementInit[initializerNodes.Count];
            for (var i = 0; i < initializers.Length; i++)
            {
                var index          = Constants.GetIndexAsString(i);
                var initializerObj = default(object);
                if (initializerNodes.TryGetValue(index, out initializerObj) == false || initializerObj is SyntaxTreeNode == false)
                {
                    return(false);                    // failed to get initializer #i
                }
                var initializerNode = (SyntaxTreeNode)initializerObj;
                var addMethodName   = initializerNode.GetMethodName(throwOnError: true);
                var addMethod       = default(MemberDescription);
                if (bindingContext.TryResolveMember(addMethodName, out addMethod) == false || addMethod.IsMethod == false)
                {
                    return(false);                    // failed to resolve 'Add' method
                }

                var argumentNodes = initializerNode.GetArguments(throwOnError: true);
                var arguments     = new Expression[argumentNodes.Count];
                for (var p = 0; p < arguments.Length; p++)
                {
                    var parameter     = addMethod.GetParameter(p);
                    var parameterType = TypeDescription.GetTypeDescription(parameter.ParameterType);
                    var argumentNode  = default(SyntaxTreeNode);
                    if (argumentNodes.TryGetValue(p, out argumentNode) == false && argumentNodes.TryGetValue(parameter.Name, out argumentNode) == false)
                    {
                        return(false);                        // failed to find argument #p
                    }

                    if (AnyBinder.TryBindInNewScope(argumentNode, bindingContext, parameterType, out arguments[p], out bindingError) == false)
                    {
                        return(false);                        // failed to bind argument #p
                    }
                }
                initializers[i] = Expression.ElementInit(addMethod, arguments);
            }
            return(true);
        }
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (expectedType == null)
            {
                throw new ArgumentNullException("expectedType");
            }

            boundExpression = null;
            bindingError    = null;

            var target     = default(Expression);
            var targetNode = node.GetExpression(throwOnError: false);
            var memberNode = node.GetMember(throwOnError: false);
            var member     = default(MemberDescription);

            if (memberNode != null && bindingContext.TryResolveMember(memberNode, out member))
            {
                if (targetNode != null && AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false)
                {
                    return(false);
                }
                boundExpression = Expression.MakeMemberAccess(target, member);
                return(true);
            }

            var isStatic            = false;
            var targetType          = default(Type);
            var propertyOrFieldName = node.GetMemberName(throwOnError: true);
            var useNullPropagation  = node.GetUseNullPropagation(throwOnError: false);

            if (bindingContext.TryResolveType(targetNode, out targetType))
            {
                target   = null;
                isStatic = true;
            }
            else if (targetNode == null)
            {
                target     = bindingContext.Global;
                targetType = target != null ? target.Type : null;
                isStatic   = false;

                switch (propertyOrFieldName)
                {
                case Constants.VALUE_NULL_STRING:
                    boundExpression = ExpressionUtils.NullConstant;
                    return(true);

                case Constants.VALUE_TRUE_STRING:
                    boundExpression = ExpressionUtils.TrueConstant;
                    return(true);

                case Constants.VALUE_FALSE_STRING:
                    boundExpression = ExpressionUtils.TrueConstant;
                    return(false);

                default:
                    if (bindingContext.TryGetParameter(propertyOrFieldName, out boundExpression))
                    {
                        return(true);
                    }
                    break;
                }
            }
            else if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError))
            {
                Debug.Assert(target != null, "target != null");

                targetType = target.Type;
                isStatic   = false;
            }
            else
            {
                target     = null;
                targetType = null;
            }

            if (target == null && targetType == null)
            {
                if (bindingError == null)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, propertyOrFieldName), node);
                }
                return(false);
            }

            Debug.Assert(targetType != null, "type != null");

            var targetTypeDescription = TypeDescription.GetTypeDescription(targetType);
            var foundMember           = default(MemberDescription);

            if (isStatic && targetTypeDescription.IsEnum)
            {
                var fieldMemberDescription = targetTypeDescription.GetMembers(propertyOrFieldName).FirstOrDefault(m => m.IsStatic);
                if (fieldMemberDescription == null)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVEMEMBERONTYPE, propertyOrFieldName, targetType), node);
                    return(false);
                }
                boundExpression = fieldMemberDescription.ConstantValueExpression;
            }
            else
            {
                foreach (var declaredMember in targetTypeDescription.GetMembers(propertyOrFieldName))
                {
                    if (declaredMember.IsStatic != isStatic)
                    {
                        continue;
                    }

                    foundMember = foundMember ?? declaredMember;

                    if (declaredMember.IsPropertyOrField == false)
                    {
                        continue;
                    }

                    if (declaredMember.TryMakeAccessor(target, out boundExpression))
                    {
                        break;
                    }
                }
            }

            if (boundExpression == null)
            {
                if (foundMember != null)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDMEMBER, propertyOrFieldName, targetType), node);
                }
                else
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVEMEMBERONTYPE, propertyOrFieldName, targetType), node);
                }
                return(false);
            }

            if (useNullPropagation && isStatic)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOAPPLYNULLCONDITIONALOPERATORONTYPEREF, targetType));
                return(false);
            }

            if (useNullPropagation && targetTypeDescription.CanBeNull)
            {
                bindingContext.RegisterNullPropagationTarget(target);
            }

            if (targetTypeDescription.IsAssignableFrom(typeof(Type)) &&
                bindingContext.IsKnownType(typeof(Type)) == false &&
                bindingContext.IsKnownType(targetType) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_RESTRICTED_MEMBER_INVOCATION, propertyOrFieldName, targetType, typeof(ITypeResolver)), node);
                return(false);
            }

            return(true);
        }
示例#4
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (expectedType == null)
            {
                throw new ArgumentNullException("expectedType");
            }

            boundExpression = null;
            bindingError    = null;

            var expressionType = node.GetExpressionType(throwOnError: true);
            var operandNode    = node.GetExpression(throwOnError: true);
            var operand        = default(Expression);
            var methodName     = node.GetMethodName(throwOnError: false);
            var methodMember   = default(MemberDescription);

            if (AnyBinder.TryBindInNewScope(operandNode, bindingContext, TypeDescription.ObjectType, out operand, out bindingError) == false)
            {
                return(false);
            }

            if (methodName != null)
            {
                bindingContext.TryResolveMember(methodName, out methodMember);
            }

            Debug.Assert(operand != null, "operand != null");

            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_NEGATE:
                if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.Negate, out boundExpression) == false)
                {
                    // fixing b_u_g in mono expression compiler: Negate on float or double = exception
                    if (operand.Type == typeof(double) || operand.Type == typeof(float))
                    {
                        boundExpression = Expression.Multiply(operand, operand.Type == typeof(float) ? ExpressionUtils.NegativeSingle : ExpressionUtils.NegativeDouble);
                    }
                    else
                    {
                        boundExpression = Expression.Negate(operand, methodMember);
                    }
                }
                break;

            case Constants.EXPRESSION_TYPE_NEGATE_CHECKED:
                if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.NegateChecked, out boundExpression) == false)
                {
                    // fixing b_u_g in mono expression compiler: Negate on float or double = exception
                    if (operand.Type == typeof(double) || operand.Type == typeof(float))
                    {
                        boundExpression = Expression.Multiply(operand, operand.Type == typeof(float) ? ExpressionUtils.NegativeSingle : ExpressionUtils.NegativeDouble);
                    }
                    else
                    {
                        boundExpression = Expression.NegateChecked(operand, methodMember);
                    }
                }
                break;

            case Constants.EXPRESSION_TYPE_COMPLEMENT:
            case Constants.EXPRESSION_TYPE_NOT:
                if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.Not, out boundExpression) == false)
                {
                    boundExpression = Expression.Not(operand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_UNARY_PLUS:
                if (ExpressionUtils.TryPromoteUnaryOperation(ref operand, ExpressionType.UnaryPlus, out boundExpression) == false)
                {
                    boundExpression = Expression.UnaryPlus(operand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_ARRAY_LENGTH:
                boundExpression = Expression.ArrayLength(operand);
                break;

            default:
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node);
                return(false);
            }
            return(true);
        }
        private static bool TryGetBinding(object bindingNode, BindingContext bindingContext, out MemberBinding memberBinding, out Exception bindingError)
        {
            bindingError  = null;
            memberBinding = null;
            var bindingNodeTree = bindingNode as SyntaxTreeNode;

            if (bindingNodeTree == null)
            {
                return(false);
            }

            var bindingType = (string)bindingNodeTree.GetTypeName(throwOnError: true);
            var memberObj   = bindingNodeTree.GetMember(throwOnError: true);
            var member      = default(MemberDescription);

            if (bindingContext.TryResolveMember(memberObj, out member) == false)
            {
                return(false);
            }
            var memberValueType = TypeDescription.GetTypeDescription(member.ResultType);

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (bindingType)
            {
            case "Assignment":
                var expressionNode = bindingNodeTree.GetExpression(throwOnError: true);
                var expression     = default(Expression);
                if (AnyBinder.TryBindInNewScope(expressionNode, bindingContext, memberValueType, out expression, out bindingError) == false)
                {
                    return(false);                            // file to bind member's value
                }

                if (member.IsMethod)
                {
                    memberBinding = Expression.Bind((MethodInfo)member, expression);
                }
                else
                {
                    memberBinding = Expression.Bind((MemberInfo)member, expression);
                }
                return(true);

            case "MemberBinding":
                var bindings = default(MemberBinding[]);
                if (TryGetBindings(bindingNodeTree, bindingContext, out bindings, out bindingError) == false)
                {
                    return(false);                            // failed to resolve bindings
                }
                if (member.IsMethod)
                {
                    memberBinding = Expression.MemberBind((MethodInfo)member, bindings);
                }
                else
                {
                    memberBinding = Expression.MemberBind((MemberInfo)member, bindings);
                }
                return(true);

            case "ListBinding":
                var initializers = default(ElementInit[]);
                if (ListInitBinder.TryGetListInitializers(bindingNodeTree, bindingContext, out initializers, out bindingError) == false)
                {
                    return(false);                            // failed to resolve list initializers
                }
                if (member.IsMethod)
                {
                    memberBinding = Expression.ListBind((MethodInfo)member, initializers);
                }
                else
                {
                    memberBinding = Expression.ListBind((MemberInfo)member, initializers);
                }
                return(true);
            }

            return(false);
        }
示例#6
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (expectedType == null)
            {
                throw new ArgumentNullException("expectedType");
            }

            boundExpression = null;
            bindingError    = null;

            var target             = default(Expression);
            var arguments          = node.GetArguments(throwOnError: false);
            var methodName         = node.GetMethodName(throwOnError: true);
            var useNullPropagation = node.GetUseNullPropagation(throwOnError: false);

            var methodMember = default(MemberDescription);

            if (bindingContext.TryResolveMember(methodName, out methodMember))
            {
                if (methodMember.IsMethod == false)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_CALLMEMBERISNOTMETHOD, methodMember.Name, methodMember.DeclaringType), node);
                    return(false);
                }

                var targetNode = node.GetExpression(throwOnError: true);

                if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false)
                {
                    return(false);
                }

                float methodQuality;
                if (methodMember.TryMakeCall(target, arguments, bindingContext, out boundExpression, out methodQuality) == false)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDMETHOD, methodMember.Name, target.Type, arguments.Count), node);
                    return(false);
                }

                return(true);
            }


            var methodRef = default(TypeReference);

            if (BindingContext.TryGetMethodReference(methodName, out methodRef) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, methodName), node);
                return(false);
            }

            var targetType = default(Type);

            if (TryBindTarget(node, bindingContext, out target, out targetType, out bindingError) == false)
            {
                return(false);
            }

            var isStatic = target == null;
            var selectedMethodQuality = MemberDescription.QUALITY_INCOMPATIBLE;
            var hasGenericParameters  = methodRef.IsGenericType;
            var genericArguments      = default(Type[]);

            if (hasGenericParameters)
            {
                genericArguments = new Type[methodRef.TypeArguments.Count];
                for (var i = 0; i < genericArguments.Length; i++)
                {
                    var typeArgument = methodRef.TypeArguments[i];
                    if (bindingContext.TryResolveType(typeArgument, out genericArguments[i]) == false)
                    {
                        bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeArgument), node);
                        return(false);
                    }
                }
            }

            var targetTypeDescription = TypeDescription.GetTypeDescription(targetType);
            var foundMethod           = default(MethodInfo);

            foreach (var memberDescription in targetTypeDescription.GetMembers(methodRef.Name))
            {
                if (memberDescription.IsMethod == false)
                {
                    continue;
                }

                var methodDescription = memberDescription;
                var method            = (MethodInfo)memberDescription;

                foundMethod = foundMethod ?? method;

                if (method.IsStatic != isStatic || method.IsGenericMethod != hasGenericParameters)
                {
                    continue;
                }

                if (hasGenericParameters && memberDescription.GenericArgumentsCount != methodRef.TypeArguments.Count)
                {
                    continue;
                }

                if (hasGenericParameters)
                {
                    try
                    {
                        methodDescription = methodDescription.MakeGenericMethod(genericArguments);
                        method            = methodDescription;
                    }
                    catch (ArgumentException exception)
                    {
                        bindingError = exception;
                        continue;                         /* An element of typeArguments does not satisfy the constraints specified for the corresponding type parameter of the current generic method definition. */
                    }
                }


                var methodQuality        = 0.0f;
                var methodCallExpression = default(Expression);
                if (methodDescription.TryMakeCall(target, arguments, bindingContext, out methodCallExpression, out methodQuality) == false)
                {
                    continue;
                }

                if (float.IsNaN(methodQuality) || methodQuality <= selectedMethodQuality)
                {
                    continue;
                }

                boundExpression       = methodCallExpression;
                selectedMethodQuality = methodQuality;

                if (Math.Abs(methodQuality - MemberDescription.QUALITY_EXACT_MATCH) < float.Epsilon)
                {
                    break;                     // best match
                }
            }

            if (bindingError != null)
            {
                return(false);
            }

            if (boundExpression == null)
            {
                if (foundMethod != null)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDMETHOD, methodRef.Name, targetType, arguments.Count), node);
                }
                else
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCALL, methodRef.Name, targetType, arguments.Count), node);
                }
                return(false);
            }

            if (useNullPropagation && target == null)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOAPPLYNULLCONDITIONALOPERATORONTYPEREF, targetType));
                return(false);
            }

            if (useNullPropagation && targetTypeDescription.CanBeNull)
            {
                bindingContext.RegisterNullPropagationTarget(target);
            }

            if (targetTypeDescription.IsAssignableFrom(typeof(Type)) &&
                bindingContext.IsKnownType(typeof(Type)) == false &&
                (bindingContext.IsKnownType(targetType) == false || methodRef.Name.Equals("InvokeMember", StringComparison.Ordinal)))
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_RESTRICTED_MEMBER_INVOCATION, methodName, targetType, typeof(ITypeResolver)), node);
                return(false);
            }

            return(true);
        }
示例#7
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (expectedType == null)
            {
                throw new ArgumentNullException("expectedType");
            }

            boundExpression = null;
            bindingError    = null;

            var expressionType   = node.GetExpressionType(throwOnError: true);
            var left             = node.GetLeftExpression(throwOnError: true);
            var right            = node.GetRightExpression(throwOnError: true);
            var methodName       = node.GetMethodName(throwOnError: false);
            var conversion       = node.GetConversion(throwOnError: false);
            var leftOperand      = default(Expression);
            var rightOperand     = default(Expression);
            var conversionLambda = default(Expression);
            var methodMember     = default(MemberDescription);

            if (AnyBinder.TryBindInNewScope(left, bindingContext, TypeDescription.ObjectType, out leftOperand, out bindingError) == false)
            {
                return(false);
            }
            if (AnyBinder.TryBindInNewScope(right, bindingContext, TypeDescription.ObjectType, out rightOperand, out bindingError) == false)
            {
                return(false);
            }

            if (methodName != null)
            {
                bindingContext.TryResolveMember(methodName, out methodMember);
            }

            if (conversion != null)
            {
                AnyBinder.TryBindInNewScope(conversion, bindingContext, TypeDescription.ObjectType, out conversionLambda, out bindingError);
                bindingError = null;
            }


            Debug.Assert(leftOperand != null, "leftOperand != null");
            Debug.Assert(rightOperand != null, "rightOperand != null");

            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_ADD:
                if (leftOperand.Type == typeof(string) || rightOperand.Type == typeof(string))
                {
                    boundExpression = Expression.Call
                                      (
                        StringConcat.GetMethodInfo(),
                        Expression.Convert(leftOperand, typeof(object)),
                        Expression.Convert(rightOperand, typeof(object))
                                      );
                    break;
                }
                else
                {
                    if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Add, out boundExpression) == false)
                    {
                        boundExpression = Expression.Add(leftOperand, rightOperand);
                    }
                    break;
                }

            case Constants.EXPRESSION_TYPE_ADD_CHECKED:
                if (leftOperand.Type == typeof(string) || rightOperand.Type == typeof(string))
                {
                    boundExpression = Expression.Call
                                      (
                        StringConcat.GetMethodInfo(),
                        Expression.Convert(leftOperand, typeof(object)),
                        Expression.Convert(rightOperand, typeof(object))
                                      );
                    break;
                }
                else
                {
                    if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.AddChecked, out boundExpression) == false)
                    {
                        boundExpression = Expression.AddChecked(leftOperand, rightOperand);
                    }
                    break;
                }

            case Constants.EXPRESSION_TYPE_SUBTRACT:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Subtract, out boundExpression) == false)
                {
                    boundExpression = Expression.Subtract(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.SubtractChecked, out boundExpression) == false)
                {
                    boundExpression = Expression.SubtractChecked(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_LEFT_SHIFT:
                ExpressionUtils.TryPromoteUnaryOperation(ref leftOperand, ExpressionType.LeftShift, out boundExpression);
                ExpressionUtils.TryPromoteUnaryOperation(ref rightOperand, ExpressionType.LeftShift, out boundExpression);
                boundExpression = Expression.LeftShift(leftOperand, rightOperand, methodMember);
                break;

            case Constants.EXPRESSION_TYPE_RIGHT_SHIFT:
                ExpressionUtils.TryPromoteUnaryOperation(ref leftOperand, ExpressionType.RightShift, out boundExpression);
                ExpressionUtils.TryPromoteUnaryOperation(ref rightOperand, ExpressionType.RightShift, out boundExpression);
                boundExpression = Expression.RightShift(leftOperand, rightOperand, methodMember);
                break;

            case Constants.EXPRESSION_TYPE_GREATER_THAN:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.GreaterThan, out boundExpression) == false)
                {
                    boundExpression = Expression.GreaterThan(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_GREATER_THAN_OR_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.GreaterThanOrEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.GreaterThanOrEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_LESS_THAN:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.LessThan, out boundExpression) == false)
                {
                    boundExpression = Expression.LessThan(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_LESS_THAN_OR_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.LessThanOrEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.LessThanOrEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_POWER:
                var resultType       = TypeDescription.GetTypeDescription(leftOperand.Type);
                var resultTypeUnwrap = resultType.IsNullable ? resultType.UnderlyingType : resultType;
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Power, out boundExpression) == false)
                {
                    var operandsType      = TypeDescription.GetTypeDescription(leftOperand.Type);
                    var operandTypeUnwrap = operandsType.IsNullable ? operandsType.UnderlyingType : operandsType;
                    var promoteToNullable = resultType.IsNullable || operandsType.IsNullable;
                    if (operandTypeUnwrap != typeof(double) && leftOperand.Type == rightOperand.Type)
                    {
                        leftOperand  = Expression.ConvertChecked(leftOperand, promoteToNullable ? typeof(double?) : typeof(double));
                        rightOperand = Expression.ConvertChecked(rightOperand, promoteToNullable ? typeof(double?) : typeof(double));
                    }
                    boundExpression = Expression.Power(leftOperand, rightOperand, methodMember);

                    if (resultType != typeof(double))
                    {
                        boundExpression = Expression.ConvertChecked(boundExpression, promoteToNullable ? resultTypeUnwrap.GetNullableType() : resultTypeUnwrap);
                    }
                }
                break;

            case Constants.EXPRESSION_TYPE_DIVIDE:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Divide, out boundExpression) == false)
                {
                    boundExpression = Expression.Divide(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_MULTIPLY:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Multiply, out boundExpression) == false)
                {
                    boundExpression = Expression.Multiply(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.MultiplyChecked, out boundExpression) == false)
                {
                    boundExpression = Expression.MultiplyChecked(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_MODULO:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Modulo, out boundExpression) == false)
                {
                    boundExpression = Expression.Modulo(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Equal, out boundExpression) == false)
                {
                    boundExpression = Expression.Equal(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_NOT_EQUAL:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.NotEqual, out boundExpression) == false)
                {
                    boundExpression = Expression.NotEqual(leftOperand, rightOperand);
                }
                break;

            case Constants.EXPRESSION_TYPE_AND:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.And, out boundExpression) == false)
                {
                    boundExpression = Expression.And(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_OR:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Or, out boundExpression) == false)
                {
                    boundExpression = Expression.Or(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_EXCLUSIVE_OR:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.ExclusiveOr, out boundExpression) == false)
                {
                    boundExpression = Expression.ExclusiveOr(leftOperand, rightOperand, methodMember);
                }
                break;

            case Constants.EXPRESSION_TYPE_AND_ALSO:
                boundExpression = Expression.AndAlso(leftOperand, rightOperand, methodMember);
                break;

            case Constants.EXPRESSION_TYPE_OR_ELSE:
                boundExpression = Expression.OrElse(leftOperand, rightOperand, methodMember);
                break;

            case Constants.EXPRESSION_TYPE_COALESCE:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Coalesce, out boundExpression) == false)
                {
                    boundExpression = Expression.Coalesce(leftOperand, rightOperand, conversionLambda as LambdaExpression);
                }
                break;

            default:
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node);
                return(false);
            }
            return(true);
        }