|
|
|
@ -22,6 +22,9 @@ trait SelectionExpressionTrait |
|
|
|
$this->assertExprCanBeUsedAsCondition($expr->cond, 'ternary condition'); |
|
|
|
$this->assertExprCanBeUsedAsCondition($expr->cond, 'ternary condition'); |
|
|
|
$this->assertExprCanBeUsedAsValue($expr->if, 'ternary branch'); |
|
|
|
$this->assertExprCanBeUsedAsValue($expr->if, 'ternary branch'); |
|
|
|
$this->assertExprCanBeUsedAsValue($expr->else, 'ternary branch'); |
|
|
|
$this->assertExprCanBeUsedAsValue($expr->else, 'ternary branch'); |
|
|
|
|
|
|
|
$ifType = $this->detectTypeOfExpr($expr->if); |
|
|
|
|
|
|
|
$elseType = $this->detectTypeOfExpr($expr->else); |
|
|
|
|
|
|
|
$typeChanged = $ifType !== $elseType; |
|
|
|
[$cond, $condBeforeStmts, $condAfterStmts] = $this->parseExprWithCapturedStmts($expr->cond); |
|
|
|
[$cond, $condBeforeStmts, $condAfterStmts] = $this->parseExprWithCapturedStmts($expr->cond); |
|
|
|
$ifBeforeStmtCount = count($this->context->beforeStmtLines); |
|
|
|
$ifBeforeStmtCount = count($this->context->beforeStmtLines); |
|
|
|
$ifAfterStmtCount = count($this->context->afterStmtLines); |
|
|
|
$ifAfterStmtCount = count($this->context->afterStmtLines); |
|
|
|
@ -40,16 +43,14 @@ trait SelectionExpressionTrait |
|
|
|
$this->context->afterStmtLines = array_slice($this->context->afterStmtLines, 0, $elseAfterStmtCount); |
|
|
|
$this->context->afterStmtLines = array_slice($this->context->afterStmtLines, 0, $elseAfterStmtCount); |
|
|
|
|
|
|
|
|
|
|
|
$hasBranchStmts = $condBeforeStmts || $condAfterStmts || $ifBeforeStmts || $ifAfterStmts || $elseBeforeStmts || $elseAfterStmts; |
|
|
|
$hasBranchStmts = $condBeforeStmts || $condAfterStmts || $ifBeforeStmts || $ifAfterStmts || $elseBeforeStmts || $elseAfterStmts; |
|
|
|
$typeChanged = $this->detectTypeOfExpr($expr->if) !== $this->detectTypeOfExpr($expr->else); |
|
|
|
|
|
|
|
if (!$hasBranchStmts && $typeChanged) { |
|
|
|
if (!$hasBranchStmts && $typeChanged) { |
|
|
|
$if = 'php::Var(' . $if . ')'; |
|
|
|
$if = 'php::Var(' . $if . ')'; |
|
|
|
$else = 'php::Var(' . $else . ')'; |
|
|
|
$else = 'php::Var(' . $else . ')'; |
|
|
|
} |
|
|
|
} |
|
|
|
if ($hasBranchStmts) { |
|
|
|
if ($hasBranchStmts) { |
|
|
|
// The materialized temporary (see getOrderedOperandTmpType) is |
|
|
|
// REF and VOID are expression implementation types, not valid |
|
|
|
// declared with the ternary's static type, so the lambda return |
|
|
|
// by-value result types for the materializing lambda. |
|
|
|
// type must match it instead of always being php::Var. |
|
|
|
$ternaryType = $this->getNormalAssignType($typeChanged ? Type::VAR : $ifType); |
|
|
|
$ternaryType = $this->detectTypeOfExpr($expr); |
|
|
|
|
|
|
|
$code = '[&]() -> ' . $ternaryType . '{'; |
|
|
|
$code = '[&]() -> ' . $ternaryType . '{'; |
|
|
|
$code .= $this->formatCapturedStmtLines($condBeforeStmts); |
|
|
|
$code .= $this->formatCapturedStmtLines($condBeforeStmts); |
|
|
|
if ($condAfterStmts) { |
|
|
|
if ($condAfterStmts) { |
|
|
|
@ -60,9 +61,9 @@ trait SelectionExpressionTrait |
|
|
|
} |
|
|
|
} |
|
|
|
$cond = $this->convertConditionExpr($expr->cond, $cond); |
|
|
|
$cond = $this->convertConditionExpr($expr->cond, $cond); |
|
|
|
$code .= $this->getIndent() . 'if (' . $cond . ') {'; |
|
|
|
$code .= $this->getIndent() . 'if (' . $cond . ') {'; |
|
|
|
$code .= $this->formatTernaryReturn($if, $ifBeforeStmts, $ifAfterStmts, $ternaryType); |
|
|
|
$code .= $this->formatTernaryReturn($expr->if, $if, $ifBeforeStmts, $ifAfterStmts, $ternaryType, $ifType); |
|
|
|
$code .= $this->getIndent() . '} else {'; |
|
|
|
$code .= $this->getIndent() . '} else {'; |
|
|
|
$code .= $this->formatTernaryReturn($else, $elseBeforeStmts, $elseAfterStmts, $ternaryType); |
|
|
|
$code .= $this->formatTernaryReturn($expr->else, $else, $elseBeforeStmts, $elseAfterStmts, $ternaryType, $elseType); |
|
|
|
$code .= $this->getIndent() . '}'; |
|
|
|
$code .= $this->getIndent() . '}'; |
|
|
|
$code .= $this->getIndent() . '}()'; |
|
|
|
$code .= $this->getIndent() . '}()'; |
|
|
|
return $code; |
|
|
|
return $code; |
|
|
|
@ -71,10 +72,22 @@ trait SelectionExpressionTrait |
|
|
|
return '(' . $cond . ') ? (' . $if . ') : (' . $else . ')'; |
|
|
|
return '(' . $cond . ') ? (' . $if . ') : (' . $else . ')'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected function formatTernaryReturn(string $value, array $beforeStmts, array $afterStmts, string $returnType): string |
|
|
|
protected function formatTernaryReturn( |
|
|
|
|
|
|
|
NodeAbstract $valueExpr, |
|
|
|
|
|
|
|
string $value, |
|
|
|
|
|
|
|
array $beforeStmts, |
|
|
|
|
|
|
|
array $afterStmts, |
|
|
|
|
|
|
|
string $returnType, |
|
|
|
|
|
|
|
string $valueType, |
|
|
|
|
|
|
|
): string |
|
|
|
{ |
|
|
|
{ |
|
|
|
$code = $this->formatCapturedStmtLines($beforeStmts); |
|
|
|
$code = $this->formatCapturedStmtLines($beforeStmts); |
|
|
|
if ($afterStmts) { |
|
|
|
$returnsReference = $valueType === Type::REF |
|
|
|
|
|
|
|
|| ($valueExpr instanceof Expr\CallLike && $this->resolveRefReturningCall($valueExpr) !== false); |
|
|
|
|
|
|
|
if ($returnType !== Type::VAR && ($beforeStmts || $afterStmts)) { |
|
|
|
|
|
|
|
$value = $this->convertExprFromType($returnType, $value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ($afterStmts || $returnsReference) { |
|
|
|
$tmpVar = $this->addTmpVar($returnType); |
|
|
|
$tmpVar = $this->addTmpVar($returnType); |
|
|
|
$code .= $this->getIndent() . "{$tmpVar} = {$value};"; |
|
|
|
$code .= $this->getIndent() . "{$tmpVar} = {$value};"; |
|
|
|
$code .= $this->formatCapturedStmtLines($afterStmts); |
|
|
|
$code .= $this->formatCapturedStmtLines($afterStmts); |
|
|
|
|