Skip to content

Commit b18480e

Browse files
committed
Implement Enums with primitive values
1 parent 455d999 commit b18480e

14 files changed

Lines changed: 378 additions & 11 deletions

src/Parser/Ast/EnumMemberDeclarationNode.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
final class EnumMemberDeclarationNode implements \JsonSerializable
3030
{
3131
private function __construct(
32-
public readonly string $name
32+
public readonly string $name,
33+
public readonly null|StringLiteralNode|NumberLiteralNode $value
3334
) {
3435
}
3536

@@ -46,15 +47,29 @@ public static function fromTokens(\Iterator $tokens): self
4647

4748
Scanner::skipOne($tokens);
4849

50+
$value = null;
51+
if (Scanner::type($tokens) === TokenType::BRACKET_ROUND_OPEN) {
52+
Scanner::skipOne($tokens);
53+
$value = match (Scanner::type($tokens)) {
54+
TokenType::STRING_QUOTED => StringLiteralNode::fromTokens($tokens),
55+
TokenType::NUMBER_DECIMAL => NumberLiteralNode::fromTokens($tokens),
56+
default => throw new \Exception('@TODO: Unexpected Token ' . Scanner::type($tokens)->value)
57+
};
58+
Scanner::assertType($tokens, TokenType::BRACKET_ROUND_CLOSE);
59+
Scanner::skipOne($tokens);
60+
}
61+
4962
return new self(
50-
name: $name
63+
name: $name,
64+
value: $value
5165
);
5266
}
5367

5468
public function jsonSerialize(): mixed
5569
{
5670
return [
5771
'name' => $this->name,
72+
'value' => $this->value,
5873
];
5974
}
6075
}

src/Target/Php/Transpiler/EnumDeclaration/EnumDeclarationTranspiler.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\EnumDeclaration;
2424

2525
use PackageFactory\ComponentEngine\Parser\Ast\EnumDeclarationNode;
26+
use PackageFactory\ComponentEngine\Parser\Ast\EnumMemberDeclarationNode;
27+
use PackageFactory\ComponentEngine\Parser\Ast\NumberLiteralNode;
28+
use PackageFactory\ComponentEngine\Parser\Ast\StringLiteralNode;
2629

2730
final class EnumDeclarationTranspiler
2831
{
@@ -43,16 +46,40 @@ public function transpile(EnumDeclarationNode $enumDeclarationNode): string
4346
$lines[] = '';
4447
$lines[] = 'namespace ' . $className->getNamespace() . ';';
4548
$lines[] = '';
46-
$lines[] = 'enum ' . $className->getShortClassName() . ' : string';
49+
$lines[] = 'enum ' . $className->getShortClassName() . ' : ' . $this->transpileBackingType($enumDeclarationNode);
4750
$lines[] = '{';
4851

4952
foreach ($enumDeclarationNode->memberDeclarations->items as $memberDeclarationNode) {
50-
$lines[] = ' case ' . $memberDeclarationNode->name . ' = \'' . $memberDeclarationNode->name . '\';';
53+
$lines[] = ' case ' . $memberDeclarationNode->name . ' = ' . $this->transpileMemberValue($memberDeclarationNode) . ';';
5154
}
5255

5356
$lines[] = '}';
5457
$lines[] = '';
5558

5659
return join("\n", $lines);
5760
}
61+
62+
private function transpileBackingType(EnumDeclarationNode $enumDeclarationNode): string
63+
{
64+
foreach ($enumDeclarationNode->memberDeclarations->items as $memberDeclarationNode) {
65+
if ($memberDeclarationNode->value instanceof NumberLiteralNode) {
66+
return 'int';
67+
} else {
68+
return 'string';
69+
}
70+
}
71+
72+
return 'string';
73+
}
74+
75+
private function transpileMemberValue(EnumMemberDeclarationNode $enumMemberDeclarationNode): string
76+
{
77+
if ($enumMemberDeclarationNode->value instanceof NumberLiteralNode) {
78+
return $enumMemberDeclarationNode->value->value;
79+
} else if ($enumMemberDeclarationNode->value instanceof StringLiteralNode) {
80+
return '\'' . $enumMemberDeclarationNode->value->value . '\'';
81+
} else {
82+
return '\'' . $enumMemberDeclarationNode->name . '\'';
83+
}
84+
}
5885
}

