@@ -40,21 +40,26 @@ protected function declaration($name) {
40
40
* - Binary expression where left- and right hand side are literals
41
41
*
42
42
* @see https://wiki.php.net/rfc/const_scalar_exprs
43
+ * @param lang.ast.Result $result
43
44
* @param lang.ast.Node $node
44
45
* @return bool
45
46
*/
46
- protected function isConstant ($ node ) {
47
+ protected function isConstant ($ result , $ node ) {
47
48
if ($ node instanceof Literal) {
48
49
return true ;
49
50
} else if ($ node instanceof ArrayLiteral) {
50
51
foreach ($ node ->values as $ node ) {
51
- if (!$ this ->isConstant ($ node )) return false ;
52
+ if (!$ this ->isConstant ($ result , $ node )) return false ;
52
53
}
53
54
return true ;
54
55
} else if ($ node instanceof ScopeExpression) {
55
- return $ node ->member instanceof Literal;
56
+ return (
57
+ $ node ->member instanceof Literal &&
58
+ is_string ($ node ->type ) &&
59
+ 'enum ' !== $ result ->lookup ($ node ->type )->kind ()
60
+ );
56
61
} else if ($ node instanceof BinaryExpression) {
57
- return $ this ->isConstant ($ node ->left ) && $ this ->isConstant ($ node ->right );
62
+ return $ this ->isConstant ($ result , $ node ->left ) && $ this ->isConstant ($ result , $ node ->right );
58
63
}
59
64
return false ;
60
65
}
@@ -188,7 +193,7 @@ protected function emitStatic($result, $static) {
188
193
foreach ($ static ->initializations as $ variable => $ initial ) {
189
194
$ result ->out ->write ('static $ ' .$ variable );
190
195
if ($ initial ) {
191
- if ($ this ->isConstant ($ initial )) {
196
+ if ($ this ->isConstant ($ result , $ initial )) {
192
197
$ result ->out ->write ('= ' );
193
198
$ this ->emitOne ($ result , $ initial );
194
199
} else {
@@ -284,7 +289,7 @@ protected function emitParameter($result, $parameter) {
284
289
$ result ->out ->write (($ parameter ->reference ? '& ' : '' ).'$ ' .$ parameter ->name );
285
290
}
286
291
if ($ parameter ->default ) {
287
- if ($ this ->isConstant ($ parameter ->default )) {
292
+ if ($ this ->isConstant ($ result , $ parameter ->default )) {
288
293
$ result ->out ->write ('= ' );
289
294
$ this ->emitOne ($ result , $ parameter ->default );
290
295
} else {
@@ -349,6 +354,46 @@ protected function emitLambda($result, $lambda) {
349
354
$ this ->emitOne ($ result , $ lambda ->body );
350
355
}
351
356
357
+ protected function emitEnumCase ($ result , $ case ) {
358
+ $ result ->out ->write ('public static $ ' .$ case ->name .'; ' );
359
+ }
360
+
361
+ protected function emitEnum ($ result , $ enum ) {
362
+ array_unshift ($ result ->type , $ enum );
363
+ array_unshift ($ result ->meta , []);
364
+ $ result ->locals = [[], []];
365
+
366
+ $ result ->out ->write ('final class ' .$ this ->declaration ($ enum ->name ).' implements \UnitEnum ' );
367
+ $ enum ->implements && $ result ->out ->write (', ' .implode (', ' , $ enum ->implements ));
368
+ $ result ->out ->write ('{ ' );
369
+
370
+ $ cases = [];
371
+ foreach ($ enum ->body as $ member ) {
372
+ if ($ member ->is ('enumcase ' )) $ cases []= $ member ;
373
+ $ this ->emitOne ($ result , $ member );
374
+ }
375
+
376
+ // Name and constructor
377
+ $ result ->out ->write ('public $name; private function __construct($name) { $this->name= $name; } ' );
378
+
379
+ // Enum cases
380
+ $ result ->out ->write ('public static function cases() { return [ ' );
381
+ foreach ($ cases as $ case ) {
382
+ $ result ->out ->write ('self::$ ' .$ case ->name .', ' );
383
+ }
384
+ $ result ->out ->write (']; } ' );
385
+
386
+ // Initializations
387
+ $ result ->out ->write ('static function __init() { ' );
388
+ foreach ($ cases as $ case ) {
389
+ $ result ->out ->write ('self::$ ' .$ case ->name .'= new self(" ' .$ case ->name .'"); ' );
390
+ }
391
+ $ this ->emitInitializations ($ result , $ result ->locals [0 ]);
392
+ $ this ->emitMeta ($ result , $ enum ->name , $ enum ->annotations , $ enum ->comment );
393
+ $ result ->out ->write ('}} ' .$ enum ->name .'::__init(); ' );
394
+ array_shift ($ result ->type );
395
+ }
396
+
352
397
protected function emitClass ($ result , $ class ) {
353
398
array_unshift ($ result ->type , $ class );
354
399
array_unshift ($ result ->meta , []);
@@ -518,7 +563,7 @@ protected function emitProperty($result, $property) {
518
563
519
564
$ result ->out ->write (implode (' ' , $ property ->modifiers ).' ' .$ this ->propertyType ($ property ->type ).' $ ' .$ property ->name );
520
565
if (isset ($ property ->expression )) {
521
- if ($ this ->isConstant ($ property ->expression )) {
566
+ if ($ this ->isConstant ($ result , $ property ->expression )) {
522
567
$ result ->out ->write ('= ' );
523
568
$ this ->emitOne ($ result , $ property ->expression );
524
569
} else if (in_array ('static ' , $ property ->modifiers )) {
@@ -571,7 +616,7 @@ protected function emitMethod($result, $method) {
571
616
];
572
617
}
573
618
574
- if (isset ($ param ->default ) && !$ this ->isConstant ($ param ->default )) {
619
+ if (isset ($ param ->default ) && !$ this ->isConstant ($ result , $ param ->default )) {
575
620
$ meta [DETAIL_TARGET_ANNO ][$ param ->name ]['default ' ]= [$ param ->default ];
576
621
}
577
622
}
@@ -911,7 +956,7 @@ protected function emitScope($result, $scope) {
911
956
$ result ->out ->write (')? ' .$ t .':: ' );
912
957
$ this ->emitOne ($ result , $ scope ->member );
913
958
$ result ->out ->write (':null ' );
914
- } else if ($ scope ->member instanceof Literal && '$ enum ' === $ result ->lookup ($ scope ->type )->kind ()) {
959
+ } else if ($ scope ->member instanceof Literal && 'enum ' === $ result ->lookup ($ scope ->type )->kind ()) {
915
960
$ result ->out ->write ($ scope ->type .'::$ ' .$ scope ->member ->expression );
916
961
} else {
917
962
$ result ->out ->write ($ scope ->type .':: ' );
0 commit comments