public function getCallable() { if ($this->callable === null) { $this->callable = $this->expression->evaluate($this->evaluationContext); } return $this->callable; }
public function visitClosure(O\ClosureExpression $expression) { $originalContext = $this->analysisContext; $this->analysisContext = $originalContext->inNewScope(); foreach ($expression->getParameters() as $parameter) { $this->walk($parameter); $typeHintType = $this->typeSystem->getTypeFromTypeHint($parameter->getTypeHint()); if (!$parameter->hasDefaultValue() || $this->analysis[$parameter->getDefaultValue()]->isEqualTo($typeHintType)) { $this->analysisContext->setExpressionType($parameter->asVariable(), $typeHintType); } else { $this->analysisContext->setExpressionType($parameter->asVariable(), $this->typeSystem->getNativeType(INativeType::TYPE_MIXED)); } } foreach ($expression->getUsedVariables() as $usedVariable) { $variable = $usedVariable->asVariable(); //TODO: handle references with used variables. Probably impossible though. $this->analysisContext->setExpressionType($variable, $originalContext->getExpressionType($variable)); } $this->walkAll($expression->getBodyExpressions()); $this->analysis[$expression] = $this->typeSystem->getObjectType('Closure'); $this->analysisContext = $originalContext; }
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; } }