diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 76a99aba..0fe4a614 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -106,7 +106,6 @@ class CompilerBase extends \PhpAot\Core\Translator protected int $floatPrecision = 17; protected bool $debugInfo = true; protected bool $noLiteralStrings = false; - protected bool $useCppNamespace = false; protected string $file; protected string $dir; @@ -644,7 +643,7 @@ class CompilerBase extends \PhpAot\Core\Translator } $fnName = $this->parseIdentifier($v->name); $returnType = $v->returnType ? $this->getTypeFromZendType($this->parseIdentifier($v->returnType)) : self::TYPE_VOID; - $functionDef = new FunctionDef($fnName, $returnType); + $functionDef = new FunctionDef($fnName, $returnType, $this->namespace); $this->functionDef = $functionDef; $this->parseParams($v->params, $functionDef); @@ -1796,6 +1795,9 @@ class CompilerBase extends \PhpAot\Core\Translator protected function findNativeFunction(string $fname): string|false { $possibleFunctionNames = [$this->escapeName($fname)]; + if (isset($this->useAliases[$fname])) { + $possibleFunctionNames[] = $this->escapeName($this->escapeNamespace($this->useAliases[$fname])); + } if ($this->namespace) { $possibleFunctionNames[] = $this->escapeNamespace($this->namespace) . self::NAMESPACE_SEPARATOR . $fname; } @@ -3102,8 +3104,8 @@ class CompilerBase extends \PhpAot\Core\Translator $this->addLocalVar($exVar, self::TYPE_OBJECT); $code .= 'catch(zend_object *_ex) {' . PHP_EOL; + $code .= $this->getIndent() . $exVar . ' = php::catchException();' . PHP_EOL; if ($catches) { - $code .= $this->getIndent() . $exVar . ' = php::catchException();' . PHP_EOL; $this->indentLevel++; foreach ($catches as $catch) { $code .= $this->parseCatch($catch, $exVar); @@ -3111,6 +3113,7 @@ class CompilerBase extends \PhpAot\Core\Translator $this->indentLevel--; } $code .= '}' . PHP_EOL; + if ($finally) { $code .= $this->parseStmts($finally->stmts); $code .= PHP_EOL; @@ -3267,28 +3270,21 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseUse(mixed $v2): string { $code = ''; - if ($this->useCppNamespace) { - foreach ($v2->uses as $use) { - $code .= 'using ' . str_replace('\\', '::', $use->name->toString()) . ';' . PHP_EOL; - } - } else { - foreach ($v2->uses as $use) { - $id = $this->parseIdentifier($use->name); - if ($use->type === Node\Stmt\Use_::TYPE_FUNCTION) { - $rpos = strrpos($id, '\\'); - $fn = substr($id, $rpos + 1); - $ns = substr($id, 0, $rpos); - // fn => namespace - $this->useFunctions[$fn] = $ns; - } else { - $this->useNamespaces[] = $id; - if ($use->alias) { - $this->useAliases[$use->alias->toString()] = $id; - } + foreach ($v2->uses as $use) { + $id = $this->parseIdentifier($use->name); + if ($use->type === Node\Stmt\Use_::TYPE_FUNCTION) { + $rpos = strrpos($id, '\\'); + $fn = substr($id, $rpos + 1); + $ns = substr($id, 0, $rpos); + // fn => namespace + $this->useFunctions[$fn] = $ns; + } else { + $this->useNamespaces[] = $id; + if ($use->alias) { + $this->useAliases[$use->alias->toString()] = $id; } } } - return $code; } diff --git a/src/Php/Entity/FunctionDef.php b/src/Php/Entity/FunctionDef.php index e6bf0875..3e896517 100644 --- a/src/Php/Entity/FunctionDef.php +++ b/src/Php/Entity/FunctionDef.php @@ -21,11 +21,18 @@ class FunctionDef public array $argInfoList = []; public int $argCountRequired = 0; public string $params = ''; + public string $namespace = ''; public bool $method = false; - public function __construct(string $name, string $returnType) + public function __construct(string $name, string $returnType, string $namespace = '') { $this->name = $name; $this->returnType = $returnType; + $this->namespace = $namespace; + } + + public function getNamespacedName(): string + { + return $this->namespace ? $this->namespace . '\\' . $this->name : $this->name; } } diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 29428ef6..cce1fb40 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -130,7 +130,7 @@ class Preprocessor extends CompilerBase protected function prepareNamespaceDef(Node\Stmt\Namespace_ $node): void { $this->resetNamespace(); - $this->namespace = $this->parseIdentifier($node->name); + $this->namespace = $node->name ? $this->parseIdentifier($node->name) : ''; foreach ($node->stmts as $v2) { $type2 = $v2->getType(); switch ($type2) { diff --git a/src/Php/Translator.php b/src/Php/Translator.php index f0edbef2..d4e7ccda 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -587,25 +587,13 @@ class Translator extends Preprocessor protected function parseNamespace(Node\Stmt\Namespace_ $node): string { - $ns = $this->parseIdentifier($node->name); + $ns = $node->name ? $this->parseIdentifier($node->name) : ''; $code = ''; $this->resetNamespace(); - if ($this->useCppNamespace) { - $ns = explode('\\', $ns); - $ns = array_filter($ns, function ($v) { - return $v !== ''; - }); - foreach ($ns as $name) { - $code .= 'namespace ' . $name . ' {' . PHP_EOL; - } - $ns_end = str_repeat('}', count($ns)); - $this->namespace = implode('::', $ns); - } else { - $this->namespace = $ns; - $ns_end = ''; - } + $this->namespace = $ns; + $ns_end = ''; foreach ($node->stmts as $v2) { $type2 = $v2->getType(); @@ -984,9 +972,9 @@ class Translator extends Preprocessor private function genFunctionWrapper(FunctionDef $functionDef): string { - $name = $functionDef->name; + $name = $functionDef->namespace ? $functionDef->namespace . '_' . $functionDef->name : $functionDef->name; $cppCode = 'ZEND_FUNCTION(' . $name . '){' . PHP_EOL; - $fn = self::PREFIX . $this->getNativeName($functionDef->name); + $fn = self::PREFIX . $this->getNativeName($functionDef->name, $functionDef->namespace); $cppCode .= $this->genWrapperFunctionArgs($fn, $functionDef); return $cppCode; diff --git a/src/template/extension.cc.php b/src/template/extension.cc.php index 8b761296..0db307d7 100644 --- a/src/template/extension.cc.php +++ b/src/template/extension.cc.php @@ -76,7 +76,12 @@ foreach ($this->functions as $functionDef): continue; } ?> +namespace): ?> +namespace . '_' . $functionDef->name; ?> + ZEND_NAMED_FE("escapeString($functionDef->getNamespacedName())?>", ZEND_FN(), arginfo_) + ZEND_FE(name?>, arginfo_name?>) + ZEND_FE_END }; diff --git a/tests/zend/str_offset_001.phpt b/tests/zend/str_offset_001.phpt new file mode 100644 index 00000000..02a9afdc --- /dev/null +++ b/tests/zend/str_offset_001.phpt @@ -0,0 +1,38 @@ +--TEST-- +string offset 001 +--FILE-- + +--EXPECTF-- +string(1) "a" +string(1) "b" +string(1) "c" +string(0) "" +string(1) "b" +string(1) "a" +string(1) "b" +string(1) "c" +string(0) "" +string(1) "b" diff --git a/tests/zend/try/try_finally_001.phpt b/tests/zend/try/try_finally_001.phpt new file mode 100644 index 00000000..9ac513ca --- /dev/null +++ b/tests/zend/try/try_finally_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +Try finally (basic test) +--FILE-- + +--EXPECTF-- +string(7) "finally" + +Fatal error: Uncaught Exception: ex %s +Stack trace: +#0 %stry_finally_001.php(%d): foo('finally') +#1 {main} + thrown in %stry_finally_001.php on line %d diff --git a/tests/zend/use_function/alias.phpt b/tests/zend/use_function/alias.phpt new file mode 100644 index 00000000..24c98687 --- /dev/null +++ b/tests/zend/use_function/alias.phpt @@ -0,0 +1,33 @@ +--TEST-- +aliasing imported functions to resolve naming conflicts +--FILE-- + +--EXPECT-- +string(7) "foo.baz" +string(7) "bar.baz" +Done