12
12
Property ,
13
13
ScopeExpression ,
14
14
UnpackExpression ,
15
+ TraitDeclaration ,
15
16
Variable
16
17
};
17
- use lang \ast \types \{IsUnion , IsFunction , IsArray , IsMap , IsNullable , IsExpression };
18
+ use lang \ast \types \{IsUnion , IsFunction , IsArray , IsMap , IsNullable , IsValue , IsExpression };
18
19
use lang \ast \{Emitter , Node , Type , Result };
19
20
20
21
abstract class PHP extends Emitter {
@@ -359,7 +360,7 @@ protected function emitEnumCase($result, $case) {
359
360
protected function emitEnum ($ result , $ enum ) {
360
361
array_unshift ($ result ->type , $ enum );
361
362
array_unshift ($ result ->meta , []);
362
- $ result ->locals = [[], []];
363
+ $ result ->locals ?: $ result -> locals = [[], [], [], []];
363
364
364
365
$ enum ->comment && $ this ->emitOne ($ result , $ enum ->comment );
365
366
$ enum ->annotations && $ this ->emitOne ($ result , $ enum ->annotations );
@@ -385,23 +386,27 @@ protected function emitEnum($result, $enum) {
385
386
$ this ->emitInitializations ($ result , $ result ->locals [0 ]);
386
387
$ this ->emitMeta ($ result , $ enum ->name , $ enum ->annotations , $ enum ->comment );
387
388
$ result ->out ->write ('}} ' .$ enum ->name ->literal ().'::__init(); ' );
389
+
388
390
array_shift ($ result ->type );
391
+ $ result ->locals = [];
389
392
}
390
393
391
394
protected function emitClass ($ result , $ class ) {
392
395
array_unshift ($ result ->type , $ class );
393
396
array_unshift ($ result ->meta , []);
394
- $ result ->locals ?: $ result ->locals = [[], [], []];
397
+ $ result ->locals ?: $ result ->locals = [[], [], [], [] ];
395
398
396
399
$ class ->comment && $ this ->emitOne ($ result , $ class ->comment );
397
400
$ class ->annotations && $ this ->emitOne ($ result , $ class ->annotations );
398
401
$ result ->at ($ class ->declared )->out ->write (implode (' ' , $ class ->modifiers ).&
6D40
#39; class ' .$ class ->declaration ());
399
402
$ class ->parent && $ result ->out ->write (' extends ' .$ class ->parent ->literal ());
400
403
404
+ $ defaults = [];
401
405
if ($ class ->implements ) {
402
406
$ list = '' ;
403
407
foreach ($ class ->implements as $ type ) {
404
408
$ list .= ', ' .$ type ->literal ();
409
+ $ result ->lookup ($ type ->literal ())->defaultImplementations () && $ defaults []= $ type ;
405
410
}
406
411
$ result ->out ->write (' implements ' .substr ($ list , 2 ));
407
412
}
@@ -447,10 +452,15 @@ protected function emitClass($result, $class) {
447
452
$ result ->out ->write ('} ' );
448
453
}
449
454
455
+ foreach ($ defaults as $ trait ) {
456
+ $ result ->out ->write ('use __ ' .substr ($ trait ->literal (), 1 ).'_Defaults; ' );
457
+ }
458
+
450
459
$ result ->out ->write ('static function __init() { ' );
451
460
$ this ->emitInitializations ($ result , $ result ->locals [0 ]);
452
461
$ this ->emitMeta ($ result , $ class ->name , $ class ->annotations , $ class ->comment );
453
462
$ result ->out ->write ('}} ' .$ class ->name ->literal ().'::__init(); ' );
463
+
454
464
array_shift ($ result ->type );
455
465
$ result ->locals = [];
456
466
}
@@ -509,7 +519,9 @@ protected function emitAnnotations($result, $annotations) {
509
519
}
510
520
511
521
protected function emitInterface ($ result , $ interface ) {
522
+ array_unshift ($ result ->type , $ interface );
512
523
array_unshift ($ result ->meta , []);
524
+ $ result ->locals ?: $ result ->locals = [[], [], [], []];
513
525
514
526
$ interface ->comment && $ this ->emitOne ($ result , $ interface ->comment );
515
527
$ interface ->annotations && $ this ->emitOne ($ result , $ interface ->annotations );
@@ -522,10 +534,24 @@ protected function emitInterface($result, $interface) {
522
534
$ result ->out ->write ('} ' );
523
535
524
536
$ this ->emitMeta ($ result , $ interface ->name , $ interface ->annotations , $ interface ->comment );
537
+
538
+ // Emit default implementations
539
+ if ($ result ->locals [3 ]) {
540
+ $ this ->emitOne ($ result , new TraitDeclaration (
541
+ [],
542
+ new IsValue ('\\__ ' .$ interface ->declaration ().'_Defaults ' ),
543
+ $ result ->locals [3 ]
544
+ ));
545
+ }
546
+
547
+ array_shift ($ result ->type );
548
+ $ result ->locals = [];
525
549
}
526
550
527
551
protected function emitTrait ($ result , $ trait ) {
552
+ array_unshift ($ result ->type , $ trait );
528
553
array_unshift ($ result ->meta , []);
554
+ $ result ->locals = [[], [], [], []];
529
555
530
556
$ trait ->comment && $ this ->emitOne ($ result , $ trait ->comment );
531
557
$ trait ->annotations && $ this ->emitOne ($ result , $ trait ->annotations );
@@ -537,6 +563,9 @@ protected function emitTrait($result, $trait) {
537
563
$ result ->out ->write ('} ' );
538
564
539
565
$ this ->emitMeta ($ result , $ trait ->name , $ trait ->annotations , $ trait ->comment );
566
+
567
+ array_shift ($ result ->type );
568
+ $ result ->locals = [];
540
569
}
541
570
542
571
protected function emitUse ($ result , $ use ) {
@@ -626,6 +655,10 @@ protected function emitMethod($result, $method) {
626
655
627
656
if (null === $ method ->body ) {
628
657
$ result ->out ->write ('; ' );
658
+ $ default = null ;
659
+ } else if ('interface ' === $ result ->type [0 ]->kind ) {
660
+ $ result ->out ->write ('; ' );
661
+ $ default = $ method ;
629
662
} else {
630
663
$ result ->out ->write (' { ' );
631
664
$ this ->emitInitializations ($ result , $ result ->locals [1 ]);
@@ -634,6 +667,7 @@ protected function emitMethod($result, $method) {
634
667
}
635
668
$ this ->emitAll ($ result , $ method ->body );
636
669
$ result ->out ->write ('} ' );
670
+ $ default = null ;
637
671
}
638
672
639
673
foreach ($ promoted as $ param ) {
@@ -646,6 +680,10 @@ protected function emitMethod($result, $method) {
646
680
foreach ($ virtual as $ name => $ access ) {
647
681
$ result ->locals [2 ][$ name ]= $ access ;
648
682
}
683
+
684
+ // Copy default implementations to class scope
685
+ $ default && $ result ->locals [3 ][]= $ default ;
686
+
649
687
$ result ->meta [0 ][self ::METHOD ][$ method ->name ]= $ meta ;
650
688
}
651
689
0 commit comments