public function testExpressionWalkerWorks() { $expression = O\Expression::variable(O\Expression::value('foo')); $expressionWalker = new O\DynamicExpressionWalker([O\ValueExpression::getType() => function (O\ValueExpression $expression) { return O\Expression::value('bar'); }]); $newExpression = $expressionWalker->walk($expression); $this->assertNotEquals($expression, $newExpression); $this->assertSame($newExpression->getName()->getValue(), 'bar'); }
public function interpretSource(O\Expression $expression) { $isQueryScope = false; $queryableQueryResolver = new O\DynamicExpressionWalker([O\TraversalExpression::getType() => function (O\TraversalExpression $expression, O\ExpressionWalker $self) use(&$isQueryScope) { $expression = $expression->updateValue($self->walk($expression->getValue())); if ($isQueryScope) { return $expression; } else { return $self->walk(O\Expression::value($expression->evaluate($this->evaluationContext))); } }, O\ValueExpression::getType() => function (O\ValueExpression $expression) use(&$isQueryScope) { if ($expression->getValue() instanceof IQueryable) { $isQueryScope = true; } return $expression; }]); $expression = $queryableQueryResolver->walk($expression); if ($isQueryScope) { $this->scopeInterpreter->interpretScope($expression); $this->interpretation->interpretQueryScope($this->getId('source-scope'), $this->scopeInterpreter->getInterpretation()); } else { $this->interpretation->interpretArrayOrIterator($this->getId('source-iterator'), $expression->evaluate($this->evaluationContext)); } }
protected function parseQueryExpression(callable $queryFunction, O\IEvaluationContext &$evaluationContext = null) { $reflection = $this->functionInterpreter->getReflection($queryFunction); $evaluationContext = $reflection->asEvaluationContext(); $function = $this->functionInterpreter->getStructure($reflection); $expressions = $function->getBodyExpressions(); $this->assertCount(1, $expressions); //Resolve the parameter variable with the queryable value and $this $parameterName = $reflection->getSignature()->getParameterExpressions()[0]->getName(); $expression = $expressions[0]; foreach ([$parameterName => $this->queryable, 'this' => $this] as $variable => $value) { $variableReplacer = new O\DynamicExpressionWalker([O\VariableExpression::getType() => function (O\VariableExpression $expression) use($variable, &$value) { if ($expression->getName() instanceof O\ValueExpression && $expression->getName()->getValue() === $variable) { return O\Expression::value($value); } else { return $expression; } }, O\ClosureExpression::getType() => function ($closure) { return $closure; }]); $expression = $variableReplacer->walk($expression); } if ($expression instanceof O\ReturnExpression) { return $expression->getValue(); } else { return $expression; } }
public function tryComputeResults(O\Expression $queryExpression, &$results) { if (isset($this->storage[$queryExpression])) { $results = $this->storage[$queryExpression]; return true; } $foundApplicableResults = false; //Searches the query expression tree and checks if any parent expressions have saved results //If so, the expression tree is updated with a Traversable implementation with the saved results $applicableScopeFinder = function (O\Expression $expression, O\ExpressionWalker $self) use(&$foundApplicableResults) { if (isset($this->storage[$expression])) { $foundApplicableResults = true; return O\Expression::value($this->newTraversable($this->storage[$expression])); } if ($expression instanceof O\ValueExpression) { return $expression; } /** @var $expression O\TraversalExpression */ return $expression->updateValue($self->walk($expression->getValue())); }; $traversalWalker = new O\DynamicExpressionWalker([O\TraversalExpression::getType() => $applicableScopeFinder, O\ValueExpression::getType() => $applicableScopeFinder]); $remainingQueryExpression = $traversalWalker->walk($queryExpression); //If found applicable results, execute the updated expression tree against the Traversable //implementation to compute the result of the query. $results = $foundApplicableResults ? $remainingQueryExpression->evaluate() : null; return $foundApplicableResults; }