Skip to content

Commit 9532b2a

Browse files
committed
Implement flexible slot type transpilation
1 parent f7f2f08 commit 9532b2a

26 files changed

Lines changed: 401 additions & 26 deletions

src/Target/Php/Transpiler/ComponentDeclaration/ComponentDeclarationStrategyInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424

2525
use PackageFactory\ComponentEngine\Parser\Ast\ComponentDeclarationNode;
2626
use PackageFactory\ComponentEngine\Target\Php\TargetSpecific\ClassName;
27+
use PackageFactory\ComponentEngine\Target\Php\Transpiler\TypeReference\TypeReferenceStrategyInterface;
2728

2829
interface ComponentDeclarationStrategyInterface
2930
{
3031
public function getClassNameFor(ComponentDeclarationNode $componentDeclarationNode): ClassName;
3132
public function getBaseClassNameFor(ComponentDeclarationNode $componentDeclarationNode): ?ClassName;
33+
public function getTypeReferenceStrategyFor(ComponentDeclarationNode $componentDeclarationNode): TypeReferenceStrategyInterface;
3234
}

src/Target/Php/Transpiler/ComponentDeclaration/ComponentDeclarationTranspiler.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public function transpile(ComponentDeclarationNode $componentDeclarationNode): s
7272

7373
if (!$componentDeclarationNode->propertyDeclarations->isEmpty()) {
7474
$lines[] = ' public function __construct(';
75-
$lines[] = $this->writeConstructorPropertyDeclarations($componentDeclarationNode->propertyDeclarations);
75+
$lines[] = $this->writeConstructorPropertyDeclarations($componentDeclarationNode);
7676
$lines[] = ' ) {';
7777
$lines[] = ' }';
7878
$lines[] = '';
@@ -88,9 +88,13 @@ public function transpile(ComponentDeclarationNode $componentDeclarationNode): s
8888
return join("\n", $lines);
8989
}
9090

91-
public function writeConstructorPropertyDeclarations(PropertyDeclarationNodes $propertyDeclarations): string
91+
public function writeConstructorPropertyDeclarations(ComponentDeclarationNode $componentDeclarationNode): string
9292
{
93-
$typeReferenceTranspiler = new TypeReferenceTranspiler();
93+
$typeReferenceTranspiler = new TypeReferenceTranspiler(
94+
scope: $this->scope,
95+
strategy: $this->strategy->getTypeReferenceStrategyFor($componentDeclarationNode)
96+
);
97+
$propertyDeclarations = $componentDeclarationNode->propertyDeclarations;
9498
$lines = [];
9599

96100
foreach ($propertyDeclarations->items as $propertyDeclaration) {

src/Target/Php/Transpiler/Module/ModuleTranspiler.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public function transpile(ModuleNode $moduleNode): string
5959
strategy: $this->strategy->getEnumDeclarationStrategyFor($moduleNode)
6060
))->transpile($exportNode->declaration),
6161
StructDeclarationNode::class => (new StructDeclarationTranspiler(
62+
scope: new ModuleScope(
63+
loader: $this->loader,
64+
moduleNode: $moduleNode,
65+
parentScope: $this->globalScope
66+
),
6267
strategy: $this->strategy->getStructDeclarationStrategyFor($moduleNode)
6368
))->transpile($exportNode->declaration)
6469
};

src/Target/Php/Transpiler/StructDeclaration/StructDeclarationStrategyInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424

2525
use PackageFactory\ComponentEngine\Parser\Ast\StructDeclarationNode;
2626
use PackageFactory\ComponentEngine\Target\Php\TargetSpecific\ClassName;
27+
use PackageFactory\ComponentEngine\Target\Php\Transpiler\TypeReference\TypeReferenceStrategyInterface;
2728

2829
interface StructDeclarationStrategyInterface
2930
{
3031
public function getClassNameFor(StructDeclarationNode $structDeclarationNode): ClassName;
3132
public function getBaseClassNameFor(StructDeclarationNode $structDeclarationNode): ?ClassName;
33+
public function getTypeReferenceStrategyFor(StructDeclarationNode $structDeclarationNode): TypeReferenceStrategyInterface;
3234
}

