1313 Expression ,
1414 InstanceExpression ,
1515 Literal ,
16+ NewExpression ,
1617 Property ,
1718 ScopeExpression ,
1819 UnpackExpression ,
@@ -126,7 +127,7 @@ protected function enclose($result, $node, $signature, $static, $emit) {
126127 $ capture = [];
127128 foreach ($ result ->codegen ->search ($ node , 'variable ' ) as $ var ) {
128129 if (isset ($ result ->locals [$ var ->pointer ])) {
129- $ capture [$ var ->pointer ]= true ;
130+ $ capture [$ var ->pointer ]??= ( $ result -> locals [ $ var -> pointer ] ? ' &$ ' : ' $ ' ). $ var -> pointer ;
130131 }
131132 }
132133 unset($ capture ['this ' ]);
@@ -144,9 +145,9 @@ protected function enclose($result, $node, $signature, $static, $emit) {
144145 }
145146
146147 if ($ capture ) {
147- $ result ->out ->write ('use($ ' .implode (', $ ' , array_keys ( $ capture) ).') ' );
148- foreach ($ capture as $ name => $ _ ) {
149- $ result ->locals [$ name ]= true ;
148+ $ result ->out ->write ('use( ' .implode (', ' , $ capture ).') ' );
149+ foreach ($ capture as $ name => $ variable ) {
150+ $ result ->locals [$ name ]= ' & ' === $ variable [ 0 ] ;
150151 }
151152 }
152153
@@ -299,7 +300,7 @@ protected function emitArray($result, $array) {
299300 }
300301
301302 protected function emitParameter ($ result , $ parameter ) {
302- $ result ->locals [$ parameter ->name ]= true ;
303+ $ result ->locals [$ parameter ->name ]= $ parameter -> reference ;
303304 $ parameter ->annotations && $ this ->emitOne ($ result , $ parameter ->annotations );
304305
305306 // If we have a non-constant default and a type, emit a nullable type hint
@@ -341,7 +342,7 @@ protected function emitSignature($result, $signature, $use= null) {
341342 if ($ use ) {
342343 $ result ->out ->write (' use( ' .implode (', ' , $ use ).') ' );
343344 foreach ($ use as $ variable ) {
344- $ result ->locals [substr ($ variable , 1 )]= true ;
345+ $ result ->locals [ltrim ($ variable , ' &$ ' )]= ' & ' === $ variable [ 0 ] ;
345346 }
346347 }
347348
@@ -464,7 +465,7 @@ protected function emitClass($result, $class) {
464465 }
465466 $ result ->out ->write (']; ' );
466467
467- $ result ->out ->write ('public function __get($name) { switch ($name) { ' );
468+ $ result ->out ->write ('public function & __get($name) { switch ($name) { ' );
468469 foreach ($ context ->virtual as $ name => $ access ) {
469470 $ result ->out ->write ($ name ? 'case " ' .$ name .'": ' : 'default: ' );
470471 $ this ->emitOne ($ result , $ access [0 ]);
@@ -646,12 +647,37 @@ protected function emitProperty($result, $property) {
646647 $ result ->codegen ->scope [0 ]->init ['$this-> ' .$ property ->name ]= $ property ->expression ;
647648 }
648649 }
649- $ result ->out ->write ('; ' );
650+
651+ if ($ property ->hooks ) {
652+ $ result ->out ->write ('{ ' );
653+ foreach ($ property ->hooks as $ type => $ hook ) {
654+ $ hook ->byref && $ result ->out ->write ('& ' );
655+ $ result ->out ->write ($ type );
656+ if ($ hook ->parameter ) {
657+ $ result ->out ->write ('( ' );
658+ $ this ->emitOne ($ result , $ hook ->parameter );
659+ $ result ->out ->write (') ' );
660+ }
661+
662+ if (null === $ hook ->expression ) {
663+ $ result ->out ->write ('; ' );
664+ } else if ($ hook ->expression instanceof Block) {
665+ $ this ->emitOne ($ result , $ hook ->expression );
666+ } else {
667+ $ result ->out ->write ('=> ' );
668+ $ this ->emitOne ($ result , $ hook ->expression );
669+ $ result ->out ->write ('; ' );
670+ }
671+ }
672+ $ result ->out ->write ('} ' );
673+ } else {
674+ $ result ->out ->write ('; ' );
675+ }
650676 }
651677
652678 protected function emitMethod ($ result , $ method ) {
653679 $ locals = $ result ->locals ;
654- $ result ->locals = ['this ' => true ];
680+ $ result ->locals = ['this ' => false ];
655681 $ meta = [
656682 DETAIL_RETURNS => $ method ->signature ->returns ? $ method ->signature ->returns ->name () : 'var ' ,
657683 DETAIL_ANNOTATIONS => $ method ->annotations ,
@@ -719,7 +745,11 @@ protected function emitMethod($result, $method) {
719745 }
720746
721747 foreach ($ promoted as $ param ) {
722- $ this ->emitProperty ($ result , new Property (explode (' ' , $ param ->promote ), $ param ->name , $ param ->type ));
748+ $ this ->emitProperty ($ result , new Property (
749+ is_array ($ param ->promote ) ? $ param ->promote : explode (' ' , $ param ->promote ),
750+ $ param ->name ,
751+ $ param ->type
752+ ));
723753 }
724754
725755 $ result ->locals = $ locals ;
@@ -770,7 +800,7 @@ protected function emitOffset($result, $offset) {
770800 protected function emitAssign ($ result , $ target ) {
771801 if ($ target instanceof Variable && $ target ->const ) {
772802 $ result ->out ->write ('$ ' .$ target ->pointer );
773- $ result ->locals [$ target ->pointer ]= true ;
803+ $ result ->locals [$ target ->pointer ]= false ;
774804 } else if ($ target instanceof ArrayLiteral) {
775805 $ result ->out ->write ('[ ' );
776806 foreach ($ target ->values as $ pair ) {
@@ -1086,15 +1116,14 @@ protected function emitInvoke($result, $invoke) {
10861116
10871117 protected function emitScope ($ result , $ scope ) {
10881118
1089- // $x::<expr> vs. e.g. invoke()::<expr> vs. T::<expr>
1090- if ($ scope ->type instanceof Variable) {
1119+ // new T()::<expr> vs. e.g. $x::<expr> vs. T::<expr>
1120+ if ($ scope ->type instanceof NewExpression) {
1121+ $ result ->out ->write ('( ' );
10911122 $ this ->emitOne ($ result , $ scope ->type );
1092- $ result ->out ->write (':: ' );
1123+ $ result ->out ->write (') :: ' );
10931124 } else if ($ scope ->type instanceof Node) {
1094- $ t = $ result ->temp ();
1095- $ result ->out ->write ('(null=== ' .$ t .'= ' );
10961125 $ this ->emitOne ($ result , $ scope ->type );
1097- $ result ->out ->write (" )?null: { $ t } :: " );
1126+ $ result ->out ->write (' :: ' );
10981127 } else {
10991128 $ result ->out ->write ("{$ scope ->type }:: " );
11001129 }
@@ -1113,7 +1142,7 @@ protected function emitScope($result, $scope) {
11131142 }
11141143
11151144 protected function emitInstance ($ result , $ instance ) {
1116- if (' new ' === $ instance ->expression -> kind ) {
1145+ if ($ instance ->expression instanceof NewExpression ) {
11171146 $ result ->out ->write ('( ' );
11181147 $ this ->emitOne ($ result , $ instance ->expression );
11191148 $ result ->out ->write (')-> ' );
0 commit comments