test/Integration/Examples/Enum/Enum.ast.json

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,32 @@
99
"enumName": "DayOfWeek",
1010
"memberDeclarations": {
1111
"MONDAY": {
12-
"name": "MONDAY"
12+
"name": "MONDAY",
13+
"value": null
1314
},
1415
"TUESDAY": {
15-
"name": "TUESDAY"
16+
"name": "TUESDAY",
17+
"value": null
1618
},
1719
"WEDNESDAY": {
18-
"name": "WEDNESDAY"
20+
"name": "WEDNESDAY",
21+
"value": null
1922
},
2023
"THURSDAY": {
21-
"name": "THURSDAY"
24+
"name": "THURSDAY",
25+
"value": null
2226
},
2327
"FRIDAY": {
24-
"name": "FRIDAY"
28+
"name": "FRIDAY",
29+
"value": null
2530
},
2631
"SATURDAY": {
27-
"name": "SATURDAY"
32+
"name": "SATURDAY",
33+
"value": null
2834
},
2935
"SUNDAY": {
30-
"name": "SUNDAY"
36+
"name": "SUNDAY",
37+
"value": null
3138
}
3239
}
3340
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum TrafficLight {
2+
RED(1)
3+
YELLOW(2)
4+
GREEN(3)
5+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"type": "ModuleNode",
3+
"payload": {
4+
"imports": {},
5+
"exports": [
6+
{
7+
"type": "EnumDeclarationNode",
8+
"payload": {
9+
"enumName": "TrafficLight",
10+
"memberDeclarations": {
11+
"RED": {
12+
"name": "RED",
13+
"value": {
14+
"type": "NumberLiteralNode",
15+
"payload": {
16+
"value": "1",
17+
"format": "DECIMAL"
18+
}
19+
}
20+
},
21+
"YELLOW": {
22+
"name": "YELLOW",
23+
"value": {
24+
"type": "NumberLiteralNode",
25+
"payload": {
26+
"value": "2",
27+
"format": "DECIMAL"
28+
}
29+
}
30+
},
31+
"GREEN": {
32+
"name": "GREEN",
33+
"value": {
34+
"type": "NumberLiteralNode",
35+
"payload": {
36+
"value": "3",
37+
"format": "DECIMAL"
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
]
45+
}
46+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Vendor\Project\Component;
6+
7+
enum TrafficLight : int
8+
{
9+
case RED = 1;
10+
case YELLOW = 2;
11+
case GREEN = 3;
12+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
[
2+
{
3+
"type": "KEYWORD_EXPORT",
4+
"value": "export"
5+
},
6+
{
7+
"type": "SPACE",
8+
"value": " "
9+
},
10+
{
11+
"type": "KEYWORD_ENUM",
12+
"value": "enum"
13+
},
14+
{
15+
"type": "SPACE",
16+
"value": " "
17+
},
18+
{
19+
"type": "STRING",
20+
"value": "TrafficLight"
21+
},
22+
{
23+
"type": "SPACE",
24+
"value": " "
25+
},
26+
{
27+
"type": "BRACKET_CURLY_OPEN",
28+
"value": "{"
29+
},
30+
{
31+
"type": "END_OF_LINE",
32+
"value": "\n"
33+
},
34+
{
35+
"type": "SPACE",
36+
"value": " "
37+
},
38+
{
39+
"type": "STRING",
40+
"value": "RED"
41+
},
42+
{
43+
"type": "BRACKET_ROUND_OPEN",
44+
"value": "("
45+
},
46+
{
47+
"type": "NUMBER_DECIMAL",
48+
"value": "1"
49+
},
50+
{
51+
"type": "BRACKET_ROUND_CLOSE",
52+
"value": ")"
53+
},
54+
{
55+
"type": "END_OF_LINE",
56+
"value": "\n"
57+
},
58+
{
59+
"type": "SPACE",
60+
"value": " "
61+
},
62+
{
63+
"type": "STRING",
64+
"value": "YELLOW"
65+
},
66+
{
67+
"type": "BRACKET_ROUND_OPEN",
68+
"value": "("
69+
},
70+
{
71+
"type": "NUMBER_DECIMAL",
72+
"value": "2"
73+
},
74+
{
75+
"type": "BRACKET_ROUND_CLOSE",
76+
"value": ")"
77+
},
78+
{
79+
"type": "END_OF_LINE",
80+
"value": "\n"
81+
},
82+
{
83+
"type": "SPACE",
84+
"value": " "
85+
},
86+
{
87+
"type": "STRING",
88+
"value": "GREEN"
89+
},
90+
{
91+
"type": "BRACKET_ROUND_OPEN",
92+
"value": "("
93+
},
94+
{
95+
"type": "NUMBER_DECIMAL",
96+
"value": "3"
97+
},
98+
{
99+
"type": "BRACKET_ROUND_CLOSE",
100+
"value": ")"
101+
},
102+
{
103+
"type": "END_OF_LINE",
104+
"value": "\n"
105+
},
106+
{
107+
"type": "BRACKET_CURLY_CLOSE",
108+
"value": "}"
109+
},
110+
{
111+
"type": "END_OF_LINE",
112+
"value": "\n"
113+
}
114+
]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum ImageLoadingMethod {
2+
EAGER("eager")
3+
LAZY("lazy")
4+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"type": "ModuleNode",
3+
"payload": {
4+
"imports": {},
5+
"exports": [
6+
{
7+
"type": "EnumDeclarationNode",
8+
"payload": {
9+
"enumName": "ImageLoadingMethod",
10+
"memberDeclarations": {
11+
"EAGER": {
12+
"name": "EAGER",
13+
"value": {
14+
"type": "StringLiteralNode",
15+
"payload": "eager"
16+
}
17+
},
18+
"LAZY": {
19+
"name": "LAZY",
20+
"value": {
21+
"type": "StringLiteralNode",
22+
"payload": "lazy"
23+
}
24+
}
25+
}
26+
}
27+
}
28+
]
29+
}
30+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Vendor\Project\Component;
6+
7+
enum ImageLoadingMethod : string
8+
{
9+
case EAGER = 'eager';
10+
case LAZY = 'lazy';
11+
}

0 commit comments

Comments
 (0)