Skip to content

Commit

Permalink
Merge pull request #131 from xp-framework/refactor/inline-nullable-ch…
Browse files Browse the repository at this point in the history
…ecks

Inline nullable checks when casting
  • Loading branch information
thekid authored Jan 29, 2022
2 parents 39f484c + 4cf5dcc commit 334817e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 9 deletions.
27 changes: 18 additions & 9 deletions src/main/php/lang/ast/emit/PHP.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
UnpackExpression,
Variable
};
use lang\ast\types\{IsUnion, IsFunction, IsArray, IsMap};
use lang\ast\types\{IsUnion, IsFunction, IsArray, IsMap, IsNullable};
use lang\ast\{Emitter, Node, Type};

abstract class PHP extends Emitter {
Expand Down Expand Up @@ -234,17 +234,26 @@ protected function emitVariable($result, $variable) {
protected function emitCast($result, $cast) {
static $native= ['string' => true, 'int' => true, 'float' => true, 'bool' => true, 'array' => true, 'object' => true];

$name= $cast->type->name();
if ('?' === $name[0]) {
$result->out->write('cast(');
$this->emitOne($result, $cast->expression);
$result->out->write(',\''.$name.'\', false)');
} else if (isset($native[$name])) {
$result->out->write('('.$cast->type->literal().')');
// Inline nullable checks using ternaries
if ($cast->type instanceof IsNullable) {
$t= $result->temp();
$result->out->write('null===('.$t.'=');
$this->emitOne($result, $cast->expression);
$result->out->write(')?null:');

$name= $cast->type->element->name();
$expression= new Variable(substr($t, 1));
} else {
$name= $cast->type->name();
$expression= $cast->expression;
}

if (isset($native[$name])) {
$result->out->write('('.$name.')');
$this->emitOne($result, $expression);
} else {
$result->out->write('cast(');
$this->emitOne($result, $cast->expression);
$this->emitOne($result, $expression);
$result->out->write(',\''.$name.'\')');
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/test/php/lang/ast/unittest/emit/CastingTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ public function run($value) {
));
}

#[Test, Values([null, 'test'])]
public function nullable_string_cast_of_expression_returning($value) {
Assert::equals($value, $this->run(
'class <T> {
public function run($value) {
$values= [$value];
return (?string)array_pop($values);
}
}',
$value
));
}

#[Test]
public function cast_braced() {
Assert::equals(['test'], $this->run(
Expand Down

0 comments on commit 334817e

Please sign in to comment.