diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 23abc6e0..ff238b82 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -32,7 +32,10 @@ class Translator extends Preprocessor protected array $phpSrcFiles = []; protected array $argInfoHeaderFiles = []; protected array $registerSymbols = []; - protected array $staticPropertyList = []; + // 类静态属性初始值 + protected array $defaultStaticPropertyList = []; + // 类属性初始值 + protected array $defaultPropertyList = []; protected bool $useRegisterSymbolsFn = false; public function __construct(string $rootPath) @@ -715,6 +718,7 @@ class Translator extends Preprocessor } $this->classCeInfo[$ce] = [ + 'classDef' => $classDef, 'deps' => $deps, 'func' => $this->getRegisterClassFunction($classDef->getNamespacedName()), 'args' => $this->getRegisterClassFunctionArgs($classDef), @@ -866,9 +870,6 @@ class Translator extends Preprocessor } } $code = $this->genNativeMethod($methodCodes); - if ($this->classDef->requireCtor and !$this->classDef->hasMethod('__construct')) { - $this->fatalError($class, "Class `{$this->class}` uses a non-empty array as the default value for an property, and the constructor must be set."); - } $this->resetClass(); return $code; @@ -937,32 +938,15 @@ class Translator extends Preprocessor protected function genMethodWrapper(ClassDef $classDef, MethodDef $methodDef): string { $name = $classDef->getNamespacedName(); - $fullClassName = $classDef->getNamespacedName(false); $cppCode = 'ZEND_METHOD(' . $name . ', ' . $methodDef->name . '){' . PHP_EOL; $cppCode .= $this->getIndent() . self::TYPE_OBJECT . ' this_(&execute_data->This);' . PHP_EOL; - - foreach ($classDef->properties as $property) { - if ($property->type === self::TYPE_ARRAY and $property->default and $property->default !== self::TYPE_ARRAY . '{}') { - if ($property->isStatic()) { - $prop = new \stdClass(); - $prop->class = $fullClassName; - $prop->name = $property->name; - $prop->default = $property->default; - $this->staticPropertyList[$name . '::' . $property->name] = $prop; - } else { - $propOffset = $this->getPropertyOffset($fullClassName, $property->name); - $cppCode .= $this->getIndent() . 'this_.attr(' . $propOffset . ') = ' . $property->default . ';' . PHP_EOL; - } - } - } - $fn = self::PREFIX . $this->getNativeMethodName($classDef, $methodDef); $cppCode .= $this->genWrapperFunctionArgs($fn, $methodDef->functionDef); return $cppCode; } - protected function getClassRegisterCeFunc(ClassDef|InterfaceDef $classDef): void + protected function getClassRegisterCeFunc(ClassDef|InterfaceDef $classDef): string { $cppCode = ''; $name = $classDef->getNamespacedName(); @@ -971,6 +955,8 @@ class Translator extends Preprocessor $cppCode .= 'zend_class_entry *' . $this->getRegisterClassFunction($name) . '(' . $argsDef . ') {' . PHP_EOL; $cppCode .= $this->getIndent() . 'return register_class_' . $name . '(' . $param . ');' . PHP_EOL; $cppCode .= '}' . PHP_EOL . PHP_EOL; + + return $cppCode; } protected function genClassWrapper(ClassDef|InterfaceDef $classDef): string @@ -979,6 +965,21 @@ class Translator extends Preprocessor // 接口没有方法实体 if ($classDef instanceof ClassDef) { + foreach ($classDef->properties as $property) { + if ($property->type === self::TYPE_ARRAY and $property->default and $property->default !== self::TYPE_ARRAY . '{}') { + $fullClassName = $classDef->getNamespacedName(false); + $fullPropName = $fullClassName . '::' . $property->name; + if ($property->isStatic()) { + $prop = new \stdClass(); + $prop->class = $fullClassName; + $prop->name = $property->name; + $prop->default = $property->default; + $this->defaultStaticPropertyList[$fullPropName] = $prop; + } else { + $this->defaultPropertyList[$fullPropName] = $property->default; + } + } + } $methods = $classDef->methods; foreach ($methods as $methodDef) { $cppCode .= $this->genMethodWrapper($classDef, $methodDef); diff --git a/src/template/extension.cc.php b/src/template/extension.cc.php index e5c873a1..07e8c0d0 100644 --- a/src/template/extension.cc.php +++ b/src/template/extension.cc.php @@ -79,9 +79,12 @@ foreach ($this->nativeConstants as $name => $const): type?> ; -// class array constants + // class classes as $classDef) : + if ($classDef->requireCtor) { + echo "static zend_object* (*create_object_" . $classDef->getNamespacedName() . ")(zend_class_entry *class_type);"; + } foreach ($classDef->constants as $constant) : if ($constant->type === Translator::TYPE_ARRAY) : $constName = Translator::PREFIX . $this->getNativeName($constant->name, $classDef->namespace, $classDef->name); @@ -119,6 +122,24 @@ foreach ($this->classCeList as $ce): $info = $this->classCeInfo[$ce] ?? $this->getInternalCeInfo($ce); ?> = (); +requireCtor): + $className = $info['classDef']->getNamespacedName(); +?> + create_object_ = ->create_object ? create_object_ : zend_objects_new; + ->create_object = [](zend_class_entry *class_type) -> zend_object* { + auto obj = create_object_(class_type); + properties as $property): + $fullPropName = $info['classDef']->getNamespacedName(true) . '::' . $property->name; + ?> + defaultPropertyList[$fullPropName])): ?> + auto value = defaultPropertyList[$fullPropName]?>; + zend_update_property_ex(obj->ce, obj, getLiteralString($property->name)?>.str(), value.ptr()); + + + return obj; + }; + // register symbols @@ -149,7 +170,7 @@ foreach ($this->globalVars as $name => $type): // static property staticPropertyList as $prop): +foreach ($this->defaultStaticPropertyList as $prop): ?> php::setStaticProperty(genCharPtr($prop->class, true)?>, genCharPtr($prop->name)?>, default?>); 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', // WebDAV; RFC 2518 + 103 => 'Early Hints', // RFC 8297 + ]; + + static public $methods = ['GET', 'PUT', 'POST',]; + + public function __construct() { + + } + + public function getPhrase() { + return $this->phrases[200] ?? 'unknown'; + } +} + +function main() { + $resp = new Response; + var_dump($resp->phrases[100]); + var_dump(Response::$methods); +} +?> +--EXPECT-- +string(8) "Continue" +array(3) { + [0]=> + string(3) "GET" + [1]=> + string(3) "PUT" + [2]=> + string(4) "POST" +} \ No newline at end of file