diff --git a/src/Php/Entity/ConstantDef.php b/src/Php/Entity/ConstantDef.php index 3c5d36f6..154fa6ac 100644 --- a/src/Php/Entity/ConstantDef.php +++ b/src/Php/Entity/ConstantDef.php @@ -8,18 +8,22 @@ namespace PhpAot\Php\Entity; +use PhpParser\Node\Expr; + class ConstantDef { public string $name; public string $type; public string $flags; public string $value; + public string $arrayExpr; - public function __construct(string $name, string $flags, string $type, string $value) + public function __construct(string $name, string $flags, string $type, string $value, string $arrayExpr = '') { $this->name = $name; $this->type = $type; $this->flags = $flags; $this->value = $value; + $this->arrayExpr = $arrayExpr; } } diff --git a/src/Php/Generator/ClosureGenerator.php b/src/Php/Generator/ClosureGenerator.php index 07e29909..c8f31b90 100644 --- a/src/Php/Generator/ClosureGenerator.php +++ b/src/Php/Generator/ClosureGenerator.php @@ -29,7 +29,7 @@ trait ClosureGenerator $tmpVar = $this->genTmpVarName(); // 必须使用 = 捕获,不能使用 & ,否则可能会出现悬空指针 // 在 PHP 中 = 赋值是浅拷贝,仅增加一次引用计数,和 zval (16 字节) 封装的赋值 - $capture = $useCurrentScope ? '=' : ''; + $capture = $useCurrentScope ? '&' : ''; $code = $this->getIndent() . 'php::ClosureFn ' . $tmpVar . ' = [' . $capture . '](' diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 8eeda76b..ed421d6d 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -419,6 +419,7 @@ class Translator extends Preprocessor { $code = '#include ' . PHP_EOL; + // 函数的默认值可能会使用字符串字面量,需要提前声明 $literalStringsCount = count($this->literalStrings); $code .= 'extern ' . self::TYPE_STR . ' ' . self::LITERAL_STRINGS . '[' . $literalStringsCount . '];' . PHP_EOL; @@ -526,14 +527,17 @@ class Translator extends Preprocessor return $scanner->scan(); } - protected function genUpdateClassConstants(): string + protected function genClassArrayConstants(): string { $code = ''; foreach ($this->classes as $classDef) { foreach ($classDef->constants as $constant) { if ($constant->type === self::TYPE_ARRAY) { $constName = self::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name); + $code .= "do {\n"; + $code .= $constant->arrayExpr; $code .= $constName . " = " . $constant->value . ";\n"; + $code .= "} while(0);\n"; } } } @@ -1061,6 +1065,7 @@ class Translator extends Preprocessor protected function parseClassConstDef(Node\Stmt\ClassConst $v): void { + $this->resetFunction(); $flags = $v->flags; if ($v->type) { $type = $this->parseTypeDecl($v->type, self::DECL_TYPE_OF_CONST); @@ -1076,7 +1081,15 @@ class Translator extends Preprocessor }; } $constName = $this->parseIdentifier($const->name); - $constInfo = new ConstantDef($constName, $flags, $type, $this->parseIdentifier($const->value)); + $constValue = $this->parseIdentifier($const->value); + $arrayExpr = ''; + if ($this->context->beforeStmtLines) { + if ($this->context->localVars) { + $arrayExpr .= $this->genLocalVarDecl(); + } + $arrayExpr .= $this->parseBeforeStmtLines(); + } + $constInfo = new ConstantDef($constName, $flags, $type, $constValue, $arrayExpr); $this->classDef->constants[$constInfo->name] = $constInfo; } } diff --git a/src/cpp/php_aot_helper.h b/src/cpp/php_aot_helper.h index d33f3ff3..eb849455 100644 --- a/src/cpp/php_aot_helper.h +++ b/src/cpp/php_aot_helper.h @@ -19,3 +19,7 @@ extern const char *php_get_called_class(php::Object &this_); extern zend_class_entry *php_get_called_ce(php::Object &this_); extern php::Scope php_switch_scope(php::Object &this_); extern void php_restore_scope(php::Scope &ori_scope); + +static inline auto php_get_create_object_fn(zend_class_entry *ce) { + return ce->create_object ? ce->create_object : zend_objects_new; +} diff --git a/src/template/extension.cc.php b/src/template/extension.cc.php index b1ffb468..ea19980a 100644 --- a/src/template/extension.cc.php +++ b/src/template/extension.cc.php @@ -123,10 +123,10 @@ foreach ($this->classCeList as $ce): ?> = (); requireCtor): + if (!empty($info['classDef']) and $info['classDef']->requireCtor): $className = $info['classDef']->getNamespacedName(); ?> - create_object_ = ->create_object ? create_object_ : zend_objects_new; + create_object_ = php_get_create_object_fn(); ->create_object = [](zend_class_entry *class_type) -> zend_object* { auto obj = create_object_(class_type); properties as $property): @@ -178,7 +178,7 @@ endforeach; ?> // class array constants - genUpdateClassConstants();?> + genClassArrayConstants();?> } void php_app_clean() {