src/Target/Php/Transpiler/StructDeclaration/StructDeclarationTranspiler.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\StructDeclaration;
2424

2525
use PackageFactory\ComponentEngine\Parser\Ast\StructDeclarationNode;
26-
use PackageFactory\ComponentEngine\Parser\Ast\PropertyDeclarationNodes;
2726
use PackageFactory\ComponentEngine\Target\Php\Transpiler\TypeReference\TypeReferenceTranspiler;
27+
use PackageFactory\ComponentEngine\TypeSystem\ScopeInterface;
2828

2929
final class StructDeclarationTranspiler
3030
{
3131
public function __construct(
32+
private readonly ScopeInterface $scope,
3233
private readonly StructDeclarationStrategyInterface $strategy
3334
) {
3435
}
@@ -59,7 +60,7 @@ public function transpile(StructDeclarationNode $structDeclarationNode): string
5960

6061
if (!$structDeclarationNode->propertyDeclarations->isEmpty()) {
6162
$lines[] = ' public function __construct(';
62-
$lines[] = $this->writeConstructorPropertyDeclarations($structDeclarationNode->propertyDeclarations);
63+
$lines[] = $this->writeConstructorPropertyDeclarations($structDeclarationNode);
6364
$lines[] = ' ) {';
6465
$lines[] = ' }';
6566
}
@@ -70,9 +71,13 @@ public function transpile(StructDeclarationNode $structDeclarationNode): string
7071
return join("\n", $lines);
7172
}
7273

