diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index e6730160..0402f4bd 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -478,7 +478,7 @@ class CompilerBase extends \PhpAot\Core\Translator $result = $this->parseLabel($v); break; case 'Stmt_Continue': - $result = 'continue;'; + $result = $this->parseContinue($v); break; case 'Stmt_Nop': $result = '// pass'; @@ -2607,4 +2607,9 @@ class CompilerBase extends \PhpAot\Core\Translator } abort($expr); } + + private function parseContinue(mixed $v): string + { + return 'continue;'; + } } diff --git a/src/Php/Translator.php b/src/Php/Translator.php index b6b7df23..9a1ccbc8 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -827,8 +827,8 @@ class Translator extends Preprocessor $code .= 'if (' . $tmpVar . ') {'. PHP_EOL; $this->indentLevel++; - $code .= $this->getIndent() .$tmpVar . '.exec("rewind");' . PHP_EOL; - $code .= $this->getIndent() .'while (' . $tmpVar . '.exec("valid")) {' . PHP_EOL; + $code .= $this->getIndent() . $tmpVar . '.exec("rewind");' . PHP_EOL; + $code .= $this->getIndent() . 'for (;' . $tmpVar . '.exec("valid"); ' . $tmpVar . '.exec("next")) {' . PHP_EOL; $this->indentLevel++; $valueVar = $this->parseIdentifier($node->valueVar); $code .= $this->getIndent() . self::TYPE_VAR . ' ' . $valueVar . ' = ' . $tmpVar . '.exec("current");' . PHP_EOL; @@ -837,12 +837,11 @@ class Translator extends Preprocessor $code .= $this->getIndent() . self::TYPE_VAR . ' ' . $keyVar . ' = ' . $tmpVar . '.exec("key");' . PHP_EOL; } $code .= $this->parseStmts($node->stmts); - $code .= $this->getIndent() . $tmpVar . '.exec("next");' . PHP_EOL; - $code .= '}'. PHP_EOL; + $code .= '}' . PHP_EOL; $this->indentLevel--; $this->indentLevel--; - $code .= '}'. PHP_EOL; - return $code; + $code .= '}' . PHP_EOL; + return $code; } } \ No newline at end of file diff --git a/tests/core/classes/iterators_003.phpt b/tests/core/classes/iterators_003.phpt new file mode 100644 index 00000000..1be7dc3e --- /dev/null +++ b/tests/core/classes/iterators_003.phpt @@ -0,0 +1,115 @@ +--TEST-- +ZE2 iterators and break +--FILE-- +obj = $obj; + } + function rewind(): void { + echo __METHOD__ . "\n"; + } + function valid(): bool { + $more = $this->num < $this->obj->max; + echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n"; + return $more; + } + function current(): mixed { + echo __METHOD__ . "\n"; + return $this->num; + } + function next(): void { + echo __METHOD__ . "\n"; + $this->num++; + } + function key(): mixed { + return $this->num; + } +} + +class c implements IteratorAggregate { + + public $max = 4; + + function getIterator(): Traversable { + echo __METHOD__ . "\n"; + return new c_iter($this); + } +} + +function main() { + $t = new c(); + + foreach($t as $v) { + if ($v == 0) { + echo "continue outer\n"; + continue; + } + foreach($t as $w) { + if ($w == 1) { + echo "continue inner\n"; + continue; + } + if ($w == 2) { + echo "break inner\n"; + break; + } + echo "double:$v:$w\n"; + } + if ($v == 2) { + echo "break outer\n"; + break; + } + } + + print "Done\n"; +} +?> +--EXPECT-- +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +continue outer +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:1:0 +c_iter::next +c_iter::valid = true +c_iter::current +continue inner +c_iter::next +c_iter::valid = true +c_iter::current +break inner +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:2:0 +c_iter::next +c_iter::valid = true +c_iter::current +continue inner +c_iter::next +c_iter::valid = true +c_iter::current +break inner +break outer +Done