Exemple #1
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 ? ")" : "]");
        }
Exemple #2
0
        private static void RenderNew(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 typeName       = syntaxTree.GetTypeName(throwOnError: true);
            var arguments      = syntaxTree.GetArguments(throwOnError: false);

            builder.Append("new ");
            RenderTypeName(typeName, builder);
            if (expressionType == Constants.EXPRESSION_TYPE_NEW_ARRAY_BOUNDS)
            {
                builder.Append("[");
            }
            else
            {
                builder.Append("(");
            }

            RenderArguments(arguments, builder, checkedScope);

            if (expressionType == Constants.EXPRESSION_TYPE_NEW_ARRAY_BOUNDS)
            {
                builder.Append("]");
            }
            else
            {
                builder.Append(")");
            }
        }
Exemple #3
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);
        }
Exemple #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 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);
        }
Exemple #5
0
        private static void RenderConstant(SyntaxTreeNode syntaxTree, StringBuilder builder)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException("syntaxTree");
            }
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            var typeObj  = default(object);
            var valueObj = default(object);

            if (syntaxTree.TryGetValue(Constants.TYPE_ATTRIBUTE, out typeObj) == false || typeObj is string == false)
            {
                throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGATTRONNODE, Constants.TYPE_ATTRIBUTE, syntaxTree.GetExpressionType(throwOnError: true)));
            }

            if (syntaxTree.TryGetValue(Constants.VALUE_ATTRIBUTE, out valueObj) == false)
            {
                throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGATTRONNODE, Constants.VALUE_ATTRIBUTE, syntaxTree.GetExpressionType(throwOnError: true)));
            }

            if (valueObj == null)
            {
                if (IsObjectType(typeObj))
                {
                    builder.Append("null");
                    return;
                }
                else
                {
                    builder.Append("default(");
                    RenderTypeName(typeObj, builder);
                    builder.Append(")");
                    return;
                }
            }

            var type  = Convert.ToString(typeObj, Constants.DefaultFormatProvider);
            var value = Convert.ToString(valueObj, Constants.DefaultFormatProvider) ?? "";

            switch (type)
            {
            case "System.Char":
            case "Char":
            case "char":
                RenderTextLiteral(value, builder, isChar: true);
                break;

            case "System.String":
            case "String":
            case "string":
                RenderTextLiteral(value, builder, isChar: false);
                break;

            case "UInt16":
            case "System.UInt16":
            case "ushort":
            case "UInt32":
            case "System.UInt32":
            case "uint":
                builder.Append(value);
                builder.Append("u");
                break;

            case "UInt64":
            case "System.UInt64":
            case "ulong":
                builder.Append(value);
                builder.Append("ul");
                break;

            case "Int64":
            case "System.Int64":
            case "long":
                builder.Append(value);
                builder.Append("l");
                break;

            case "Single":
            case "System.Single":
            case "float":
                builder.Append(value);
                builder.Append("f");
                break;

            case "Double":
            case "System.Double":
            case "double":
                builder.Append(value);
                if (value.IndexOf('.') == -1)
                {
                    builder.Append("d");
                }
                break;

            case "Decimal":
            case "System.Decimal":
            case "decimal":
                builder.Append(value);
                builder.Append("m");
                break;

            case "Boolean":
            case "System.Boolean":
            case "bool":
                builder.Append(value.ToLowerInvariant());
                break;

            default:
                builder.Append(value);
                break;
            }
        }
Exemple #6
0
        private static void RenderBinary(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 leftObj = default(object);

            if (syntaxTree.TryGetValue(Constants.LEFT_ATTRIBUTE, out leftObj) == false || leftObj is SyntaxTreeNode == false)
            {
                throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGATTRONNODE, Constants.LEFT_ATTRIBUTE, expressionType));
            }
            var rightObj = default(object);

            if (syntaxTree.TryGetValue(Constants.RIGHT_ATTRIBUTE, out rightObj) == false || rightObj is SyntaxTreeNode == false)
            {
                throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGATTRONNODE, Constants.RIGHT_ATTRIBUTE, expressionType));
            }

            var left             = (SyntaxTreeNode)leftObj;
            var right            = (SyntaxTreeNode)rightObj;
            var checkedOperation = expressionType == Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED || expressionType == Constants.EXPRESSION_TYPE_ADD_CHECKED || expressionType == Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED ? true :
                                   expressionType == Constants.EXPRESSION_TYPE_MULTIPLY || expressionType == Constants.EXPRESSION_TYPE_ADD || expressionType == Constants.EXPRESSION_TYPE_SUBTRACT ? 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;
            }

            Render(left, builder, false, checkedOperation);
            switch (expressionType)
            {
            case Constants.EXPRESSION_TYPE_DIVIDE: builder.Append(" / "); break;

            case Constants.EXPRESSION_TYPE_MULTIPLY:
            case Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED: builder.Append(" * "); break;

            case Constants.EXPRESSION_TYPE_MODULO: builder.Append(" % "); break;

            case Constants.EXPRESSION_TYPE_ADD_CHECKED:
            case Constants.EXPRESSION_TYPE_ADD: builder.Append(" + "); break;

            case Constants.EXPRESSION_TYPE_SUBTRACT:
            case Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED: builder.Append(" - "); break;

            case Constants.EXPRESSION_TYPE_LEFT_SHIFT: builder.Append(" << "); break;

            case Constants.EXPRESSION_TYPE_RIGHT_SHIFT: builder.Append(" >> "); break;

            case Constants.EXPRESSION_TYPE_GREATER_THAN: builder.Append(" > "); break;

            case Constants.EXPRESSION_TYPE_GREATER_THAN_OR_EQUAL: builder.Append(" >= "); break;

            case Constants.EXPRESSION_TYPE_LESS_THAN: builder.Append(" < "); break;

            case Constants.EXPRESSION_TYPE_LESS_THAN_OR_EQUAL: builder.Append(" <= "); break;

            case Constants.EXPRESSION_TYPE_EQUAL: builder.Append(" == "); break;

            case Constants.EXPRESSION_TYPE_NOT_EQUAL: builder.Append(" != "); break;

            case Constants.EXPRESSION_TYPE_AND: builder.Append(" & "); break;

            case Constants.EXPRESSION_TYPE_OR: builder.Append(" | "); break;

            case Constants.EXPRESSION_TYPE_EXCLUSIVE_OR: builder.Append(" ^ "); break;

            case Constants.EXPRESSION_TYPE_POWER: builder.Append(" ** "); break;

            case Constants.EXPRESSION_TYPE_AND_ALSO: builder.Append(" && "); break;

            case Constants.EXPRESSION_TYPE_OR_ELSE: builder.Append(" || "); break;

            case Constants.EXPRESSION_TYPE_COALESCE: builder.Append(" ?? "); break;

            default: throw new InvalidOperationException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType));
            }
            Render(right, builder, false, checkedOperation);

            if (closeParent)
            {
                builder.Append(")");
            }
        }
