From a4c6d63fb752d75a060bd43b4a2c11987f07a902 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Thu, 16 Oct 2025 08:42:05 +0000 Subject: [PATCH 1/3] Apply HINT_BLOCK_SCOPE to lexical variable declarations At present, any `else {...}` block is wrapped in an ENTER/LEAVE pair, even if no new scope is warranted, which causes runtime inefficiency. For example, this block doesn't need a scope but gets one anyway: ``` } else { return 1; } ``` However, this behaviour means that an object like `$kaboom` will reliably be destroyed when the `else` block is exited: ``` } else { my $kaboom = TickTick->new; } ``` In contrast, `if () {...}` or `elsif () {...}` blocks default to not having an `ENTER/LEAVE` pair, which is more efficient but arguably incorrect, as `$marvin` in this code won't be destroyed when the `if` block is exited: ``` if ( $x ) { my $marvin = TickTick->new; } ``` Exactly when it is destroyed is dependent upon where the next scope exit happens to be, and this could be some ways away from its block. This behaviour is also very brittle, as shown in this case where the no-op `0;` statement causes - via a quirk of parsing - the `if` block to be assigned an `ENTER/LEAVE` pair: ``` if ( $x ) { 0; my $marvin = TickTick->new; } ``` Whether a block gains a scope via `ENTER/LEAVE` pair or is just parented by a `SCOPE` OP (that will be optimized away), is decided by `Perl_op_scope` on the basis of the `OPf_PARENS` flag on a block's `LINESEQ` OP. The parser always sets this flag for `else` blocks, a variety of circumstances determines whether it is set otherwise. This commit makes two changes: * Removes the enforced use of the `OPf_PARENS` flag on `else` blocks. The same rules now apply to `if`, `elsif`, and `else`, hopefully making destruction behaviour more predictable. * Changes the tokenizer such that occurrances of `my`, `our`, and `state` set the `OPf_PARENS` flag, and the containing block will be wrapped in an `ENTER/LEAVE` pair. After this commit, neither of the `if` or `else` block in this example will have an unnecessary`ENTER/LEAVE` pair: ``` if ($x ) { return 0; } else { return 1; } ``` And in this example, both objects will be destroyed when the relevant block is entered: ``` if ( $x ) { my $kaboom_true = TickTick->new; } else { my $kaboom_else = TickTick->new; } ``` Sadly, both blocks in this example will still have unnecessary scopes, but fixing that is for a different PR: ``` if ($x ) { 0; return 0; } else { 0; return 1; } ``` There are two downsides to this commit: 1. It has the potential to change the destruction timing of objects created in an `if` block and assigned to a lexical declared within the block, if the block hasn't ended up with an `ENTER/LEAVE` pair. As noted above though. that behaviour is very brittle and already sensitive to even minor changes to the Perl code - and also to minor parser/optimization changes within the interpreter. 2. The old `else` behaviour meant that the first statement's `NEXTSTATE` OP stays in place and consequently any error messages arising from the first statement mention the correct (or closer) line number. The `if`/`elsif` behaviour is more likely to cause the `NEXTSTATE` OP to be optimized away, causing any error messages to contain the line number for where the `if` or `elsif` keyword keyword occurred, which could be many lines away. Following this commit, first-line error messages will be just as bad for an `else` block as they are for `if`/`elsif` blocks. However, that's a separate issue and should not be a reason to avoid this commit. --- perly.act | 419 +++++++++++++++++++++++++++--------------------------- perly.h | 2 +- perly.tab | 56 ++++---- perly.y | 1 - toke.c | 1 + 5 files changed, 239 insertions(+), 240 deletions(-) diff --git a/perly.act b/perly.act index 34bfba27efa2..304fe1a6fb2f 100644 --- a/perly.act +++ b/perly.act @@ -790,14 +790,13 @@ case 2: /* @1: %empty */ case 114: /* else: KW_ELSE mblock */ #line 953 "perly.y" { - ((ps[0].val.opval))->op_flags |= OPf_PARENS; (yyval.opval) = op_scope((ps[0].val.opval)); } break; case 115: /* else: KW_ELSIF PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock else */ -#line 958 "perly.y" +#line 957 "perly.y" { parser->copline = (line_t)(ps[-5].val.ival); (yyval.opval) = newCONDOP(0, newSTATEOP(OPf_SPECIAL,NULL,(ps[-3].val.opval)), @@ -808,25 +807,25 @@ case 2: /* @1: %empty */ break; case 117: /* cont: KW_CONTINUE block */ -#line 970 "perly.y" +#line 969 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; case 118: /* finally: %empty */ -#line 975 "perly.y" +#line 974 "perly.y" { (yyval.opval) = NULL; } break; case 119: /* finally: KW_FINALLY block */ -#line 977 "perly.y" +#line 976 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; case 120: /* mintro: %empty */ -#line 982 "perly.y" +#line 981 "perly.y" { (yyval.ival) = (PL_min_intro_pending && PL_max_intro_pending >= PL_min_intro_pending); intro_my(); } @@ -834,7 +833,7 @@ case 2: /* @1: %empty */ break; case 123: /* texpr: %empty */ -#line 994 "perly.y" +#line 993 "perly.y" { YYSTYPE tmplval; (void)scan_num("1", &tmplval); (yyval.opval) = tmplval.opval; } @@ -842,59 +841,59 @@ case 2: /* @1: %empty */ break; case 125: /* iexpr: expr */ -#line 1002 "perly.y" +#line 1001 "perly.y" { (yyval.opval) = invert(scalar((ps[0].val.opval))); } break; case 126: /* mexpr: expr */ -#line 1007 "perly.y" +#line 1006 "perly.y" { (yyval.opval) = (ps[0].val.opval); intro_my(); } break; case 127: /* mnexpr: nexpr */ -#line 1011 "perly.y" +#line 1010 "perly.y" { (yyval.opval) = (ps[0].val.opval); intro_my(); } break; case 128: /* formname: BAREWORD */ -#line 1014 "perly.y" +#line 1013 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 130: /* startsub: %empty */ -#line 1019 "perly.y" +#line 1018 "perly.y" { (yyval.ival) = start_subparse(FALSE, 0); SAVEFREESV(PL_compcv); } break; case 131: /* startanonsub: %empty */ -#line 1025 "perly.y" +#line 1024 "perly.y" { (yyval.ival) = start_subparse(FALSE, CVf_ANON); SAVEFREESV(PL_compcv); } break; case 132: /* startanonmethod: %empty */ -#line 1030 "perly.y" +#line 1029 "perly.y" { (yyval.ival) = start_subparse(FALSE, CVf_ANON|CVf_IsMETHOD); SAVEFREESV(PL_compcv); } break; case 133: /* startformsub: %empty */ -#line 1035 "perly.y" +#line 1034 "perly.y" { (yyval.ival) = start_subparse(TRUE, 0); SAVEFREESV(PL_compcv); } break; case 139: /* subattrlist: COLONATTR THING */ -#line 1054 "perly.y" +#line 1053 "perly.y" { OP *attrlist = (ps[0].val.opval); if(attrlist && !PL_parser->sig_seen) @@ -905,49 +904,49 @@ case 2: /* @1: %empty */ break; case 140: /* subattrlist: COLONATTR */ -#line 1061 "perly.y" +#line 1060 "perly.y" { (yyval.opval) = NULL; } break; case 141: /* myattrlist: COLONATTR THING */ -#line 1066 "perly.y" +#line 1065 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 142: /* myattrlist: COLONATTR */ -#line 1068 "perly.y" +#line 1067 "perly.y" { (yyval.opval) = NULL; } break; case 143: /* sigvar: %empty */ -#line 1079 "perly.y" +#line 1078 "perly.y" { parser->in_my = 0; (yyval.ival) = 0; } break; case 144: /* sigvar: PRIVATEREF */ -#line 1081 "perly.y" +#line 1080 "perly.y" { parser->in_my = 0; (yyval.ival) = (ps[0].val.opval)->op_targ; op_free((ps[0].val.opval)); } break; case 145: /* sigslurpsigil: PERLY_SNAIL */ -#line 1086 "perly.y" +#line 1085 "perly.y" { (yyval.ival) = '@'; } break; case 146: /* sigslurpsigil: PERLY_PERCENT_SIGN */ -#line 1088 "perly.y" +#line 1087 "perly.y" { (yyval.ival) = '%'; } break; case 147: /* sigslurpelem: sigslurpsigil sigvar */ -#line 1092 "perly.y" +#line 1091 "perly.y" { subsignature_append_slurpy((ps[-1].val.ival), (ps[0].val.ival)); (yyval.opval) = NULL; @@ -956,7 +955,7 @@ case 2: /* @1: %empty */ break; case 148: /* sigslurpelem: sigslurpsigil sigvar ASSIGNOP */ -#line 1097 "perly.y" +#line 1096 "perly.y" { yyerror("A slurpy parameter may not have a default value"); } @@ -964,7 +963,7 @@ case 2: /* @1: %empty */ break; case 149: /* sigslurpelem: sigslurpsigil sigvar ASSIGNOP term */ -#line 1101 "perly.y" +#line 1100 "perly.y" { yyerror("A slurpy parameter may not have a default value"); } @@ -972,7 +971,7 @@ case 2: /* @1: %empty */ break; case 150: /* sigscalarelem: PERLY_DOLLAR sigvar */ -#line 1109 "perly.y" +#line 1108 "perly.y" { subsignature_append_positional((ps[0].val.ival), 0, NULL); (yyval.opval) = NULL; @@ -981,7 +980,7 @@ case 2: /* @1: %empty */ break; case 151: /* sigscalarelem: PERLY_DOLLAR sigvar ASSIGNOP optsigscalardefault */ -#line 1114 "perly.y" +#line 1113 "perly.y" { subsignature_append_positional((ps[-2].val.ival), (ps[-1].val.ival), (ps[0].val.opval)); (yyval.opval) = NULL; @@ -990,31 +989,31 @@ case 2: /* @1: %empty */ break; case 152: /* optsigscalardefault: %empty */ -#line 1122 "perly.y" +#line 1121 "perly.y" { (yyval.opval) = newOP(OP_NULL, 0); } break; case 154: /* sigelem: sigscalarelem */ -#line 1129 "perly.y" +#line 1128 "perly.y" { parser->in_my = KEY_sigvar; (yyval.opval) = (ps[0].val.opval); } break; case 155: /* sigelem: sigslurpelem */ -#line 1131 "perly.y" +#line 1130 "perly.y" { parser->in_my = KEY_sigvar; (yyval.opval) = (ps[0].val.opval); } break; case 163: /* subsignature: PERLY_PAREN_OPEN subsigguts PERLY_PAREN_CLOSE */ -#line 1157 "perly.y" +#line 1156 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; case 164: /* $@20: %empty */ -#line 1160 "perly.y" +#line 1159 "perly.y" { ENTER; subsignature_start(); @@ -1024,7 +1023,7 @@ case 2: /* @1: %empty */ break; case 165: /* subsigguts: $@20 optsiglist */ -#line 1166 "perly.y" +#line 1165 "perly.y" { if (!FEATURE_SIGNATURES_IS_ENABLED && !CvIsMETHOD(PL_compcv)) croak("Experimental " @@ -1052,13 +1051,13 @@ case 2: /* @1: %empty */ break; case 167: /* optsubbody: PERLY_SEMICOLON */ -#line 1194 "perly.y" +#line 1193 "perly.y" { (yyval.opval) = NULL; } break; case 168: /* subbody: remember PERLY_BRACE_OPEN stmtseq PERLY_BRACE_CLOSE */ -#line 1200 "perly.y" +#line 1199 "perly.y" { if (parser->copline > (line_t)(ps[-2].val.ival)) parser->copline = (line_t)(ps[-2].val.ival); @@ -1068,19 +1067,19 @@ case 2: /* @1: %empty */ break; case 170: /* optsigsubbody: PERLY_SEMICOLON */ -#line 1212 "perly.y" +#line 1211 "perly.y" { (yyval.opval) = NULL; } break; case 171: /* $@21: %empty */ -#line 1217 "perly.y" +#line 1216 "perly.y" { PL_parser->sig_seen = FALSE; } break; case 172: /* sigsubbody: remember optsubsignature PERLY_BRACE_OPEN $@21 stmtseq PERLY_BRACE_CLOSE */ -#line 1219 "perly.y" +#line 1218 "perly.y" { if (parser->copline > (line_t)(ps[-3].val.ival)) parser->copline = (line_t)(ps[-3].val.ival); @@ -1091,37 +1090,37 @@ case 2: /* @1: %empty */ break; case 173: /* expr: expr ANDOP expr */ -#line 1230 "perly.y" +#line 1229 "perly.y" { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; case 174: /* expr: expr PLUGIN_LOGICAL_AND_LOW_OP expr */ -#line 1232 "perly.y" +#line 1231 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 175: /* expr: expr OROP expr */ -#line 1234 "perly.y" +#line 1233 "perly.y" { (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; case 176: /* expr: expr PLUGIN_LOGICAL_OR_LOW_OP expr */ -#line 1236 "perly.y" +#line 1235 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 178: /* listexpr: listexpr PERLY_COMMA */ -#line 1242 "perly.y" +#line 1241 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; case 179: /* listexpr: listexpr PERLY_COMMA term */ -#line 1244 "perly.y" +#line 1243 "perly.y" { OP* term = (ps[0].val.opval); (yyval.opval) = op_append_elem(OP_LIST, (ps[-2].val.opval), term); @@ -1130,7 +1129,7 @@ case 2: /* @1: %empty */ break; case 181: /* listop: LSTOP indirob listexpr */ -#line 1253 "perly.y" +#line 1252 "perly.y" { (yyval.opval) = op_convert_list((ps[-2].val.ival), OPf_STACKED, op_prepend_elem(OP_LIST, newGVREF((ps[-2].val.ival),(ps[-1].val.opval)), (ps[0].val.opval)) ); } @@ -1138,7 +1137,7 @@ case 2: /* @1: %empty */ break; case 182: /* listop: BLKLSTOP block listexpr */ -#line 1257 "perly.y" +#line 1256 "perly.y" { (yyval.opval) = op_convert_list((ps[-2].val.ival), OPf_STACKED, op_prepend_elem(OP_LIST, newUNOP(OP_NULL, 0, op_scope((ps[-1].val.opval))), (ps[0].val.opval)) ); } @@ -1146,7 +1145,7 @@ case 2: /* @1: %empty */ break; case 183: /* listop: FUNC PERLY_PAREN_OPEN indirob expr PERLY_PAREN_CLOSE */ -#line 1261 "perly.y" +#line 1260 "perly.y" { (yyval.opval) = op_convert_list((ps[-4].val.ival), OPf_STACKED, op_prepend_elem(OP_LIST, newGVREF((ps[-4].val.ival),(ps[-2].val.opval)), (ps[-1].val.opval)) ); } @@ -1154,7 +1153,7 @@ case 2: /* @1: %empty */ break; case 184: /* listop: term ARROW methodname PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1265 "perly.y" +#line 1264 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, scalar((ps[-5].val.opval)), (ps[-1].val.opval)), @@ -1164,7 +1163,7 @@ case 2: /* @1: %empty */ break; case 185: /* listop: term ARROW methodname */ -#line 1271 "perly.y" +#line 1270 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, scalar((ps[-2].val.opval)), newMETHOP(OP_METHOD, 0, (ps[0].val.opval)))); @@ -1173,7 +1172,7 @@ case 2: /* @1: %empty */ break; case 186: /* listop: term ARROW PERLY_AMPERSAND subname PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1276 "perly.y" +#line 1275 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, scalar((ps[-6].val.opval)), (ps[-1].val.opval)), @@ -1183,7 +1182,7 @@ case 2: /* @1: %empty */ break; case 187: /* listop: term ARROW PERLY_AMPERSAND subname */ -#line 1282 "perly.y" +#line 1281 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, scalar((ps[-3].val.opval)), @@ -1193,7 +1192,7 @@ case 2: /* @1: %empty */ break; case 188: /* listop: METHCALL0 indirob optlistexpr */ -#line 1288 "perly.y" +#line 1287 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)), @@ -1203,7 +1202,7 @@ case 2: /* @1: %empty */ break; case 189: /* listop: METHCALL indirob PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1294 "perly.y" +#line 1293 "perly.y" { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-3].val.opval), (ps[-1].val.opval)), @@ -1213,25 +1212,25 @@ case 2: /* @1: %empty */ break; case 190: /* listop: LSTOP optlistexpr */ -#line 1300 "perly.y" +#line 1299 "perly.y" { (yyval.opval) = op_convert_list((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; case 191: /* listop: FUNC PERLY_PAREN_OPEN optexpr PERLY_PAREN_CLOSE */ -#line 1302 "perly.y" +#line 1301 "perly.y" { (yyval.opval) = op_convert_list((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; case 192: /* listop: FUNC SUBLEXSTART optexpr SUBLEXEND */ -#line 1304 "perly.y" +#line 1303 "perly.y" { (yyval.opval) = op_convert_list((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; case 193: /* @22: %empty */ -#line 1306 "perly.y" +#line 1305 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-1].val.ival), 0, NULL, (ps[0].val.opval)); /* prevent double op_free() if the following fails to parse */ @@ -1241,7 +1240,7 @@ case 2: /* @1: %empty */ break; case 194: /* listop: LSTOPSUB startanonsub block @22 optlistexpr */ -#line 1312 "perly.y" +#line 1311 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)), (ps[-4].val.opval))); @@ -1250,20 +1249,20 @@ case 2: /* @1: %empty */ break; case 197: /* subscripted: gelem PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1327 "perly.y" +#line 1326 "perly.y" { (yyval.opval) = newBINOP(OP_GELEM, 0, (ps[-4].val.opval), scalar((ps[-2].val.opval))); } break; case 198: /* subscripted: scalar PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1329 "perly.y" +#line 1328 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, oopsAV((ps[-3].val.opval)), scalar((ps[-1].val.opval))); } break; case 199: /* subscripted: term ARROW PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1332 "perly.y" +#line 1331 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[-4].val.opval)),OP_RV2AV), scalar((ps[-1].val.opval))); @@ -1272,7 +1271,7 @@ case 2: /* @1: %empty */ break; case 200: /* subscripted: subscripted PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1337 "perly.y" +#line 1336 "perly.y" { (yyval.opval) = newBINOP(OP_AELEM, 0, ref(newAVREF((ps[-3].val.opval)),OP_RV2AV), scalar((ps[-1].val.opval))); @@ -1281,14 +1280,14 @@ case 2: /* @1: %empty */ break; case 201: /* subscripted: scalar PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1342 "perly.y" +#line 1341 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, oopsHV((ps[-4].val.opval)), jmaybe((ps[-2].val.opval))); } break; case 202: /* subscripted: term ARROW PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1345 "perly.y" +#line 1344 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[-5].val.opval)),OP_RV2HV), jmaybe((ps[-2].val.opval))); } @@ -1296,7 +1295,7 @@ case 2: /* @1: %empty */ break; case 203: /* subscripted: subscripted PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1349 "perly.y" +#line 1348 "perly.y" { (yyval.opval) = newBINOP(OP_HELEM, 0, ref(newHVREF((ps[-4].val.opval)),OP_RV2HV), jmaybe((ps[-2].val.opval))); } @@ -1304,7 +1303,7 @@ case 2: /* @1: %empty */ break; case 204: /* subscripted: term ARROW PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1353 "perly.y" +#line 1352 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, newCVREF(0, scalar((ps[-3].val.opval)))); if (parser->expect == XBLOCK) @@ -1314,7 +1313,7 @@ case 2: /* @1: %empty */ break; case 205: /* subscripted: term ARROW PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1359 "perly.y" +#line 1358 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), newCVREF(0, scalar((ps[-4].val.opval))))); @@ -1325,7 +1324,7 @@ case 2: /* @1: %empty */ break; case 206: /* subscripted: subscripted PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1367 "perly.y" +#line 1366 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), newCVREF(0, scalar((ps[-3].val.opval))))); @@ -1336,7 +1335,7 @@ case 2: /* @1: %empty */ break; case 207: /* subscripted: subscripted PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1374 "perly.y" +#line 1373 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, newCVREF(0, scalar((ps[-2].val.opval)))); if (parser->expect == XBLOCK) @@ -1346,55 +1345,55 @@ case 2: /* @1: %empty */ break; case 208: /* subscripted: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1380 "perly.y" +#line 1379 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-4].val.opval)); } break; case 209: /* subscripted: QWLIST PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1382 "perly.y" +#line 1381 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-3].val.opval)); } break; case 210: /* subscripted: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1384 "perly.y" +#line 1383 "perly.y" { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), NULL); } break; case 211: /* termbinop: term PLUGIN_HIGH_OP term */ -#line 1389 "perly.y" +#line 1388 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 212: /* termbinop: term ASSIGNOP term */ -#line 1391 "perly.y" +#line 1390 "perly.y" { (yyval.opval) = newASSIGNOP(OPf_STACKED, (ps[-2].val.opval), (ps[-1].val.ival), (ps[0].val.opval)); } break; case 213: /* termbinop: term PLUGIN_ASSIGN_OP term */ -#line 1393 "perly.y" +#line 1392 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 214: /* termbinop: term POWOP term */ -#line 1395 "perly.y" +#line 1394 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 215: /* termbinop: term PLUGIN_POW_OP term */ -#line 1397 "perly.y" +#line 1396 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 216: /* termbinop: term MULOP term */ -#line 1399 "perly.y" +#line 1398 "perly.y" { if ((ps[-1].val.ival) != OP_REPEAT) scalar((ps[-2].val.opval)); (yyval.opval) = newBINOP((ps[-1].val.ival), 0, (ps[-2].val.opval), scalar((ps[0].val.opval))); @@ -1403,219 +1402,219 @@ case 2: /* @1: %empty */ break; case 217: /* termbinop: term PLUGIN_MUL_OP term */ -#line 1404 "perly.y" +#line 1403 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 218: /* termbinop: term ADDOP term */ -#line 1406 "perly.y" +#line 1405 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 219: /* termbinop: term PLUGIN_ADD_OP term */ -#line 1408 "perly.y" +#line 1407 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 220: /* termbinop: term SHIFTOP term */ -#line 1410 "perly.y" +#line 1409 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 221: /* termbinop: termrelop */ -#line 1412 "perly.y" +#line 1411 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 222: /* termbinop: termeqop */ -#line 1414 "perly.y" +#line 1413 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 223: /* termbinop: term BITANDOP term */ -#line 1416 "perly.y" +#line 1415 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 224: /* termbinop: term BITOROP term */ -#line 1418 "perly.y" +#line 1417 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 225: /* termbinop: term DOTDOT term */ -#line 1420 "perly.y" +#line 1419 "perly.y" { (yyval.opval) = newRANGE((ps[-1].val.ival), scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 226: /* termbinop: term ANDAND term */ -#line 1422 "perly.y" +#line 1421 "perly.y" { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; case 227: /* termbinop: term PLUGIN_LOGICAL_AND_OP term */ -#line 1424 "perly.y" +#line 1423 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 228: /* termbinop: term OROR term */ -#line 1426 "perly.y" +#line 1425 "perly.y" { (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; case 229: /* termbinop: term PLUGIN_LOGICAL_OR_OP term */ -#line 1428 "perly.y" +#line 1427 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 230: /* termbinop: term DORDOR term */ -#line 1430 "perly.y" +#line 1429 "perly.y" { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[-2].val.opval), (ps[0].val.opval)); } break; case 231: /* termbinop: term MATCHOP term */ -#line 1432 "perly.y" +#line 1431 "perly.y" { (yyval.opval) = bind_match((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 232: /* termbinop: term PLUGIN_LOW_OP term */ -#line 1434 "perly.y" +#line 1433 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 233: /* termrelop: relopchain */ -#line 1438 "perly.y" +#line 1437 "perly.y" { (yyval.opval) = cmpchain_finish((ps[0].val.opval)); } break; case 234: /* termrelop: term NCRELOP term */ -#line 1440 "perly.y" +#line 1439 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 235: /* termrelop: termrelop NCRELOP */ -#line 1442 "perly.y" +#line 1441 "perly.y" { yyerror("syntax error"); YYERROR; } break; case 236: /* termrelop: termrelop CHRELOP */ -#line 1444 "perly.y" +#line 1443 "perly.y" { yyerror("syntax error"); YYERROR; } break; case 237: /* termrelop: term PLUGIN_REL_OP term */ -#line 1446 "perly.y" +#line 1445 "perly.y" { (yyval.opval) = build_infix_plugin((ps[-2].val.opval), (ps[0].val.opval), (ps[-1].val.pval)); } break; case 238: /* relopchain: term CHRELOP term */ -#line 1450 "perly.y" +#line 1449 "perly.y" { (yyval.opval) = cmpchain_start((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 239: /* relopchain: relopchain CHRELOP term */ -#line 1452 "perly.y" +#line 1451 "perly.y" { (yyval.opval) = cmpchain_extend((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 240: /* termeqop: eqopchain */ -#line 1456 "perly.y" +#line 1455 "perly.y" { (yyval.opval) = cmpchain_finish((ps[0].val.opval)); } break; case 241: /* termeqop: term NCEQOP term */ -#line 1458 "perly.y" +#line 1457 "perly.y" { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); } break; case 242: /* termeqop: termeqop NCEQOP */ -#line 1460 "perly.y" +#line 1459 "perly.y" { yyerror("syntax error"); YYERROR; } break; case 243: /* termeqop: termeqop CHEQOP */ -#line 1462 "perly.y" +#line 1461 "perly.y" { yyerror("syntax error"); YYERROR; } break; case 244: /* eqopchain: term CHEQOP term */ -#line 1466 "perly.y" +#line 1465 "perly.y" { (yyval.opval) = cmpchain_start((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 245: /* eqopchain: eqopchain CHEQOP term */ -#line 1468 "perly.y" +#line 1467 "perly.y" { (yyval.opval) = cmpchain_extend((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 246: /* termunop: PERLY_MINUS term */ -#line 1473 "perly.y" +#line 1472 "perly.y" { (yyval.opval) = newUNOP(OP_NEGATE, 0, scalar((ps[0].val.opval))); } break; case 247: /* termunop: PERLY_PLUS term */ -#line 1475 "perly.y" +#line 1474 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 248: /* termunop: PERLY_EXCLAMATION_MARK term */ -#line 1478 "perly.y" +#line 1477 "perly.y" { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); } break; case 249: /* termunop: PERLY_TILDE term */ -#line 1480 "perly.y" +#line 1479 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, scalar((ps[0].val.opval))); } break; case 250: /* termunop: term POSTINC */ -#line 1482 "perly.y" +#line 1481 "perly.y" { (yyval.opval) = newUNOP(OP_POSTINC, 0, op_lvalue(scalar((ps[-1].val.opval)), OP_POSTINC)); } break; case 251: /* termunop: term POSTDEC */ -#line 1485 "perly.y" +#line 1484 "perly.y" { (yyval.opval) = newUNOP(OP_POSTDEC, 0, op_lvalue(scalar((ps[-1].val.opval)), OP_POSTDEC));} break; case 252: /* termunop: term POSTJOIN */ -#line 1488 "perly.y" +#line 1487 "perly.y" { (yyval.opval) = op_convert_list(OP_JOIN, 0, op_append_elem( OP_LIST, @@ -1630,59 +1629,59 @@ case 2: /* @1: %empty */ break; case 253: /* termunop: PREINC term */ -#line 1499 "perly.y" +#line 1498 "perly.y" { (yyval.opval) = newUNOP(OP_PREINC, 0, op_lvalue(scalar((ps[0].val.opval)), OP_PREINC)); } break; case 254: /* termunop: PREDEC term */ -#line 1502 "perly.y" +#line 1501 "perly.y" { (yyval.opval) = newUNOP(OP_PREDEC, 0, op_lvalue(scalar((ps[0].val.opval)), OP_PREDEC)); } break; case 255: /* anonymous: PERLY_BRACKET_OPEN optexpr PERLY_BRACKET_CLOSE */ -#line 1510 "perly.y" +#line 1509 "perly.y" { (yyval.opval) = newANONLIST((ps[-1].val.opval)); } break; case 256: /* anonymous: HASHBRACK optexpr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1512 "perly.y" +#line 1511 "perly.y" { (yyval.opval) = newANONHASH((ps[-2].val.opval)); } break; case 257: /* anonymous: KW_SUB_anon startanonsub proto subattrlist subbody */ -#line 1514 "perly.y" +#line 1513 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-3].val.ival), (ps[-2].val.opval), (ps[-1].val.opval), (ps[0].val.opval)); } break; case 258: /* anonymous: KW_SUB_anon startanonsub proto subattrlist */ -#line 1517 "perly.y" +#line 1516 "perly.y" { yyerror("Illegal declaration of anonymous subroutine"); YYERROR; } break; case 259: /* anonymous: KW_SUB_anon_sig startanonsub subattrlist sigsubbody */ -#line 1519 "perly.y" +#line 1518 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-2].val.ival), NULL, (ps[-1].val.opval), (ps[0].val.opval)); } break; case 260: /* anonymous: KW_SUB_anon_sig startanonsub subattrlist */ -#line 1522 "perly.y" +#line 1521 "perly.y" { yyerror("Illegal declaration of anonymous subroutine"); YYERROR; } break; case 261: /* anonymous: KW_METHOD_anon startanonmethod subattrlist sigsubbody */ -#line 1524 "perly.y" +#line 1523 "perly.y" { SvREFCNT_inc_simple_void(PL_compcv); (yyval.opval) = newANONATTRSUB((ps[-2].val.ival), NULL, (ps[-1].val.opval), (ps[0].val.opval)); @@ -1691,103 +1690,103 @@ case 2: /* @1: %empty */ break; case 262: /* anonymous: KW_METHOD_anon startanonmethod subattrlist */ -#line 1529 "perly.y" +#line 1528 "perly.y" { yyerror("Illegal declaration of anonymous subroutine"); YYERROR; } break; case 263: /* termdo: KW_DO term */ -#line 1534 "perly.y" +#line 1533 "perly.y" { (yyval.opval) = dofile((ps[0].val.opval), (ps[-1].val.ival));} break; case 264: /* termdo: KW_DO block */ -#line 1536 "perly.y" +#line 1535 "perly.y" { (yyval.opval) = newUNOP(OP_NULL, OPf_SPECIAL, op_scope((ps[0].val.opval)));} break; case 269: /* term: term PERLY_QUESTION_MARK term PERLY_COLON term */ -#line 1544 "perly.y" +#line 1543 "perly.y" { (yyval.opval) = newCONDOP(0, (ps[-4].val.opval), (ps[-2].val.opval), (ps[0].val.opval)); } break; case 270: /* term: REFGEN term */ -#line 1546 "perly.y" +#line 1545 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, (ps[0].val.opval)); } break; case 271: /* term: myattrterm */ -#line 1548 "perly.y" +#line 1547 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 272: /* term: KW_LOCAL term */ -#line 1550 "perly.y" +#line 1549 "perly.y" { (yyval.opval) = localize((ps[0].val.opval),0); } break; case 273: /* term: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1552 "perly.y" +#line 1551 "perly.y" { (yyval.opval) = sawparens((ps[-1].val.opval)); } break; case 274: /* term: QWLIST */ -#line 1554 "perly.y" +#line 1553 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 275: /* term: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1556 "perly.y" +#line 1555 "perly.y" { (yyval.opval) = sawparens(newNULLLIST()); } break; case 276: /* term: scalar */ -#line 1558 "perly.y" +#line 1557 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 277: /* term: star */ -#line 1560 "perly.y" +#line 1559 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 278: /* term: hsh */ -#line 1562 "perly.y" +#line 1561 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 279: /* term: ary */ -#line 1564 "perly.y" +#line 1563 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 280: /* term: arylen */ -#line 1566 "perly.y" +#line 1565 "perly.y" { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((ps[0].val.opval), OP_AV2ARYLEN));} break; case 281: /* term: subscripted */ -#line 1568 "perly.y" +#line 1567 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 282: /* term: sliceme PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1570 "perly.y" +#line 1569 "perly.y" { (yyval.opval) = op_prepend_elem(OP_ASLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_ASLICE, 0, @@ -1801,7 +1800,7 @@ case 2: /* @1: %empty */ break; case 283: /* term: kvslice PERLY_BRACKET_OPEN expr PERLY_BRACKET_CLOSE */ -#line 1580 "perly.y" +#line 1579 "perly.y" { (yyval.opval) = op_prepend_elem(OP_KVASLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_KVASLICE, 0, @@ -1815,7 +1814,7 @@ case 2: /* @1: %empty */ break; case 284: /* term: sliceme PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1590 "perly.y" +#line 1589 "perly.y" { (yyval.opval) = op_prepend_elem(OP_HSLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_HSLICE, 0, @@ -1829,7 +1828,7 @@ case 2: /* @1: %empty */ break; case 285: /* term: kvslice PERLY_BRACE_OPEN expr PERLY_SEMICOLON PERLY_BRACE_CLOSE */ -#line 1600 "perly.y" +#line 1599 "perly.y" { (yyval.opval) = op_prepend_elem(OP_KVHSLICE, newOP(OP_PUSHMARK, 0), newLISTOP(OP_KVHSLICE, 0, @@ -1843,26 +1842,26 @@ case 2: /* @1: %empty */ break; case 286: /* term: THING */ -#line 1610 "perly.y" +#line 1609 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 287: /* term: amper */ -#line 1612 "perly.y" +#line 1611 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((ps[0].val.opval))); } break; case 288: /* term: amper PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1614 "perly.y" +#line 1613 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[-2].val.opval))); } break; case 289: /* term: amper PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1617 "perly.y" +#line 1616 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[-1].val.opval), scalar((ps[-3].val.opval)))); @@ -1871,7 +1870,7 @@ case 2: /* @1: %empty */ break; case 290: /* term: NOAMP subname optlistexpr */ -#line 1622 "perly.y" +#line 1621 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval)))); } @@ -1879,130 +1878,130 @@ case 2: /* @1: %empty */ break; case 291: /* term: term ARROW PERLY_DOLLAR PERLY_STAR */ -#line 1626 "perly.y" +#line 1625 "perly.y" { (yyval.opval) = newSVREF((ps[-3].val.opval)); } break; case 292: /* term: term ARROW PERLY_SNAIL PERLY_STAR */ -#line 1628 "perly.y" +#line 1627 "perly.y" { (yyval.opval) = newAVREF((ps[-3].val.opval)); } break; case 293: /* term: term ARROW PERLY_PERCENT_SIGN PERLY_STAR */ -#line 1630 "perly.y" +#line 1629 "perly.y" { (yyval.opval) = newHVREF((ps[-3].val.opval)); } break; case 294: /* term: term ARROW PERLY_AMPERSAND PERLY_STAR */ -#line 1632 "perly.y" +#line 1631 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar(newCVREF((ps[-1].val.ival),(ps[-3].val.opval)))); } break; case 295: /* term: term ARROW PERLY_STAR PERLY_STAR */ -#line 1635 "perly.y" +#line 1634 "perly.y" { (yyval.opval) = newGVREF(0,(ps[-3].val.opval)); } break; case 296: /* term: LOOPEX */ -#line 1637 "perly.y" +#line 1636 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), OPf_SPECIAL); PL_hints |= HINT_BLOCK_SCOPE; } break; case 297: /* term: LOOPEX term */ -#line 1640 "perly.y" +#line 1639 "perly.y" { (yyval.opval) = newLOOPEX((ps[-1].val.ival),(ps[0].val.opval)); } break; case 298: /* term: NOTOP listexpr */ -#line 1642 "perly.y" +#line 1641 "perly.y" { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); } break; case 299: /* term: UNIOP */ -#line 1644 "perly.y" +#line 1643 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), 0); } break; case 300: /* term: UNIOP block */ -#line 1646 "perly.y" +#line 1645 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; case 301: /* term: UNIOP term */ -#line 1648 "perly.y" +#line 1647 "perly.y" { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); } break; case 302: /* term: KW_REQUIRE */ -#line 1650 "perly.y" +#line 1649 "perly.y" { (yyval.opval) = newOP(OP_REQUIRE, (ps[0].val.ival) ? OPf_SPECIAL : 0); } break; case 303: /* term: KW_REQUIRE term */ -#line 1652 "perly.y" +#line 1651 "perly.y" { (yyval.opval) = newUNOP(OP_REQUIRE, (ps[-1].val.ival) ? OPf_SPECIAL : 0, (ps[0].val.opval)); } break; case 304: /* term: UNIOPSUB */ -#line 1654 "perly.y" +#line 1653 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); } break; case 305: /* term: UNIOPSUB term */ -#line 1656 "perly.y" +#line 1655 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval)))); } break; case 306: /* term: FUNC0 */ -#line 1659 "perly.y" +#line 1658 "perly.y" { (yyval.opval) = newOP((ps[0].val.ival), 0); } break; case 307: /* term: FUNC0 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1661 "perly.y" +#line 1660 "perly.y" { (yyval.opval) = newOP((ps[-2].val.ival), 0);} break; case 308: /* term: FUNC0OP */ -#line 1663 "perly.y" +#line 1662 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 309: /* term: FUNC0OP PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1665 "perly.y" +#line 1664 "perly.y" { (yyval.opval) = (ps[-2].val.opval); } break; case 310: /* term: FUNC0SUB */ -#line 1667 "perly.y" +#line 1666 "perly.y" { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); } break; case 311: /* term: FUNC1 PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1669 "perly.y" +#line 1668 "perly.y" { (yyval.opval) = ((ps[-2].val.ival) == OP_NOT) ? newUNOP((ps[-2].val.ival), 0, newSVOP(OP_CONST, 0, newSViv(0))) : newOP((ps[-2].val.ival), OPf_SPECIAL); } @@ -2010,13 +2009,13 @@ case 2: /* @1: %empty */ break; case 312: /* term: FUNC1 PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1673 "perly.y" +#line 1672 "perly.y" { (yyval.opval) = newUNOP((ps[-3].val.ival), 0, (ps[-1].val.opval)); } break; case 313: /* @23: %empty */ -#line 1675 "perly.y" +#line 1674 "perly.y" { if ( (ps[0].val.opval)->op_type != OP_TRANS && (ps[0].val.opval)->op_type != OP_TRANSR @@ -2031,67 +2030,67 @@ case 2: /* @1: %empty */ break; case 314: /* term: PMFUNC @23 SUBLEXSTART listexpr optrepl SUBLEXEND */ -#line 1686 "perly.y" +#line 1685 "perly.y" { (yyval.opval) = pmruntime((ps[-5].val.opval), (ps[-2].val.opval), (ps[-1].val.opval), 1, (ps[-4].val.ival)); } break; case 318: /* myattrterm: KW_MY myterm myattrlist */ -#line 1695 "perly.y" +#line 1694 "perly.y" { (yyval.opval) = my_attrs((ps[-1].val.opval),(ps[0].val.opval)); } break; case 319: /* myattrterm: KW_MY myterm */ -#line 1697 "perly.y" +#line 1696 "perly.y" { (yyval.opval) = localize((ps[0].val.opval),1); } break; case 320: /* myattrterm: KW_MY REFGEN myterm myattrlist */ -#line 1699 "perly.y" +#line 1698 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, my_attrs((ps[-1].val.opval),(ps[0].val.opval))); } break; case 321: /* myattrterm: KW_MY REFGEN term */ -#line 1701 "perly.y" +#line 1700 "perly.y" { (yyval.opval) = newUNOP(OP_REFGEN, 0, localize((ps[0].val.opval),1)); } break; case 322: /* myterm: PERLY_PAREN_OPEN expr PERLY_PAREN_CLOSE */ -#line 1706 "perly.y" +#line 1705 "perly.y" { (yyval.opval) = sawparens((ps[-1].val.opval)); } break; case 323: /* myterm: PERLY_PAREN_OPEN PERLY_PAREN_CLOSE */ -#line 1708 "perly.y" +#line 1707 "perly.y" { (yyval.opval) = sawparens(newNULLLIST()); } break; case 324: /* myterm: scalar */ -#line 1711 "perly.y" +#line 1710 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 325: /* myterm: hsh */ -#line 1713 "perly.y" +#line 1712 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 326: /* myterm: ary */ -#line 1715 "perly.y" +#line 1714 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 327: /* fieldvar: scalar */ -#line 1720 "perly.y" +#line 1719 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2100,7 +2099,7 @@ case 2: /* @1: %empty */ break; case 328: /* fieldvar: hsh */ -#line 1725 "perly.y" +#line 1724 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2109,7 +2108,7 @@ case 2: /* @1: %empty */ break; case 329: /* fieldvar: ary */ -#line 1730 "perly.y" +#line 1729 "perly.y" { (yyval.pval) = PadnamelistARRAY(PL_comppad_name)[(ps[0].val.opval)->op_targ]; op_free((ps[0].val.opval)); @@ -2118,19 +2117,19 @@ case 2: /* @1: %empty */ break; case 330: /* optfieldattrlist: COLONATTR THING */ -#line 1738 "perly.y" +#line 1737 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 331: /* optfieldattrlist: COLONATTR */ -#line 1740 "perly.y" +#line 1739 "perly.y" { (yyval.opval) = NULL; } break; case 333: /* fielddecl: KW_FIELD fieldvar optfieldattrlist */ -#line 1746 "perly.y" +#line 1745 "perly.y" { parser->in_my = 0; if((ps[0].val.opval)) @@ -2141,7 +2140,7 @@ case 2: /* @1: %empty */ break; case 334: /* $@24: %empty */ -#line 1753 "perly.y" +#line 1752 "perly.y" { parser->in_my = 0; if((ps[-1].val.opval)) @@ -2153,7 +2152,7 @@ case 2: /* @1: %empty */ break; case 335: /* fielddecl: KW_FIELD fieldvar optfieldattrlist ASSIGNOP $@24 term */ -#line 1761 "perly.y" +#line 1760 "perly.y" { class_set_field_defop((PADNAME *)(ps[-4].val.pval), (ps[-2].val.ival), (ps[0].val.opval)); LEAVE; @@ -2163,25 +2162,25 @@ case 2: /* @1: %empty */ break; case 341: /* optrepl: PERLY_SLASH expr */ -#line 1781 "perly.y" +#line 1780 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; case 342: /* my_scalar: scalar */ -#line 1787 "perly.y" +#line 1786 "perly.y" { parser->in_my = 0; (yyval.opval) = my((ps[0].val.opval)); } break; case 343: /* list_of_scalars: list_of_scalars PERLY_COMMA */ -#line 1792 "perly.y" +#line 1791 "perly.y" { (yyval.opval) = (ps[-1].val.opval); } break; case 344: /* list_of_scalars: list_of_scalars PERLY_COMMA scalar */ -#line 1794 "perly.y" +#line 1793 "perly.y" { (yyval.opval) = op_append_elem(OP_LIST, (ps[-2].val.opval), (ps[0].val.opval)); } @@ -2189,25 +2188,25 @@ case 2: /* @1: %empty */ break; case 346: /* my_list_of_scalars: list_of_scalars */ -#line 1801 "perly.y" +#line 1800 "perly.y" { parser->in_my = 0; (yyval.opval) = (ps[0].val.opval); } break; case 354: /* amper: PERLY_AMPERSAND indirob */ -#line 1818 "perly.y" +#line 1817 "perly.y" { (yyval.opval) = newCVREF((ps[-1].val.ival),(ps[0].val.opval)); } break; case 355: /* scalar: PERLY_DOLLAR indirob */ -#line 1822 "perly.y" +#line 1821 "perly.y" { (yyval.opval) = newSVREF((ps[0].val.opval)); } break; case 356: /* ary: PERLY_SNAIL indirob */ -#line 1826 "perly.y" +#line 1825 "perly.y" { (yyval.opval) = newAVREF((ps[0].val.opval)); if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival); } @@ -2215,7 +2214,7 @@ case 2: /* @1: %empty */ break; case 357: /* hsh: PERLY_PERCENT_SIGN indirob */ -#line 1832 "perly.y" +#line 1831 "perly.y" { (yyval.opval) = newHVREF((ps[0].val.opval)); if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival); } @@ -2223,61 +2222,61 @@ case 2: /* @1: %empty */ break; case 358: /* arylen: DOLSHARP indirob */ -#line 1838 "perly.y" +#line 1837 "perly.y" { (yyval.opval) = newAVREF((ps[0].val.opval)); } break; case 359: /* arylen: term ARROW DOLSHARP PERLY_STAR */ -#line 1840 "perly.y" +#line 1839 "perly.y" { (yyval.opval) = newAVREF((ps[-3].val.opval)); } break; case 360: /* star: PERLY_STAR indirob */ -#line 1844 "perly.y" +#line 1843 "perly.y" { (yyval.opval) = newGVREF(0,(ps[0].val.opval)); } break; case 362: /* sliceme: term ARROW PERLY_SNAIL */ -#line 1849 "perly.y" +#line 1848 "perly.y" { (yyval.opval) = newAVREF((ps[-2].val.opval)); } break; case 364: /* kvslice: term ARROW PERLY_PERCENT_SIGN */ -#line 1854 "perly.y" +#line 1853 "perly.y" { (yyval.opval) = newHVREF((ps[-2].val.opval)); } break; case 366: /* gelem: term ARROW PERLY_STAR */ -#line 1859 "perly.y" +#line 1858 "perly.y" { (yyval.opval) = newGVREF(0,(ps[-2].val.opval)); } break; case 367: /* indirob: BAREWORD */ -#line 1864 "perly.y" +#line 1863 "perly.y" { (yyval.opval) = scalar((ps[0].val.opval)); } break; case 368: /* indirob: scalar */ -#line 1866 "perly.y" +#line 1865 "perly.y" { (yyval.opval) = scalar((ps[0].val.opval)); } break; case 369: /* indirob: block */ -#line 1868 "perly.y" +#line 1867 "perly.y" { (yyval.opval) = op_scope((ps[0].val.opval)); } break; case 370: /* indirob: PRIVATEREF */ -#line 1871 "perly.y" +#line 1870 "perly.y" { (yyval.opval) = (ps[0].val.opval); } break; @@ -2289,6 +2288,6 @@ case 2: /* @1: %empty */ /* Generated from: - * 518d99fb6b32e38f3b668033ccd9846a65b84d5b9381db7009114282219cbe63 perly.y + * 63825672364da1eed08dfd244f613112d3f2966ca04a4a6666dfdf5a3b37b4b7 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.h b/perly.h index e7373ad33149..61a93594c011 100644 --- a/perly.h +++ b/perly.h @@ -246,6 +246,6 @@ int yyparse (void); /* Generated from: - * 518d99fb6b32e38f3b668033ccd9846a65b84d5b9381db7009114282219cbe63 perly.y + * 63825672364da1eed08dfd244f613112d3f2966ca04a4a6666dfdf5a3b37b4b7 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.tab b/perly.tab index 71029d5f59d1..1ceae8364f05 100644 --- a/perly.tab +++ b/perly.tab @@ -369,33 +369,33 @@ static const yytype_int16 yyrline[] = 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 903, 921, 922, 926, 930, 932, 934, 936, 938, - 940, 942, 945, 951, 952, 957, 968, 969, 974, 976, - 981, 988, 989, 993, 997, 1001, 1006, 1010, 1014, 1015, - 1018, 1024, 1029, 1034, 1040, 1041, 1046, 1047, 1052, 1053, - 1060, 1065, 1067, 1078, 1080, 1085, 1087, 1091, 1096, 1100, - 1108, 1113, 1121, 1123, 1128, 1130, 1138, 1139, 1140, 1145, - 1146, 1151, 1152, 1156, 1160, 1160, 1193, 1194, 1199, 1211, - 1212, 1217, 1216, 1229, 1231, 1233, 1235, 1237, 1241, 1243, - 1248, 1252, 1256, 1260, 1264, 1270, 1275, 1281, 1287, 1293, - 1299, 1301, 1303, 1306, 1305, 1319, 1320, 1324, 1328, 1331, - 1336, 1341, 1344, 1348, 1352, 1358, 1366, 1373, 1379, 1381, - 1383, 1388, 1390, 1392, 1394, 1396, 1398, 1403, 1405, 1407, - 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1423, 1425, 1427, - 1429, 1431, 1433, 1437, 1439, 1441, 1443, 1445, 1449, 1451, - 1455, 1457, 1459, 1461, 1465, 1467, 1472, 1474, 1477, 1479, - 1481, 1484, 1487, 1498, 1501, 1509, 1511, 1513, 1516, 1518, - 1521, 1523, 1528, 1533, 1535, 1539, 1540, 1541, 1542, 1543, - 1545, 1547, 1549, 1551, 1553, 1555, 1557, 1559, 1561, 1563, - 1565, 1567, 1569, 1579, 1589, 1599, 1609, 1611, 1613, 1616, - 1621, 1625, 1627, 1629, 1631, 1634, 1636, 1639, 1641, 1643, - 1645, 1647, 1649, 1651, 1653, 1655, 1658, 1660, 1662, 1664, - 1666, 1668, 1672, 1675, 1674, 1687, 1688, 1689, 1694, 1696, - 1698, 1700, 1705, 1707, 1710, 1712, 1714, 1719, 1724, 1729, - 1737, 1739, 1741, 1745, 1753, 1752, 1770, 1771, 1775, 1776, - 1780, 1781, 1786, 1791, 1793, 1797, 1800, 1804, 1805, 1806, - 1809, 1810, 1813, 1814, 1817, 1821, 1825, 1831, 1837, 1839, - 1843, 1847, 1848, 1852, 1853, 1857, 1858, 1863, 1865, 1867, - 1870 + 940, 942, 945, 951, 952, 956, 967, 968, 973, 975, + 980, 987, 988, 992, 996, 1000, 1005, 1009, 1013, 1014, + 1017, 1023, 1028, 1033, 1039, 1040, 1045, 1046, 1051, 1052, + 1059, 1064, 1066, 1077, 1079, 1084, 1086, 1090, 1095, 1099, + 1107, 1112, 1120, 1122, 1127, 1129, 1137, 1138, 1139, 1144, + 1145, 1150, 1151, 1155, 1159, 1159, 1192, 1193, 1198, 1210, + 1211, 1216, 1215, 1228, 1230, 1232, 1234, 1236, 1240, 1242, + 1247, 1251, 1255, 1259, 1263, 1269, 1274, 1280, 1286, 1292, + 1298, 1300, 1302, 1305, 1304, 1318, 1319, 1323, 1327, 1330, + 1335, 1340, 1343, 1347, 1351, 1357, 1365, 1372, 1378, 1380, + 1382, 1387, 1389, 1391, 1393, 1395, 1397, 1402, 1404, 1406, + 1408, 1410, 1412, 1414, 1416, 1418, 1420, 1422, 1424, 1426, + 1428, 1430, 1432, 1436, 1438, 1440, 1442, 1444, 1448, 1450, + 1454, 1456, 1458, 1460, 1464, 1466, 1471, 1473, 1476, 1478, + 1480, 1483, 1486, 1497, 1500, 1508, 1510, 1512, 1515, 1517, + 1520, 1522, 1527, 1532, 1534, 1538, 1539, 1540, 1541, 1542, + 1544, 1546, 1548, 1550, 1552, 1554, 1556, 1558, 1560, 1562, + 1564, 1566, 1568, 1578, 1588, 1598, 1608, 1610, 1612, 1615, + 1620, 1624, 1626, 1628, 1630, 1633, 1635, 1638, 1640, 1642, + 1644, 1646, 1648, 1650, 1652, 1654, 1657, 1659, 1661, 1663, + 1665, 1667, 1671, 1674, 1673, 1686, 1687, 1688, 1693, 1695, + 1697, 1699, 1704, 1706, 1709, 1711, 1713, 1718, 1723, 1728, + 1736, 1738, 1740, 1744, 1752, 1751, 1769, 1770, 1774, 1775, + 1779, 1780, 1785, 1790, 1792, 1796, 1799, 1803, 1804, 1805, + 1808, 1809, 1812, 1813, 1816, 1820, 1824, 1830, 1836, 1838, + 1842, 1846, 1847, 1851, 1852, 1856, 1857, 1862, 1864, 1866, + 1869 }; #endif @@ -1673,6 +1673,6 @@ static const toketypes yy_type_tab[] = }; /* Generated from: - * 518d99fb6b32e38f3b668033ccd9846a65b84d5b9381db7009114282219cbe63 perly.y + * 63825672364da1eed08dfd244f613112d3f2966ca04a4a6666dfdf5a3b37b4b7 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.y b/perly.y index 723d287a32e2..588c852bad16 100644 --- a/perly.y +++ b/perly.y @@ -951,7 +951,6 @@ else : empty | KW_ELSE mblock { - ($mblock)->op_flags |= OPf_PARENS; $$ = op_scope($mblock); } | KW_ELSIF PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock else[else.recurse] diff --git a/toke.c b/toke.c index f9a20bdd9250..da55d3b0fd46 100644 --- a/toke.c +++ b/toke.c @@ -8697,6 +8697,7 @@ yyl_word_or_keyword(pTHX_ char *s, STRLEN len, I32 key, I32 orig_keyword, struct case KEY_our: case KEY_my: case KEY_state: + PL_hints |= HINT_BLOCK_SCOPE; return yyl_my(aTHX_ s, key); case KEY_next: From 2f42d3ca9550fbe41c0bcd413b4468c9375a45d0 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Thu, 16 Oct 2025 21:17:29 +0000 Subject: [PATCH 2/3] Adjust B tests to match new scoping arrangements --- ext/B/t/optree_check.t | 8 +-- ext/B/t/optree_for.t | 24 ++++----- ext/B/t/optree_misc.t | 40 +++++++------- ext/B/t/optree_samples.t | 112 +++++++++++++++++---------------------- ext/B/t/optree_sort.t | 24 ++++----- ext/B/t/optree_varinit.t | 20 +++---- 6 files changed, 106 insertions(+), 122 deletions(-) diff --git a/ext/B/t/optree_check.t b/ext/B/t/optree_check.t index 1b87839f01c3..56935500cb00 100644 --- a/ext/B/t/optree_check.t +++ b/ext/B/t/optree_check.t @@ -144,11 +144,11 @@ checkOptree ( name => 'fixup nextstate (in reftext)', code => sub {my $a}, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate( NOTE THAT THIS CAN BE ANYTHING ) v:>,<,% +# 1 <;> nextstate( NOTE THAT THIS CAN BE ANYTHING ) v:>,<,%,{ # 2 <0> padsv[$a:54,55] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 54 optree_concise.t:84) v:>,<,% +# 1 <;> nextstate(main 54 optree_concise.t:84) v:>,<,%,{ # 2 <0> padsv[$a:54,55] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -159,11 +159,11 @@ checkOptree ( name => 'fixup opcode args', code => sub {my $a}, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate(main 56 optree_concise.t:96) v:>,<,% +# 1 <;> nextstate(main 56 optree_concise.t:96) v:>,<,%,{ # 2 <0> padsv[$a:56,57] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 56 optree_concise.t:96) v:>,<,% +# 1 <;> nextstate(main 56 optree_concise.t:96) v:>,<,%,{ # 2 <0> padsv[$a:56,57] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EONT_EONT diff --git a/ext/B/t/optree_for.t b/ext/B/t/optree_for.t index bddb43752902..f5d5a4d2434c 100644 --- a/ext/B/t/optree_for.t +++ b/ext/B/t/optree_for.t @@ -116,7 +116,7 @@ checkOptree ( name => 'for my $var (@a)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1459 optree_for.t:90) v +1 <;> nextstate(main 1459 optree_for.t:90) v:{ 2 <0> pushmark sM 3 <#> gv[*a] s 4 <1> rv2av[t3] sKRM/1 @@ -128,7 +128,7 @@ checkOptree ( name => 'for my $var (@a)', 9 <2> leaveloop K/2 a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:14) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:14) v:>,<,%,{ 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t2] sKRM/1 @@ -146,7 +146,7 @@ checkOptree ( name => 'for our $var (@a)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1466 optree_for.t:100) v +1 <;> nextstate(main 1466 optree_for.t:100) v:{ 2 <0> pushmark sM 3 <#> gv[*a] s 4 <1> rv2av[t4] sKRM/1 @@ -160,7 +160,7 @@ a <|> and(other->8) K/1 b <2> leaveloop K/2 c <1> leavesub[1 ref] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%,{ 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t2] sKRM/1 @@ -180,7 +180,7 @@ checkOptree ( name => 'for my ($var) (@a)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1466 optree_for.t:100) v +1 <;> nextstate(main 1466 optree_for.t:100) v:{ 2 <0> pushmark sM 3 <#> gv[*a] s 4 <1> rv2av[t3] sKRM/1 @@ -192,7 +192,7 @@ checkOptree ( name => 'for my ($var) (@a)', 9 <2> leaveloop K/2 a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%,{ 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t2] sKRM/1 @@ -210,7 +210,7 @@ checkOptree ( name => 'for my ($var) (@lexical)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1466 optree_for.t:100) v +1 <;> nextstate(main 1466 optree_for.t:100) v:{ 2 <0> pushmark sM 3 <0> padav[@lexical:FAKE::7] sRM 4 <{> enteriter(next->5 last->8 redo->5)[$var:1481,1484] KPS/LVINTRO @@ -221,7 +221,7 @@ checkOptree ( name => 'for my ($var) (@lexical)', 8 <2> leaveloop K/2 9 <1> leavesub[2 refs] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%,{ 2 <0> pushmark sM 3 <0> padav[@lexical:FAKE::2] sRM 4 <{> enteriter(next->5 last->8 redo->5)[$var:1481,1484] KPS/LVINTRO @@ -238,7 +238,7 @@ checkOptree ( name => 'for my ($key, $value) (%h)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1466 optree_for.t:100) v +1 <;> nextstate(main 1466 optree_for.t:100) v:{ 2 <0> pushmark sM 3 <#> gv[*h] s 4 <1> rv2hv[t4] lKM @@ -250,7 +250,7 @@ checkOptree ( name => 'for my ($key, $value) (%h)', 9 <2> leaveloop K/2 a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%,{ 2 <0> pushmark sM 3 <$> gv(*h) s 4 <1> rv2hv[t3] lKM @@ -268,7 +268,7 @@ checkOptree ( name => 'for my ($foo, $bar, $baz) (@a)', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 1466 optree_for.t:100) v +1 <;> nextstate(main 1466 optree_for.t:100) v:{ 2 <0> pushmark sM 3 <#> gv[*a] s 4 <1> rv2av[t5] sKRM/1 @@ -280,7 +280,7 @@ checkOptree ( name => 'for my ($foo, $bar, $baz) (@a)', 9 <2> leaveloop K/2 a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% +1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%,{ 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t4] sKRM/1 diff --git a/ext/B/t/optree_misc.t b/ext/B/t/optree_misc.t index 44c4b564cd74..31b7fb112c6e 100644 --- a/ext/B/t/optree_misc.t +++ b/ext/B/t/optree_misc.t @@ -25,9 +25,9 @@ checkOptree ( name => 'OP_AELEMFAST opclass', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # 7 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->7 -# 1 <;> nextstate(main 634 optree_misc.t:25) v:>,<,% ->2 +# 1 <;> nextstate(main 634 optree_misc.t:25) v:>,<,%,{ ->2 # 2 <0> padav[@x:634,636] vM/LVINTRO ->3 -# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,% ->3 +# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,%,{ ->3 # - <1> rv2av[t4] vK/OURINTR,1 ->3 # - <#> gv[*y] s ->- # 3 <;> nextstate(main 636 optree_misc.t:25) v:>,<,%,{ ->4 @@ -42,9 +42,9 @@ checkOptree ( name => 'OP_AELEMFAST opclass', EOT_EOT # 7 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->7 -# 1 <;> nextstate(main 634 optree_misc.t:27) v:>,<,% ->2 +# 1 <;> nextstate(main 634 optree_misc.t:27) v:>,<,%,{ ->2 # 2 <0> padav[@x:634,636] vM/LVINTRO ->3 -# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,% ->3 +# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,%,{ ->3 # - <1> rv2av[t3] vK/OURINTR,1 ->3 # - <$> gv(*y) s ->- # 3 <;> nextstate(main 636 optree_misc.t:27) v:>,<,%,{ ->4 @@ -168,12 +168,12 @@ checkOptree ( name => 'padrange', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # f <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->f -# 1 <;> nextstate(main 1 -e:1) v:>,<,% ->2 +# 1 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->2 # - <@> list vKP ->3 # 2 <0> padrange[$x:1,2; $y:1,2] vM/LVINTRO,range=2 ->3 # - <0> padsv[$x:1,2] vM/LVINTRO ->- # - <0> padsv[$y:1,2] vM/LVINTRO ->- -# 3 <;> nextstate(main 2 -e:1) v:>,<,% ->4 +# 3 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->4 # 8 <2> aassign[t4] vKS/COM_AGG ->9 # - <1> ex-list lKP ->5 # 4 <0> padrange[$x:1,2; $y:1,2] /range=2 ->5 @@ -196,12 +196,12 @@ checkOptree ( name => 'padrange', EOT_EOT # f <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->f -# 1 <;> nextstate(main 1 -e:1) v:>,<,% ->2 +# 1 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->2 # - <@> list vKP ->3 # 2 <0> padrange[$x:1,2; $y:1,2] vM/LVINTRO,range=2 ->3 # - <0> padsv[$x:1,2] vM/LVINTRO ->- # - <0> padsv[$y:1,2] vM/LVINTRO ->- -# 3 <;> nextstate(main 2 -e:1) v:>,<,% ->4 +# 3 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->4 # 8 <2> aassign[t4] vKS/COM_AGG ->9 # - <1> ex-list lKP ->5 # 4 <0> padrange[$x:1,2; $y:1,2] /range=2 ->5 @@ -233,7 +233,7 @@ checkOptree ( name => 'padrange and @_', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # d <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->d -# 1 <;> nextstate(main 1 p3:1) v:>,<,% ->2 +# 1 <;> nextstate(main 1 p3:1) v:>,<,%,{ ->2 # 3 <2> aassign[t5] vKS ->4 # - <1> ex-list lK ->- # 2 <0> padrange[$a:1,4; $b:1,4] */LVINTRO,range=2 ->3 @@ -243,7 +243,7 @@ checkOptree ( name => 'padrange and @_', # - <0> pushmark sRM*/LVINTRO ->- # - <0> padsv[$a:1,4] sRM*/LVINTRO ->- # - <0> padsv[$b:1,4] sRM*/LVINTRO ->- -# 4 <;> nextstate(main 2 p3:2) v:>,<,% ->5 +# 4 <;> nextstate(main 2 p3:2) v:>,<,%,{ ->5 # 9 <2> aassign[t10] vKS/COM_RC1 ->a # - <1> ex-list lK ->8 # 5 <0> pushmark s ->6 @@ -266,7 +266,7 @@ checkOptree ( name => 'padrange and @_', EOT_EOT # d <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->d -# 1 <;> nextstate(main 1 p3:1) v:>,<,% ->2 +# 1 <;> nextstate(main 1 p3:1) v:>,<,%,{ ->2 # 3 <2> aassign[t5] vKS ->4 # - <1> ex-list lK ->- # 2 <0> padrange[$a:1,4; $b:1,4] */LVINTRO,range=2 ->3 @@ -276,7 +276,7 @@ EOT_EOT # - <0> pushmark sRM*/LVINTRO ->- # - <0> padsv[$a:1,4] sRM*/LVINTRO ->- # - <0> padsv[$b:1,4] sRM*/LVINTRO ->- -# 4 <;> nextstate(main 2 p3:2) v:>,<,% ->5 +# 4 <;> nextstate(main 2 p3:2) v:>,<,%,{ ->5 # 9 <2> aassign[t10] vKS/COM_RC1 ->a # - <1> ex-list lK ->8 # 5 <0> pushmark s ->6 @@ -304,12 +304,12 @@ checkOptree ( name => 'consolidate padranges', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # 5 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->5 -# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,% ->2 +# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,%,{ ->2 # - <@> list vKP ->- # 2 <0> padrange[$a:900,902; $b:900,902; $c:901,902; $d:901,902] vM/LVINTRO,range=4 ->3 # - <0> padsv[$a:900,902] vM/LVINTRO ->- # - <0> padsv[$b:900,902] vM/LVINTRO ->- -# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,% ->- +# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,%,{ ->- # - <@> list vKP ->3 # - <0> pushmark vM/LVINTRO ->- # - <0> padsv[$c:901,902] vM/LVINTRO ->- @@ -319,12 +319,12 @@ checkOptree ( name => 'consolidate padranges', EOT_EOT # 5 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->5 -# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,% ->2 +# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,%,{ ->2 # - <@> list vKP ->- # 2 <0> padrange[$a:900,902; $b:900,902; $c:901,902; $d:901,902] vM/LVINTRO,range=4 ->3 # - <0> padsv[$a:900,902] vM/LVINTRO ->- # - <0> padsv[$b:900,902] vM/LVINTRO ->- -# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,% ->- +# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,%,{ ->- # - <@> list vKP ->3 # - <0> pushmark vM/LVINTRO ->- # - <0> padsv[$c:901,902] vM/LVINTRO ->- @@ -341,12 +341,12 @@ checkOptree ( name => 'consolidate padranges and singletons', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # 5 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->5 -# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,% ->2 +# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,%,{ ->2 # - <@> list vKP ->- # 2 <0> padrange[$a:903,910; $b:903,910; $c:904,910; $d:905,910; $e:905,910; @f:906,910; $g:907,910; $h:908,910; $i:908,910; %j:909,910] vM/LVINTRO,range=10 ->3 # - <0> padsv[$a:903,910] vM/LVINTRO ->- # - <0> padsv[$b:903,910] vM/LVINTRO ->- -# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,% ->- +# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,%,{ ->- # - <0> padsv[$c:904,910] vM/LVINTRO ->- # - <;> nextstate(main 905 optree_misc.t:371) v:>,<,%,{ ->- # - <@> list vKP ->- @@ -369,12 +369,12 @@ checkOptree ( name => 'consolidate padranges and singletons', EOT_EOT # 5 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->5 -# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,% ->2 +# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,%,{ ->2 # - <@> list vKP ->- # 2 <0> padrange[$a:903,910; $b:903,910; $c:904,910; $d:905,910; $e:905,910; @f:906,910; $g:907,910; $h:908,910; $i:908,910; %j:909,910] vM/LVINTRO,range=10 ->3 # - <0> padsv[$a:903,910] vM/LVINTRO ->- # - <0> padsv[$b:903,910] vM/LVINTRO ->- -# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,% ->- +# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,%,{ ->- # - <0> padsv[$c:904,910] vM/LVINTRO ->- # - <;> nextstate(main 905 optree_misc.t:371) v:>,<,%,{ ->- # - <@> list vKP ->- diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t index 88e1ddf80cdd..e20d68519bee 100644 --- a/ext/B/t/optree_samples.t +++ b/ext/B/t/optree_samples.t @@ -33,12 +33,11 @@ checkOptree ( name => '-basic sub {if shift print then,else}', # 6 <@> print sK ->7 # 4 <0> pushmark s ->5 # 5 <$> const[PV "then"] s ->6 -# d <@> leave KP ->7 -# 8 <0> enter ->9 -# 9 <;> nextstate(main 663 optree_samples.t:25) v:>,<,% ->a -# c <@> print sK ->d -# a <0> pushmark s ->b -# b <$> const[PV "else"] s ->c +# - <@> scope K ->- +# - <;> ex-nextstate(main 1591 optree_samples.t:21) v ->8 +# a <@> print sK ->7 +# 8 <0> pushmark s ->9 +# 9 <$> const[PV "else"] s ->a EOT_EOT # 7 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->7 @@ -51,12 +50,11 @@ EOT_EOT # 6 <@> print sK ->7 # 4 <0> pushmark s ->5 # 5 <$> const(PV "then") s ->6 -# d <@> leave KP ->7 -# 8 <0> enter ->9 -# 9 <;> nextstate(main 663 optree_samples.t:25) v:>,<,% ->a -# c <@> print sK ->d -# a <0> pushmark s ->b -# b <$> const(PV "else") s ->c +# - <@> scope K ->- +# - <;> ex-nextstate(main 1591 optree_samples.t:21) v ->8 +# a <@> print sK ->7 +# 8 <0> pushmark s ->9 +# 9 <$> const(PV "else") s ->a EONT_EONT checkOptree ( name => '-basic (see above, with my $a = shift)', @@ -69,47 +67,45 @@ checkOptree ( name => '-basic (see above, with my $a = shift)', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # a <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->a -# 1 <;> nextstate(main 666 optree_samples.t:70) v:>,<,% ->2 -# 3 <1> padsv_store[$a:666,670] vKS/LVINTRO ->4 +# 1 <;> nextstate(main 1595 optree_samples.t:64) v:{ ->2 +# 3 <1> padsv_store[$a:1595,1602] vKS/LVINTRO ->4 # 2 <0> shift s* ->3 # - <0> ex-padsv sRM*/LVINTRO ->3 -# 4 <;> nextstate(main 670 optree_samples.t:71) v:>,<,% ->5 +# 4 <;> nextstate(main 1596 optree_samples.t:65) v:{ ->5 # - <1> null K/1 ->- # 6 <|> cond_expr(other->7) K/1 ->b -# 5 <0> padsv[$a:666,670] s ->6 +# 5 <0> padsv[$a:1595,1602] s ->6 # - <@> scope K ->- -# - <;> ex-nextstate(main 1510 optree_samples.t:66) v:>,<,% ->7 +# - <;> ex-nextstate(main 1598 optree_samples.t:65) v ->7 # 9 <@> print sK ->a # 7 <0> pushmark s ->8 # 8 <$> const[PV "foo"] s ->9 -# g <@> leave KP ->a -# b <0> enter ->c -# c <;> nextstate(main 1510 optree_samples.t:66) v:>,<,% ->d -# f <@> print sK ->g -# d <0> pushmark s ->e -# e <$> const[PV "bar"] s ->f +# - <@> scope K ->- +# - <;> ex-nextstate(main 1600 optree_samples.t:66) v ->b +# d <@> print sK ->a +# b <0> pushmark s ->c +# c <$> const[PV "bar"] s ->d EOT_EOT # a <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->a -# 1 <;> nextstate(main 666 optree_samples.t:70) v:>,<,% ->2 -# 3 <1> padsv_store[$a:666,670] vKS/LVINTRO ->4 +# 1 <;> nextstate(main 1595 optree_samples.t:64) v:{ ->2 +# 3 <1> padsv_store[$a:1595,1602] vKS/LVINTRO ->4 # 2 <0> shift s* ->3 # - <0> ex-padsv sRM*/LVINTRO ->3 -# 4 <;> nextstate(main 670 optree_samples.t:71) v:>,<,% ->5 +# 4 <;> nextstate(main 1596 optree_samples.t:65) v:{ ->5 # - <1> null K/1 ->- # 6 <|> cond_expr(other->7) K/1 ->b -# 5 <0> padsv[$a:666,670] s ->6 +# 5 <0> padsv[$a:1595,1602] s ->6 # - <@> scope K ->- -# - <;> ex-nextstate(main 1510 optree_samples.t:70) v:>,<,% ->7 +# - <;> ex-nextstate(main 1598 optree_samples.t:65) v ->7 # 9 <@> print sK ->a # 7 <0> pushmark s ->8 # 8 <$> const(PV "foo") s ->9 -# g <@> leave KP ->a -# b <0> enter ->c -# c <;> nextstate(main 668 optree_samples.t:72) v:>,<,% ->d -# f <@> print sK ->g -# d <0> pushmark s ->e -# e <$> const(PV "bar") s ->f +# - <@> scope K ->- +# - <;> ex-nextstate(main 1600 optree_samples.t:66) v ->b +# d <@> print sK ->a +# b <0> pushmark s ->c +# c <$> const(PV "bar") s ->d EONT_EONT checkOptree ( name => '-exec sub {if shift print then,else}', @@ -126,12 +122,9 @@ checkOptree ( name => '-exec sub {if shift print then,else}', # 5 <$> const[PV "then"] s # 6 <@> print sK # goto 7 -# 8 <0> enter -# 9 <;> nextstate(main 672 optree_samples.t:126) v:>,<,% -# a <0> pushmark s -# b <$> const[PV "else"] s -# c <@> print sK -# d <@> leave KP +# 8 <0> pushmark s +# 9 <$> const[PV "else"] s +# a <@> print sK # 7 <1> leavesub[1 ref] K/REFC,1 EOT_EOT # 1 <;> nextstate(main 674 optree_samples.t:129) v:>,<,% @@ -141,12 +134,9 @@ EOT_EOT # 5 <$> const(PV "then") s # 6 <@> print sK # goto 7 -# 8 <0> enter -# 9 <;> nextstate(main 672 optree_samples.t:130) v:>,<,% -# a <0> pushmark s -# b <$> const(PV "else") s -# c <@> print sK -# d <@> leave KP +# 8 <0> pushmark s +# 9 <$> const(PV "else") s +# a <@> print sK # 7 <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -158,40 +148,34 @@ checkOptree ( name => '-exec (see above, with my $a = shift)', }, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate(main 675 optree_samples.t:165) v:>,<,% +# 1 <;> nextstate(main 675 optree_samples.t:165) v:>,<,%,{ # 2 <0> shift s* # 3 <1> padsv_store[$a:1522,1529] vKS/LVINTRO -# 4 <;> nextstate(main 679 optree_samples.t:166) v:>,<,% +# 4 <;> nextstate(main 679 optree_samples.t:166) v:>,<,%,{ # 5 <0> padsv[$a:675,679] s # 6 <|> cond_expr(other->7) K/1 # 7 <0> pushmark s # 8 <$> const[PV "foo"] s # 9 <@> print sK # goto a -# b <0> enter -# c <;> nextstate(main 677 optree_samples.t:167) v:>,<,% -# d <0> pushmark s -# e <$> const[PV "bar"] s -# f <@> print sK -# g <@> leave KP +# b <0> pushmark s +# c <$> const[PV "bar"] s +# d <@> print sK # a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 675 optree_samples.t:171) v:>,<,% +# 1 <;> nextstate(main 675 optree_samples.t:171) v:>,<,%,{ # 2 <0> shift s* # 3 <1> padsv_store[$a:1522,1529] vKS/LVINTRO -# 4 <;> nextstate(main 679 optree_samples.t:172) v:>,<,% +# 4 <;> nextstate(main 679 optree_samples.t:172) v:>,<,%,{ # 5 <0> padsv[$a:675,679] s # 6 <|> cond_expr(other->7) K/1 # 7 <0> pushmark s # 8 <$> const(PV "foo") s # 9 <@> print sK # goto a -# b <0> enter -# c <;> nextstate(main 677 optree_samples.t:173) v:>,<,% -# d <0> pushmark s -# e <$> const(PV "bar") s -# f <@> print sK -# g <@> leave KP +# b <0> pushmark s +# c <$> const(PV "bar") s +# d <@> print sK # a <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -682,13 +666,13 @@ checkOptree ( name => 'my $a; my @b; my %c; return 1', code => 'my $a; my @b; my %c; return 1', bcopts => '-exec', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate(main 991 (eval 17):1) v +# 1 <;> nextstate(main 991 (eval 17):1) v:{ # 2 <0> padrange[$a:991,994; @b:992,994; %c:993,994] vM/LVINTRO,range=3 # 3 <;> nextstate(main 994 (eval 17):1) v:{ # 4 <$> const[IV 1] s # 5 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 991 (eval 17):1) v +# 1 <;> nextstate(main 991 (eval 17):1) v:{ # 2 <0> padrange[$a:991,994; @b:992,994; %c:993,994] vM/LVINTRO,range=3 # 3 <;> nextstate(main 994 (eval 17):1) v:{ # 4 <$> const(IV 1) s diff --git a/ext/B/t/optree_sort.t b/ext/B/t/optree_sort.t index f2a8f5c2ca4e..c78560446af9 100644 --- a/ext/B/t/optree_sort.t +++ b/ext/B/t/optree_sort.t @@ -184,9 +184,9 @@ checkOptree ( name => 'sub {my @a; @a = sort @a}', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main -437 optree.t:254) v:>,<,% +1 <;> nextstate(main -437 optree.t:254) v:>,<,%,{ 2 <0> padav[@a:-437,-436] vM/LVINTRO -3 <;> nextstate(main -436 optree.t:256) v:>,<,% +3 <;> nextstate(main -436 optree.t:256) v:>,<,%,{ 4 <0> pushmark s 5 <0> pushmark s 6 <0> padav[@a:-437,-436] l @@ -196,9 +196,9 @@ checkOptree ( name => 'sub {my @a; @a = sort @a}', a <2> aassign[t2] KS/COM_AGG b <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 427 optree_sort.t:172) v:>,<,% +# 1 <;> nextstate(main 427 optree_sort.t:172) v:>,<,%,{ # 2 <0> padav[@a:427,428] vM/LVINTRO -# 3 <;> nextstate(main 428 optree_sort.t:173) v:>,<,% +# 3 <;> nextstate(main 428 optree_sort.t:173) v:>,<,%,{ # 4 <0> pushmark s # 5 <0> pushmark s # 6 <0> padav[@a:427,428] l @@ -241,9 +241,9 @@ checkOptree ( name => 'sub {my @a; @a = sort @a; push @a, 1}', debug => 0, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main -437 optree.t:325) v:>,<,% +1 <;> nextstate(main -437 optree.t:325) v:>,<,%,{ 2 <0> padav[@a:-437,-436] vM/LVINTRO -3 <;> nextstate(main -436 optree.t:325) v:>,<,% +3 <;> nextstate(main -436 optree.t:325) v:>,<,%,{ 4 <0> pushmark s 5 <0> pushmark s 6 <0> padav[@a:-437,-436] lRM* @@ -255,9 +255,9 @@ b <$> const[IV 1] s c <@> push[t3] sK/2 d <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 429 optree_sort.t:219) v:>,<,% +# 1 <;> nextstate(main 429 optree_sort.t:219) v:>,<,%,{ # 2 <0> padav[@a:429,430] vM/LVINTRO -# 3 <;> nextstate(main 430 optree_sort.t:220) v:>,<,% +# 3 <;> nextstate(main 430 optree_sort.t:220) v:>,<,%,{ # 4 <0> pushmark s # 5 <0> pushmark s # 6 <0> padav[@a:429,430] lRM* @@ -276,9 +276,9 @@ checkOptree ( name => 'sub {my @a; @a = sort @a; 1}', debug => 0, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main -437 optree.t:325) v:>,<,% +1 <;> nextstate(main -437 optree.t:325) v:>,<,%,{ 2 <0> padav[@a:-437,-436] vM/LVINTRO -3 <;> nextstate(main -436 optree.t:325) v:>,<,% +3 <;> nextstate(main -436 optree.t:325) v:>,<,%,{ 4 <0> pushmark s 5 <0> pushmark s 6 <0> padav[@a:-437,-436] lRM* @@ -287,9 +287,9 @@ checkOptree ( name => 'sub {my @a; @a = sort @a; 1}', 9 <$> const[IV 1] s a <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 431 optree_sort.t:250) v:>,<,% +# 1 <;> nextstate(main 431 optree_sort.t:250) v:>,<,%,{ # 2 <0> padav[@a:431,432] vM/LVINTRO -# 3 <;> nextstate(main 432 optree_sort.t:251) v:>,<,% +# 3 <;> nextstate(main 432 optree_sort.t:251) v:>,<,%,{ # 4 <0> pushmark s # 5 <0> pushmark s # 6 <0> padav[@a:431,432] lRM* diff --git a/ext/B/t/optree_varinit.t b/ext/B/t/optree_varinit.t index 25ab49452c17..235486b78896 100644 --- a/ext/B/t/optree_varinit.t +++ b/ext/B/t/optree_varinit.t @@ -18,11 +18,11 @@ checkOptree ( name => 'sub {my $a}', code => sub {my $a}, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate(main 45 optree.t:23) v:>,<,% +# 1 <;> nextstate(main 45 optree.t:23) v:>,<,%,{ # 2 <0> padsv[$a:45,46] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 45 optree.t:23) v:>,<,% +# 1 <;> nextstate(main 45 optree.t:23) v:>,<,%,{ # 2 <0> padsv[$a:45,46] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -32,11 +32,11 @@ checkOptree ( name => '-exec sub {my $a}', code => sub {my $a}, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# 1 <;> nextstate(main 49 optree.t:52) v:>,<,% +# 1 <;> nextstate(main 49 optree.t:52) v:>,<,%,{ # 2 <0> padsv[$a:49,50] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 49 optree.t:45) v:>,<,% +# 1 <;> nextstate(main 49 optree.t:45) v:>,<,%,{ # 2 <0> padsv[$a:49,50] sM/LVINTRO # 3 <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -46,11 +46,11 @@ checkOptree ( name => 'sub {our $a}', code => sub {our $a}, strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main 21 optree.t:47) v:>,<,% +1 <;> nextstate(main 21 optree.t:47) v:>,<,%,{ 2 <#> gvsv[*a] s/OURINTR 3 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 51 optree.t:56) v:>,<,% +# 1 <;> nextstate(main 51 optree.t:56) v:>,<,%,{ # 2 <$> gvsv(*a) s/OURINTR # 3 <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -131,14 +131,14 @@ checkOptree ( name => 'sub {my $a=undef}', expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 3 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq KP ->3 -1 <;> nextstate(main 1517 optree_varinit.t:128) v ->2 +1 <;> nextstate(main 1517 optree_varinit.t:128) v:{ ->2 - <1> ex-sassign sKS/2 ->- 2 <0> undef[$a:1517,1518] s/LVINTRO,KEEP_PV,TARGMY ->3 - <0> ex-padsv sRM*/LVINTRO ->- EOT_EOT # 3 <1> leavesub[1 ref] K/REFC,1 ->(end) # - <@> lineseq KP ->3 -# 1 <;> nextstate(main 1517 optree_varinit.t:128) v ->2 +# 1 <;> nextstate(main 1517 optree_varinit.t:128) v:{ ->2 # - <1> ex-sassign sKS/2 ->- # 2 <0> undef[$a:1517,1518] s/LVINTRO,KEEP_PV,TARGMY ->3 # - <0> ex-padsv sRM*/LVINTRO ->- @@ -262,13 +262,13 @@ checkOptree ( name => 'sub {my $a=()}', bcopts => '-exec', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -1 <;> nextstate(main -439 optree.t:105) v:>,<,% +1 <;> nextstate(main -439 optree.t:105) v:>,<,%,{ 2 <0> stub sP 3 <0> padsv[$a:1567,1568] sRM*/LVINTRO 4 <2> sassign sKS/2 5 <1> leavesub[1 ref] K/REFC,1 EOT_EOT -# 1 <;> nextstate(main 438 optree_varinit.t:247) v:>,<,% +# 1 <;> nextstate(main 438 optree_varinit.t:247) v:>,<,%,{ # 2 <0> stub sP # 3 <0> padsv[$a:1567,1568] sRM*/LVINTRO # 4 <2> sassign sKS/2 From ef1394126e13e630d6efdce895b98601f823763c Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Sat, 18 Oct 2025 10:26:49 +0000 Subject: [PATCH 3/3] Perl_rpeep: Fix empty else {} optimization in OP_COND_EXPR case Until `else` blocks were subject to the same block scoping rules as `if` and `elsif`, an empty `else` block or ternary condition would arrive at the peephole optimizer as a bare stub OP: +--null (ex-stub) OP(0x562e555a7310) FLAGS = (...,PARENS,SLABBED) Now, it could arrive in that form OR as a SCOPE + NULL: scope LISTOP(0x5603b282b190) PARENT ===> 3 [cond_expr 0x5603b282b770] FLAGS = (VOID,KIDS,SLABBED) | +--null (ex-stub) OP(0x5603b282b350) ===> 1 [scope 0x5603b282b190] FLAGS = (VOID,SLABBED) This commit updates the "empty else" optimization on `OP_COND_EXPR`s so that the OPs associated with empty "else" conditions are removed (when not in scalar context) regardless of which form they arrive in. --- op.c | 7 +++++++ peep.c | 48 ++++++++++++++++-------------------------------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/op.c b/op.c index 4e302ccdca77..5e2d7d56d673 100644 --- a/op.c +++ b/op.c @@ -4552,6 +4552,13 @@ Perl_op_scope(pTHX_ OP *o) kid = OpSIBLING(kid); if (kid && OP_TYPE_IS_COP_NN(kid)) op_null(kid); + } else if (OP_TYPE_IS(kid, OP_STUB)) { + OP *sib = OpSIBLING(kid); + if (OP_TYPE_IS(sib, OP_NULL) && !OpSIBLING(sib) && + !(sib->op_flags & OPf_KIDS)) { + op_sibling_splice(o,kid,1,NULL); + op_free(sib); + } } } else diff --git a/peep.c b/peep.c index 11ce7e712d7c..ef485b56dc31 100644 --- a/peep.c +++ b/peep.c @@ -3645,10 +3645,10 @@ Perl_rpeep(pTHX_ OP *o) /* Is there an empty "else" block or ternary false branch? If so, optimise away the OP_STUB if safe to do so. */ stub = o->op_next; - if ((stub->op_flags & OPf_WANT) != OPf_WANT_SCALAR) { + if ((stub == falseop) && (stub->op_flags & OPf_WANT) != OPf_WANT_SCALAR) { if (stub->op_type == OP_STUB && !OpSIBLING(stub) ){ OP *stubsib = OpSIBLING(stub); - if ((stub == falseop) && !stubsib) { + if (!stubsib) { /* cond_expr * -condition- * - if - @@ -3659,41 +3659,25 @@ Perl_rpeep(pTHX_ OP *o) o->op_next = stub->op_next; op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL); op_free(stub); + } } else { /* Unexpected */ } - } else if (OP_TYPE_IS(stub,OP_ENTER) && - OP_TYPE_IS(falseop, OP_LEAVE)) { - OP *enter = stub; - OP *stub = OpSIBLING(enter); - if (stub && OP_TYPE_IS(stub, OP_STUB) ){ - assert(!(stub->op_flags & OPf_KIDS)); - OP *stubsib = OpSIBLING(stub); - assert(stubsib); - if (OP_TYPE_IS(stubsib, OP_NULL) && - !OpSIBLING(stubsib) && - !(stubsib->op_flags & OPf_KIDS) ) { - /* cond_expr - * -condition- - * - if - - * leave - * enter - * stub - * null - */ - /* Ignoring it for now, pending further exploration.*/ - /* - o->op_flags |= OPf_SPECIAL; // For B::Deparse + } else if (OP_TYPE_IS(falseop,OP_SCOPE) && + (falseop->op_flags & OPf_KIDS)) { + OP* stub = cLISTOPx(falseop)->op_first; + if (OP_TYPE_IS_OR_WAS(stub, OP_STUB) && !OpSIBLING(stub)) { + assert(o->op_next != falseop); + assert(!(stub->op_flags & OPf_KIDS)); + o->op_flags |= OPf_SPECIAL; /* For B::Deparse */ + op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL); + if (o->op_next == stub) { + if (stub->op_next == falseop) o->op_next = falseop->op_next; - op_sibling_splice(o, OpSIBLING(cLOGOP->op_first), 1, NULL); - op_free(enter); - op_free(stub); - op_free(stubsib); - op_free(falseop); - */ - } + else + o->op_next = stub->op_next; } + op_free(falseop); } } - } /* FALLTHROUGH */ case OP_MAPWHILE: