@@ -1027,6 +1027,10 @@ class QAST::OperationsJS {
1027
1027
" \}\n " ], : node($ node ));
1028
1028
});
1029
1029
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
+ }
1030
1034
1031
1035
for <if unless with without > -> $ op_name {
1032
1036
add_op($ op_name , sub ($ comp , $ node , : $ want , : $ cps ) {
@@ -1041,10 +1045,6 @@ class QAST::OperationsJS {
1041
1045
nqp ::die(" Operation '" ~ $ node . op~ " ' needs either 2 or 3 operands" )
1042
1046
if $ operands < 2 || $operands > 3 ;
1043
1047
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
- }
1048
1048
1049
1049
1050
1050
my int $ cond_type := (needs_cond_passed($ node [1 ]) || needs_cond_passed($ node [2 ]) || $ is_withy )
@@ -1101,9 +1101,10 @@ class QAST::OperationsJS {
1101
1101
}
1102
1102
1103
1103
1104
- # TODO ->
1105
1104
1106
1105
if nqp ::istype($ cond , ChunkCPS) || nqp ::istype($ then , ChunkCPS) || nqp ::istype($ else , ChunkCPS) {
1106
+ # TODO ->
1107
+
1107
1108
if needs_cond_passed($ then ) || needs_cond_passed($ else ) {
1108
1109
return $ comp . NYI(" if ... -> \{ ...\} in CPS mode" );
1109
1110
}
@@ -1288,18 +1289,32 @@ class QAST::OperationsJS {
1288
1289
}
1289
1290
1290
1291
return $ comp . NYI(" 3 argument $ op" ) if + @ operands == 3 && $ op ne ' while' ;
1291
- # TODO while ... -> $cond {}
1292
1292
1293
1293
my $ loop := LoopInfo. new ($ * LOOP , : $ label );
1294
1294
1295
- my $ cond ;
1295
+
1296
+ my int $ cond_type := needs_cond_passed($ node [1 ]) ?? $ T_OBJ !! $ T_BOOL ;
1297
+
1298
+
1299
+ my $ check_cond ;
1296
1300
my $ body ;
1297
1301
{
1298
1302
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
+ }
1301
1315
}
1302
1316
1317
+
1303
1318
my $ post := ' ' ;
1304
1319
1305
1320
if + @ operands == 3 {
@@ -1318,8 +1333,8 @@ class QAST::OperationsJS {
1318
1333
~ " { $ loop . redo} = false;\n "
1319
1334
~ " \} else \{\n "
1320
1335
!! ' ' ),
1321
- $ cond ,
1322
- " if ($ neg { $ cond . expr} ) \{ break;\}\n " ,
1336
+ $ check_cond ,
1337
+ " if ($ neg { $ check_cond . expr} ) \{ break;\}\n " ,
1323
1338
($ loop . has_redo ?? " \}\n " !! ' ' ),
1324
1339
$ handled ,
1325
1340
" \} "
@@ -1331,8 +1346,8 @@ class QAST::OperationsJS {
1331
1346
Chunk. void (
1332
1347
" do \{\n " ,
1333
1348
$ body ,
1334
- $ cond ,
1335
- " \} while ($ neg { $ cond . expr} );"
1349
+ $ check_cond ,
1350
+ " \} while ($ neg { $ check_cond . expr} );"
1336
1351
);
1337
1352
}
1338
1353
});
0 commit comments