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");
            }

            bindingError    = null;
            boundExpression = null;

            var test           = node.GetTestExpression(throwOnError: true);
            var ifTrue         = node.GetIfTrueExpression(throwOnError: true);
            var ifFalse        = node.GetIfFalseExpression(throwOnError: true);
            var testExpression = default(Expression);
            var ifTrueBranch   = default(Expression);
            var ifFalseBranch  = default(Expression);

            if (AnyBinder.TryBindInNewScope(test, bindingContext, TypeDescription.GetTypeDescription(typeof(bool)), out testExpression, out bindingError) == false)
            {
                return(false);
            }
            if (AnyBinder.TryBindInNewScope(ifTrue, bindingContext, TypeDescription.ObjectType, out ifTrueBranch, out bindingError) == false)
            {
                return(false);
            }
            if (AnyBinder.TryBindInNewScope(ifFalse, bindingContext, TypeDescription.ObjectType, out ifFalseBranch, out bindingError) == false)
            {
                return(false);
            }

            Debug.Assert(testExpression != null, "testExpression != null");
            Debug.Assert(ifTrueBranch != null, "ifTrueBranch != null");
            Debug.Assert(ifFalseBranch != null, "ifFalseBranch != null");

            if (ExpressionUtils.TryPromoteBinaryOperation(ref ifTrueBranch, ref ifFalseBranch, ExpressionType.Conditional, out boundExpression) == false)
            {
                if (ifTrueBranch.Type != ifFalseBranch.Type)
                {
                    float quality;
                    ExpressionUtils.TryMorphType(ref ifTrueBranch, ifFalseBranch.Type, out quality);
                }

                boundExpression = Expression.Condition(testExpression, ifTrueBranch, ifFalseBranch);
            }
            return(true);
        }
Exemplo n.º 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 typeName = node.GetTypeName(throwOnError: true);
            var type     = default(Type);

            if (bindingContext.TryResolveType(typeName, out type) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node);
                return(false);
            }

            var indexTypeDescription = TypeDescription.Int32Type;
            var arguments            = node.GetArguments(throwOnError: true);
            var argumentExpressions  = new Expression[arguments.Count];

            for (var i = 0; i < arguments.Count; i++)
            {
                var argument = default(SyntaxTreeNode);
                if (arguments.TryGetValue(i, out argument) == false)
                {
                    bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BOUNDEXPR_ARGSDOESNTMATCHPARAMS, node);
                    return(false);
                }

                if (AnyBinder.TryBindInNewScope(argument, bindingContext, indexTypeDescription, out argumentExpressions[i], out bindingError) == false)
                {
                    return(false);
                }

                Debug.Assert(argumentExpressions[i] != null, "argumentExpressions[i] != null");
            }

            boundExpression = Expression.NewArrayBounds(type, argumentExpressions);
            return(true);
        }
Exemplo n.º 4
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            bindingError = null;

            boundExpression = null;
            bindingError    = null;

            var operandNode = node.GetExpression(throwOnError: true);
            var operand     = default(Expression);

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

            boundExpression = Expression.Quote(operand);
            return(true);
        }
Exemplo n.º 5
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 expressionNode = node.GetExpression(throwOnError: true);

            return(AnyBinder.TryBindInNewScope(expressionNode, bindingContext, expectedType, out boundExpression, out bindingError));
        }
Exemplo n.º 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 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);
        }
