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