Exemple #7
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(")");
            }
        }
        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);
        }
Exemple #9
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");
            }

            try
            {
                var expressionType = node.GetExpressionType(throwOnError: true);
                switch (expressionType)
                {
                case Constants.EXPRESSION_TYPE_PROPERTY_OR_FIELD:
                    return(PropertyOrFieldBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_CONSTANT:
                    return(ConstantBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_CALL:
                    return(CallBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case "Enclose":
                case Constants.EXPRESSION_TYPE_UNCHECKED_SCOPE:
                case Constants.EXPRESSION_TYPE_CHECKED_SCOPE:
                case Constants.EXPRESSION_TYPE_GROUP:
                    return(GroupBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_INVOKE:
                    return(InvokeBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_LAMBDA:
                    return(LambdaBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_INDEX:
                    return(IndexBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_TYPEOF:
                    return(TypeOfBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_CONVERT:
                case Constants.EXPRESSION_TYPE_CONVERTCHECKED:
                case Constants.EXPRESSION_TYPE_TYPEIS:
                case Constants.EXPRESSION_TYPE_TYPEAS:
                    return(TypeBinaryBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_DEFAULT:
                    return(DefaultBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_NEW:
                    return(NewBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_NEW_ARRAY_BOUNDS:
                    return(NewArrayBoundsBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_ADD:
                case Constants.EXPRESSION_TYPE_ADD_CHECKED:
                case Constants.EXPRESSION_TYPE_SUBTRACT:
                case Constants.EXPRESSION_TYPE_SUBTRACT_CHECKED:
                case Constants.EXPRESSION_TYPE_LEFTSHIFT:
                case Constants.EXPRESSION_TYPE_RIGHTSHIFT:
                case Constants.EXPRESSION_TYPE_GREATERTHAN:
                case Constants.EXPRESSION_TYPE_GREATERTHAN_OR_EQUAL:
                case Constants.EXPRESSION_TYPE_LESSTHAN:
                case Constants.EXPRESSION_TYPE_LESSTHAN_OR_EQUAL:
                case Constants.EXPRESSION_TYPE_POWER:
                case Constants.EXPRESSION_TYPE_DIVIDE:
                case Constants.EXPRESSION_TYPE_MULTIPLY:
                case Constants.EXPRESSION_TYPE_MULTIPLY_CHECKED:
                case Constants.EXPRESSION_TYPE_MODULO:
                case Constants.EXPRESSION_TYPE_EQUAL:
                case Constants.EXPRESSION_TYPE_NOTEQUAL:
                case Constants.EXPRESSION_TYPE_AND:
                case Constants.EXPRESSION_TYPE_OR:
                case Constants.EXPRESSION_TYPE_EXCLUSIVEOR:
                case Constants.EXPRESSION_TYPE_ANDALSO:
                case Constants.EXPRESSION_TYPE_ORELSE:
                case Constants.EXPRESSION_TYPE_COALESCE:
                    return(BinaryBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_NEGATE:
                case Constants.EXPRESSION_TYPE_NEGATE_CHECKED:
                case Constants.EXPRESSION_TYPE_COMPLEMENT:
                case Constants.EXPRESSION_TYPE_NOT:
                case Constants.EXPRESSION_TYPE_UNARYPLUS:
                    return(UnaryBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                case Constants.EXPRESSION_TYPE_CONDITION:
                    return(ConditionBinder.TryBind(node, bindingContext, expectedType, out boundExpression, out bindingError));

                default:
                    boundExpression = null;
                    bindingError    = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNKNOWNEXPRTYPE, expressionType), node);
                    return(false);
                }
            }
            catch (ExpressionParserException error)
            {
                boundExpression = null;
                bindingError    = error;
                return(false);
            }
            catch (Exception error)
            {
                boundExpression = null;
                bindingError    = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_FAILEDTOBIND, node.GetExpressionType(throwOnError: false) ?? "<unknown>", error.Message), error, node);
                return(false);
            }
        }
Exemple #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 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);
        }