예제 #1
0
            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());
            }
예제 #2
0
        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");
        }
예제 #3
0
 private void AssertMethodCanBeVisited(Ast.Expression methodInvocationExpression, MethodDefinition method)
 {
     if (_methodDefinitionStack.Contains(method))
     {
         UnsupportedExpression(methodInvocationExpression);
     }
 }
예제 #4
0
            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);
                }
            }
예제 #5
0
            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();
                }
            }
예제 #6
0
            private object Pop(Ast.Expression node, Type expectedType)
            {
                var value = Pop();

                AssertType(value, expectedType, node);
                return(value);
            }
예제 #7
0
            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));
                }
            }
예제 #8
0
 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()}");
     }
 }
예제 #9
0
            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;
                }
            }
예제 #10
0
            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();
                    }
                }
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
 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();
     }
 }
예제 #14
0
파일: Scopes.cs 프로젝트: johtela/Compose3D
 public Ast.Variable DeclareLocal(Ast.Variable local, Ast.Expression value)
 {
     CodeOut(Ast.DeclVar(local, value));
     LocalVars.Add(local.Name, local);
     return(local);
 }
예제 #15
0
파일: Scopes.cs 프로젝트: johtela/Compose3D
 public Ast.Variable DeclareLocal(Type type, string name, Ast.Expression value)
 {
     return(DeclareLocal(Ast.Var(type, name), value));
 }
예제 #16
0
        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");
        }
예제 #17
0
 private NQExpression Convert(Ast.Expression node)
 {
     return(ReconstructNullComparisonIfNecessary(node));
 }
예제 #18
0
 public IEnumerable <T> Execute(Ast.Expression expression)
 {
     this.Visit(expression);
     return(new List <T>().AsEnumerable());
 }
예제 #19
0
 public Expression(Ast.Expression expression)
 {
     Expr = expression;
 }
예제 #20
0
 private static void UnsupportedExpression(Ast.Expression node)
 {
     UnsupportedPredicate("Unsupported expression: " + Ast.ExpressionPrinter.ToString(node));
 }
예제 #21
0
 private FieldValue PopFieldValue(Ast.Expression node)
 {
     return((FieldValue)Pop(node, typeof(FieldValue)));
 }
예제 #22
0
 private FieldValue ToFieldValue(Ast.Expression node)
 {
     Visit(node);
     return(PopFieldValue(node));
 }