/** * @param array <array<LocatedFunctionNode>> $locatedFunctionNodes * @param IFunctionReflection $reflection * * @throws InvalidFunctionException * @return LocatedFunctionNode */ private function getMatchingFunctionNode(array $locatedFunctionNodes, IFunctionReflection $reflection) { $locationHash = $reflection->getLocation()->getHash(); if (empty($locatedFunctionNodes[$locationHash])) { throw InvalidFunctionException::invalidFunctionMessage('Cannot parse function, the function could not be located', $reflection->getInnerReflection()); } // If multiple functions defined on a single line we // perform all possible resolution to resolve the conflict. // Magic constants / scopes are resolved in parameter expressions // to allow matching of functions with these special constants in // default values. /** @var $matchedFunctionsByLocation LocatedFunctionNode[] */ $matchedFunctionsByLocation = $locatedFunctionNodes[$locationHash]; $functionSignature = $reflection->getSignature(); $fullyMatchedFunctions = []; foreach ($matchedFunctionsByLocation as $matchedFunction) { $magicData = $reflection->resolveMagic($matchedFunction->getDeclaration()); $resolvedMatchedFunctionSignature = $matchedFunction->getSignature()->resolveMagic($magicData); if ($functionSignature->getHash() === $resolvedMatchedFunctionSignature->getHash()) { $fullyMatchedFunctions[] = $matchedFunction; } } if (empty($fullyMatchedFunctions)) { throw InvalidFunctionException::invalidFunctionMessage('Cannot parse function, the function\'s signature could not be matched', $reflection->getInnerReflection()); } elseif (count($fullyMatchedFunctions) > 1) { throw InvalidFunctionException::invalidFunctionMessage('Cannot parse function, %d ambiguous functions are defined on the same line ' . 'with identical signatures', $reflection->getInnerReflection(), count($locatedFunctionNodes[$locationHash])); } return $fullyMatchedFunctions[0]; }
private function recompile(Parsing\IFunctionReflection $reflection, Parsing\IFunctionStructure $structure, &$closureExpression = null) { $signature = $reflection->getSignature(); $usedVariables = array_map(function ($name) { return O\Expression::closureUsedVariable($name); }, $signature->getScopedVariableNames() ?: []); $closureExpression = O\Expression::closure($signature->returnsReference(), $reflection->getInnerReflection()->getClosureScopeClass() === null, $signature->getParameterExpressions(), $usedVariables, $structure->getBodyExpressions()); return $closureExpression->evaluate($reflection->asEvaluationContext()); }
protected final function resolveFunctionScope(IFunction $function, Parsing\IFunctionReflection $reflection) { $this->hash .= $reflection->getGlobalHash(); if (!$reflection->getSignature()->isStatic()) { $this->resolveParameter($this->getFunctionScopedVariableParameter($function, 'this'), $reflection->getScope()->getThis()); } $variableValueMap = $reflection->getScope()->getVariableTable(); foreach ($variableValueMap as $variableName => $value) { $this->resolveParameter($this->getFunctionScopedVariableParameter($function, $variableName), $value); } }