Finish listReference
This commit is contained in:
parent
2cb2f73898
commit
37e0cfac27
@ -17,7 +17,6 @@ use PhpParser\Node\Expr\Cast\Bool_;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\Ternary;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
@ -181,13 +180,13 @@ class Context
|
||||
$parent->setAttribute('currentNodeIndex', $nodeKeyIndex - 1);
|
||||
return; // Done, inserted!
|
||||
}
|
||||
|
||||
|
||||
// Cannot insert, parent is not a statement
|
||||
$node = &$parent->{$nodeKey};
|
||||
// If we insert before a conditional branch of a conditional expression,
|
||||
// make sure the conditional branch has no side effects;
|
||||
// make sure the conditional branch has no side effects;
|
||||
// if it does, turn the entire conditional expression into an if, and bubble it up
|
||||
//
|
||||
//
|
||||
// Unless we want to go crazy, do not consider side effect evaluation order for stuff like function call arguments, maths and so on.
|
||||
//
|
||||
if ($node instanceof BooleanOr && $nodeKey === 'right' && Tools::hasSideEffects($node->right)) {
|
||||
|
@ -6,6 +6,7 @@ use Phabel\Context;
|
||||
use Phabel\Plugin;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\AssignRef;
|
||||
use PhpParser\Node\Expr\List_;
|
||||
@ -26,13 +27,13 @@ class ListReference extends Plugin
|
||||
*/
|
||||
public function enterForeach(Foreach_ $node, Context $ctx): void
|
||||
{
|
||||
if (!($node->valueVar instanceof List_ || $node->valueVar instanceof Array_) || !$this->shouldSplit($node->valueVar)) {
|
||||
if (!($node->valueVar instanceof List_ || $node->valueVar instanceof Array_) || !$this->shouldSplit($node->valueVar, true)) {
|
||||
return;
|
||||
}
|
||||
$list = $node->valueVar;
|
||||
$var = $node->valueVar = $ctx->getVariable();
|
||||
$assignments = self::splitList($list, $var);
|
||||
$node->stmts
|
||||
$node->stmts = \array_merge($assignments, $node->stmts);
|
||||
}
|
||||
/**
|
||||
* Parse list assignment with custom keys.
|
||||
@ -46,8 +47,19 @@ class ListReference extends Plugin
|
||||
if (!($node->var instanceof List_ || $node->var instanceof Array_) || !$this->shouldSplit($node->var)) {
|
||||
return;
|
||||
}
|
||||
[$node->var, $array] = $this->splitList($node->var, $ctx);
|
||||
$node->expr = self::callPoly('destructure', $array, $node->expr);
|
||||
$isStmt = $ctx->parents[0]->getAttribute('currentNode') === 'stmts';
|
||||
$list = $node->var;
|
||||
$var = $ctx->getVariable();
|
||||
$assignments = self::splitList($list, $var);
|
||||
if ($isStmt) {
|
||||
$last = \array_pop($assignments);
|
||||
$ctx->insertBefore($node, new Assign($node->var, $node->expr), ...$assignments);
|
||||
return $last;
|
||||
}
|
||||
|
||||
// On newer versions of php, list assignment returns the original array
|
||||
$ctx->insertBefore($node, new Assign($var, $node->expr), ...$assignments);
|
||||
return $var;
|
||||
}
|
||||
/**
|
||||
* Split referenced list into multiple assignments.
|
||||
@ -66,9 +78,7 @@ class ListReference extends Plugin
|
||||
continue;
|
||||
}
|
||||
$curKey = $item->key ?? $key++;
|
||||
if ($item->value instanceof List_ || $item->value instanceof Array_) {
|
||||
// Do nothing, will re-split later if needed
|
||||
} else if ($item->byRef) {
|
||||
if ($item->byRef) {
|
||||
$assignments []= new AssignRef($item->value, new ArrayDimFetch($var, $curKey));
|
||||
} else {
|
||||
$assignments []= new Assign($item->value, new ArrayDimFetch($var, $curKey));
|
||||
@ -79,15 +89,21 @@ class ListReference extends Plugin
|
||||
/**
|
||||
* Whether this is a referenced list.
|
||||
*
|
||||
* @param List_|Array_ $list List
|
||||
* @param List_|Array_ $list List
|
||||
* @param bool $recurse Whether to recurse while checking
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function shouldSplit($list): bool
|
||||
private function shouldSplit($list, bool $recurse = false): bool
|
||||
{
|
||||
/** @var ArrayItem $item */
|
||||
foreach ($list->items ?? [] as $item) {
|
||||
if ($item->byRef) {
|
||||
return true;
|
||||
} elseif ($recurse && ($item->value instanceof List_ || $item->value instanceof Array_)) {
|
||||
if ($this->shouldSplit($item->value, $recurse)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user