Skip to content

Commit 0adb4c0

Browse files
committed
TASK: Cleanup InferredTypes and extract duplicated logic to TypeInferrerContext
1 parent 22df4ba commit 0adb4c0

File tree

4 files changed

+49
-29
lines changed

4 files changed

+49
-29
lines changed

src/TypeSystem/Inferrer/InferredTypes.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,30 @@
2727
class InferredTypes
2828
{
2929
/**
30-
* @var TypeInterface[]
30+
* Map of identifierName to the corresponding inferred type
31+
* @var array<string,TypeInterface>
3132
*/
32-
public readonly array $types;
33+
private readonly array $types;
3334

34-
public function __construct(
35+
private function __construct(
3536
TypeInterface ...$types
3637
) {
38+
// @phpstan-ignore-next-line
3739
$this->types = $types;
3840
}
41+
42+
public static function empty(): self
43+
{
44+
return new self();
45+
}
46+
47+
public static function fromType(string $identifierName, TypeInterface $type): self
48+
{
49+
return new self(...[$identifierName => $type]);
50+
}
51+
52+
public function getType(string $identifierName): ?TypeInterface
53+
{
54+
return $this->types[$identifierName] ?? null;
55+
}
3956
}

src/TypeSystem/Inferrer/TypeInferrer.php

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
use PackageFactory\ComponentEngine\Parser\Ast\IdentifierNode;
2929
use PackageFactory\ComponentEngine\Parser\Ast\NullLiteralNode;
3030
use PackageFactory\ComponentEngine\TypeSystem\ScopeInterface;
31-
use PackageFactory\ComponentEngine\TypeSystem\Type\NullType\NullType;
32-
use PackageFactory\ComponentEngine\TypeSystem\Type\UnionType\UnionType;
3331

3432
/**
3533
* This class handles the analysis of identifier types that are used in a condition
@@ -53,22 +51,19 @@ public function inferTypesInCondition(ExpressionNode $conditionNode, TypeInferre
5351
{
5452
if ($conditionNode->root instanceof IdentifierNode) {
5553
$type = $this->scope->lookupTypeFor($conditionNode->root->value);
56-
// case `nullableString ? "nullableString is not null" : "nullableString is null"`
57-
if (!$type instanceof UnionType || !$type->containsNull()) {
58-
return new InferredTypes();
54+
if (!$type) {
55+
return InferredTypes::empty();
5956
}
60-
61-
return new InferredTypes(
62-
...[$conditionNode->root->value => $context->isTrue() ? $type->withoutNull() : NullType::get()]
63-
);
57+
// case `nullableString ? "nullableString is not null" : "nullableString is null"`
58+
return InferredTypes::fromType($conditionNode->root->value, $context->narrowDownType($type));
6459
}
6560

6661
if (($binaryOperationNode = $conditionNode->root) instanceof BinaryOperationNode) {
6762
// cases
6863
// `nullableString === null ? "nullableString is null" : "nullableString is not null"`
6964
// `nullableString !== null ? "nullableString is not null" : "nullableString is null"`
7065
if (count($binaryOperationNode->operands->rest) !== 1) {
71-
return new InferredTypes();
66+
return InferredTypes::empty();
7267
}
7368
$first = $binaryOperationNode->operands->first;
7469
$second = $binaryOperationNode->operands->rest[0];
@@ -82,26 +77,21 @@ public function inferTypesInCondition(ExpressionNode $conditionNode, TypeInferre
8277
};
8378

8479
if ($comparedIdentifierValueToNull === null) {
85-
return new InferredTypes();
80+
return InferredTypes::empty();
8681
}
87-
8882
$type = $this->scope->lookupTypeFor($comparedIdentifierValueToNull);
89-
if (!$type instanceof UnionType || !$type->containsNull()) {
90-
return new InferredTypes();
83+
if (!$type) {
84+
return InferredTypes::empty();
9185
}
9286

9387
if ($binaryOperationNode->operator === BinaryOperator::EQUAL) {
94-
return new InferredTypes(
95-
...[$comparedIdentifierValueToNull => $context->isTrue() ? NullType::get() : $type->withoutNull()]
96-
);
88+
return InferredTypes::fromType($comparedIdentifierValueToNull, $context->negate()->narrowDownType($type));
9789
}
9890
if ($binaryOperationNode->operator === BinaryOperator::NOT_EQUAL) {
99-
return new InferredTypes(
100-
...[$comparedIdentifierValueToNull => $context->isTrue() ? $type->withoutNull() : NullType::get()]
101-
);
91+
return InferredTypes::fromType($comparedIdentifierValueToNull, $context->narrowDownType($type));
10292
}
10393
}
10494

105-
return new InferredTypes();
95+
return InferredTypes::empty();
10696
}
10797
}

src/TypeSystem/Inferrer/TypeInferrerContext.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,32 @@
2222

2323
namespace PackageFactory\ComponentEngine\TypeSystem\Inferrer;
2424

25+
use PackageFactory\ComponentEngine\TypeSystem\Type\NullType\NullType;
26+
use PackageFactory\ComponentEngine\TypeSystem\Type\UnionType\UnionType;
27+
use PackageFactory\ComponentEngine\TypeSystem\TypeInterface;
28+
2529
enum TypeInferrerContext
2630
{
2731
case TRUTHY;
2832

2933
case FALSY;
3034

31-
public function isTrue(): bool
35+
public function negate(): self
3236
{
33-
return $this === self::TRUTHY;
37+
return match ($this) {
38+
self::TRUTHY => self::FALSY,
39+
self::FALSY => self::TRUTHY
40+
};
3441
}
3542

36-
public function isFalse(): bool
43+
public function narrowDownType(TypeInterface $type): TypeInterface
3744
{
38-
return $this === self::FALSY;
45+
if (!$type instanceof UnionType || !$type->containsNull()) {
46+
return $type;
47+
}
48+
return match ($this) {
49+
self::TRUTHY => $type->withoutNull(),
50+
self::FALSY => NullType::get()
51+
};
3952
}
4053
}

src/TypeSystem/Scope/TernaryBranchScope/TernaryBranchScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static function forFalsyBranch(ExpressionNode $conditionNode, ScopeInterf
5656

5757
public function lookupTypeFor(string $name): ?TypeInterface
5858
{
59-
return $this->inferredTypes->types[$name] ?? $this->parentScope->lookupTypeFor($name);
59+
return $this->inferredTypes->getType($name) ?? $this->parentScope->lookupTypeFor($name);
6060
}
6161

6262
public function resolveTypeReference(TypeReferenceNode $typeReferenceNode): TypeInterface

0 commit comments

Comments
 (0)