feat(compiler): 添加对 Match 表达式和枚举的支持

- 在 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 展示枚举用法
pull/1/head
韩天峰 7 months ago
parent bd06dcf0a5
commit 46e15ca247
  1. 26
      examples/enum1.php
  2. 9
      src/Php/CompilerBase.php
  3. 5
      src/Php/Preprocessor.php
  4. 17
      src/Php/Translator.php
  5. 54
      tests/zend/closures/closure_016.phpt
  6. 10
      tests/zend/closures/closure_017.phpt

@ -0,0 +1,26 @@
<?php
interface Colorful {
public function color(): string;
}
enum Suit implements Colorful {
case Hearts;
case Diamonds;
case Clubs;
case Spades;
public function color(): string {
return match ($this) {
self::Hearts, self::Diamonds => '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";
}

@ -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, '>'));

@ -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;

@ -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:

@ -0,0 +1,54 @@
--TEST--
Closure 016: closures and is_callable()
--FILE--
<?php
class Foo {
function __invoke() {
echo "Hello World!\n";
}
}
function foo() {
return function() {
echo "Hello World!\n";
};
}
function main() {
$test = new Foo;
var_dump(is_callable($test, true, $name));
echo $name."\n";
var_dump(is_callable($test, false, $name));
echo $name."\n";
var_dump(is_callable(array($test,"__invoke"), true, $name));
echo $name."\n";
var_dump(is_callable(array($test,"__invoke"), false, $name));
echo $name."\n";
$test = foo();
var_dump(is_callable($test, true, $name));
echo $name."\n";
var_dump(is_callable($test, false, $name));
echo $name."\n";
var_dump(is_callable(array($test,"__invoke"), true, $name));
echo $name."\n";
var_dump(is_callable(array($test,"__invoke"), false, $name));
echo $name."\n";
}
?>
--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

@ -0,0 +1,10 @@
--TEST--
Closure 017: Trying to destroy an active lambda function
--FILE--
<?php
$a = function(&$a) { $a = 1; };
$a($a);
echo "DONE\n";
?>
--EXPECT--
DONE
Loading…
Cancel
Save