Exemplo n.º 1
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");
            }

            if (TryBindMethodCall(node, bindingContext, expectedType, out boundExpression, out bindingError))
            {
                return(true);
            }

            var targetNode = node.GetExpression(throwOnError: true);
            var arguments  = node.GetArguments(throwOnError: false);
            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 typeDescription = TypeDescription.GetTypeDescription(target.Type);

            if (typeDescription.IsDelegate == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOINVOKENONDELEG, target.Type), node);
                return(false);
            }

            var methodDescription = typeDescription.GetMembers(Constants.DELEGATE_INVOKE_NAME).FirstOrDefault(m => m.IsMethod && !m.IsStatic);

            if (methodDescription == null)
            {
                throw new MissingMethodException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGMETHOD, target.Type.FullName, Constants.DELEGATE_INVOKE_NAME));
            }

            var expressionQuality = 0.0f;

            if (methodDescription.TryMakeCall(target, arguments, bindingContext, out boundExpression, out expressionQuality) == false)
            {
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDDELEG, target.Type, methodDescription), node);
                return(false);
            }

            return(true);
        }
Exemplo n.º 2
0
        private static bool TryBindTarget(SyntaxTreeNode node, BindingContext bindingContext, out Expression target, out Type type, out Exception bindingError)
        {
            type         = null;
            target       = null;
            bindingError = null;

            // target is passed as Expression from InvokeBinder
            var targetObj = default(object);

            if (node.TryGetValue(Constants.EXPRESSION_ATTRIBUTE, out targetObj))
            {
                if (targetObj is Expression)
                {
                    target = (Expression)targetObj;
                    type   = target.Type;
                    return(true);
                }
                else if (targetObj is Type)
                {
                    target = null;
                    type   = (Type)targetObj;
                    return(true);
                }
            }

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

            if (targetNode == null)
            {
                if (bindingContext.Global == null)
                {
                    var methodName = node.GetMethodName(throwOnError: false);
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, methodName ?? "<unknown>"), node);
                    return(false);
                }

                target = bindingContext.Global;
                type   = target.Type;
            }
            else if (bindingContext.TryResolveType(targetNode, out type))
            {
                target = null;
            }
            else
            {
                if (TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false)
                {
                    return(false);
                }

                type = target.Type;
            }
            return(true);
        }
Exemplo n.º 3
0
        private static void RenderArrayLength(SyntaxTreeNode syntaxTree, StringBuilder builder, bool checkedScope)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            Render(syntaxTree.GetExpression(throwOnError: true), builder, false, checkedScope);
            builder.Append(".Length");
        }
Exemplo n.º 4
0
        private static void RenderPropertyOrField(SyntaxTreeNode syntaxTree, StringBuilder builder, bool checkedScope)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            var target = syntaxTree.GetExpression(throwOnError: false);
            var propertyOrFieldName = syntaxTree.GetMemberName(throwOnError: true);
            var useNullPropagation  = syntaxTree.GetUseNullPropagation(throwOnError: false);
            var arguments           = syntaxTree.GetArguments(throwOnError: false);

            if (target != null)
            {
                Render(target, builder, false, checkedScope);
                if (useNullPropagation)
                {
                    builder.Append("?.");
                }
                else
                {
                    builder.Append(".");
                }
            }
            builder.Append(propertyOrFieldName);
            if (arguments != null && arguments.Count > 0)
            {
                builder.Append("<");
                for (var i = 0; i < arguments.Count; i++)
                {
                    if (i != 0)
                    {
                        builder.Append(",");
                    }
                    var typeArgument = default(SyntaxTreeNode);
                    if (arguments.TryGetValue(i, out typeArgument))
                    {
                        Render(typeArgument, builder, true, checkedScope);
                    }
                }
                builder.Append(">");
            }
        }
Exemplo n.º 5
0
        private static void RenderLambda(SyntaxTreeNode syntaxTree, StringBuilder builder, bool wrapped, bool checkedScope)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentException("builder");
            }

            if (!wrapped)
            {
                builder.Append("(");
            }

            var arguments = syntaxTree.GetArguments(throwOnError: false);
            var body      = syntaxTree.GetExpression(throwOnError: true);

            if (arguments.Count != 1)
            {
                builder.Append("(");
            }
            var firstParam = true;

            foreach (var param in arguments.Values)
            {
                if (firstParam == false)
                {
                    builder.Append(", ");
                }
                Render(param, builder, true, checkedScope);
                firstParam = false;
            }
            if (arguments.Count != 1)
            {
                builder.Append(")");
            }
            builder.Append(" => ");
            Render(body, builder, false, checkedScope);

            if (!wrapped)
            {
                builder.Append(")");
            }
        }
Exemplo n.º 6
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.º 7
0
        private static void RenderInvokeOrIndex(SyntaxTreeNode syntaxTree, StringBuilder builder, bool checkedScope)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            var expressionType     = syntaxTree.GetExpressionType(throwOnError: true);
            var target             = syntaxTree.GetExpression(throwOnError: true);
            var arguments          = syntaxTree.GetArguments(throwOnError: false);
            var useNullPropagation = syntaxTree.GetUseNullPropagation(throwOnError: false);

            Render(target, builder, false, checkedScope);
            builder.Append(expressionType == Constants.DELEGATE_INVOKE_NAME ? "(" : (useNullPropagation ? "?[" : "["));
            RenderArguments(arguments, builder, checkedScope);
            builder.Append(expressionType == Constants.DELEGATE_INVOKE_NAME ? ")" : "]");
        }
