From 46e15ca247a807394c68cee057ec566b9207c0aa Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 10 Feb 2026 18:36:58 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=20Match=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=92=8C=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 CompilerBase 中添加了对 Expr_Match 节点的解析支持 - 修改 parseTernary 方法参数类型为 Node\Expr\Ternary - 添加了 parseMatch 方法用于处理 Match 表达式 - 在 Preprocessor 中添加对 Stmt_Enum 和 Stmt_EnumCase 的预处理支持 - 扩展 prepareClass 方法以支持枚举类型的处理 - 在 Translator 中添加对 Stmt_Enum 的翻译支持 - 修改 parseClass 方法以正确处理枚举定义 - 添加测试文件 closure_016.phpt 和 closure_017.phpt 验证闭包功能 - 添加枚举示例文件 enum1.php 展示枚举用法 --- examples/enum1.php | 26 ++++++++++++++ src/Php/CompilerBase.php | 9 ++++- src/Php/Preprocessor.php | 5 ++- src/Php/Translator.php | 17 ++++++--- tests/zend/closures/closure_016.phpt | 54 ++++++++++++++++++++++++++++ tests/zend/closures/closure_017.phpt | 10 ++++++ 6 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 examples/enum1.php create mode 100644 tests/zend/closures/closure_016.phpt create mode 100644 tests/zend/closures/closure_017.phpt diff --git a/examples/enum1.php b/examples/enum1.php new file mode 100644 index 00000000..b59e3119 --- /dev/null +++ b/examples/enum1.php @@ -0,0 +1,26 @@ + 'Red', + self::Clubs, self::Spades => 'Black', + }; + } +} + +function main() +{ + echo Suit::Hearts->color() . "\n"; + echo Suit::Diamonds->color() . "\n"; + echo Suit::Clubs->color() . "\n"; + echo Suit::Spades->color() . "\n"; +} \ No newline at end of file diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 46be2532..e56d632c 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -360,6 +360,8 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->parseBinaryOpPow($expr); case 'Expr_Ternary': return $this->parseTernary($expr); + case 'Expr_Match': + return $this->parseMatch($expr); case 'Expr_FuncCall': return $this->parseFuncCall($expr); case 'Expr_MethodCall': @@ -2025,7 +2027,7 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->parsePostOp($expr, '+'); } - protected function parseTernary(mixed $expr): string + protected function parseTernary(Node\Expr\Ternary $expr): string { $cond = $expr->cond; $if = $expr->if; @@ -2038,6 +2040,11 @@ class CompilerBase extends \PhpAot\Core\Translator return '(' . $this->parseExpr($cond) . ') ? (' . $this->parseExpr($if) . ') : (' . $this->parseExpr($else) . ')'; } + protected function parseMatch(Node\Expr\Match_ $expr): string + { + abort($expr); + } + protected function parseBinaryOpGreater(mixed $expr): string { return $this->convertBoolExpr($this->parseBinaryOp($expr->left, $expr->right, '>')); diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 7b777f60..d5f5d592 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -90,6 +90,7 @@ class Preprocessor extends CompilerBase case 'Stmt_Namespace': $this->prepareNamespaceDef($v); break; + case 'Stmt_Enum': case 'Stmt_Class': case 'Stmt_Trait': $this->prepareClass($v); @@ -135,6 +136,7 @@ class Preprocessor extends CompilerBase $type2 = $v2->getType(); switch ($type2) { case 'Stmt_Class': + case 'Stmt_Enum': $this->prepareClass($v2); break; case 'Stmt_Function': @@ -162,7 +164,7 @@ class Preprocessor extends CompilerBase } } - protected function prepareClass(Node\Stmt\Class_|Node\Stmt\Trait_ $class): string + protected function prepareClass(Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): string { $this->class = $this->parseIdentifier($class->name); $code = ''; @@ -173,6 +175,7 @@ class Preprocessor extends CompilerBase case 'Stmt_Property': case 'Stmt_Nop': case 'Stmt_TraitUse': + case 'Stmt_EnumCase': break; case 'Stmt_ClassMethod': $code .= $this->prepareFunction($v) . PHP_EOL; diff --git a/src/Php/Translator.php b/src/Php/Translator.php index e7f26630..c07afe59 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -479,6 +479,7 @@ class Translator extends Preprocessor break; case 'Stmt_Class': case 'Stmt_Trait': + case 'Stmt_Enum': $cppCode .= $this->parseClass($v); break; case 'Stmt_Use': @@ -649,11 +650,18 @@ class Translator extends Preprocessor $this->argInfoHeaderFiles[] = $headerFile; } - protected function parseClass(Node\Stmt\Class_|Node\Stmt\Trait_ $class): string + protected function parseClass(Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): string { - $this->class = $this->parseIdentifier($class->name); - $this->classDef = new ClassDef($this->class, $class->flags, $this->namespace); - if ($class->extends) { + $this->class = $this->parseIdentifier($class->name); + if ($class instanceof Node\Stmt\Enum_) { + $flags = Modifiers::PUBLIC; + $extends = ''; + } else { + $flags = $class->flags; + $extends = $class->extends; + } + $this->classDef = new ClassDef($this->class, $flags, $this->namespace); + if ($extends) { $this->classDef->extends = $this->parseIdentifier($class->extends); if (isset($this->classes[$this->classDef->extends])) { $parent = $this->classes[$this->classDef->extends]; @@ -682,6 +690,7 @@ class Translator extends Preprocessor case 'Stmt_ClassMethod': $this->parseClassMethod($v, $methodCodes); break; + case 'Stmt_EnumCase': case 'Stmt_Nop': break; default: diff --git a/tests/zend/closures/closure_016.phpt b/tests/zend/closures/closure_016.phpt new file mode 100644 index 00000000..5014ba70 --- /dev/null +++ b/tests/zend/closures/closure_016.phpt @@ -0,0 +1,54 @@ +--TEST-- +Closure 016: closures and is_callable() +--FILE-- + +--EXPECT-- +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Foo::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke +bool(true) +Closure::__invoke diff --git a/tests/zend/closures/closure_017.phpt b/tests/zend/closures/closure_017.phpt new file mode 100644 index 00000000..15611aea --- /dev/null +++ b/tests/zend/closures/closure_017.phpt @@ -0,0 +1,10 @@ +--TEST-- +Closure 017: Trying to destroy an active lambda function +--FILE-- + +--EXPECT-- +DONE \ No newline at end of file