public IEnumerable <Book> Execute(Ast.Expression expression) { this.Visit(expression); var result = source.AsQueryable(); if (this.expression != null) { var lambda = Expression.Lambda(this.expression, new[] { parameter }); var func = (Func <Book, bool>)lambda.Compile(); result = source.Where(func).AsQueryable(); } foreach (var methodCall in methodCalls) { var parameters = new Expression[methodCall.Paramters.Length + 1]; parameters[0] = Expression.Constant(result); for (int index = 0; index < methodCall.Paramters.Length; index++) { parameters[index + 1] = Expression.Constant(methodCall.Paramters[index].Value, methodCall.Paramters[index].Type); } var exp = Expression.Call(methodCall.Method, parameters); result = (IQueryable <Book>)Expression.Lambda(exp).Compile().DynamicInvoke(); } return(result.AsEnumerable()); }
internal Ast.Expression Visit(Ast.Expression expression) { switch (expression.CodeType) { case CodeType.BlockExpression: return(VisitBlockExpression((Ast.BlockExpression)expression)); case CodeType.TypeExpression: return(VisitTypeExpression((Ast.TypeExpression)expression)); case CodeType.LambdaExpresion: return(VisitLambdaExpression((Ast.LambdaExpression)expression)); case CodeType.LogicalExpression: return(VisitLogicalExpression((Ast.LogicalExpression)expression)); case CodeType.BinaryExpression: return(VisitBinaryExpression((Ast.BinaryExpression)expression)); case CodeType.LiteralExpression: return(VisitLiteralExpression((Ast.LiteralExpression)expression)); case CodeType.MemberExpression: return(VisitMemberExpression((Ast.MemberExpression)expression)); case CodeType.OrderbyExpression: return(VisitOrderbyExpression((Ast.OrderbyExpression)expression)); case CodeType.MethodCallExpression: return(VisitMethodCallExpression((Ast.MethodCallExpression)expression)); } throw new ArgumentException("Expression type is not supported"); }
private void AssertMethodCanBeVisited(Ast.Expression methodInvocationExpression, MethodDefinition method) { if (_methodDefinitionStack.Contains(method)) { UnsupportedExpression(methodInvocationExpression); } }
private void ProcessCandidateMethodInvocation(Ast.Expression methodInvocationExpression, Ast.MethodReferenceExpression methodRef) { var method = GetMethodDefinition(methodRef); if (null == method) { UnsupportedExpression(methodInvocationExpression); } AssertMethodCanBeVisited(methodInvocationExpression, method); var expression = GetQueryExpression(method); if (null == expression) { UnsupportedExpression(methodInvocationExpression); } EnterCandidateMethod(method); try { Visit(expression); } finally { LeaveCandidateMethod(method); } }
private void PushComparison(Ast.Expression lhs, Ast.Expression rhs, ComparisonOperator op) { Visit(lhs); var left = Pop(); Visit(rhs); var right = Pop(); var areOperandsSwapped = IsCandidateFieldValue(right); if (areOperandsSwapped) { var temp = left; left = right; right = temp; } AssertType(left, typeof(FieldValue), lhs); AssertType(right, typeof(IComparisonOperand), rhs); Push(new ComparisonExpression((FieldValue)left, (IComparisonOperand)right, op)); if (areOperandsSwapped && !op.IsSymmetric()) { Negate(); } }
private object Pop(Ast.Expression node, Type expectedType) { var value = Pop(); AssertType(value, expectedType, node); return(value); }
private static void AssertType(object value, Type expectedType, Ast.Expression sourceExpression) { var actualType = value.GetType(); if (!expectedType.IsAssignableFrom(actualType)) { UnsupportedPredicate( string.Format("Unsupported expression: {0}. Unexpected type on stack. Expected: {1}, Got: {2}.", Ast.ExpressionPrinter.ToString(sourceExpression), expectedType, actualType)); } }
static void SerializeArgumentValue(IndentingWriter writer, Ast.Expression argValue) { if (argValue is Ast.StringLiteral stringLiteral) { SerializeStringLiteral(writer, stringLiteral); } else if (argValue is Ast.NumberLiteral numberLiteral) { SerializeNumberLiteral(writer, numberLiteral); } else { throw new InvalidOperationException( $"Unknown argument type: {argValue.GetType()}"); } }
private void PushFieldValueForTarget(Ast.FieldReferenceExpression node, Ast.Expression target) { switch (target.CodeElementType) { case Ast.CodeElementType.ArgumentReferenceExpression: PushFieldValue(CandidateFieldRoot.Instance, node.Field); break; case Ast.CodeElementType.ThisReferenceExpression: if (InsideCandidate) { if (_current != null) { var current = PopFieldValue(node); PushFieldValue(current, node.Field); } else { PushFieldValue(CandidateFieldRoot.Instance, node.Field); } } else { PushFieldValue(PredicateFieldRoot.Instance, node.Field); } break; case Ast.CodeElementType.MethodInvocationExpression: case Ast.CodeElementType.FieldReferenceExpression: var value = ToFieldValue(target); PushFieldValue(value, node.Field); break; case Ast.CodeElementType.CastExpression: PushFieldValueForTarget(node, ((Ast.CastExpression)node.Target).Target); break; default: UnsupportedExpression(node); break; } }
private NQExpression ReconstructNullComparisonIfNecessary(Ast.Expression node) { Visit(node); var top = Pop(); var fieldValue = top as FieldValue; if (fieldValue == null) { AssertType(top, typeof(NQExpression), node); return((NQExpression)top); } return (new NotExpression( new ComparisonExpression( fieldValue, new ConstValue(null), ComparisonOperator.ValueEquality))); }
public static object Execute(CodeContext context, ActionBinder binder, DynamicAction action, params object[] args) { switch (args.Length) { case 1: return(binder.ExecuteRule <DynamicSiteTarget <object, object> >(context, action, args)); case 2: return(binder.ExecuteRule <DynamicSiteTarget <object, object, object> >(context, action, args)); case 3: return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object> >(context, action, args)); case 4: return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object> >(context, action, args)); case 5: return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object, object> >(context, action, args)); case 6: return(binder.ExecuteRule <DynamicSiteTarget <object, object, object, object, object, object, object> >(context, action, args)); default: //TODO: use CompilerHelpers.GetTypes(args) instead? Type tupleType = Tuple.MakeTupleType(CompilerHelpers.MakeRepeatedArray <Type>(typeof(object), args.Length)); Type targetType = typeof(BigDynamicSiteTarget <,>).MakeGenericType(tupleType, typeof(object)); Type ruleType = typeof(StandardRule <>).MakeGenericType(targetType); MethodInfo getRule = typeof(ActionBinder).GetMethod("GetRule").MakeGenericMethod(targetType); while (true) { object ruleN = getRule.Invoke(binder, new object[] { context, action, args }); Ast.Expression test = (Ast.Expression)ruleType.GetProperty("Test").GetValue(ruleN, null); Ast.Statement target = (Ast.Statement)ruleType.GetProperty("Target").GetValue(ruleN, null); Ast.Variable[] paramVars = (Ast.Variable[])ruleType.GetProperty("ParamVariables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ruleN, null); Ast.Variable[] tempVars = (Ast.Variable[])ruleType.GetProperty("TemporaryVariables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ruleN, null); Tuple t = Tuple.MakeTuple(tupleType, args); object[] tupArg = new object[] { t }; CodeContext tmpCtx = context.Scope.GetTemporaryVariableContext(context, paramVars, tupArg); try { bool result = (bool)test.Evaluate(tmpCtx); if (!result) { // The test may evaluate as false if: // 1. The rule was generated as invalid. In this case, the language binder should be fixed to avoid // generating invalid rules. // 2. The rule was invalidated in the small window between calling GetRule and Evaluate. This is a // valid scenario. In such a case, we need to call Evaluate again to ensure that all expected // side-effects are visible to Execute below. // This assert is not valid in the face to #2 above. However, it is left here until all issues in // the interpreter and the language binders are flushed out Debug.Assert(result); continue; } return(target.Execute(tmpCtx)); } finally { tmpCtx.Scope.TemporaryStorage.Clear(); } } } }
private Ast.Expression ParseExpression(bool allowIndirectIdentifier = false) { Ast.Expression expression = null; var token = currentToken; switch (token.Type) { case TokenType.Identifier: if (token.Value == "true") { expression = new Ast.LiteralExpression(new Ast.Literal(true) { Span = token.Span }) { Span = token.Span } } ; else if (token.Value == "false") { expression = new Ast.LiteralExpression(new Ast.Literal(false) { Span = token.Span }) { Span = token.Span } } ; else if (string.Compare(token.Value, "null", StringComparison.OrdinalIgnoreCase) == 0) { expression = new Ast.LiteralExpression(new Ast.Literal(null) { Span = token.Span }) { Span = token.Span } } ; else if (token.Value == "compile") { expression = ParseCompileExpression(); } else { var nextIdentifier = ParseIdentifier(token, true); // check next token BeginPreviewToken(); var nextToken = NextToken(); EndPreviewToken(); switch (nextToken.Type) { case TokenType.LeftParent: var methodExpression = ParseMethodExpression(); methodExpression.Name = nextIdentifier; expression = methodExpression; break; case TokenType.Equal: var assignExpression = ParseAssignExpression(); assignExpression.Name = nextIdentifier; expression = assignExpression; break; default: expression = new Ast.IdentifierExpression(nextIdentifier) { Span = token.Span }; break; } } break; case TokenType.LeftParent: expression = ParseArrayInitializerExpression(TokenType.RightParent); //expression = ParseExpression(); //ExpectNext(TokenType.RightParent); break; case TokenType.String: // TODO doesn't support escaped strings var str = token.Value.Substring(1, token.Value.Length - 2); // Temporary escape str = str.Replace("\\r\\n", "\r\n"); str = str.Replace("\\n", "\n"); str = str.Replace("\\t", "\t"); expression = new Ast.LiteralExpression(new Ast.Literal(str) { Span = token.Span }) { Span = token.Span }; break; case TokenType.Number: var numberStr = token.Value.Replace(" ", ""); object numberValue; if (numberStr.EndsWith("f", false, CultureInfo.InvariantCulture) || numberStr.Contains("e") || numberStr.Contains("E") || numberStr.Contains(".")) { var floatStr = numberStr.TrimEnd('f'); numberValue = float.Parse(floatStr, NumberStyles.Float, CultureInfo.InvariantCulture); } else { numberValue = int.Parse(numberStr, NumberStyles.Integer, CultureInfo.InvariantCulture); } expression = new Ast.LiteralExpression(new Ast.Literal(numberValue) { Span = token.Span }) { Span = token.Span }; break; case TokenType.Hexa: var intValue = int.Parse(token.Value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); expression = new Ast.LiteralExpression(new Ast.Literal(intValue) { Span = token.Span }) { Span = token.Span }; break; case TokenType.LeftCurlyBrace: expression = ParseArrayInitializerExpression(TokenType.RightCurlyBrace); break; default: if (token.Type == TokenType.LessThan && allowIndirectIdentifier) { NextToken(); var identifierExpression = ParseExpression() as Ast.IdentifierExpression; bool isClosedIndirect = ExpectNext(TokenType.GreaterThan); if (identifierExpression == null) { Logger.Error("Unexpected expression inside indirect reference.", token.Span); } else { identifierExpression.Name.IsIndirect = isClosedIndirect; expression = identifierExpression; } } else { Logger.Error("Unexpected token [{0}]. Expecting tokens ['identifier', 'string', 'number', '{{']", currentToken.Span, currentToken); } break; } return(expression); }
public ExpressionItem(Ast.Expression expression) { if (expression.IsArrayAllocationExpression) { var typedExpression = (Ast.Expression.ArrayAllocationExpression)expression; Text = "Array Allocation Expression"; Children = new TreeItemBase[] { new SimpleItem("Type: " + typedExpression.Item1), new SimpleItem("Size", new[] { new ExpressionItem(typedExpression.Item2) }) }; } else if (expression.IsArrayIdentifierExpression) { var typedExpression = (Ast.Expression.ArrayIdentifierExpression)expression; Text = "Array Identifier Expression: " + typedExpression.Item1.Identifier; Children = new[] { new SimpleItem("Index", new[] { new ExpressionItem(typedExpression.Item2) }) }; } else if (expression.IsArraySizeExpression) { var typedExpression = (Ast.Expression.ArraySizeExpression)expression; Text = "Array Size Expression: " + typedExpression.Item.Identifier; } else if (expression.IsScalarAssignmentExpression) { var typedExpression = (Ast.Expression.ScalarAssignmentExpression)expression; Text = "Scalar Assignment Expression"; Children = new TreeItemBase[] { new SimpleItem("Variable: " + typedExpression.Item1.Identifier), new SimpleItem("Expression", new[] { new ExpressionItem(typedExpression.Item2) }) }; } else if (expression.IsArrayAssignmentExpression) { var typedExpression = (Ast.Expression.ArrayAssignmentExpression)expression; Text = "Array Assignment Expression"; Children = new TreeItemBase[] { new SimpleItem("Variable: " + typedExpression.Item1.Identifier), new SimpleItem("Index", new[] { new ExpressionItem(typedExpression.Item2) }), new SimpleItem("Expression", new[] { new ExpressionItem(typedExpression.Item3) }) }; } else if (expression.IsBinaryExpression) { var typedExpression = (Ast.Expression.BinaryExpression)expression; Text = "Binary Expression"; Children = new TreeItemBase[] { new SimpleItem("Left", new[] { new ExpressionItem(typedExpression.Item1) }), new SimpleItem("Operator: " + typedExpression.Item2), new SimpleItem("Right", new[] { new ExpressionItem(typedExpression.Item3) }) }; } else if (expression.IsFunctionCallExpression) { var typedExpression = (Ast.Expression.FunctionCallExpression)expression; Text = "Function Call Expression"; Children = new TreeItemBase[] { new SimpleItem("Name: " + typedExpression.Item1), new SimpleItem("Arguments", typedExpression.Item2.Select(x => new ExpressionItem(x))) }; } else if (expression.IsIdentifierExpression) { Text = "Identifier Expression: " + ((Ast.Expression.IdentifierExpression)expression).Item.Identifier; } else if (expression.IsLiteralExpression) { Text = "Literal Expression: " + ((Ast.Expression.LiteralExpression)expression).Item; } else if (expression.IsUnaryExpression) { var typedExpression = (Ast.Expression.UnaryExpression)expression; Text = "Unary Expression"; Children = new TreeItemBase[] { new SimpleItem("Operator: " + typedExpression.Item1), new SimpleItem("Expression", new[] { new ExpressionItem(typedExpression.Item2) }) }; } else { throw new System.NotImplementedException(); } }
public Ast.Variable DeclareLocal(Ast.Variable local, Ast.Expression value) { CodeOut(Ast.DeclVar(local, value)); LocalVars.Add(local.Name, local); return(local); }
public Ast.Variable DeclareLocal(Type type, string name, Ast.Expression value) { return(DeclareLocal(Ast.Var(type, name), value)); }
public static Ast.Expression Transform(LangParser.ExpressionContext ctx) { var name = ctx.NAME(); var exprs = ctx.expression(); // function call if (name != null) { var expressions = new Ast.Expression[exprs.Length]; for (uint i = 0; i < exprs.Length; i++) { expressions[i] = Transform(exprs[i]); } return(new Ast.FunctionCall(name.GetText(), expressions)); } var atom = ctx.atom(); if (ctx.LBRACK() != null || atom != null) { Ast.Expression transformed; if (atom != null) { transformed = Transform(atom); } else { transformed = Transform(exprs[0]); } if (ctx.ADD() != null) { return(new Ast.UnaryOperator(transformed, Ast.UnaryOperator.Operation.PLS)); } if (ctx.SUB() != null) { return(new Ast.UnaryOperator(transformed, Ast.UnaryOperator.Operation.NEG)); } return(transformed); } if (exprs.Length == 2) { var mul = ctx.MULPRIOR(); if (mul != null) { var asStr = mul.GetText(); if (asStr == "*") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.MUL)); } if (asStr == "/") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.DIV)); } } var rel = ctx.RELATIONPRIOR(); if (rel != null) { var asStr = rel.GetText(); if (asStr == "<") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.ROL)); } if (asStr == ">") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.ROG)); } if (asStr == "==") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.ROE)); } if (asStr == "!=") { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.RONE)); } throw new NotSupportedException("Kernel error : unsupported relation type"); } if (ctx.OPAND() != null) { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.AND)); } if (ctx.OPOR() != null) { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.OR)); } if (ctx.ADD() != null) { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.ADD)); } if (ctx.SUB() != null) { return(new Ast.BinaryOperator(Transform(exprs[0]), Transform(exprs[1]), Ast.BinaryOperator.Operation.SUB)); } } throw new NotSupportedException("Kernel error : unsupported expression type"); }
private NQExpression Convert(Ast.Expression node) { return(ReconstructNullComparisonIfNecessary(node)); }
public IEnumerable <T> Execute(Ast.Expression expression) { this.Visit(expression); return(new List <T>().AsEnumerable()); }
public Expression(Ast.Expression expression) { Expr = expression; }
private static void UnsupportedExpression(Ast.Expression node) { UnsupportedPredicate("Unsupported expression: " + Ast.ExpressionPrinter.ToString(node)); }
private FieldValue PopFieldValue(Ast.Expression node) { return((FieldValue)Pop(node, typeof(FieldValue))); }
private FieldValue ToFieldValue(Ast.Expression node) { Visit(node); return(PopFieldValue(node)); }