diff --git a/composer.json b/composer.json index e0c519b4..13a0c980 100755 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "require" : { "xp-framework/core": "^12.0 | ^11.6 | ^10.16", "xp-framework/reflection": "^3.2 | ^2.15", - "xp-framework/ast": "^12.1", + "xp-framework/ast": "^12.2", "php" : ">=7.4.0" }, "require-dev" : { diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php index 572a82ba..163ff27b 100755 --- a/src/main/php/lang/ast/emit/PHP.class.php +++ b/src/main/php/lang/ast/emit/PHP.class.php @@ -357,9 +357,15 @@ protected function emitFunction($result, $function) { $result->out->write('function '.($function->signature->byref ? '&' : '').$function->name); $this->emitSignature($result, $function->signature); - $result->out->write('{'); - $this->emitAll($result, $function->body); - $result->out->write('}'); + if ($function->body instanceof Block) { + $result->out->write('{'); + $this->emitAll($result, $function->body->statements); + $result->out->write('}'); + } else { + $result->out->write('{ return '); + $this->emitOne($result, $function->body); + $result->out->write('; }'); + } $result->locals= $locals; } @@ -371,9 +377,15 @@ protected function emitClosure($result, $closure) { $closure->static ? $result->out->write('static function') : $result->out->write('function'); $this->emitSignature($result, $closure->signature, $closure->use); - $result->out->write('{'); - $this->emitAll($result, $closure->body); - $result->out->write('}'); + if ($closure->body instanceof Block) { + $result->out->write('{'); + $this->emitAll($result, $closure->body->statements); + $result->out->write('}'); + } else { + $result->out->write('{ return '); + $this->emitOne($result, $closure->body); + $result->out->write('; }'); + } $result->locals= $locals; } @@ -384,6 +396,7 @@ protected function emitLambda($result, $lambda) { $lambda->static ? $result->out->write('static fn') : $result->out->write('fn'); $this->emitSignature($result, $lambda->signature); $result->out->write('=>'); + $this->emitOne($result, $lambda->body); $result->locals= $locals; @@ -719,7 +732,7 @@ protected function emitMethod($result, $method) { if (null === $method->body) { $result->out->write(';'); } else { - $result->out->write(' {'); + $result->out->write('{'); // Emit non-constant parameter defaults foreach ($init as $param) { @@ -739,8 +752,14 @@ protected function emitMethod($result, $method) { $result->codegen->scope[0]->init= []; } - $this->emitAll($result, $method->body); - $result->out->write('}'); + if ($method->body instanceof Block) { + $this->emitAll($result, $method->body->statements); + $result->out->write('}'); + } else { + $result->out->write('return '); + $this->emitOne($result, $method->body); + $result->out->write('; }'); + } } foreach ($promoted as $param) { diff --git a/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php b/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php index 299374a0..8d26a7ac 100755 --- a/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/ControlStructuresTest.class.php @@ -121,11 +121,11 @@ public function run($type) { $value= "Test"; return match ($type) { "PING" => "+PONG", - "MSG" => { + "MSG" { $reply= "Re: ".$value; return "+OK $reply"; }, - default => { + default { return "-ERR Unknown ".$type; } }; @@ -243,7 +243,7 @@ public function run() { $test= "Original"; (function() use(&$test) { match (true) { - true => { + true { $test= "Changed"; return true; } diff --git a/src/test/php/lang/ast/unittest/emit/InvocationTest.class.php b/src/test/php/lang/ast/unittest/emit/InvocationTest.class.php index 15ae41bf..ae2864c4 100755 --- a/src/test/php/lang/ast/unittest/emit/InvocationTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/InvocationTest.class.php @@ -78,32 +78,45 @@ public function run() { )); } - #[Test] - public function closure() { + #[Test, Values(['function() { return "closure"; }', 'function() => "closure"'])] + public function closure($expr) { Assert::equals('closure', $this->run( 'class %T { public function run() { - $f= function() { return "closure"; }; + $f= '.$expr.'; return $f(); } }' )); } - #[Test] - public function global_function() { - Assert::equals('function', $this->run( - 'function fixture() { return "function"; } - class %T { + #[Test, Values(['fn() { return "lambda"; }', 'fn() => "lambda"'])] + public function lambda($expr) { + Assert::equals('lambda', $this->run( + 'class %T { public function run() { - return fixture(); + $f= '.$expr.'; + return $f(); } }' )); } + #[Test, Values(['function t%1$s() { return "function"; }', 'function t%1$s() => "function";'])] + public function global_function($decl) { + Assert::equals('function', $this->run(sprintf( + $decl.' class %%T { + + public function run() { + return t%1$s(); + } + }', + uniqid() + ))); + } + #[Test] public function function_self_reference() { Assert::equals(13, $this->run( diff --git a/src/test/php/lang/ast/unittest/emit/LambdasTest.class.php b/src/test/php/lang/ast/unittest/emit/LambdasTest.class.php index 26ad8fd9..1de05063 100755 --- a/src/test/php/lang/ast/unittest/emit/LambdasTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/LambdasTest.class.php @@ -193,7 +193,7 @@ public function run() { public function with_block() { $r= $this->run('class %T { public function run() { - return fn() => { + return fn() { $a= 1; return $a + 1; }; @@ -208,7 +208,7 @@ public function capturing_with_block() { $r= $this->run('class %T { public function run() { $a= 1; - return fn() => { + return fn() { return $a + 1; }; } @@ -231,7 +231,7 @@ public function issue_176() { $r= $this->run('class %T { public function run(iterable $records) { $nonNull= fn($record) => null !== $record; - $process= fn($records, $filter) => { + $process= fn($records, $filter) { foreach ($records as $record) { if ($filter($record)) yield $record; }