diff --git a/ChangeLog.md b/ChangeLog.md index c190850c..5e61efb2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,10 @@ XP Compiler ChangeLog ## ?.?.? / ????-??-?? +## 5.1.2 / 2020-04-04 + +* Fixed promotion for by-reference arguments - @thekid + ## 5.1.1 / 2020-03-29 * Fixed ternary and instanceof operators' precedence - @thekid diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php index 9a2d97fc..d96e99e4 100755 --- a/src/main/php/lang/ast/emit/PHP.class.php +++ b/src/main/php/lang/ast/emit/PHP.class.php @@ -406,7 +406,7 @@ protected function emitMethod($result, $method) { foreach ($method->signature->parameters as $param) { if (isset($param->promote)) { $declare.= $param->promote.' $'.$param->name.';'; - $promote.= '$this->'.$param->name.'= $'.$param->name.';'; + $promote.= '$this->'.$param->name.'= '.($param->reference ? '&$' : '$').$param->name.';'; $result->meta[0][self::PROPERTY][$param->name]= [ DETAIL_RETURNS => $param->type ? $param->type->name() : 'var', DETAIL_ANNOTATIONS => [], diff --git a/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php b/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php index c0fb8395..07bee4aa 100755 --- a/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php @@ -42,6 +42,22 @@ public function run() { Assert::equals('tested', $r); } + #[@test] + public function parameter_accessible() { + $r= $this->run('class { + public function __construct(private $id= "test") { + if (null === $id) { + throw new \\lang\\IllegalArgumentException("ID not set"); + } + } + + public function run() { + return $this->id; + } + }'); + Assert::equals('test', $r); + } + #[@test] public function in_method() { $r= $this->run('class { @@ -85,4 +101,20 @@ public function __construct(public string $name, string $initial= null) { Assert::equals(['name'], array_map(function($f) { return $f->getName(); }, $t->getFields())); Assert::equals('Timm J.', $t->newInstance('Timm', 'J')->name); } + + #[@test] + public function promoted_by_reference_argument() { + $t= $this->type('class { + public function __construct(public array &$list) { } + + public static function test() { + $list= [1, 2, 3]; + $self= new self($list); + $list[]= 4; + return $self->list; + } + }'); + + Assert::equals([1, 2, 3, 4], $t->getMethod('test')->invoke(null, [])); + } } \ No newline at end of file