internal static LambdaNode ParseAndBindLambda(IHostEnvironment env, string expression, int ivec, DataViewType[] inputTypes, out int[] perm) { perm = Utils.GetIdentityPermutation(inputTypes.Length); if (ivec >= 0) { if (ivec > 0) { perm[0] = ivec; for (int i = 1; i <= ivec; i++) { perm[i] = i - 1; } } } CharCursor chars = new CharCursor(expression); var node = LambdaParser.Parse(out List <Error> errors, out List <int> lineMap, chars, perm, inputTypes); if (Utils.Size(errors) > 0) { throw env.ExceptParam(nameof(expression), $"parsing failed: {errors[0].GetMessage()}"); } using (var ch = env.Start("LabmdaBinder.Run")) LambdaBinder.Run(env, ref errors, node, msg => ch.Error(msg)); if (Utils.Size(errors) > 0) { throw env.ExceptParam(nameof(expression), $"binding failed: {errors[0].GetMessage()}"); } return(node); }
/// <summary> /// Binds specified syntax tree to concrete types and optional context. /// </summary> /// <param name="node">Syntax tree. Not null.</param> /// <param name="global">Context expression. Can be null. Usually <see cref="Expression.Constant(object)"/>.</param> /// <returns></returns> public LambdaExpression Bind(SyntaxTreeNode node, Expression global = null) { if (node == null) { throw new ArgumentNullException("node"); } var bindingContext = default(BindingContext); // lambda binding substitution feature if (node.GetExpressionType(throwOnError: true) == Constants.EXPRESSION_TYPE_LAMBDA && this.resultType.IsDelegate == false) { var newParameterNames = LambdaBinder.ExtractArgumentNames(node); if (newParameterNames.Length != this.parameters.Count) { throw new ExpressionParserException(Resources.EXCEPTION_BIND_UNABLEREMAPPARAMETERSCOUNTMISMATCH, node); } var newParameters = new ParameterExpression[newParameterNames.Length]; for (var i = 0; i < newParameters.Length; i++) { newParameters[i] = Expression.Parameter(this.parameters[i].Type, newParameterNames[i]); } bindingContext = new BindingContext(this.typeResolver, new ReadOnlyCollection <ParameterExpression>(newParameters), this.resultType, global); node = node.GetExpression(throwOnError: true); } else { bindingContext = new BindingContext(this.typeResolver, this.parameters, this.resultType, global); } var body = default(Expression); var bindingError = default(Exception); if (AnyBinder.TryBind(node, bindingContext, this.resultType, out body, out bindingError) == false) { throw bindingError; } Debug.Assert(body != null, "body != null"); bindingContext.CompleteNullPropagation(ref body); if (body.Type != this.resultType && this.resultType.IsVoid == false) { try { body = Expression.ConvertChecked(body, this.resultType); } catch (InvalidOperationException) { throw new InvalidOperationException(string.Format(Resources.EXCEPTION_BIND_INVALIDLAMBDABODYTYPE, body.Type, this.resultType)); } } return(Expression.Lambda(this.lambdaType, body, bindingContext.Parameters)); }
public void AnyTokenWithEntityCollectionParentConstantExpression() { var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); var anyToken = this.CreateTestAnyQueryToken(); var result = binder.BindLambdaToken(anyToken, state); result.ShouldBeAnyQueryNode().And.Source.ShouldBeEntitySetQueryNode(HardCodedTestModel.GetPeopleSet()); result.Body.ShouldBeConstantQueryNode(true); }
public void BindLambdaTokenShouldPassForOpenPropertyParent() { this.parentQueryNode = new CollectionOpenPropertyAccessNode(new ConstantNode(null), "SomeCollectionProperty"); var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPaintingTypeReference(), HardCodedTestModel.GetPaintingsSet()); var allToken = this.CreateTestAllQueryToken(); Action bind = () => binder.BindLambdaToken(allToken, state); bind.ShouldNotThrow(); }
public void BindLambdaTokenShouldFailForNonCollectionParent() { this.parentQueryNode = new ConstantNode(true); var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); var allToken = this.CreateTestAllQueryToken(); Action bind = () => binder.BindLambdaToken(allToken, state); bind.Throws <ODataException>(Strings.MetadataBinder_LambdaParentMustBeCollection); }
public void BindLambdaTokenShouldFailForNonBoolExpression() { this.expressionQueryNode = new ConstantNode(0); var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); var allToken = this.CreateTestAnyQueryToken(); Action bind = () => binder.BindLambdaToken(allToken, state); bind.Throws <ODataException>(Strings.MetadataBinder_AnyAllExpressionNotSingleValue); }
public void AllTokenWithNonEntityCollectionParentNonConstantExpression() { this.parentQueryNode = new CollectionPropertyAccessNode(new ConstantNode(null), HardCodedTestModel.GetDogNicknamesProperty()); this.expressionQueryNode = new BinaryOperatorNode(BinaryOperatorKind.LessThanOrEqual, new ConstantNode(1), new ConstantNode(5)); var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); var allToken = this.CreateTestAllQueryToken(); var result = binder.BindLambdaToken(allToken, state); result.ShouldBeAllQueryNode().And.Source.ShouldBeCollectionPropertyAccessQueryNode(HardCodedTestModel.GetDogNicknamesProperty()); result.Body.ShouldBeBinaryOperatorNode(BinaryOperatorKind.LessThanOrEqual); }
public void AnyTokenWithNonConstantExpressionNullParameter() { this.expressionQueryNode = new UnaryOperatorNode(UnaryOperatorKind.Negate, new ConstantNode(false)); var binder = new LambdaBinder(this.FakeBindMethod); var state = this.GetBindingStateForTest(HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()); var expression = new LiteralToken("foo"); var parent = new LiteralToken("bar"); var anyToken = new AnyToken(expression, null, parent); var result = binder.BindLambdaToken(anyToken, state); result.ShouldBeAnyQueryNode().And.Source.ShouldBeEntitySetQueryNode(HardCodedTestModel.GetPeopleSet()); result.Body.ShouldBeUnaryOperatorNode(UnaryOperatorKind.Negate); }
private void Run(string name) { string outDir = "ExprParser"; string text = GetResText(InResName(name)); string inName = name + "Input.txt"; string outName = name + "Output.txt"; string outNameAssem = name + "Output.Assem.txt"; string outPath = DeleteOutputPath(outDir, outName); string outPathAssem = DeleteOutputPath(outDir, outNameAssem); using (var wr = OpenWriter(outPath)) { var wrt = new IndentedTextWriter(wr, " "); // Individual scripts are separated by $. // Inputs start after #. int count = 0; int ichLim = 0; int lineLim = 1; for (; ichLim < text.Length; ichLim++) { int ichMin = ichLim; int lineMin = lineLim; while (ichLim < text.Length && text[ichLim] != '$') { if (text[ichLim] == '\n') { lineLim++; } ichLim++; } while (ichMin < ichLim && char.IsWhiteSpace(text[ichMin])) { if (text[ichMin] == '\n') { lineMin++; } ichMin++; } if (ichMin >= ichLim) { continue; } // Process the script. count++; string scriptName = string.Format("Script {0}, lines {1} to {2}", count, lineMin, lineLim); wrt.WriteLine("===== Start {0} =====", scriptName); var types = ParseTypes(text, ref ichMin, ichLim); int ichLimChars = text.IndexOf('#', ichMin); if (ichLimChars < 0 || ichLimChars >= ichLim) { ichLimChars = ichLim; } else { Contracts.Assert(ichMin < ichLimChars && ichLimChars < ichLim); } CharCursor chars = new CharCursor(text, ichMin, ichLimChars); Delegate del = null; lock (_sync) { try { LambdaNode node; List <Error> errors; List <int> lineMap; var perm = Utils.GetIdentityPermutation(types.Length); using (wrt.Nest()) { node = LambdaParser.Parse(out errors, out lineMap, chars, perm, types); } Check(node != null, "Null LambdaNode"); if (Utils.Size(errors) > 0) { DumpErrors(wrt, lineMap, lineMin, inName, "Parsing", errors); goto LDone; } LambdaBinder.Run(Env, ref errors, node, msg => wr.WriteLine(msg)); if (Utils.Size(errors) > 0) { DumpErrors(wrt, lineMap, lineMin, inName, "Binding", errors); goto LDone; } wrt.WriteLine("Binding succeeded. Output type: {0}", node.ResultType); del = LambdaCompiler.Compile(out errors, node); Contracts.Assert(TestFuncs1.Writer == null); TestFuncs1.Writer = wr; if (Utils.Size(errors) > 0) { DumpErrors(wrt, lineMap, lineMin, inName, "Compiling", errors); goto LDone; } wrt.WriteLine("Compiling succeeded."); if (ichLimChars < ichLim) { Evaluate(wrt, del, node.ResultType, types, text, ichLimChars + 1, ichLim); } } catch (Exception ex) { if (!ex.IsMarked()) { wrt.WriteLine("Unknown Exception: {0}!", del != null ? del.GetMethodInfo().DeclaringType : (object)"<null>"); } wrt.WriteLine("Exception: {0}", ex.Message); } finally { TestFuncs1.Writer = null; } LDone: wrt.WriteLine("===== End {0} =====", scriptName); } } } CheckEquality(outDir, outName, digitsOfPrecision: 6); Done(); }