73-
public function writeConstructorPropertyDeclarations(PropertyDeclarationNodes $propertyDeclarations): string
74+
public function writeConstructorPropertyDeclarations(StructDeclarationNode $structDeclarationNode): string
7475
{
75-
$typeReferenceTranspiler = new TypeReferenceTranspiler();
76+
$typeReferenceTranspiler = new TypeReferenceTranspiler(
77+
scope: $this->scope,
78+
strategy: $this->strategy->getTypeReferenceStrategyFor($structDeclarationNode)
79+
);
80+
$propertyDeclarations = $structDeclarationNode->propertyDeclarations;
7681
$lines = [];
7782

7883
foreach ($propertyDeclarations->items as $propertyDeclaration) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\TypeReference;
24+
25+
use PackageFactory\ComponentEngine\Parser\Ast\TypeReferenceNode;
26+
use PackageFactory\ComponentEngine\TypeSystem\Type\ComponentType\ComponentType;
27+
use PackageFactory\ComponentEngine\TypeSystem\Type\EnumType\EnumType;
28+
use PackageFactory\ComponentEngine\TypeSystem\Type\SlotType\SlotType;
29+
use PackageFactory\ComponentEngine\TypeSystem\Type\StructType\StructType;
30+
use PackageFactory\ComponentEngine\TypeSystem\TypeInterface;
31+
32+
interface TypeReferenceStrategyInterface
33+
{
34+
public function getPhpTypeReferenceForSlotType(SlotType $slotType, TypeReferenceNode $typeReferenceNode): string;
35+
public function getPhpTypeReferenceForComponentType(ComponentType $componentType, TypeReferenceNode $typeReferenceNode): string;
36+
public function getPhpTypeReferenceForEnumType(EnumType $enumType, TypeReferenceNode $typeReferenceNode): string;
37+
public function getPhpTypeReferenceForStructType(StructType $structType, TypeReferenceNode $typeReferenceNode): string;
38+
public function getPhpTypeReferenceForCustomType(TypeInterface $customType, TypeReferenceNode $typeReferenceNode): string;
39+
}

src/Target/Php/Transpiler/TypeReference/TypeReferenceTranspiler.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,36 @@
2323
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\TypeReference;
2424

2525
use PackageFactory\ComponentEngine\Parser\Ast\TypeReferenceNode;
26+
use PackageFactory\ComponentEngine\TypeSystem\ScopeInterface;
27+
use PackageFactory\ComponentEngine\TypeSystem\Type\BooleanType\BooleanType;
28+
use PackageFactory\ComponentEngine\TypeSystem\Type\ComponentType\ComponentType;
29+
use PackageFactory\ComponentEngine\TypeSystem\Type\EnumType\EnumType;
30+
use PackageFactory\ComponentEngine\TypeSystem\Type\NumberType\NumberType;
31+
use PackageFactory\ComponentEngine\TypeSystem\Type\SlotType\SlotType;
32+
use PackageFactory\ComponentEngine\TypeSystem\Type\StringType\StringType;
33+
use PackageFactory\ComponentEngine\TypeSystem\Type\StructType\StructType;
2634

2735
final class TypeReferenceTranspiler
2836
{
37+
public function __construct(
38+
private readonly ScopeInterface $scope,
39+
private readonly TypeReferenceStrategyInterface $strategy
40+
) {
41+
}
42+
2943
public function transpile(TypeReferenceNode $typeReferenceNode): string
3044
{
31-
return match ($typeReferenceNode->name) {
32-
'number' => 'int|float',
33-
'string' => 'string',
34-
'boolean' => 'bool',
35-
default => $typeReferenceNode->name
45+
$type = $this->scope->resolveTypeReference($typeReferenceNode);
46+
47+
return match ($type::class) {
48+
NumberType::class => 'int|float',
49+
StringType::class => 'string',
50+
BooleanType::class => 'bool',
51+
SlotType::class => $this->strategy->getPhpTypeReferenceForSlotType($type, $typeReferenceNode),
52+
ComponentType::class => $this->strategy->getPhpTypeReferenceForComponentType($type, $typeReferenceNode),
53+
EnumType::class => $this->strategy->getPhpTypeReferenceForEnumType($type, $typeReferenceNode),
54+
StructType::class => $this->strategy->getPhpTypeReferenceForStructType($type, $typeReferenceNode),
55+
default => $this->strategy->getPhpTypeReferenceForCustomType($type, $typeReferenceNode)
3656
};
3757
}
3858
}

src/TypeSystem/Scope/GlobalScope/GlobalScope.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use PackageFactory\ComponentEngine\TypeSystem\ScopeInterface;
2828
use PackageFactory\ComponentEngine\TypeSystem\Type\BooleanType\BooleanType;
2929
use PackageFactory\ComponentEngine\TypeSystem\Type\NumberType\NumberType;
30+
use PackageFactory\ComponentEngine\TypeSystem\Type\SlotType\SlotType;
3031
use PackageFactory\ComponentEngine\TypeSystem\Type\StringType\StringType;
3132
use PackageFactory\ComponentEngine\TypeSystem\TypeInterface;
3233

@@ -54,6 +55,7 @@ public function resolveTypeReference(TypeReferenceNode $typeReferenceNode): Type
5455
'string' => StringType::get(),
5556
'number' => NumberType::get(),
5657
'boolean' => BooleanType::get(),
58+
'slot' => SlotType::get(),
5759
default => throw new \Exception('@TODO: Unknown Type ' . $typeReferenceNode->name)
5860
};
5961
}

src/TypeSystem/Type/ComponentType/ComponentType.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@
2727

2828
final class ComponentType implements TypeInterface
2929
{
30+
private function __construct(public readonly string $componentName)
31+
{
32+
}
33+
3034
public static function fromComponentDeclarationNode(ComponentDeclarationNode $componentDeclarationNode): self
3135
{
32-
return new self();
36+
return new self(
37+
componentName: $componentDeclarationNode->componentName
38+
);
3339
}
3440

3541
public function is(TypeInterface $other): bool

src/TypeSystem/Type/EnumType/EnumStaticType.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@
2727

2828
final class EnumStaticType implements TypeInterface
2929
{
30+
private function __construct(public readonly string $enumName)
31+
{
32+
}
33+
3034
public static function fromEnumDeclarationNode(EnumDeclarationNode $enumDeclarationNode): self
3135
{
32-
return new self();
36+
return new self(
37+
enumName: $enumDeclarationNode->enumName
38+
);
3339
}
3440

3541
public function is(TypeInterface $other): bool

0 commit comments

Comments
 (0)