From 6ff687e1da6a484af486c53698ecdc7c913b84d4 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 14 Jan 2026 17:09:54 +0800 Subject: [PATCH] =?UTF-8?q?Interface=EF=BC=8Cce=20=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E5=85=B3=E7=B3=BB=E5=A4=84=E7=90=86=EF=BC=8C=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 3 +- composer.lock | 64 +++++++++++++++++++++++++- src/Php/ClassLikeDef.php | 3 +- src/Php/CompilerBase.php | 12 +++++ src/Php/Translator.php | 85 ++++++++++++++++++++++++++++------- src/template/extension.cc.php | 34 ++++---------- 6 files changed, 157 insertions(+), 44 deletions(-) diff --git a/composer.json b/composer.json index bcb0151d..377cdbef 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,8 @@ { "require": { "nikic/php-parser": "5.6.1", - "league/climate": "^3.10" + "league/climate": "^3.10", + "marcj/topsort": "^2.0" }, "require-dev": { "phpunit/phpunit": "^10.4", diff --git a/composer.lock b/composer.lock index 060156f4..f3291ecc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dff0db7b08aac2e595d7436d35f1ac3c", + "content-hash": "d4e35915568beccdcd533360bf30a206", "packages": [ { "name": "league/climate", @@ -72,6 +72,68 @@ }, "time": "2024-11-18T09:09:55+00:00" }, + { + "name": "marcj/topsort", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/marcj/topsort.php.git", + "reference": "972f58e42b5f110a0a1d8433247f65248abcfd5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marcj/topsort.php/zipball/972f58e42b5f110a0a1d8433247f65248abcfd5c", + "reference": "972f58e42b5f110a0a1d8433247f65248abcfd5c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master", + "phpunit/phpunit": "^9", + "symfony/console": "~2.5 || ~3.0 || ~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "MJS\\TopSort\\": "src/", + "MJS\\TopSort\\Tests\\": "tests/Tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marc J. Schmidt", + "email": "marc@marcjschmidt.de" + } + ], + "description": "High-Performance TopSort/Dependency resolving algorithm", + "keywords": [ + "dependency resolving", + "topological sort", + "topsort" + ], + "support": { + "issues": "https://github.com/marcj/topsort.php/issues", + "source": "https://github.com/marcj/topsort.php/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/marcj", + "type": "github" + } + ], + "time": "2020-09-24T12:39:55+00:00" + }, { "name": "nikic/php-parser", "version": "v5.6.1", diff --git a/src/Php/ClassLikeDef.php b/src/Php/ClassLikeDef.php index b68f055e..9f0fe3f3 100644 --- a/src/Php/ClassLikeDef.php +++ b/src/Php/ClassLikeDef.php @@ -5,7 +5,8 @@ namespace PhpAot\Php; class ClassLikeDef { public string $name; - public string $namespace = ''; + public string $namespace; + public string $extends = ''; public function __construct(string $name, string $namespace = '') { diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 74c8c5d9..639de6ab 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -82,6 +82,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected array $useNamespaces = []; protected array $useFunctions = []; protected string $class = ''; + protected string $interface = ''; /** * @var array */ @@ -91,8 +92,18 @@ class CompilerBase extends \PhpAot\Core\Translator * @var array */ protected array $classesDefineInFile = []; + /** + * @var array + */ + protected array $interfacesDefineInFile = []; + /** + * @var array + */ + protected array $classCeList = []; + protected array $classCeInfo = []; protected FunctionDef $functionDef; protected ClassDef $classDef; + protected InterfaceDef $interfaceDef; protected array $globalVars = [ '_GET' => self::TYPE_ARRAY, '_POST' => self::TYPE_ARRAY, @@ -203,6 +214,7 @@ class CompilerBase extends \PhpAot\Core\Translator $this->indentLevel = 0; $this->strictTypes = false; $this->classesDefineInFile = []; + $this->interfaceDefineInFile = []; } protected function resetNamespace(): void diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 1eae9c53..37820ae4 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -2,6 +2,7 @@ namespace PhpAot\Php; +use MJS\TopSort\Implementations\StringSort; use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\NodeTraverser; @@ -131,25 +132,33 @@ class Translator extends Preprocessor return self::PREFIX . 'register_class_' . $name; } - protected function getRegisterClassFunctionCeList(ClassDef $classDef): array + protected function getRegisterClassFunctionCeList(ClassDef|InterfaceDef $classDef): array { $list = []; $parentCe = $this->getParentClassCe($classDef); - $implements = $this->getImplementCe($classDef); - if ($parentCe) { + if ($parentCe !== '') { $list = [$parentCe]; } + // interface 没有 implements + if ($classDef instanceof InterfaceDef) { + return $list; + } + $implements = $this->getImplementCe($classDef); return array_merge($list, $implements); } - public function getRegisterClassFunctionArgs(ClassDef $classDef): string + public function getRegisterClassFunctionArgs(ClassDef|InterfaceDef $classDef): string { return implode(', ', $this->getRegisterClassFunctionCeList($classDef)); } - private function getRegisterClassFunctionArgDef(ClassDef $classDef): string + private function getRegisterClassFunctionArgDef(ClassDef|InterfaceDef $classDef): string { - return 'zend_class_entry *' . implode(', zend_class_entry *', $this->getRegisterClassFunctionCeList($classDef)); + $depsCeList = $this->getRegisterClassFunctionCeList($classDef); + if (empty($depsCeList)) { + return ''; + } + return 'zend_class_entry *' . implode(', zend_class_entry *', $depsCeList); } protected function getClassCe(ClassLikeDef $classDef): string @@ -157,7 +166,7 @@ class Translator extends Preprocessor return self::PREFIX . 'class_entry_' . $classDef->getNamespacedName(); } - protected function getParentClassCe(ClassDef $classDef): string + protected function getParentClassCe(ClassLikeDef $classDef): string { if (!$classDef->extends) { return ''; @@ -165,7 +174,7 @@ class Translator extends Preprocessor return self::PREFIX . 'class_entry_' . $classDef->extends; } - private function getImplementCe(ClassLikeDef $classDef): array + private function getImplementCe(ClassDef $classDef): array { return array_map(fn($v) => self::PREFIX . 'class_entry_' . $v, $classDef->implements); } @@ -217,6 +226,10 @@ class Translator extends Preprocessor $cppCode .= $this->genClassWrapper($classDef); } + foreach ($this->interfacesDefineInFile as $interfaceDef) { + $cppCode .= $this->genClassWrapper($interfaceDef); + } + return $this->genIncludeHeaderFiles() . $cppCode; } @@ -265,9 +278,45 @@ class Translator extends Preprocessor return ob_get_clean(); } + protected function genClassCeList(): void + { + $sorter = new StringSort(); + + foreach ($this->interfacesDefineInFile as $interfaceDef) { + $ce = $this->getClassCe($interfaceDef); + $parentCe = $this->getParentClassCe($interfaceDef); + $deps = []; + if ($parentCe !== '') { + $deps[] = $parentCe; + } + $this->classCeInfo[$ce] = [ + 'deps' => $deps, + 'func' => $this->getRegisterClassFunction($interfaceDef->getNamespacedName()), + 'args' => $this->getRegisterClassFunctionArgs($interfaceDef), + 'argDef' => $this->getRegisterClassFunctionArgDef($interfaceDef), + ]; + $sorter->add($ce, $deps); + } + + foreach ($this->classesDefineInFile as $classDef) { + $ce = $this->getClassCe($classDef); + $depsCeList = $this->getRegisterClassFunctionCeList($classDef); + $this->classCeInfo[$ce] = [ + 'deps' => $depsCeList, + 'func' => $this->getRegisterClassFunction($classDef->getNamespacedName()), + 'args' => $this->getRegisterClassFunctionArgs($classDef), + 'argDef' => $this->getRegisterClassFunctionArgDef($classDef), + ]; + $sorter->add($ce, $depsCeList); + } + + $this->classCeList = $sorter->sort(); + } + public function genExtension(string $file): void { $this->localHeaders = []; + $this->genClassCeList(); $code = $this->render('extension.cc.php'); $this->writeFile($file, $code); $this->formatCppCode($file); @@ -342,7 +391,7 @@ class Translator extends Preprocessor protected function getMethodName(Node\Stmt\ClassMethod $v): string { - return strtolower($this->parseIdentifier($v->name)); + return $this->parseIdentifier($v->name); } protected function getNativeMethodName(ClassDef $classDef, MethodDef $methodDef): string @@ -498,7 +547,7 @@ class Translator extends Preprocessor } - protected function genClassWrapper(ClassDef $classDef): string + protected function genClassWrapper(ClassDef|InterfaceDef $classDef): string { $cppCode = ''; $name = $classDef->getNamespacedName(); @@ -508,10 +557,13 @@ class Translator extends Preprocessor $cppCode .= $this->getIndent() . 'return register_class_' . $name . '(' . $param . ');' . PHP_EOL; $cppCode .= '}' . PHP_EOL . PHP_EOL; - $methods = $classDef->methods; - foreach ($methods as $methodDef) { - $cppCode .= $this->genMethodWrapper($classDef, $methodDef); + if ($classDef instanceof ClassDef) { + $methods = $classDef->methods; + foreach ($methods as $methodDef) { + $cppCode .= $this->genMethodWrapper($classDef, $methodDef); + } } + return $cppCode; } @@ -705,9 +757,12 @@ class Translator extends Preprocessor return $list; } - private function parseInterface(Node $v): void + private function parseInterface(Node\Stmt\Interface_ $v): void { $name = $this->parseIdentifier($v->name); - $this->interfaces[$name] = new InterfaceDef($name, $this->namespace); + $this->interface = $name; + $this->interfaceDef = new InterfaceDef($name, $this->namespace); + $this->interfaces[$name] = $this->interfaceDef; + $this->interfacesDefineInFile[$this->interface] = $this->interfaceDef; } } \ No newline at end of file diff --git a/src/template/extension.cc.php b/src/template/extension.cc.php index cd5a0c34..0cac5b1d 100644 --- a/src/template/extension.cc.php +++ b/src/template/extension.cc.php @@ -14,20 +14,13 @@ foreach ($this->globalVars as $name => $type): ; -// class entries -classes as $classDef) : -?> -zend_class_entry * getClassCe($classDef) ?>; - - // class register functions classes as $classDef): - $name = $classDef->getNamespacedName(); - $argDef = $this->getRegisterClassFunctionArgDef($classDef); +foreach ($this->classCeList as $ce): + $info = $this->classCeInfo[$ce]; ?> -extern zend_class_entry *getRegisterClassFunction($name) ?>(); +zend_class_entry * ; +extern zend_class_entry *(); // literal strings @@ -59,23 +52,12 @@ static const zend_function_entry ext_functions[] = { }; static PHP_MINIT_FUNCTION(app) { -// class -classes as $classDef): - $name = $classDef->getNamespacedName(); - $params = $this->getRegisterClassFunctionArgs($classDef); - $fn = $this->getRegisterClassFunction($name); -?> - getClassCe($classDef)?> = (); - - - +// class/interface class entries interfaces as $interfaceDef): - $name = $interfaceDef->name; - $fn = $this->getRegisterClassFunction($name); +foreach ($this->classCeList as $ce): + $info = $this->classCeInfo[$ce]; ?> - getClassCe($interfaceDef)?> = (); + = (); return SUCCESS;