Exemplo n.º 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 leftOperand    = default(Expression);
            var rightOperand   = default(Expression);

            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);
            }

            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.Method,
                        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.Method,
                        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);
                }
                break;

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

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

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

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

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

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

            case Constants.EXPRESSION_TYPE_LESSTHAN_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);

                    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);
                }
                break;

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

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

            case Constants.EXPRESSION_TYPE_MODULO:
                if (ExpressionUtils.TryPromoteBinaryOperation(ref leftOperand, ref rightOperand, ExpressionType.Modulo, out boundExpression) == false)
                {
                    boundExpression = Expression.Modulo(leftOperand, rightOperand);
                }
                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_NOTEQUAL:
                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);
                }
                break;

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

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

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

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

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

                break;

            default:
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node);
                return(false);
            }
            return(true);
        }
        public bool TryMakeCall(Expression target, ArgumentsTree argumentsTree, BindingContext bindingContext, out Expression expression, out float expressionQuality)
        {
            if (argumentsTree == null)
            {
                throw new ArgumentNullException("argumentsTree");
            }
            if (bindingContext == null)
            {
                throw new ArgumentNullException("bindingContext");
            }
            if (!this.IsStatic && !this.IsConstructor && target == null)
            {
                throw new ArgumentNullException("target");
            }

            expression        = null;
            expressionQuality = QUALITY_INCOMPATIBLE;

            if (this.parameters == null)             // not a method, constructor, indexer
            {
                return(false);
            }

            // check argument count
            if (argumentsTree.Count > this.parameters.Length)
            {
                return(false);                // not all arguments are bound to parameters
            }
            var requiredParametersCount = this.parameters.Length - this.parameters.Count(p => p.IsOptional);

            if (argumentsTree.Count < requiredParametersCount)
            {
                return(false);                // not all required parameters has values
            }
            // bind arguments
            var parametersQuality = 0.0f;
            var arguments         = default(Expression[]);

            foreach (var argumentName in argumentsTree.Keys)
            {
                var parameter      = default(ParameterInfo);
                var parameterIndex = 0;
                if (HasDigitsOnly(argumentName))
                {
                    parameterIndex = int.Parse(argumentName, Constants.DefaultFormatProvider);
                    if (parameterIndex >= this.parameters.Length)
                    {
                        return(false);                        // position out of range
                    }
                    parameter = this.parameters[parameterIndex];

                    if (argumentsTree.ContainsKey(parameter.Name))
                    {
                        return(false);                        // positional intersects named
                    }
                }
                else
                {
                    if (this.parametersByName.TryGetValue(argumentName, out parameter) == false)
                    {
                        return(false);                        // parameter is not found
                    }
                    parameterIndex = parameter.Position;
                }

                var expectedType = TypeDescription.GetTypeDescription(parameter.ParameterType);
                var argValue     = default(Expression);
                var bindingError = default(Exception);
                if (AnyBinder.TryBindInNewScope(argumentsTree[argumentName], bindingContext, expectedType, out argValue, out bindingError) == false)
                {
                    return(false);
                }

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

                var quality = 0.0f;
                if (ExpressionUtils.TryMorphType(ref argValue, expectedType, out quality) == false || quality <= 0)
                {
                    return(false);                   // failed to bind parameter
                }
                parametersQuality += quality;        // casted
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                arguments[parameterIndex] = argValue;
            }

            if (this.parameters.Length > 0)
            {
                if (arguments == null)
                {
                    arguments = new Expression[this.parameters.Length];
                }
                for (var i = 0; i < arguments.Length; i++)
                {
                    if (arguments[i] != null)
                    {
                        continue;
                    }
                    var parameter = this.parameters[i];
                    if (parameter.IsOptional == false)
                    {
                        return(false);                        // missing required parameter
                    }
                    var typeDescription = TypeDescription.GetTypeDescription(parameter.ParameterType);
                    arguments[i]       = typeDescription.DefaultExpression;
                    parametersQuality += TypeConversion.QUALITY_SAME_TYPE;
                }

                expressionQuality = parametersQuality / this.parameters.Length;
            }
            else
            {
                expressionQuality = QUALITY_EXACT_MATCH;
            }


            if (this.member is MethodInfo)
            {
                if (this.IsStatic)
                {
                    expression = Expression.Call(this, arguments);
                }
                else if (this.Name == Constants.DELEGATE_INVOKE_NAME && this.DeclaringType.IsDelegate)
                {
                    expression = Expression.Invoke(target, arguments);
                }
                else
                {
                    expression = Expression.Call(target, this, arguments);
                }
                return(true);
            }
            else if (this.member is ConstructorInfo)
            {
                expression = Expression.New((ConstructorInfo)this.member, arguments);
                return(true);
            }
            else if (this.member is PropertyInfo)
            {
                if (this.IsStatic)
                {
                    expression = Expression.Call(this, arguments);
                }
                else
                {
                    expression = Expression.Call(target, this, arguments);
                }
                return(true);
            }
            expressionQuality = QUALITY_INCOMPATIBLE;
            return(false);
        }
        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);
        }
