Skip to content

Commit e819450

Browse files
committed
Optimize literal values
1 parent 769a8c2 commit e819450

20 files changed

Lines changed: 109 additions & 153 deletions

libs/parser/src/Node/Identifier.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
namespace TypeLang\Parser\Node;
66

7-
final class Identifier extends Node implements \Stringable
7+
/**
8+
* @phpstan-consistent-constructor
9+
*/
10+
class Identifier extends Node implements \Stringable
811
{
912
/**
1013
* @var list<non-empty-string>
1114
*/
12-
private const array SPECIAL_CLASS_NAME = [
15+
protected const array SPECIAL_CLASS_NAME = [
1316
'self',
1417
'parent',
1518
'static',
@@ -18,7 +21,7 @@ final class Identifier extends Node implements \Stringable
1821
/**
1922
* @var list<non-empty-string>
2023
*/
21-
private const array BUILTIN_TYPE_NAME = [
24+
protected const array BUILTIN_TYPE_NAME = [
2225
'mixed',
2326
'string',
2427
'int',
@@ -52,14 +55,14 @@ final class Identifier extends Node implements \Stringable
5255
* Returns {@see true} in case of name contains special class reference.
5356
*/
5457
public bool $isSpecial {
55-
get => self::isLooksLikeSpecial($this->value);
58+
get => static::isLooksLikeSpecial($this->value);
5659
}
5760

5861
/**
5962
* Returns {@see true} in case of name contains builtin type name.
6063
*/
6164
public bool $isBuiltin {
62-
get => self::isLooksLikeBuiltin($this->value);
65+
get => static::isLooksLikeBuiltin($this->value);
6366
}
6467

6568
public function __construct(
@@ -77,7 +80,7 @@ public static function createFromString(string|\Stringable $value): self
7780
throw new \InvalidArgumentException('Name identifier cannot be empty');
7881
}
7982

80-
return new self($normalized);
83+
return new static($normalized);
8184
}
8285

8386
/**
@@ -86,7 +89,7 @@ public static function createFromString(string|\Stringable $value): self
8689
*/
8790
public static function isLooksLikeSpecial(string $name): bool
8891
{
89-
return \in_array(\strtolower($name), self::SPECIAL_CLASS_NAME, true);
92+
return \in_array(\strtolower($name), static::SPECIAL_CLASS_NAME, true);
9093
}
9194

9295
/**
@@ -95,7 +98,7 @@ public static function isLooksLikeSpecial(string $name): bool
9598
*/
9699
public static function isLooksLikeBuiltin(string $value): bool
97100
{
98-
return \in_array(\strtolower($value), self::BUILTIN_TYPE_NAME, true);
101+
return \in_array(\strtolower($value), static::BUILTIN_TYPE_NAME, true);
99102
}
100103

101104
/**

libs/parser/src/Node/Literal/BoolLiteralNode.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,14 @@
1212
class BoolLiteralNode extends LiteralNode implements ParsableLiteralNodeInterface
1313
{
1414
public function __construct(
15-
public readonly bool $value,
15+
bool $value,
1616
?string $raw = null,
1717
) {
18-
parent::__construct($raw ?? ($value ? 'true' : 'false'));
18+
parent::__construct($value, $raw ?? ($value ? 'true' : 'false'));
1919
}
2020

2121
public static function parse(string $value): static
2222
{
2323
return new static(\strtolower($value) === 'true', $value);
2424
}
25-
26-
public function getValue(): bool
27-
{
28-
return $this->value;
29-
}
3025
}

libs/parser/src/Node/Literal/FloatLiteralNode.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
class FloatLiteralNode extends LiteralNode implements ParsableLiteralNodeInterface
1313
{
1414
public function __construct(
15-
public readonly float $value,
15+
float $value,
1616
?string $raw = null,
1717
) {
18-
parent::__construct($raw ?? (string) $this->value);
18+
parent::__construct($value, $raw ?? (string) $this->value);
1919
}
2020

2121
public static function parse(string $value): static
@@ -26,9 +26,4 @@ public static function parse(string $value): static
2626

2727
return new static((float) $value, $value);
2828
}
29-
30-
public function getValue(): float
31-
{
32-
return $this->value;
33-
}
3429
}

libs/parser/src/Node/Literal/IntLiteralNode.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ class IntLiteralNode extends LiteralNode implements ParsableLiteralNodeInterface
2020
* @param numeric-string|null $decimal
2121
*/
2222
public function __construct(
23-
public readonly int $value,
23+
int $value,
2424
?string $raw = null,
2525
?string $decimal = null,
2626
) {
2727
$this->decimal = $decimal ?? (string) $this->value;
2828

29-
parent::__construct($raw ?? (string) $this->value);
29+
parent::__construct($value, $raw ?? (string) $this->value);
3030
}
3131

3232
public static function parse(string $value): static
@@ -76,17 +76,4 @@ private static function split(string $literal): array
7676
/** @var array{bool, numeric-string} */
7777
return [$negative, $literal];
7878
}
79-
80-
/**
81-
* @return numeric-string
82-
*/
83-
public function getValueAsDecimalString(): string
84-
{
85-
return $this->decimal;
86-
}
87-
88-
public function getValue(): int
89-
{
90-
return $this->value;
91-
}
9279
}

libs/parser/src/Node/Literal/LiteralNode.php

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,13 @@
1313
abstract class LiteralNode extends TypeStatement implements LiteralNodeInterface
1414
{
1515
public function __construct(
16+
/**
17+
* @var TValue
18+
*/
19+
public readonly mixed $value,
1620
public readonly string $raw,
1721
) {}
1822

19-
/**
20-
* Returns parsed literal value.
21-
*/
22-
abstract public function getValue(): mixed;
23-
24-
/**
25-
* Returns raw literal value string representation.
26-
*/
27-
public function getRawValue(): string
28-
{
29-
return $this->raw;
30-
}
31-
3223
public function __toString(): string
3324
{
3425
return $this->raw;

libs/parser/src/Node/Literal/LiteralNodeInterface.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,28 @@
55
namespace TypeLang\Parser\Node\Literal;
66

77
/**
8-
* @template TValue of mixed = mixed
8+
* @template-covariant TValue of mixed = mixed
99
*/
1010
interface LiteralNodeInterface extends \Stringable
1111
{
1212
/**
13-
* Returns a PHP representation of the literal value.
13+
* Gets a PHP representation of the literal value.
1414
*
15-
* @return TValue
15+
* @var TValue
1616
*/
17-
public function getValue(): mixed;
17+
public mixed $value {
18+
get;
19+
}
1820

1921
/**
20-
* Returns the original literal value specified in the token.
22+
* Gets the original literal value specified in the token.
2123
*/
22-
public function getRawValue(): string;
24+
public string $raw {
25+
get;
26+
}
2327

2428
/**
25-
* Returns the processed ({@see getValue()}) literal value as a string.
29+
* Returns the processed ({@see $value}) literal value as a string.
2630
*/
2731
public function __toString(): string;
2832
}

libs/parser/src/Node/Literal/NullLiteralNode.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ class NullLiteralNode extends LiteralNode
1111
{
1212
public function __construct(?string $raw = null)
1313
{
14-
parent::__construct($raw ?? 'null');
15-
}
16-
17-
/**
18-
* @return null Note: Standalone `null` literal available since php 8.2.
19-
*/
20-
public function getValue(): mixed
21-
{
22-
return null;
14+
parent::__construct(null, $raw ?? 'null');
2315
}
2416
}

libs/parser/src/Node/Literal/ParsableLiteralNodeInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ interface ParsableLiteralNodeInterface
88
{
99
/**
1010
* Parse raw literal string value.
11+
*
12+
* @throws \InvalidArgumentException in case of value parsing error occurs
1113
*/
1214
public static function parse(string $value): self;
1315
}

libs/parser/src/Node/Literal/StringLiteralNode.php

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ class StringLiteralNode extends LiteralNode implements ParsableLiteralNodeInterf
1414
/**
1515
* @var non-empty-string
1616
*/
17-
private const UTF_SEQUENCE_PATTERN = '/(?<!\\\\)\\\\u\{([0-9a-fA-F]+)}/u';
17+
private const string UTF_SEQUENCE_PATTERN = '/(?<!\\\\)\\\\u\{([0-9a-fA-F]+)}/u';
1818

1919
/**
2020
* @var non-empty-string
2121
*/
22-
private const HEX_SEQUENCE_PATTERN = '/(?<!\\\\)\\\\x([0-9a-fA-F]{1,2})/iu';
22+
private const string HEX_SEQUENCE_PATTERN = '/(?<!\\\\)\\\\x([0-9a-fA-F]{1,2})/iu';
2323

2424
/**
2525
* @var non-empty-array<non-empty-string, non-empty-string>
2626
*/
27-
private const ESCAPED_CHARS = [
27+
private const array ESCAPED_CHARS = [
2828
'\n' => "\n",
2929
'\r' => "\r",
3030
'\t' => "\t",
@@ -35,23 +35,19 @@ class StringLiteralNode extends LiteralNode implements ParsableLiteralNodeInterf
3535
];
3636

3737
final public function __construct(
38-
public readonly string $value,
38+
string $value,
3939
?string $raw = null,
4040
) {
41-
parent::__construct($raw ?? $this->value);
42-
}
41+
$raw ??= \sprintf('"%s"', \addcslashes($value, '"'));
4342

44-
public static function createFromValue(string $value): static
45-
{
46-
return new static(
47-
value: $value,
48-
raw: \sprintf('"%s"', \addcslashes($value, '"')),
49-
);
43+
parent::__construct($value, $raw);
5044
}
5145

5246
public static function parse(string $value): static
5347
{
54-
assert(\strlen($value) >= 2, new \InvalidArgumentException('Could not parse non-quoted string'));
48+
if (\strlen($value) < 2) {
49+
throw new \InvalidArgumentException('Could not parse non-quoted string');
50+
}
5551

5652
if ($value[0] === '"') {
5753
return static::createFromDoubleQuotedString($value);
@@ -65,7 +61,9 @@ public static function parse(string $value): static
6561
*/
6662
public static function createFromDoubleQuotedString(string $value): static
6763
{
68-
assert(\strlen($value) >= 2, new \InvalidArgumentException('Could not parse non-quoted string'));
64+
if (\strlen($value) < 2) {
65+
throw new \InvalidArgumentException('Could not parse non-quoted string');
66+
}
6967

7068
$body = \substr($value, 1, -1);
7169

@@ -80,7 +78,9 @@ public static function createFromDoubleQuotedString(string $value): static
8078
*/
8179
public static function createFromSingleQuotedString(string $value): static
8280
{
83-
assert(\strlen($value) >= 2, new \InvalidArgumentException('Could not parse non-quoted string'));
81+
if (\strlen($value) < 2) {
82+
throw new \InvalidArgumentException('Could not parse non-quoted string');
83+
}
8484

8585
$body = \substr($value, 1, -1);
8686

@@ -163,24 +163,19 @@ private static function renderUtfSequences(string $body): string
163163

164164
if (0x800 > $code) {
165165
return \chr(0xC0 | $code >> 6)
166-
. \chr(0x80 | $code & 0x3F);
166+
. \chr(0x80 | $code & 0x3F);
167167
}
168168

169169
if (0x10000 > $code) {
170170
return \chr(0xE0 | $code >> 12)
171-
. \chr(0x80 | $code >> 6 & 0x3F)
172-
. \chr(0x80 | $code & 0x3F);
171+
. \chr(0x80 | $code >> 6 & 0x3F)
172+
. \chr(0x80 | $code & 0x3F);
173173
}
174174

175175
return \chr(0xF0 | $code >> 18)
176-
. \chr(0x80 | $code >> 12 & 0x3F)
177-
. \chr(0x80 | $code >> 6 & 0x3F)
178-
. \chr(0x80 | $code & 0x3F);
176+
. \chr(0x80 | $code >> 12 & 0x3F)
177+
. \chr(0x80 | $code >> 6 & 0x3F)
178+
. \chr(0x80 | $code & 0x3F);
179179
}, $body) ?? $body;
180180
}
181-
182-
public function getValue(): string
183-
{
184-
return $this->value;
185-
}
186181
}

libs/parser/src/Node/Literal/VariableLiteralNode.php

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,23 @@
1111
*/
1212
class VariableLiteralNode extends LiteralNode implements ParsableLiteralNodeInterface
1313
{
14-
/**
15-
* @var non-empty-string
16-
*/
17-
private readonly string $value;
18-
1914
/**
2015
* @param non-empty-string $value
2116
*/
2217
public function __construct(string $value)
2318
{
24-
assert(\strlen($value) > 1, new \InvalidArgumentException(
25-
'Variable name length must be greater than 1',
26-
));
19+
if (\strlen($value) < 2) {
20+
throw new \InvalidArgumentException('Variable name length must be greater than 1');
21+
}
2722

28-
assert(\str_starts_with($value, '$'), new \InvalidArgumentException(
29-
'Variable name must start with "$" character',
30-
));
23+
if (!\str_starts_with($value, '$')) {
24+
throw new \InvalidArgumentException('Variable name must start with "$" character');
25+
}
3126

32-
// @phpstan-ignore-next-line : Variable name gte than 2
33-
$this->value = \substr($value, 1);
27+
/** @var non-empty-string $normalized */
28+
$normalized = \substr($value, 1);
3429

35-
parent::__construct($value);
30+
parent::__construct($normalized, $value);
3631
}
3732

3833
public static function parse(string $value): static
@@ -43,10 +38,4 @@ public static function parse(string $value): static
4338

4439
return new static($value);
4540
}
46-
47-
public function getValue(): string
48-
{
49-
/** @var non-empty-string */
50-
return $this->value;
51-
}
5241
}

0 commit comments

Comments
 (0)