Skip to content

Commit

Permalink
Rewrite mapper to use match instead of constant fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
olsavmic committed Sep 6, 2024
1 parent ed75eea commit fa11c89
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 296 deletions.
21 changes: 14 additions & 7 deletions src/Compiler/Mapper/Object/MapDiscriminatedObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,17 @@ public function __construct(

public function compile(Expr $value, Expr $path, PhpCodeBuilder $builder): CompiledExpr
{
$objectMapperMethods = [];
$objectMapperMethodCalls = [];

foreach ($this->objectMappers as $key => $objectMapper) {
$objectMapperMethodName = $builder->uniqMethodName('map' . ucfirst($key));
$objectMapperMethod = $builder->mapperMethod($objectMapperMethodName, $objectMapper)->makePrivate()->getNode();
$objectMapperMethods[$key] = $objectMapperMethodName;
$objectMapperMethodCall = $builder->methodCall($builder->var('this'), $objectMapperMethodName, [$value, $path]);
$objectMapperMethodCalls[$key] = $objectMapperMethodCall;

$builder->addMethod($objectMapperMethod);
}

$validMappingKeysConstName = $builder->uniqConstantName('VALID_MAPPINGS', $objectMapperMethods);
$builder->addConstant($validMappingKeysConstName, $objectMapperMethods);

$statements = [
$builder->if($builder->not($builder->funcCall($builder->importFunction('is_array'), [$value])), [
$builder->throw(
Expand Down Expand Up @@ -108,10 +106,19 @@ public function compile(Expr $value, Expr $path, PhpCodeBuilder $builder): Compi
),
]);

$selectedMapperMethodName = $builder->arrayDimFetch($builder->classConstFetch('self', $validMappingKeysConstName), $discriminatorMapperCall);
$subtypeMatchArms = [];

foreach ($objectMapperMethodCalls as $key => $objectMapperMethodCall) {
$subtypeMatchArms[] = $builder->matchArm(
$builder->val($key),
$objectMapperMethodCall,
);
}

$matchedSubtype = $builder->match($discriminatorMapperCall, $subtypeMatchArms);

return new CompiledExpr(
$builder->methodCall($builder->var('this'), $selectedMapperMethodName, [$value, $path]),
$matchedSubtype,
$statements,
);
}
Expand Down
23 changes: 23 additions & 0 deletions src/Compiler/Php/PhpCodeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
use PhpParser\Node\Expr\BinaryOp\SmallerOrEqual;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Instanceof_;
use PhpParser\Node\Expr\Match_;
use PhpParser\Node\Expr\PreInc;
use PhpParser\Node\Expr\Ternary;
use PhpParser\Node\MatchArm;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_ as ClassNode;
Expand Down Expand Up @@ -216,6 +218,22 @@ public function if(Expr $if, array $then, ?array $else = null): If_
return new If_($if, ['stmts' => $then, 'elseifs' => $elseIfClauses, 'else' => $elseClause]);
}

/**
* @param list<MatchArm> $arms
*/
public function match(Expr $cond, array $arms = []): Match_
{
return new Match_($cond, $arms);
}

public function matchArm(?Expr $cond, Expr $body): MatchArm
{
return new MatchArm(
$cond !== null ? [$cond] : null,
$body,
);
}

/**
* @param list<Stmt> $statements
*/
Expand Down Expand Up @@ -260,6 +278,11 @@ public function throw(Expr $expr): Throw_
return new Throw_($expr);
}

public function throwExpr(Expr $expr): Expr\Throw_
{
return new Expr\Throw_($expr);
}

public function assign(Expr $var, Expr $expr): Expression
{
return new Expression(new Assign($var, $expr));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
*/
class HierarchicalParentInputMapper implements Mapper
{
private const VALID_MAPPINGS = ['childOne' => 'mapChildOne', 'childTwo' => 'mapChildTwo'];

public function __construct(private readonly MapperProvider $provider)
{
}
Expand All @@ -49,7 +47,10 @@ public function map(mixed $data, array $path = []): HierarchicalParentInput
throw MappingFailedException::incorrectValue($data['type'], [...$path, 'type'], 'one of ' . implode(', ', ['childOne', 'childTwo']));
}

return $this->{self::VALID_MAPPINGS[$this->mapType3($data['type'], [...$path, 'type'])]}($data, $path);
return match ($this->mapType3($data['type'], [...$path, 'type'])) {
'childOne' => $this->mapChildOne($data, $path),
'childTwo' => $this->mapChildTwo($data, $path),
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
*/
class HierarchicalWithEnumParentInputMapper implements Mapper
{
private const VALID_MAPPINGS = ['childOne' => 'mapChildOne'];

public function __construct(private readonly MapperProvider $provider)
{
}
Expand All @@ -48,7 +46,9 @@ public function map(mixed $data, array $path = []): HierarchicalWithEnumParentIn
throw MappingFailedException::incorrectValue($data['type'], [...$path, 'type'], 'one of ' . implode(', ', ['childOne']));
}

return $this->{self::VALID_MAPPINGS[$this->mapType2($data['type'], [...$path, 'type'])]}($data, $path);
return match ($this->mapType2($data['type'], [...$path, 'type'])) {
'childOne' => $this->mapChildOne($data, $path),
};
}

/**
Expand Down
Loading

0 comments on commit fa11c89

Please sign in to comment.