Exemplo n.º 10
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;

            // try get type of lambda from node
            var lambdaTypeName = node.GetTypeName(throwOnError: false);
            var lambdaType     = default(Type);

            if (lambdaTypeName != null)
            {
                if (bindingContext.TryResolveType(lambdaTypeName, out lambdaType) == false)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, lambdaTypeName), node);
                    return(false);
                }
                else
                {
                    expectedType = TypeDescription.GetTypeDescription(lambdaType);
                }
            }

            if (expectedType.HasGenericParameters || !expectedType.IsDelegate)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_VALIDDELEGATETYPEISEXPECTED, expectedType.ToString()));
                return(false);
            }

            var expressionType     = node.GetExpressionType(throwOnError: true);
            var bodyNode           = node.GetExpression(throwOnError: true);
            var argumentsTree      = node.GetArguments(throwOnError: false);
            var lambdaInvokeMethod = expectedType.GetMembers(Constants.DELEGATE_INVOKE_NAME).FirstOrDefault(m => m.IsMethod && !m.IsStatic);

            if (lambdaInvokeMethod == null)
            {
                bindingError = new MissingMethodException(string.Format(Resources.EXCEPTION_BIND_MISSINGMETHOD, expectedType.ToString(), Constants.DELEGATE_INVOKE_NAME));
                return(false);
            }

            if (lambdaInvokeMethod.GetParametersCount() != argumentsTree.Count)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_INVALIDLAMBDAARGUMENTS, expectedType));
                return(false);
            }

            var argumentNames = new string[argumentsTree.Count];

            for (var i = 0; i < argumentNames.Length; i++)
            {
                var argumentNameTree     = default(SyntaxTreeNode);
                var argumentNameTreeType = default(string);
                if (argumentsTree.TryGetValue(i, out argumentNameTree) == false ||
                    argumentNameTree == null ||
                    (argumentNameTreeType = argumentNameTree.GetExpressionType(throwOnError: true)) == null ||
                    (argumentNameTreeType == Constants.EXPRESSION_TYPE_PROPERTY_OR_FIELD ||
                     argumentNameTreeType == Constants.EXPRESSION_TYPE_MEMBER_RESOLVE ||
                     argumentNameTreeType == Constants.EXPRESSION_TYPE_PARAMETER) == false)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGATTRONNODE, Constants.EXPRESSION_ATTRIBUTE, expressionType), node);
                    return(false);
                }
                argumentNames[i] = argumentNameTree.GetMemberName(throwOnError: true);
            }

            var lambdaParameters = new ParameterExpression[argumentsTree.Count];

            for (var i = 0; i < argumentsTree.Count; i++)
            {
                lambdaParameters[i] = Expression.Parameter(lambdaInvokeMethod.GetParameter(i).ParameterType, argumentNames[i]);
            }

            var currentParameters = bindingContext.Parameters;
            var newParameters     = new List <ParameterExpression>(lambdaParameters.Length + currentParameters.Count);

            // add all lambda's parameters
            newParameters.AddRange(lambdaParameters);
            // add closure parameters
            foreach (var parameterExpr in currentParameters)
            {
                if (Array.IndexOf(argumentNames, parameterExpr.Name) < 0)
                {
                    newParameters.Add(parameterExpr);
                }
            }

            var nestedBindingContext = bindingContext.CreateNestedContext(newParameters.AsReadOnly(), lambdaInvokeMethod.ResultType);
            var body = default(Expression);

            if (AnyBinder.TryBindInNewScope(bodyNode, nestedBindingContext, TypeDescription.GetTypeDescription(lambdaInvokeMethod.ResultType), out body, out bindingError) == false)
            {
                return(false);
            }

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

            boundExpression = Expression.Lambda(expectedType, body, lambdaParameters);
            return(true);
        }
Exemplo n.º 11
0
        public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError)
        {
            boundExpression = null;
            bindingError    = null;

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

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

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

            var targetTypeDescription = TypeDescription.GetTypeDescription(target.Type);

            if (target.Type.IsArray)
            {
                var indexType           = TypeDescription.Int32Type;
                var indexingExpressions = new Expression[arguments.Count];
                for (var i = 0; i < indexingExpressions.Length; i++)
                {
                    var argument = default(SyntaxTreeNode);
                    if (arguments.TryGetValue(i, out argument) == false)
                    {
                        bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_MISSINGMETHODPARAMETER, i), node);
                        return(false);
                    }

                    if (AnyBinder.TryBindInNewScope(argument, bindingContext, indexType, out indexingExpressions[i], out bindingError) == false)
                    {
                        return(false);
                    }

                    Debug.Assert(indexingExpressions[i] != null, "indexingExpressions[i] != null");
                }

                try
                {
                    if (indexingExpressions.Length == 1)
                    {
                        boundExpression = Expression.ArrayIndex(target, indexingExpressions[0]);
                    }
                    else
                    {
                        boundExpression = Expression.ArrayIndex(target, indexingExpressions);
                    }
                }
                catch (Exception exception)
                {
                    bindingError = new ExpressionParserException(exception.Message, exception, node);
                    return(false);
                }
            }
            else
            {
                var selectedIndexerQuality = MemberDescription.QUALITY_INCOMPATIBLE;
                foreach (var indexer in targetTypeDescription.Indexers)
                {
                    var indexerQuality = MemberDescription.QUALITY_INCOMPATIBLE;
                    var indexerCall    = default(Expression);
                    if (indexer.TryMakeCall(target, arguments, bindingContext, out indexerCall, out indexerQuality) == false)
                    {
                        continue;
                    }
                    if (indexerQuality <= selectedIndexerQuality)
                    {
                        continue;
                    }

                    boundExpression        = indexerCall;
                    selectedIndexerQuality = indexerQuality;
                }
            }
            if (boundExpression == null)
            {
                bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_UNABLETOBINDINDEXER, target.Type), node);
                return(false);
            }

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

            return(true);
        }
Exemplo n.º 12
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 targetNode     = node.GetExpression(throwOnError: true);
            var typeName       = node.GetTypeName(throwOnError: true);
            var type           = default(Type);

            if (bindingContext.TryResolveType(typeName, out type) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeName), node);
                return(false);
            }

            var target = default(Expression);

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

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

            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_TYPE_IS:
                boundExpression = Expression.TypeIs(target, type);
                break;

            case Constants.EXPRESSION_TYPE_TYPE_AS:
                boundExpression = Expression.TypeAs(target, type);
                break;

            case Constants.EXPRESSION_TYPE_CONVERT:
                boundExpression = Expression.Convert(target, type);
                break;

            case Constants.EXPRESSION_TYPE_CONVERT_CHECKED:
                boundExpression = Expression.ConvertChecked(target, type);
                break;

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