diff --git a/src/Php/ClassDef.php b/src/Php/ClassDef.php index dacb4203..ccd37f95 100644 --- a/src/Php/ClassDef.php +++ b/src/Php/ClassDef.php @@ -6,15 +6,15 @@ class ClassDef { public string $name; /** - * @var array< MethodDef> + * @var array */ public array $methods = []; /** - * @var array + * @var array */ public array $properties = []; /** - * @var array + * @var array */ public array $constants = []; public string $namespace = ''; diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index af399649..24a7bcd3 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -31,6 +31,7 @@ class CompilerBase extends \PhpAot\Core\Translator public const string TYPE_ARRAY = 'php::Array'; public const string TYPE_STR = 'php::Str'; public const string TYPE_REF = 'php::Var'; + public const string TYPE_VOID = 'void'; public const string VALUE_NAN = 'std::numeric_limits::quiet_NaN()'; public const string VALUE_INF = 'std::numeric_limits::infinity()'; @@ -215,14 +216,19 @@ class CompilerBase extends \PhpAot\Core\Translator $this->namespace = ''; } - protected function getFunctionName(Node $v): string + protected function getFunctionName(FunctionLike $v): string { - $names[] = $this->escapeFunction($this->parseIdentifier($v->name)); - if ($this->namespace) { - $names[] = $this->escapeNamespace($this->namespace); + return $this->getNativeFunctionName($this->parseIdentifier($v->name), $this->namespace, $this->class); + } + + protected function getNativeFunctionName(string $fn, string $ns = '', string $class = ''): string + { + $names[] = $this->escapeFunction($fn); + if ($ns) { + $names[] = $this->escapeNamespace($ns); } - if ($this->class) { - $names[] = $this->escapeClass($this->class); + if ($class) { + $names[] = $this->escapeClass($class); } return implode(self::NAMESPACE_SEPARATOR, array_reverse($names)); } @@ -1785,7 +1791,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected function escapeClass(string $class): string { - return $class; + return strtolower($class); } protected function unescapeVarName(string $name): string @@ -1950,8 +1956,8 @@ class CompilerBase extends \PhpAot\Core\Translator protected function formatCppCode(string $file): void { $cmd = 'cd ' . $this->rootPath . ' && clang-format -i ' . $file; - $this->writeLog('formatting ' . $file . '...'); - $this->writeLog($cmd); + $this->climate->info('formatting ' . $file ); + $this->climate->comment($cmd); shell_exec($cmd); } diff --git a/src/Php/MethodDef.php b/src/Php/MethodDef.php index 38b0ed0c..da8ea4ac 100644 --- a/src/Php/MethodDef.php +++ b/src/Php/MethodDef.php @@ -4,13 +4,14 @@ namespace PhpAot\Php; class MethodDef { - public string $name; - public string $flags; + public int $flags; + public string $returnType; - public function __construct(string $name, string $flags) + public function __construct(string $name, int $flags, string $returnType) { $this->name = $name; $this->flags = $flags; + $this->returnType = $returnType; } } \ No newline at end of file diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 969df148..64f95697 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -165,22 +165,9 @@ class Translator extends Preprocessor } foreach ($this->classesDefineInFile as $classDef) { - $name = $classDef->getNamespacedName(); - - if ($classDef->extends) { - $parentName = 'zend_class_entry *parent_ce'; - $param = 'parent_ce'; - } else { - $parentName = ''; - $param = ''; - } - $cppCode .= 'zend_class_entry *' . $this->getRegisterClassFunction($name) . '(' . $parentName . ') {' . PHP_EOL; - $cppCode .= $this->getIndent() . 'return ' . $this->getRegisterClassFunction($name) . '(' . $param . ');' . PHP_EOL; - $cppCode .= '}' . PHP_EOL . PHP_EOL; + $cppCode .= $this->genClassWrapper($classDef); } - $cppCode .= PHP_EOL; - // include + extern global vars + function impl return $this->genIncludeHeaderFiles() . $cppCode; } @@ -362,6 +349,11 @@ class Translator extends Preprocessor return strtolower($this->parseIdentifier($v->name)); } + protected function getNativeMethodName(ClassDef $classDef, MethodDef $methodDef): string + { + return $this->getNativeFunctionName($methodDef->name, $classDef->namespace, $classDef->name); + } + protected function parseNamespace(Node\Stmt\Namespace_ $node): string { $ns = $this->parseIdentifier($node->name); @@ -450,7 +442,7 @@ class Translator extends Preprocessor abort($v); } } - $code = $this->genZendClass($methodCodes); + $code = $this->genNativeMethod($methodCodes); $this->class = ''; return $code; } @@ -466,7 +458,7 @@ class Translator extends Preprocessor } } - protected function genZendClass($methodCodes): string + protected function genNativeMethod($methodCodes): string { $code = ''; $classDef = $this->classDef; @@ -476,6 +468,48 @@ class Translator extends Preprocessor return $code; } + protected function genMethodWrapper(ClassDef $classDef, MethodDef $methodDef): string + { + $name = $classDef->getNamespacedName(); + $cppCode = 'ZEND_METHOD(' . $name . ', ' . $methodDef->name . '){' . PHP_EOL; + $cppCode .= $this->getIndent() . self::TYPE_OBJECT . ' this_(&execute_data->This);' . PHP_EOL; + $fn = self::PREFIX . $this->getNativeMethodName($classDef, $methodDef); + + if ($methodDef->returnType !== self::TYPE_VOID) { + $cppCode .= $this->getIndent() . 'auto retval = ' . $fn . '(this_);' . PHP_EOL; + $cppCode .= $this->getIndent() . 'php::move(retval, return_value);' . PHP_EOL; + } else { + $cppCode .= $this->getIndent() . $fn . '(this_);' . PHP_EOL; + } + $cppCode .= '}' . PHP_EOL . PHP_EOL; + + return $cppCode; + } + + + protected function genClassWrapper(ClassDef $classDef): string + { + $cppCode = ''; + $name = $classDef->getNamespacedName(); + + if ($classDef->extends) { + $parentName = 'zend_class_entry *parent_ce'; + $param = 'parent_ce'; + } else { + $parentName = ''; + $param = ''; + } + $cppCode .= 'zend_class_entry *' . $this->getRegisterClassFunction($name) . '(' . $parentName . ') {' . PHP_EOL; + $cppCode .= $this->getIndent() . 'return ' . $this->getRegisterClassFunction($name) . '(' . $param . ');' . PHP_EOL; + $cppCode .= '}' . PHP_EOL . PHP_EOL; + + $methods = $classDef->methods; + foreach ($methods as $methodDef) { + $cppCode .= $this->genMethodWrapper($classDef, $methodDef); + } + return $cppCode; + } + private function genClassNative(): string { $code = 'class ' . $this->class . ' { '; @@ -624,7 +658,7 @@ class Translator extends Preprocessor $type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR; foreach ($v->consts as $const) { $constInfo = new ConstantDef($this->parseIdentifier($const->name), $flags, $type, $this->parseIdentifier($const->value)); - $this->classDef->constants[] = $constInfo; + $this->classDef->constants[$constInfo->name] = $constInfo; } } @@ -638,7 +672,7 @@ class Translator extends Preprocessor if ($prop->default) { $propDef->default = $this->parseIdentifier($prop->default); } - $this->classDef->properties[] = $propDef; + $this->classDef->properties[$propDef->name] = $propDef; } } @@ -646,7 +680,8 @@ class Translator extends Preprocessor { $name = $this->getMethodName($v); $flags = $v->flags; - $methodDef = new MethodDef($name, $flags); + $returnType = $v->returnType ? $this->getTypeFromZendType($this->parseIdentifier($v->returnType)) : self::TYPE_VOID; + $methodDef = new MethodDef($name, $flags, $returnType); $this->classDef->methods[$name] = $methodDef; $methodCodes[$name] = $this->parseFunction($v); }