Skip to content

Commit

Permalink
NodeScopeResolver - refactoring before optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 26, 2024
1 parent a07996a commit 1a0099d
Showing 1 changed file with 43 additions and 61 deletions.
104 changes: 43 additions & 61 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5055,7 +5055,7 @@ private function processAssignVar(
$valueToWrite = $scope->getType($assignedExpr);
$nativeValueToWrite = $scope->getNativeType($assignedExpr);
$originalValueToWrite = $valueToWrite;
$originalNativeValueToWrite = $valueToWrite;
$originalNativeValueToWrite = $nativeValueToWrite;

// 3. eval assigned expr
$result = $processExprCallback($scope);
Expand All @@ -5076,67 +5076,9 @@ private function processAssignVar(
}
$offsetValueType = $varType;
$offsetNativeValueType = $varNativeType;
$offsetValueTypeStack = [$offsetValueType];
$offsetValueNativeTypeStack = [$offsetNativeValueType];
foreach (array_slice($offsetTypes, 0, -1) as $offsetType) {
if ($offsetType === null) {
$offsetValueType = new ConstantArrayType([], []);

} else {
$offsetValueType = $offsetValueType->getOffsetValueType($offsetType);
if ($offsetValueType instanceof ErrorType) {
$offsetValueType = new ConstantArrayType([], []);
}
}

$offsetValueTypeStack[] = $offsetValueType;
}
foreach (array_slice($offsetNativeTypes, 0, -1) as $offsetNativeType) {
if ($offsetNativeType === null) {
$offsetNativeValueType = new ConstantArrayType([], []);

} else {
$offsetNativeValueType = $offsetNativeValueType->getOffsetValueType($offsetNativeType);
if ($offsetNativeValueType instanceof ErrorType) {
$offsetNativeValueType = new ConstantArrayType([], []);
}
}

$offsetValueNativeTypeStack[] = $offsetNativeValueType;
}

foreach (array_reverse($offsetTypes) as $i => $offsetType) {
/** @var Type $offsetValueType */
$offsetValueType = array_pop($offsetValueTypeStack);
if (!$offsetValueType instanceof MixedType) {
$types = [
new ArrayType(new MixedType(), new MixedType()),
new ObjectType(ArrayAccess::class),
new NullType(),
];
if ($offsetType !== null && $offsetType->isInteger()->yes()) {
$types[] = new StringType();
}
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
}
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
}
foreach (array_reverse($offsetNativeTypes) as $i => $offsetNativeType) {
/** @var Type $offsetNativeValueType */
$offsetNativeValueType = array_pop($offsetValueNativeTypeStack);
if (!$offsetNativeValueType instanceof MixedType) {
$types = [
new ArrayType(new MixedType(), new MixedType()),
new ObjectType(ArrayAccess::class),
new NullType(),
];
if ($offsetNativeType !== null && $offsetNativeType->isInteger()->yes()) {
$types[] = new StringType();
}
$offsetNativeValueType = TypeCombinator::intersect($offsetNativeValueType, TypeCombinator::union(...$types));
}
$nativeValueToWrite = $offsetNativeValueType->setOffsetValueType($offsetNativeType, $nativeValueToWrite, $i === 0);
}
$valueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetTypes, $offsetValueType, $valueToWrite);
$nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite);

if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) {
if ($var instanceof Variable && is_string($var->name)) {
Expand Down Expand Up @@ -5409,6 +5351,46 @@ static function (): void {
return new ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints);
}

/**
* @param list<Type|null> $offsetTypes
*/
private function produceArrayDimFetchAssignValueToWrite(array $offsetTypes, Type $offsetValueType, Type $valueToWrite): Type
{
$offsetValueTypeStack = [$offsetValueType];
foreach (array_slice($offsetTypes, 0, -1) as $offsetType) {
if ($offsetType === null) {
$offsetValueType = new ConstantArrayType([], []);

} else {
$offsetValueType = $offsetValueType->getOffsetValueType($offsetType);
if ($offsetValueType instanceof ErrorType) {
$offsetValueType = new ConstantArrayType([], []);
}
}

$offsetValueTypeStack[] = $offsetValueType;
}

foreach (array_reverse($offsetTypes) as $i => $offsetType) {
/** @var Type $offsetValueType */
$offsetValueType = array_pop($offsetValueTypeStack);
if (!$offsetValueType instanceof MixedType) {
$types = [
new ArrayType(new MixedType(), new MixedType()),
new ObjectType(ArrayAccess::class),
new NullType(),
];
if ($offsetType !== null && $offsetType->isInteger()->yes()) {
$types[] = new StringType();
}
$offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types));
}
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
}

return $valueToWrite;
}

private function unwrapAssign(Expr $expr): Expr
{
if ($expr instanceof Assign) {
Expand Down

0 comments on commit 1a0099d

Please sign in to comment.