TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.5 KiB
94 lines
2.5 KiB
<?php
|
|
|
|
namespace PhpAot\Php;
|
|
|
|
class FileSorter
|
|
{
|
|
private array $functionDeclInFile;
|
|
private array $functionCallInFile;
|
|
|
|
public function __construct(array $functionDeclInFile, array $functionCallInFile)
|
|
{
|
|
$this->functionDeclInFile = $functionDeclInFile;
|
|
$this->functionCallInFile = $functionCallInFile;
|
|
}
|
|
|
|
public function sort(): array
|
|
{
|
|
$dependencies = $this->buildDependencies();
|
|
|
|
$allFiles = $this->getAllFiles();
|
|
|
|
$inDegree = array_fill_keys($allFiles, 0);
|
|
foreach ($dependencies as $deps) {
|
|
foreach ($deps as $dep) {
|
|
$inDegree[$dep]++;
|
|
}
|
|
}
|
|
|
|
$queue = [];
|
|
foreach ($inDegree as $file => $degree) {
|
|
if ($degree === 0) {
|
|
$queue[] = $file;
|
|
}
|
|
}
|
|
|
|
$sorted = [];
|
|
while (!empty($queue)) {
|
|
$current = array_shift($queue);
|
|
$sorted[] = $current;
|
|
|
|
if (isset($dependencies[$current])) {
|
|
foreach ($dependencies[$current] as $dep) {
|
|
$inDegree[$dep]--;
|
|
if ($inDegree[$dep] === 0) {
|
|
$queue[] = $dep;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count($sorted) !== count($allFiles)) {
|
|
throw new \RuntimeException("Circular dependency of function call detected");
|
|
}
|
|
|
|
return array_reverse($sorted);
|
|
}
|
|
|
|
private function buildDependencies(): array
|
|
{
|
|
$dependencies = [];
|
|
|
|
foreach ($this->functionCallInFile as $call) {
|
|
$callerFile = $call['file'];
|
|
$functionName = $call['name'];
|
|
|
|
if (isset($this->functionDeclInFile[$functionName])) {
|
|
$declFile = $this->functionDeclInFile[$functionName];
|
|
|
|
if ($callerFile !== $declFile) {
|
|
if (!isset($dependencies[$callerFile])) {
|
|
$dependencies[$callerFile] = [];
|
|
}
|
|
|
|
if (!in_array($declFile, $dependencies[$callerFile])) {
|
|
$dependencies[$callerFile][] = $declFile;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $dependencies;
|
|
}
|
|
|
|
private function getAllFiles(): array
|
|
{
|
|
$files = array_values($this->functionDeclInFile);
|
|
|
|
foreach ($this->functionCallInFile as $call) {
|
|
$files[] = $call['file'];
|
|
}
|
|
|
|
return array_unique($files);
|
|
}
|
|
}
|
|
|