Exemplo n.º 8
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));
        }
        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 propertyOrFieldName = node.GetPropertyOrFieldName(throwOnError: true);
            var useNullPropagation  = node.GetUseNullPropagation(throwOnError: false);

            var targetType = default(Type);
            var isStatic   = 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);

            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 member in targetTypeDescription.GetMembers(propertyOrFieldName))
                {
                    if (member.IsStatic != isStatic || member.IsPropertyOrField == false)
                    {
                        continue;
                    }

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

            if (boundExpression == null)
            {
                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);
            }

            return(true);
        }
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;

            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.º 11
0
        private static void RenderTypeBinary(SyntaxTreeNode syntaxTree, StringBuilder builder, bool wrapped, bool checkedScope)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            var expressionType = syntaxTree.GetExpressionType(throwOnError: true);
            var typeName       = syntaxTree.GetTypeName(throwOnError: true);
            var target         = syntaxTree.GetExpression(throwOnError: true);

            var checkedOperation = expressionType == Constants.EXPRESSION_TYPE_CONVERT_CHECKED ? true :
                                   expressionType == Constants.EXPRESSION_TYPE_CONVERT ? false : checkedScope;

            var closeParent = false;

            if (checkedOperation && !checkedScope)
            {
                builder.Append("checked(");
                checkedScope = true;
                closeParent  = true;
            }
            else if (!checkedOperation && checkedScope)
            {
                builder.Append("unchecked(");
                checkedScope = false;
                closeParent  = true;
            }
            else if (!wrapped)
            {
                builder.Append("(");
                closeParent = true;
            }

            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_CONVERT:
            case Constants.EXPRESSION_TYPE_CONVERT_CHECKED:
                builder.Append("(");
                RenderTypeName(typeName, builder);
                builder.Append(")");
                Render(target, builder, false, checkedOperation);
                break;

            case Constants.EXPRESSION_TYPE_TYPE_IS:
                Render(target, builder, false, checkedScope);
                builder.Append(" is ");
                RenderTypeName(typeName, builder);
                break;

            case Constants.EXPRESSION_TYPE_TYPE_AS:
                Render(target, builder, false, checkedScope);
                builder.Append(" as ");
                RenderTypeName(typeName, builder);
                break;

            default: throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType));
            }

            if (closeParent)
            {
                builder.Append(")");
            }
        }
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 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);
        }
Exemplo n.º 13
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.º 14
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.º 15
0
        public static bool TryBindMethodCall(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 could return null from this method
            bindingError    = null;
            boundExpression = null;

            var methodNameNode     = node.GetExpression(throwOnError: true);
            var methodNameNodeType = methodNameNode.GetExpressionType(throwOnError: true);

            if (methodNameNodeType != Constants.EXPRESSION_TYPE_PROPERTY_OR_FIELD &&
                methodNameNodeType != Constants.EXPRESSION_TYPE_MEMBER_RESOLVE)
            {
                return(false);
            }
            var methodTargetNode = methodNameNode.GetExpression(throwOnError: false);
            var methodTarget     = default(Expression);

            var type          = default(Type);
            var typeReference = default(TypeReference);
            var isStatic      = false;

            if (methodTargetNode == null && bindingContext.Global != null)
            {
                methodTarget = bindingContext.Global;
                type         = methodTarget.Type;
                isStatic     = false;
            }
            else if (methodTargetNode == null)
            {
                var methodName = methodNameNode.GetMemberName(throwOnError: false);
                bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, methodName ?? "<unknown>"), node);
                return(false);
            }
            else if (BindingContext.TryGetTypeReference(methodTargetNode, out typeReference) && bindingContext.TryResolveType(typeReference, out type))
            {
                isStatic = true;
            }
            else if (AnyBinder.TryBind(methodTargetNode, bindingContext, TypeDescription.ObjectType, out methodTarget, out bindingError))
            {
                Debug.Assert(methodTarget != null, "methodTarget != null");

                isStatic = false;
                type     = methodTarget.Type;
            }
            else
            {
                if (typeReference != null && bindingError == null)
                {
                    bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeReference), node);
                }
                return(false);
            }

            var methodRef = default(TypeReference);

            if (type == null || BindingContext.TryGetMethodReference(methodNameNode, out methodRef) == false)
            {
                return(false);
            }

            var typeDescription = TypeDescription.GetTypeDescription(type);

            foreach (var member in typeDescription.GetMembers(methodRef.Name))
            {
                if (member.IsMethod == false || member.IsStatic != isStatic)
                {
                    continue;
                }

                var callNode = new SyntaxTreeNode(new Dictionary <string, object>
                {
                    { Constants.EXPRESSION_ATTRIBUTE, methodTarget ?? (object)type },
                    { Constants.ARGUMENTS_ATTRIBUTE, node.GetValueOrDefault(Constants.ARGUMENTS_ATTRIBUTE, default(object)) },
                    { Constants.METHOD_ATTRIBUTE, methodRef },
                    { Constants.USE_NULL_PROPAGATION_ATTRIBUTE, methodNameNode.GetValueOrDefault(Constants.USE_NULL_PROPAGATION_ATTRIBUTE, default(object)) },
                    { Constants.EXPRESSION_POSITION, methodNameNode.GetPosition(throwOnError: false) }
                });

                return(CallBinder.TryBind(callNode, bindingContext, expectedType, out boundExpression, out bindingError));
            }

            return(false);
        }
Exemplo n.º 16
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);
        }