Skip to content

Commit b195a1e

Browse files
committed
[js] Implement while ... -> $cond {...}
1 parent f914dc4 commit b195a1e

File tree

1 file changed

+28
-13
lines changed

1 file changed

+28
-13
lines changed

src/vm/js/Operations.nqp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,10 @@ class QAST::OperationsJS {
10271027
"\}\n"], :node($node));
10281028
});
10291029

1030+
my sub needs_cond_passed($n) {
1031+
nqp::istype($n, QAST::Block) && $n.arity > 0 &&
1032+
($n.blocktype eq 'immediate' || $n.blocktype eq 'immediate_static')
1033+
}
10301034

10311035
for <if unless with without> -> $op_name {
10321036
add_op($op_name, sub ($comp, $node, :$want, :$cps) {
@@ -1041,10 +1045,6 @@ class QAST::OperationsJS {
10411045
nqp::die("Operation '"~$node.op~"' needs either 2 or 3 operands")
10421046
if $operands < 2 || $operands > 3;
10431047

1044-
my sub needs_cond_passed($n) {
1045-
nqp::istype($n, QAST::Block) && $n.arity > 0 &&
1046-
($n.blocktype eq 'immediate' || $n.blocktype eq 'immediate_static')
1047-
}
10481048

10491049

10501050
my int $cond_type := (needs_cond_passed($node[1]) || needs_cond_passed($node[2]) || $is_withy)
@@ -1101,9 +1101,10 @@ class QAST::OperationsJS {
11011101
}
11021102

11031103

1104-
# TODO ->
11051104

11061105
if nqp::istype($cond, ChunkCPS) || nqp::istype($then, ChunkCPS) || nqp::istype($else, ChunkCPS) {
1106+
# TODO ->
1107+
11071108
if needs_cond_passed($then) || needs_cond_passed($else) {
11081109
return $comp.NYI("if ... -> \{...\} in CPS mode");
11091110
}
@@ -1288,18 +1289,32 @@ class QAST::OperationsJS {
12881289
}
12891290

12901291
return $comp.NYI("3 argument $op") if +@operands == 3 && $op ne 'while';
1291-
# TODO while ... -> $cond {}
12921292

12931293
my $loop := LoopInfo.new($*LOOP, :$label);
12941294

1295-
my $cond;
1295+
1296+
my int $cond_type := needs_cond_passed($node[1]) ?? $T_OBJ !! $T_BOOL;
1297+
1298+
1299+
my $check_cond;
12961300
my $body;
12971301
{
12981302
my $*LOOP := $loop;
1299-
$cond := $comp.as_js(@operands[0], :want($T_BOOL));
1300-
$body := $comp.as_js(@operands[1], :want($T_VOID));
1303+
my $cond := $comp.as_js(@operands[0], :want($T_BOOL));
1304+
$check_cond := $comp.coerce($cond, $T_BOOL);
1305+
my $cond_without_sideeffects := Chunk.new($cond.type, $cond.expr);
1306+
1307+
if needs_cond_passed(@operands[1]) {
1308+
my $block := try $*BLOCK;
1309+
my $loop := try $*LOOP;
1310+
$body := $comp.compile_block(@operands[1], $block, $loop, :want($T_VOID), :extra_args([$cond_without_sideeffects]));
1311+
}
1312+
else {
1313+
$body := $comp.as_js(@operands[1], :want($T_VOID), :$cps);
1314+
}
13011315
}
13021316

1317+
13031318
my $post := '';
13041319

13051320
if +@operands == 3 {
@@ -1318,8 +1333,8 @@ class QAST::OperationsJS {
13181333
~ "{$loop.redo} = false;\n"
13191334
~ "\} else \{\n"
13201335
!! ''),
1321-
$cond,
1322-
"if ($neg {$cond.expr}) \{break;\}\n",
1336+
$check_cond,
1337+
"if ($neg {$check_cond.expr}) \{break;\}\n",
13231338
($loop.has_redo ?? "\}\n" !! ''),
13241339
$handled,
13251340
"\}"
@@ -1331,8 +1346,8 @@ class QAST::OperationsJS {
13311346
Chunk.void(
13321347
"do \{\n",
13331348
$body,
1334-
$cond,
1335-
"\} while ($neg {$cond.expr});"
1349+
$check_cond,
1350+
"\} while ($neg {$check_cond.expr});"
13361351
);
13371352
}
13381353
});

0 commit comments

Comments
 (0)