@@ -105,8 +105,10 @@ typedef struct FuncScope {
105
105
#define FSCOPE_GOLA 0x04 /* Goto or label used in scope. */
106
106
#define FSCOPE_UPVAL 0x08 /* Upvalue in scope. */
107
107
#define FSCOPE_NOCLOSE 0x10 /* Do not close upvalues. */
108
+ #define FSCOPE_CONTINUE 0x20 /* Continue used in scope (FSCOPE_GOLA must also be set). */
108
109
109
110
#define NAME_BREAK ((GCstr *)(uintptr_t)1)
111
+ #define NAME_CONTINUE ((GCstr *)(uintptr_t)2)
110
112
111
113
/* Index into variable stack. */
112
114
typedef uint16_t VarIndex ;
@@ -1145,7 +1147,7 @@ static MSize gola_new(LexState *ls, GCstr *name, uint8_t info, BCPos pc)
1145
1147
lj_lex_error (ls , 0 , LJ_ERR_XLIMC , LJ_MAX_VSTACK );
1146
1148
lj_mem_growvec (ls -> L , ls -> vstack , ls -> sizevstack , LJ_MAX_VSTACK , VarInfo );
1147
1149
}
1148
- lua_assert (name == NAME_BREAK || lj_tab_getstr (fs -> kt , name ) != NULL );
1150
+ lua_assert (name == NAME_BREAK || name == NAME_CONTINUE || lj_tab_getstr (fs -> kt , name ) != NULL );
1149
1151
/* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */
1150
1152
setgcref (ls -> vstack [vtop ].name , obj2gco (name ));
1151
1153
ls -> vstack [vtop ].startpc = pc ;
@@ -1197,7 +1199,7 @@ static void gola_resolve(LexState *ls, FuncScope *bl, MSize idx)
1197
1199
GCstr * name = strref (var_get (ls , ls -> fs , vg -> slot ).name );
1198
1200
lua_assert ((uintptr_t )name >= VARNAME__MAX );
1199
1201
ls -> linenumber = ls -> fs -> bcbase [vg -> startpc ].line ;
1200
- lua_assert (strref (vg -> name ) != NAME_BREAK );
1202
+ lua_assert (strref (vg -> name ) != NAME_BREAK && strref ( vg -> name ) != NAME_CONTINUE );
1201
1203
lj_lex_error (ls , 0 , LJ_ERR_XGSCOPE ,
1202
1204
strdata (strref (vg -> name )), strdata (name ));
1203
1205
}
@@ -1223,15 +1225,25 @@ static void gola_fixup(LexState *ls, FuncScope *bl)
1223
1225
gola_patch (ls , vg , v );
1224
1226
}
1225
1227
} else if (gola_isgoto (v )) {
1226
- if (bl -> prev ) { /* Propagate goto or break to outer scope. */
1227
- bl -> prev -> flags |= name == NAME_BREAK ? FSCOPE_BREAK : FSCOPE_GOLA ;
1228
+ if (bl -> prev ) { /* Propagate goto, continue or break to outer scope. */
1229
+ /* If this is a loop, we should never see unresolved NAME_CONTINUEs.
1230
+ * If this happens, a loop failed to call fscope_loop_continue before
1231
+ * closing the scope. */
1232
+ if (bl -> flags & FSCOPE_LOOP )
1233
+ lua_assert (name != NAME_CONTINUE );
1234
+ bl -> prev -> flags |=
1235
+ name == NAME_BREAK ? FSCOPE_BREAK :
1236
+ name == NAME_CONTINUE ? FSCOPE_CONTINUE :
1237
+ FSCOPE_GOLA ;
1228
1238
v -> slot = bl -> nactvar ;
1229
1239
if ((bl -> flags & FSCOPE_UPVAL ))
1230
1240
gola_close (ls , v );
1231
1241
} else { /* No outer scope: undefined goto label or no loop. */
1232
1242
ls -> linenumber = ls -> fs -> bcbase [v -> startpc ].line ;
1233
1243
if (name == NAME_BREAK )
1234
1244
lj_lex_error (ls , 0 , LJ_ERR_XBREAK );
1245
+ else if (name == NAME_CONTINUE )
1246
+ lj_lex_error (ls , 0 , LJ_ERR_XCONTINUE );
1235
1247
else
1236
1248
lj_lex_error (ls , 0 , LJ_ERR_XLUNDEF , strdata (name ));
1237
1249
}
@@ -1264,6 +1276,29 @@ static void fscope_begin(FuncState *fs, FuncScope *bl, int flags)
1264
1276
lua_assert (fs -> freereg == fs -> nactvar );
1265
1277
}
1266
1278
1279
+ /* When an FSCOPE_LOOP is ending, this is called to set the instruction continue statements
1280
+ * should jump to. */
1281
+ static void fscope_loop_continue (FuncState * fs , BCPos pos )
1282
+ {
1283
+ FuncScope * bl = fs -> bl ;
1284
+ LexState * ls = fs -> ls ;
1285
+
1286
+ /* This must be called before the loop is closed, so we don't propagate FSCOPE_CONTINUE
1287
+ * out to the enclosing scope. */
1288
+ lua_assert ((bl -> flags & FSCOPE_LOOP ));
1289
+
1290
+ /* If continue wasn't used in this scope, we have nothing to do. */
1291
+ if (!(bl -> flags & FSCOPE_CONTINUE ))
1292
+ return ;
1293
+
1294
+ bl -> flags &= ~FSCOPE_CONTINUE ;
1295
+
1296
+ /* Generate a CONTINUE label, and resolve continues inside this scope to it. */
1297
+ MSize idx = gola_new (ls , NAME_CONTINUE , VSTACK_LABEL , pos );
1298
+ ls -> vtop = idx ; /* Drop continue label immediately. */
1299
+ gola_resolve (ls , bl , idx );
1300
+ }
1301
+
1267
1302
/* End a scope. */
1268
1303
static void fscope_end (FuncState * fs )
1269
1304
{
@@ -1285,7 +1320,7 @@ static void fscope_end(FuncState *fs)
1285
1320
return ;
1286
1321
}
1287
1322
}
1288
- if ((bl -> flags & FSCOPE_GOLA )) {
1323
+ if ((bl -> flags & FSCOPE_GOLA ) || ( bl -> flags & FSCOPE_CONTINUE ) ) {
1289
1324
gola_fixup (ls , bl );
1290
1325
}
1291
1326
}
@@ -2389,6 +2424,13 @@ static void parse_goto(LexState *ls)
2389
2424
gola_new (ls , name , VSTACK_GOTO , bcemit_jmp (fs ));
2390
2425
}
2391
2426
2427
+ static void parse_continue (LexState * ls )
2428
+ {
2429
+ FuncState * fs = ls -> fs ;
2430
+ fs -> bl -> flags |= FSCOPE_CONTINUE ;
2431
+ gola_new (ls , NAME_CONTINUE , VSTACK_GOTO , bcemit_jmp (fs ));
2432
+ }
2433
+
2392
2434
/* Parse label. */
2393
2435
static void parse_label (LexState * ls )
2394
2436
{
@@ -2448,6 +2490,7 @@ static void parse_while(LexState *ls, BCLine line)
2448
2490
parse_block (ls );
2449
2491
jmp_patch (fs , bcemit_jmp (fs ), start );
2450
2492
lex_match (ls , TK_end , TK_while , line );
2493
+ fscope_loop_continue (fs , start ); /* continue statements jump to start */
2451
2494
fscope_end (fs );
2452
2495
jmp_tohere (fs , condexit );
2453
2496
jmp_patchins (fs , loop , fs -> pc );
@@ -2458,14 +2501,15 @@ static void parse_repeat(LexState *ls, BCLine line)
2458
2501
{
2459
2502
FuncState * fs = ls -> fs ;
2460
2503
BCPos loop = fs -> lasttarget = fs -> pc ;
2461
- BCPos condexit ;
2504
+ BCPos condexit , iter ;
2462
2505
FuncScope bl1 , bl2 ;
2463
2506
fscope_begin (fs , & bl1 , FSCOPE_LOOP ); /* Breakable loop scope. */
2464
2507
fscope_begin (fs , & bl2 , 0 ); /* Inner scope. */
2465
2508
lj_lex_next (ls ); /* Skip 'repeat'. */
2466
2509
bcemit_AD (fs , BC_LOOP , fs -> nactvar , 0 );
2467
2510
parse_chunk (ls );
2468
2511
lex_match (ls , TK_until , TK_repeat , line );
2512
+ iter = fs -> pc ; // continue jumps here
2469
2513
condexit = expr_cond (ls ); /* Parse condition (still inside inner scope). */
2470
2514
if (!(bl2 .flags & FSCOPE_UPVAL )) { /* No upvalues? Just end inner scope. */
2471
2515
fscope_end (fs );
@@ -2477,6 +2521,7 @@ static void parse_repeat(LexState *ls, BCLine line)
2477
2521
}
2478
2522
jmp_patch (fs , condexit , loop ); /* Jump backwards if !cond. */
2479
2523
jmp_patchins (fs , loop , fs -> pc );
2524
+ fscope_loop_continue (fs , iter ); /* continue statements jump to condexit. */
2480
2525
fscope_end (fs ); /* End loop scope. */
2481
2526
}
2482
2527
@@ -2516,6 +2561,7 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
2516
2561
fs -> bcbase [loopend ].line = line ; /* Fix line for control ins. */
2517
2562
jmp_patchins (fs , loopend , loop + 1 );
2518
2563
jmp_patchins (fs , loop , fs -> pc );
2564
+ fscope_loop_continue (fs , loopend ); /* continue statements jump to loopend. */
2519
2565
}
2520
2566
2521
2567
/* Try to predict whether the iterator is next() and specialize the bytecode.
@@ -2558,7 +2604,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2558
2604
BCReg nvars = 0 ;
2559
2605
BCLine line ;
2560
2606
BCReg base = fs -> freereg + 3 ;
2561
- BCPos loop , loopend , exprpc = fs -> pc ;
2607
+ BCPos loop , loopend , iter , exprpc = fs -> pc ;
2562
2608
FuncScope bl ;
2563
2609
int isnext ;
2564
2610
/* Hidden control variables. */
@@ -2584,11 +2630,12 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2584
2630
fscope_end (fs );
2585
2631
/* Perform loop inversion. Loop control instructions are at the end. */
2586
2632
jmp_patchins (fs , loop , fs -> pc );
2587
- bcemit_ABC (fs , isnext ? BC_ITERN : BC_ITERC , base , nvars - 3 + 1 , 2 + 1 );
2633
+ iter = bcemit_ABC (fs , isnext ? BC_ITERN : BC_ITERC , base , nvars - 3 + 1 , 2 + 1 );
2588
2634
loopend = bcemit_AJ (fs , BC_ITERL , base , NO_JMP );
2589
2635
fs -> bcbase [loopend - 1 ].line = line ; /* Fix line for control ins. */
2590
2636
fs -> bcbase [loopend ].line = line ;
2591
2637
jmp_patchins (fs , loopend , loop + 1 );
2638
+ fscope_loop_continue (fs , iter ); /* continue statements jump to iter. */
2592
2639
}
2593
2640
2594
2641
/* Parse 'for' statement. */
@@ -2691,6 +2738,10 @@ static int parse_stmt(LexState *ls)
2691
2738
case TK_label :
2692
2739
parse_label (ls );
2693
2740
break ;
2741
+ case TK_continue :
2742
+ lj_lex_next (ls );
2743
+ parse_continue (ls );
2744
+ break ;
2694
2745
case TK_goto :
2695
2746
if (LJ_52 || lj_lex_lookahead (ls ) == TK_name ) {
2696
2747
lj_lex_next (ls );
0 commit comments