aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-03-21 09:14:34 +0800
committerLi Jin <dragon-fly@qq.com>2024-03-21 09:14:34 +0800
commit4a3cc26c6dfd74e61c8b6480038d6a292ea86e47 (patch)
tree9554b94cfc15e4acee0c2e60b63af16f1b828207 /src
parent80b65520da432843f0c63431a1867bd2620bc4ac (diff)
downloadyuescript-4a3cc26c6dfd74e61c8b6480038d6a292ea86e47.tar.gz
yuescript-4a3cc26c6dfd74e61c8b6480038d6a292ea86e47.tar.bz2
yuescript-4a3cc26c6dfd74e61c8b6480038d6a292ea86e47.zip
remove redundant 'do' blocks in code generation.
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_compiler.cpp325
1 files changed, 199 insertions, 126 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 1864846..ae6c0e4 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.23.0"sv; 78const std::string_view version = "0.23.1"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -431,6 +431,7 @@ private:
431 }; 431 };
432 struct Scope { 432 struct Scope {
433 GlobalMode mode = GlobalMode::None; 433 GlobalMode mode = GlobalMode::None;
434 bool lastStatement = false;
434 std::unique_ptr<std::unordered_map<std::string, VarType>> vars; 435 std::unique_ptr<std::unordered_map<std::string, VarType>> vars;
435 std::unique_ptr<std::unordered_set<std::string>> allows; 436 std::unique_ptr<std::unordered_set<std::string>> allows;
436 std::unique_ptr<std::unordered_set<std::string>> globals; 437 std::unique_ptr<std::unordered_set<std::string>> globals;
@@ -1854,12 +1855,17 @@ private:
1854 preAssignment->expList.set(preExplist); 1855 preAssignment->expList.set(preExplist);
1855 str_list temp; 1856 str_list temp;
1856 temp.push_back(getPreDefineLine(assignment)); 1857 temp.push_back(getPreDefineLine(assignment));
1857 temp.push_back(indent() + "do"s + nll(assignment)); 1858 bool needScope = !currentScope().lastStatement;
1858 pushScope(); 1859 if (needScope) {
1860 temp.push_back(indent() + "do"s + nll(assignment));
1861 pushScope();
1862 }
1859 transformAssignmentCommon(preAssignment, temp); 1863 transformAssignmentCommon(preAssignment, temp);
1860 transformAssignment(assignment, temp); 1864 transformAssignment(assignment, temp);
1861 popScope(); 1865 if (needScope) {
1862 temp.push_back(indent() + "end"s + nll(assignment)); 1866 popScope();
1867 temp.push_back(indent() + "end"s + nll(assignment));
1868 }
1863 out.push_back(join(temp)); 1869 out.push_back(join(temp));
1864 return; 1870 return;
1865 BLOCK_END 1871 BLOCK_END
@@ -1906,11 +1912,14 @@ private:
1906 } 1912 }
1907 } 1913 }
1908 auto varName = singleVariableFrom(tmpChain, AccessType::Write); 1914 auto varName = singleVariableFrom(tmpChain, AccessType::Write);
1909 bool isScoped = false; 1915 bool needScope = !currentScope().lastStatement;
1916 bool extraScoped = false;
1910 if (varName.empty() || !isLocal(varName)) { 1917 if (varName.empty() || !isLocal(varName)) {
1911 isScoped = true; 1918 if (needScope) {
1912 temp.push_back(indent() + "do"s + nll(x)); 1919 extraScoped = true;
1913 pushScope(); 1920 temp.push_back(indent() + "do"s + nll(x));
1921 pushScope();
1922 }
1914 auto objVar = getUnusedName("_obj_"sv); 1923 auto objVar = getUnusedName("_obj_"sv);
1915 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1924 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1916 newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); 1925 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
@@ -1929,7 +1938,7 @@ private:
1929 assign->values.push_back(*vit); 1938 assign->values.push_back(*vit);
1930 newAssignment->action.set(assign); 1939 newAssignment->action.set(assign);
1931 transformAssignment(newAssignment, temp); 1940 transformAssignment(newAssignment, temp);
1932 if (isScoped) { 1941 if (extraScoped) {
1933 popScope(); 1942 popScope();
1934 temp.push_back(indent() + "end"s + nlr(x)); 1943 temp.push_back(indent() + "end"s + nlr(x));
1935 } 1944 }
@@ -2126,6 +2135,8 @@ private:
2126 } else { 2135 } else {
2127 auto x = assignment; 2136 auto x = assignment;
2128 str_list temp; 2137 str_list temp;
2138 bool needScope = !currentScope().lastStatement;
2139 bool extraScope = false;
2129 if (info.extraScope) { 2140 if (info.extraScope) {
2130 str_list defs; 2141 str_list defs;
2131 for (auto& destruct : info.destructures) { 2142 for (auto& destruct : info.destructures) {
@@ -2144,8 +2155,11 @@ private:
2144 } 2155 }
2145 temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); 2156 temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x));
2146 } 2157 }
2147 temp.push_back(indent() + "do"s + nll(x)); 2158 if (needScope) {
2148 pushScope(); 2159 extraScope = true;
2160 temp.push_back(indent() + "do"s + nll(x));
2161 pushScope();
2162 }
2149 } 2163 }
2150 if (info.assignment) { 2164 if (info.assignment) {
2151 transformAssignmentCommon(info.assignment, temp); 2165 transformAssignmentCommon(info.assignment, temp);
@@ -2355,7 +2369,7 @@ private:
2355 temp.push_back(clearBuf()); 2369 temp.push_back(clearBuf());
2356 } 2370 }
2357 } 2371 }
2358 if (info.extraScope) { 2372 if (extraScope) {
2359 popScope(); 2373 popScope();
2360 temp.push_back(indent() + "end"s + nlr(x)); 2374 temp.push_back(indent() + "end"s + nlr(x));
2361 } 2375 }
@@ -3202,6 +3216,7 @@ private:
3202 auto asmt = firstIfCond->assignment.get(); 3216 auto asmt = firstIfCond->assignment.get();
3203 bool storingValue = false; 3217 bool storingValue = false;
3204 ast_ptr<false, ExpListAssign_t> extraAssignment; 3218 ast_ptr<false, ExpListAssign_t> extraAssignment;
3219 bool extraScope = false;
3205 if (asmt) { 3220 if (asmt) {
3206 auto exp = firstIfCond->condition.get(); 3221 auto exp = firstIfCond->condition.get();
3207 auto x = exp; 3222 auto x = exp;
@@ -3218,8 +3233,11 @@ private:
3218 } 3233 }
3219 if (storingValue) { 3234 if (storingValue) {
3220 if (usage != ExpUsage::Closure) { 3235 if (usage != ExpUsage::Closure) {
3221 temp.push_back(indent() + "do"s + nll(asmt)); 3236 if (!currentScope().lastStatement) {
3222 pushScope(); 3237 extraScope = true;
3238 temp.push_back(indent() + "do"s + nll(asmt));
3239 pushScope();
3240 }
3223 } 3241 }
3224 auto expList = toAst<ExpList_t>(desVar, x); 3242 auto expList = toAst<ExpList_t>(desVar, x);
3225 auto assignment = x->new_ptr<ExpListAssign_t>(); 3243 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -3248,8 +3266,11 @@ private:
3248 if (!isDefined(var)) { 3266 if (!isDefined(var)) {
3249 storingValue = true; 3267 storingValue = true;
3250 if (usage != ExpUsage::Closure) { 3268 if (usage != ExpUsage::Closure) {
3251 temp.push_back(indent() + "do"s + nll(asmt)); 3269 if (!currentScope().lastStatement) {
3252 pushScope(); 3270 extraScope = true;
3271 temp.push_back(indent() + "do"s + nll(asmt));
3272 pushScope();
3273 }
3253 } 3274 }
3254 } 3275 }
3255 auto expList = x->new_ptr<ExpList_t>(); 3276 auto expList = x->new_ptr<ExpList_t>();
@@ -3295,7 +3316,7 @@ private:
3295 break; 3316 break;
3296 } 3317 }
3297 } 3318 }
3298 if (storingValue && usage != ExpUsage::Closure) { 3319 if (extraScope) {
3299 popScope(); 3320 popScope();
3300 temp.push_back(indent() + "end"s + nlr(nodes.front())); 3321 temp.push_back(indent() + "end"s + nlr(nodes.front()));
3301 } 3322 }
@@ -3823,9 +3844,12 @@ private:
3823 auto objVar = singleVariableFrom(left, AccessType::Read); 3844 auto objVar = singleVariableFrom(left, AccessType::Read);
3824 auto prepareValue = [&](bool forAssignment = false) { 3845 auto prepareValue = [&](bool forAssignment = false) {
3825 if (objVar.empty() || !isLocal(objVar)) { 3846 if (objVar.empty() || !isLocal(objVar)) {
3847 bool extraScope = !currentScope().lastStatement;
3826 if (forAssignment) { 3848 if (forAssignment) {
3827 temp.push_back(indent() + "do"s + nll(x)); 3849 if (extraScope) {
3828 pushScope(); 3850 temp.push_back(indent() + "do"s + nll(x));
3851 pushScope();
3852 }
3829 } 3853 }
3830 objVar = getUnusedName("_exp_"sv); 3854 objVar = getUnusedName("_exp_"sv);
3831 auto expList = toAst<ExpList_t>(objVar, x); 3855 auto expList = toAst<ExpList_t>(objVar, x);
@@ -3835,7 +3859,7 @@ private:
3835 assignment->expList.set(expList); 3859 assignment->expList.set(expList);
3836 assignment->action.set(assign); 3860 assignment->action.set(assign);
3837 transformAssignment(assignment, temp); 3861 transformAssignment(assignment, temp);
3838 return forAssignment; 3862 return extraScope;
3839 } 3863 }
3840 return false; 3864 return false;
3841 }; 3865 };
@@ -4531,6 +4555,7 @@ private:
4531 if (!nodes.empty()) { 4555 if (!nodes.empty()) {
4532 str_list temp; 4556 str_list temp;
4533 for (auto node : nodes) { 4557 for (auto node : nodes) {
4558 currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None;
4534 transformStatement(static_cast<Statement_t*>(node), temp); 4559 transformStatement(static_cast<Statement_t*>(node), temp);
4535 if (isRoot && !_rootDefs.empty()) { 4560 if (isRoot && !_rootDefs.empty()) {
4536 auto last = std::move(temp.back()); 4561 auto last = std::move(temp.back());
@@ -5166,12 +5191,14 @@ private:
5166 auto objVar = singleVariableFrom(partOne, AccessType::Read); 5191 auto objVar = singleVariableFrom(partOne, AccessType::Read);
5167 bool isScoped = false; 5192 bool isScoped = false;
5168 if (objVar.empty() || !isLocal(objVar)) { 5193 if (objVar.empty() || !isLocal(objVar)) {
5169 switch (usage) { 5194 if (!currentScope().lastStatement) {
5170 case ExpUsage::Common: 5195 switch (usage) {
5171 case ExpUsage::Assignment: 5196 case ExpUsage::Common:
5172 isScoped = true; 5197 case ExpUsage::Assignment:
5173 break; 5198 isScoped = true;
5174 default: break; 5199 break;
5200 default: break;
5201 }
5175 } 5202 }
5176 if (isScoped) { 5203 if (isScoped) {
5177 temp.push_back(indent() + "do"s + nll(x)); 5204 temp.push_back(indent() + "do"s + nll(x));
@@ -5302,10 +5329,13 @@ private:
5302 auto x = chainList.front(); 5329 auto x = chainList.front();
5303 str_list temp; 5330 str_list temp;
5304 std::string* funcStart = nullptr; 5331 std::string* funcStart = nullptr;
5332 bool isScoped = !currentScope().lastStatement;
5305 switch (usage) { 5333 switch (usage) {
5306 case ExpUsage::Assignment: 5334 case ExpUsage::Assignment:
5307 temp.push_back(indent() + "do"s + nll(x)); 5335 if (isScoped) {
5308 pushScope(); 5336 temp.push_back(indent() + "do"s + nll(x));
5337 pushScope();
5338 }
5309 break; 5339 break;
5310 case ExpUsage::Closure: 5340 case ExpUsage::Closure:
5311 pushAnonFunctionScope(); 5341 pushAnonFunctionScope();
@@ -5378,8 +5408,10 @@ private:
5378 } 5408 }
5379 switch (usage) { 5409 switch (usage) {
5380 case ExpUsage::Assignment: 5410 case ExpUsage::Assignment:
5381 popScope(); 5411 if (isScoped) {
5382 temp.push_back(indent() + "end"s + nlr(x)); 5412 popScope();
5413 temp.push_back(indent() + "end"s + nlr(x));
5414 }
5383 break; 5415 break;
5384 case ExpUsage::Closure: 5416 case ExpUsage::Closure:
5385 popScope(); 5417 popScope();
@@ -5432,6 +5464,7 @@ private:
5432 case id<ColonChainItem_t>(): { 5464 case id<ColonChainItem_t>(): {
5433 auto colon = static_cast<ColonChainItem_t*>(*opIt); 5465 auto colon = static_cast<ColonChainItem_t*>(*opIt);
5434 auto meta = colon->name.to<Metamethod_t>(); 5466 auto meta = colon->name.to<Metamethod_t>();
5467 bool isScoped = !currentScope().lastStatement;
5435 switch (meta->item->get_id()) { 5468 switch (meta->item->get_id()) {
5436 case id<Name_t>(): { 5469 case id<Name_t>(): {
5437 auto name = _parser.toString(meta->item); 5470 auto name = _parser.toString(meta->item);
@@ -5457,8 +5490,10 @@ private:
5457 funcStart = &temp.emplace_back(); 5490 funcStart = &temp.emplace_back();
5458 pushScope(); 5491 pushScope();
5459 } else if (usage != ExpUsage::Return) { 5492 } else if (usage != ExpUsage::Return) {
5460 temp.push_back(indent() + "do"s + nll(x)); 5493 if (isScoped) {
5461 pushScope(); 5494 temp.push_back(indent() + "do"s + nll(x));
5495 pushScope();
5496 }
5462 } 5497 }
5463 auto var = getUnusedName("_obj_"sv); 5498 auto var = getUnusedName("_obj_"sv);
5464 auto target = toAst<Exp_t>(var, x); 5499 auto target = toAst<Exp_t>(var, x);
@@ -5513,14 +5548,18 @@ private:
5513 assign->values.push_back(newChainExp); 5548 assign->values.push_back(newChainExp);
5514 assignment->action.set(assign); 5549 assignment->action.set(assign);
5515 transformAssignment(assignment, temp); 5550 transformAssignment(assignment, temp);
5516 popScope(); 5551 if (isScoped) {
5517 temp.push_back(indent() + "end"s + nlr(x)); 5552 popScope();
5553 temp.push_back(indent() + "end"s + nlr(x));
5554 }
5518 break; 5555 break;
5519 } 5556 }
5520 case ExpUsage::Common: 5557 case ExpUsage::Common:
5521 transformExp(newChainExp, temp, usage); 5558 transformExp(newChainExp, temp, usage);
5522 popScope(); 5559 if (isScoped) {
5523 temp.push_back(indent() + "end"s + nlr(x)); 5560 popScope();
5561 temp.push_back(indent() + "end"s + nlr(x));
5562 }
5524 break; 5563 break;
5525 } 5564 }
5526 out.push_back(join(temp)); 5565 out.push_back(join(temp));
@@ -6060,36 +6099,6 @@ private:
6060 if (auto blockEnd = info.node.as<BlockEnd_t>()) { 6099 if (auto blockEnd = info.node.as<BlockEnd_t>()) {
6061 auto block = blockEnd->block.get(); 6100 auto block = blockEnd->block.get();
6062 info.node.set(block); 6101 info.node.set(block);
6063 for (auto stmt_ : block->statements.objects()) {
6064 auto stmt = static_cast<Statement_t*>(stmt_);
6065 if (auto global = stmt->content.as<Global_t>()) {
6066 if (global->item.is<GlobalOp_t>()) {
6067 throw CompileError("can not use global statement with wildcard operator in macro"sv, x);
6068 }
6069 } else if (auto local = stmt->content.as<Local_t>()) {
6070 if (local->item.is<LocalFlag_t>()) {
6071 throw CompileError("can not use local statement with wildcard operator in macro"sv, x);
6072 }
6073 } else if (auto localAttrib = stmt->content.as<LocalAttrib_t>()) {
6074 if (localAttrib->attrib.is<CloseAttrib_t>()) {
6075 throw CompileError("can not use close attribute statement in macro"sv, x);
6076 }
6077 } else if (stmt->content.as<Backcall_t>()) {
6078 throw CompileError("can not use back call statement in macro"sv, x);
6079 } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>();
6080 expListAssign && expListAssign->action && expListAssign->action.is<Assign_t>()) {
6081 BLOCK_START
6082 auto unary = singleUnaryExpFrom(expListAssign->expList->exprs.back());
6083 BREAK_IF(!unary->ops.empty());
6084 auto value = static_cast<Value_t*>(unary->expos.front());
6085 auto simpleValue = value->item.as<SimpleValue_t>();
6086 BREAK_IF(!simpleValue);
6087 auto varArg = simpleValue->value.as<VarArg_t>();
6088 BREAK_IF(!varArg);
6089 throw CompileError("can not use variadic arguments assignment statement in macro"sv, x);
6090 BLOCK_END
6091 }
6092 }
6093 } 6102 }
6094 return {info.node, std::move(info.codes), Empty, std::move(localVars)}; 6103 return {info.node, std::move(info.codes), Empty, std::move(localVars)};
6095 } else { 6104 } else {
@@ -6118,7 +6127,15 @@ private:
6118 return; 6127 return;
6119 } 6128 }
6120 if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { 6129 if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) {
6121 transformBlock(node.to<Block_t>(), out, usage, assignList); 6130 if (node.to<Block_t>()->statements.empty()) {
6131 out.push_back(Empty);
6132 } else {
6133 auto doBody = node->new_ptr<Body_t>();
6134 doBody->content.set(node);
6135 auto doNode = node->new_ptr<Do_t>();
6136 doNode->body.set(doBody);
6137 transformDo(doNode, out, usage, assignList);
6138 }
6122 } else { 6139 } else {
6123 auto x = chainValue; 6140 auto x = chainValue;
6124 switch (usage) { 6141 switch (usage) {
@@ -6428,6 +6445,7 @@ private:
6428 } 6445 }
6429 if (varName.empty()) { 6446 if (varName.empty()) {
6430 str_list temp; 6447 str_list temp;
6448 bool isScoped = !currentScope().lastStatement;
6431 if (usage == ExpUsage::Closure) { 6449 if (usage == ExpUsage::Closure) {
6432 if (transformAsUpValueFunc(newExp(unary_exp, unary_exp), out)) { 6450 if (transformAsUpValueFunc(newExp(unary_exp, unary_exp), out)) {
6433 return; 6451 return;
@@ -6436,8 +6454,10 @@ private:
6436 pushAnonVarArg(); 6454 pushAnonVarArg();
6437 pushScope(); 6455 pushScope();
6438 } else if (usage == ExpUsage::Assignment) { 6456 } else if (usage == ExpUsage::Assignment) {
6439 temp.push_back(indent() + "do"s + nll(x)); 6457 if (isScoped) {
6440 pushScope(); 6458 temp.push_back(indent() + "do"s + nll(x));
6459 pushScope();
6460 }
6441 } 6461 }
6442 auto newUnaryExp = x->new_ptr<UnaryExp_t>(); 6462 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
6443 newUnaryExp->ops.dup(unary_exp->ops); 6463 newUnaryExp->ops.dup(unary_exp->ops);
@@ -6485,8 +6505,10 @@ private:
6485 popAnonVarArg(); 6505 popAnonVarArg();
6486 popFunctionScope(); 6506 popFunctionScope();
6487 } else if (usage == ExpUsage::Assignment) { 6507 } else if (usage == ExpUsage::Assignment) {
6488 popScope(); 6508 if (isScoped) {
6489 temp.push_back(indent() + "end"s + nll(x)); 6509 popScope();
6510 temp.push_back(indent() + "end"s + nll(x));
6511 }
6490 out.push_back(join(temp)); 6512 out.push_back(join(temp));
6491 } else { 6513 } else {
6492 out.push_back(join(temp)); 6514 out.push_back(join(temp));
@@ -6573,6 +6595,7 @@ private:
6573 6595
6574 void transformSpreadTable(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 6596 void transformSpreadTable(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
6575 auto x = values.front(); 6597 auto x = values.front();
6598 bool extraScope = false;
6576 switch (usage) { 6599 switch (usage) {
6577 case ExpUsage::Closure: { 6600 case ExpUsage::Closure: {
6578 auto tableLit = x->new_ptr<TableLit_t>(); 6601 auto tableLit = x->new_ptr<TableLit_t>();
@@ -6590,7 +6613,10 @@ private:
6590 break; 6613 break;
6591 } 6614 }
6592 case ExpUsage::Assignment: 6615 case ExpUsage::Assignment:
6593 pushScope(); 6616 if (!currentScope().lastStatement) {
6617 extraScope = true;
6618 pushScope();
6619 }
6594 break; 6620 break;
6595 default: 6621 default:
6596 break; 6622 break;
@@ -6850,9 +6876,11 @@ private:
6850 assignment->expList.set(assignList); 6876 assignment->expList.set(assignList);
6851 assignment->action.set(assign); 6877 assignment->action.set(assign);
6852 transformAssignment(assignment, temp); 6878 transformAssignment(assignment, temp);
6853 popScope(); 6879 if (extraScope) popScope();
6854 out.push_back(join(temp)); 6880 out.push_back(join(temp));
6855 out.back() = indent() + "do"s + nll(x) + out.back() + indent() + "end"s + nlr(x); 6881 if (extraScope) {
6882 out.back() = indent() + "do"s + nll(x) + out.back() + indent() + "end"s + nlr(x);
6883 }
6856 break; 6884 break;
6857 } 6885 }
6858 case ExpUsage::Return: 6886 case ExpUsage::Return:
@@ -7107,6 +7135,7 @@ private:
7107 if (!def || def->defVal) { 7135 if (!def || def->defVal) {
7108 throw CompileError("invalid comprehension expression", comp->items.front()); 7136 throw CompileError("invalid comprehension expression", comp->items.front());
7109 } 7137 }
7138 bool extraScope = false;
7110 switch (usage) { 7139 switch (usage) {
7111 case ExpUsage::Closure: { 7140 case ExpUsage::Closure: {
7112 auto simpleValue = x->new_ptr<SimpleValue_t>(); 7141 auto simpleValue = x->new_ptr<SimpleValue_t>();
@@ -7120,7 +7149,10 @@ private:
7120 break; 7149 break;
7121 } 7150 }
7122 case ExpUsage::Assignment: 7151 case ExpUsage::Assignment:
7123 pushScope(); 7152 if (!currentScope().lastStatement) {
7153 extraScope = true;
7154 pushScope();
7155 }
7124 break; 7156 break;
7125 default: 7157 default:
7126 break; 7158 break;
@@ -7191,8 +7223,11 @@ private:
7191 assignment->expList.set(assignList); 7223 assignment->expList.set(assignList);
7192 assignment->action.set(assign); 7224 assignment->action.set(assign);
7193 transformAssignment(assignment, temp); 7225 transformAssignment(assignment, temp);
7194 popScope(); 7226 out.back().append(temp.back());
7195 out.back() = indent() + "do"s + nll(comp) + out.back() + temp.back() + indent() + "end"s + nlr(comp); 7227 if (extraScope) {
7228 popScope();
7229 out.back() = indent() + "do"s + nll(comp) + out.back() + indent() + "end"s + nlr(comp);
7230 }
7196 break; 7231 break;
7197 } 7232 }
7198 case ExpUsage::Return: 7233 case ExpUsage::Return:
@@ -7204,13 +7239,14 @@ private:
7204 } 7239 }
7205 } 7240 }
7206 7241
7207 bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool isStatement = false) { 7242 bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) {
7208 auto x = nameList; 7243 auto x = nameList;
7209 str_list temp; 7244 str_list temp;
7210 str_list vars; 7245 str_list vars;
7211 str_list varBefore, varAfter; 7246 str_list varBefore, varAfter;
7212 std::string varConstAfter; 7247 std::string varConstAfter;
7213 bool extraScope = false; 7248 bool extraScope = false;
7249 bool needScope = !currentScope().lastStatement;
7214 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs; 7250 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs;
7215 for (auto _item : nameList->items.objects()) { 7251 for (auto _item : nameList->items.objects()) {
7216 auto item = static_cast<NameOrDestructure_t*>(_item)->item.get(); 7252 auto item = static_cast<NameOrDestructure_t*>(_item)->item.get();
@@ -7287,7 +7323,7 @@ private:
7287 } 7323 }
7288 if (listVar.empty()) { 7324 if (listVar.empty()) {
7289 std::string prefix; 7325 std::string prefix;
7290 if (isStatement) { 7326 if (!inClosure && needScope) {
7291 extraScope = true; 7327 extraScope = true;
7292 prefix = indent() + "do"s + nll(x); 7328 prefix = indent() + "do"s + nll(x);
7293 pushScope(); 7329 pushScope();
@@ -7300,7 +7336,7 @@ private:
7300 std::string maxVar; 7336 std::string maxVar;
7301 if (!stopValue.empty()) { 7337 if (!stopValue.empty()) {
7302 std::string prefix; 7338 std::string prefix;
7303 if (isStatement && !extraScope) { 7339 if (!extraScope && !inClosure && needScope) {
7304 extraScope = true; 7340 extraScope = true;
7305 prefix = indent() + "do"s + nll(x); 7341 prefix = indent() + "do"s + nll(x);
7306 pushScope(); 7342 pushScope();
@@ -7376,7 +7412,7 @@ private:
7376 } 7412 }
7377 7413
7378 void transformCompForEach(CompForEach_t* comp, str_list& out) { 7414 void transformCompForEach(CompForEach_t* comp, str_list& out) {
7379 transformForEachHead(comp->nameList, comp->loopValue, out); 7415 transformForEachHead(comp->nameList, comp->loopValue, out, true);
7380 } 7416 }
7381 7417
7382 void transformInvokeArgs(InvokeArgs_t* invokeArgs, str_list& out) { 7418 void transformInvokeArgs(InvokeArgs_t* invokeArgs, str_list& out) {
@@ -7741,9 +7777,12 @@ private:
7741 void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { 7777 void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) {
7742 auto x = forNode; 7778 auto x = forNode;
7743 str_list temp; 7779 str_list temp;
7780 bool isScoped = !currentScope().lastStatement;
7744 if (assignExpList) { 7781 if (assignExpList) {
7745 _buf << indent() << "do"sv << nll(forNode); 7782 if (isScoped) {
7746 pushScope(); 7783 _buf << indent() << "do"sv << nll(forNode);
7784 pushScope();
7785 }
7747 auto accum = transformForInner(forNode, temp); 7786 auto accum = transformForInner(forNode, temp);
7748 auto assign = x->new_ptr<Assign_t>(); 7787 auto assign = x->new_ptr<Assign_t>();
7749 assign->values.push_back(toAst<Exp_t>(accum, x)); 7788 assign->values.push_back(toAst<Exp_t>(accum, x));
@@ -7751,8 +7790,10 @@ private:
7751 assignment->expList.set(assignExpList); 7790 assignment->expList.set(assignExpList);
7752 assignment->action.set(assign); 7791 assignment->action.set(assign);
7753 transformAssignment(assignment, temp); 7792 transformAssignment(assignment, temp);
7754 popScope(); 7793 if (isScoped) {
7755 temp.push_back(indent() + "end"s + nlr(forNode)); 7794 popScope();
7795 temp.push_back(indent() + "end"s + nlr(forNode));
7796 }
7756 } else { 7797 } else {
7757 auto accum = transformForInner(forNode, temp); 7798 auto accum = transformForInner(forNode, temp);
7758 auto returnNode = x->new_ptr<Return_t>(); 7799 auto returnNode = x->new_ptr<Return_t>();
@@ -7783,11 +7824,11 @@ private:
7783 7824
7784 void transformForEach(ForEach_t* forEach, str_list& out) { 7825 void transformForEach(ForEach_t* forEach, str_list& out) {
7785 str_list temp; 7826 str_list temp;
7786 bool extraScope = transformForEachHead(forEach->nameList, forEach->loopValue, temp, true); 7827 bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false);
7787 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); 7828 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common);
7788 popScope(); 7829 popScope();
7789 out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); 7830 out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach));
7790 if (extraScope) { 7831 if (extraScoped) {
7791 popScope(); 7832 popScope();
7792 out.back().append(indent() + "end"s + nlr(forEach)); 7833 out.back().append(indent() + "end"s + nlr(forEach));
7793 } 7834 }
@@ -7802,7 +7843,7 @@ private:
7802 _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); 7843 _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach);
7803 _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); 7844 _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach);
7804 out.push_back(clearBuf()); 7845 out.push_back(clearBuf());
7805 transformForEachHead(forEach->nameList, forEach->loopValue, out); 7846 transformForEachHead(forEach->nameList, forEach->loopValue, out, true);
7806 auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); 7847 auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x);
7807 auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body); 7848 auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body);
7808 transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList); 7849 transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList);
@@ -7835,9 +7876,12 @@ private:
7835 void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { 7876 void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) {
7836 auto x = forEach; 7877 auto x = forEach;
7837 str_list temp; 7878 str_list temp;
7879 bool isScoped = !currentScope().lastStatement;
7838 if (assignExpList) { 7880 if (assignExpList) {
7839 _buf << indent() << "do"sv << nll(forEach); 7881 if (isScoped) {
7840 pushScope(); 7882 _buf << indent() << "do"sv << nll(forEach);
7883 pushScope();
7884 }
7841 auto accum = transformForEachInner(forEach, temp); 7885 auto accum = transformForEachInner(forEach, temp);
7842 auto assign = x->new_ptr<Assign_t>(); 7886 auto assign = x->new_ptr<Assign_t>();
7843 assign->values.push_back(toAst<Exp_t>(accum, x)); 7887 assign->values.push_back(toAst<Exp_t>(accum, x));
@@ -7845,8 +7889,10 @@ private:
7845 assignment->expList.set(assignExpList); 7889 assignment->expList.set(assignExpList);
7846 assignment->action.set(assign); 7890 assignment->action.set(assign);
7847 transformAssignment(assignment, temp); 7891 transformAssignment(assignment, temp);
7848 popScope(); 7892 if (isScoped) {
7849 temp.push_back(indent() + "end"s + nlr(forEach)); 7893 popScope();
7894 temp.push_back(indent() + "end"s + nlr(forEach));
7895 }
7850 } else { 7896 } else {
7851 auto accum = transformForEachInner(forEach, temp); 7897 auto accum = transformForEachInner(forEach, temp);
7852 auto returnNode = x->new_ptr<Return_t>(); 7898 auto returnNode = x->new_ptr<Return_t>();
@@ -8035,6 +8081,7 @@ private:
8035 std::string className; 8081 std::string className;
8036 std::string assignItem; 8082 std::string assignItem;
8037 std::string classTextName; 8083 std::string classTextName;
8084 bool isScoped = !currentScope().lastStatement;
8038 if (assignable) { 8085 if (assignable) {
8039 if (!isAssignable(assignable)) { 8086 if (!isAssignable(assignable)) {
8040 throw CompileError("left hand expression is not assignable"sv, assignable); 8087 throw CompileError("left hand expression is not assignable"sv, assignable);
@@ -8078,8 +8125,10 @@ private:
8078 } 8125 }
8079 } 8126 }
8080 } 8127 }
8081 temp.push_back(indent() + "do"s + nll(classDecl)); 8128 if (isScoped) {
8082 pushScope(); 8129 temp.push_back(indent() + "do"s + nll(classDecl));
8130 pushScope();
8131 }
8083 auto classVar = getUnusedName("_class_"sv); 8132 auto classVar = getUnusedName("_class_"sv);
8084 addToScope(classVar); 8133 addToScope(classVar);
8085 temp.push_back(indent() + "local "s + classVar + nll(classDecl)); 8134 temp.push_back(indent() + "local "s + classVar + nll(classDecl));
@@ -8295,8 +8344,10 @@ private:
8295 default: break; 8344 default: break;
8296 } 8345 }
8297 temp.push_back(clearBuf()); 8346 temp.push_back(clearBuf());
8298 popScope(); 8347 if (isScoped) {
8299 temp.push_back(indent() + "end"s + nlr(classDecl)); 8348 popScope();
8349 temp.push_back(indent() + "end"s + nlr(classDecl));
8350 }
8300 out.push_back(join(temp)); 8351 out.push_back(join(temp));
8301 } 8352 }
8302 8353
@@ -8469,7 +8520,8 @@ private:
8469 auto x = with; 8520 auto x = with;
8470 str_list temp; 8521 str_list temp;
8471 std::string withVar; 8522 std::string withVar;
8472 bool scoped = false; 8523 bool needScope = !currentScope().lastStatement && !returnValue;
8524 bool extraScope = false;
8473 if (with->assigns) { 8525 if (with->assigns) {
8474 auto vars = getAssignVars(with); 8526 auto vars = getAssignVars(with);
8475 if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { 8527 if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) {
@@ -8486,8 +8538,8 @@ private:
8486 auto assign = x->new_ptr<Assign_t>(); 8538 auto assign = x->new_ptr<Assign_t>();
8487 assign->values.push_back(with->assigns->values.objects().front()); 8539 assign->values.push_back(with->assigns->values.objects().front());
8488 assignment->action.set(assign); 8540 assignment->action.set(assign);
8489 if (!returnValue) { 8541 if (needScope) {
8490 scoped = true; 8542 extraScope = true;
8491 temp.push_back(indent() + "do"s + nll(with)); 8543 temp.push_back(indent() + "do"s + nll(with));
8492 pushScope(); 8544 pushScope();
8493 } 8545 }
@@ -8512,8 +8564,8 @@ private:
8512 auto assignment = x->new_ptr<ExpListAssign_t>(); 8564 auto assignment = x->new_ptr<ExpListAssign_t>();
8513 assignment->expList.set(with->valueList); 8565 assignment->expList.set(with->valueList);
8514 assignment->action.set(with->assigns); 8566 assignment->action.set(with->assigns);
8515 if (!returnValue) { 8567 if (needScope) {
8516 scoped = true; 8568 extraScope = true;
8517 temp.push_back(indent() + "do"s + nll(with)); 8569 temp.push_back(indent() + "do"s + nll(with));
8518 pushScope(); 8570 pushScope();
8519 } 8571 }
@@ -8528,17 +8580,17 @@ private:
8528 auto assign = x->new_ptr<Assign_t>(); 8580 auto assign = x->new_ptr<Assign_t>();
8529 assign->values.dup(with->valueList->exprs); 8581 assign->values.dup(with->valueList->exprs);
8530 assignment->action.set(assign); 8582 assignment->action.set(assign);
8531 if (!returnValue) { 8583 if (needScope) {
8532 scoped = true; 8584 extraScope = true;
8533 temp.push_back(indent() + "do"s + nll(with)); 8585 temp.push_back(indent() + "do"s + nll(with));
8534 pushScope(); 8586 pushScope();
8535 } 8587 }
8536 transformAssignment(assignment, temp); 8588 transformAssignment(assignment, temp);
8537 } 8589 }
8538 } 8590 }
8539 if (!with->eop && !scoped && !returnValue) { 8591 if (needScope && !with->eop && !extraScope) {
8540 pushScope(); 8592 pushScope();
8541 scoped = traversal::Stop == with->body->traverse([&](ast_node* node) { 8593 extraScope = traversal::Stop == with->body->traverse([&](ast_node* node) {
8542 if (auto statement = ast_cast<Statement_t>(node)) { 8594 if (auto statement = ast_cast<Statement_t>(node)) {
8543 ClassDecl_t* clsDecl = nullptr; 8595 ClassDecl_t* clsDecl = nullptr;
8544 if (auto assignment = assignmentFrom(statement)) { 8596 if (auto assignment = assignmentFrom(statement)) {
@@ -8576,7 +8628,7 @@ private:
8576 return traversal::Continue; 8628 return traversal::Continue;
8577 }); 8629 });
8578 popScope(); 8630 popScope();
8579 if (scoped) { 8631 if (extraScope) {
8580 temp.push_back(indent() + "do"s + nll(with)); 8632 temp.push_back(indent() + "do"s + nll(with));
8581 pushScope(); 8633 pushScope();
8582 } 8634 }
@@ -8606,7 +8658,7 @@ private:
8606 temp.push_back(indent() + "return "s + withVar + nll(with)); 8658 temp.push_back(indent() + "return "s + withVar + nll(with));
8607 } 8659 }
8608 } 8660 }
8609 if (scoped) { 8661 if (extraScope) {
8610 popScope(); 8662 popScope();
8611 temp.push_back(indent() + "end"s + nll(with)); 8663 temp.push_back(indent() + "end"s + nll(with));
8612 } 8664 }
@@ -8863,6 +8915,7 @@ private:
8863 } 8915 }
8864 8916
8865 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 8917 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
8918 bool extraScope = false;
8866 switch (usage) { 8919 switch (usage) {
8867 case ExpUsage::Closure: { 8920 case ExpUsage::Closure: {
8868 auto simpleValue = comp->new_ptr<SimpleValue_t>(); 8921 auto simpleValue = comp->new_ptr<SimpleValue_t>();
@@ -8876,7 +8929,10 @@ private:
8876 break; 8929 break;
8877 } 8930 }
8878 case ExpUsage::Assignment: 8931 case ExpUsage::Assignment:
8879 pushScope(); 8932 if (!currentScope().lastStatement) {
8933 extraScope = true;
8934 pushScope();
8935 }
8880 break; 8936 break;
8881 default: 8937 default:
8882 break; 8938 break;
@@ -8944,9 +9000,11 @@ private:
8944 assignment->action.set(assign); 9000 assignment->action.set(assign);
8945 transformAssignment(assignment, temp); 9001 transformAssignment(assignment, temp);
8946 out.back().append(temp.back()); 9002 out.back().append(temp.back());
8947 popScope(); 9003 if (extraScope) {
8948 out.back().insert(0, indent() + "do"s + nll(comp)); 9004 popScope();
8949 out.back().append(indent() + "end"s + nlr(comp)); 9005 out.back().insert(0, indent() + "do"s + nll(comp));
9006 out.back().append(indent() + "end"s + nlr(comp));
9007 }
8950 break; 9008 break;
8951 } 9009 }
8952 case ExpUsage::Return: 9010 case ExpUsage::Return:
@@ -8986,18 +9044,20 @@ private:
8986 pushAnonFunctionScope(); 9044 pushAnonFunctionScope();
8987 pushAnonVarArg(); 9045 pushAnonVarArg();
8988 funcStart = &temp.emplace_back(); 9046 funcStart = &temp.emplace_back();
9047 pushScope();
8989 } else { 9048 } else {
8990 temp.push_back(indent() + "do"s + nll(doNode)); 9049 temp.push_back(indent() + "do"s + nll(doNode));
9050 pushScope();
8991 } 9051 }
8992 pushScope();
8993 transformBody(doNode->body, temp, usage, assignList); 9052 transformBody(doNode->body, temp, usage, assignList);
8994 popScope();
8995 if (usage == ExpUsage::Closure) { 9053 if (usage == ExpUsage::Closure) {
9054 popScope();
8996 *funcStart = anonFuncStart() + nll(doNode); 9055 *funcStart = anonFuncStart() + nll(doNode);
8997 temp.push_back(indent() + anonFuncEnd()); 9056 temp.push_back(indent() + anonFuncEnd());
8998 popAnonVarArg(); 9057 popAnonVarArg();
8999 popFunctionScope(); 9058 popFunctionScope();
9000 } else { 9059 } else {
9060 popScope();
9001 temp.push_back(indent() + "end"s + nlr(doNode)); 9061 temp.push_back(indent() + "end"s + nlr(doNode));
9002 } 9062 }
9003 out.push_back(join(temp)); 9063 out.push_back(join(temp));
@@ -9225,13 +9285,17 @@ private:
9225 default: YUEE("AST node mismatch", name); break; 9285 default: YUEE("AST node mismatch", name); break;
9226 } 9286 }
9227 } 9287 }
9288 bool extraScope = false;
9228 if (objAssign) { 9289 if (objAssign) {
9229 auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); 9290 auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark));
9230 if (!preDef.empty()) { 9291 if (!preDef.empty()) {
9231 temp.push_back(preDef + nll(importNode)); 9292 temp.push_back(preDef + nll(importNode));
9232 } 9293 }
9233 temp.push_back(indent() + "do"s + nll(importNode)); 9294 if (!currentScope().lastStatement) {
9234 pushScope(); 9295 extraScope = true;
9296 temp.push_back(indent() + "do"s + nll(importNode));
9297 pushScope();
9298 }
9235 transformAssignment(objAssign, temp); 9299 transformAssignment(objAssign, temp);
9236 } 9300 }
9237 auto assignment = x->new_ptr<ExpListAssign_t>(); 9301 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -9239,8 +9303,10 @@ private:
9239 assignment->action.set(assign); 9303 assignment->action.set(assign);
9240 transformAssignment(assignment, temp); 9304 transformAssignment(assignment, temp);
9241 if (objAssign) { 9305 if (objAssign) {
9242 popScope(); 9306 if (extraScope) {
9243 temp.push_back(indent() + "end"s + nlr(importNode)); 9307 popScope();
9308 temp.push_back(indent() + "end"s + nlr(importNode));
9309 }
9244 } 9310 }
9245 out.push_back(join(temp)); 9311 out.push_back(join(temp));
9246 auto vars = getAssignVars(assignment); 9312 auto vars = getAssignVars(assignment);
@@ -9485,9 +9551,13 @@ private:
9485 void transformWhileInPlace(While_t* whileNode, str_list& out, ExpList_t* expList = nullptr) { 9551 void transformWhileInPlace(While_t* whileNode, str_list& out, ExpList_t* expList = nullptr) {
9486 auto x = whileNode; 9552 auto x = whileNode;
9487 str_list temp; 9553 str_list temp;
9554 bool extraScope = false;
9488 if (expList) { 9555 if (expList) {
9489 temp.push_back(indent() + "do"s + nll(whileNode)); 9556 if (!currentScope().lastStatement) {
9490 pushScope(); 9557 extraScope = true;
9558 temp.push_back(indent() + "do"s + nll(whileNode));
9559 pushScope();
9560 }
9491 } 9561 }
9492 auto accumVar = getUnusedName("_accum_"sv); 9562 auto accumVar = getUnusedName("_accum_"sv);
9493 addToScope(accumVar); 9563 addToScope(accumVar);
@@ -9511,11 +9581,11 @@ private:
9511 assignment->expList.set(expList); 9581 assignment->expList.set(expList);
9512 assignment->action.set(assign); 9582 assignment->action.set(assign);
9513 transformAssignment(assignment, temp); 9583 transformAssignment(assignment, temp);
9514 popScope(); 9584 if (extraScope) popScope();
9515 } else { 9585 } else {
9516 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); 9586 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode));
9517 } 9587 }
9518 if (expList) { 9588 if (expList && extraScope) {
9519 temp.push_back(indent() + "end"s + nlr(whileNode)); 9589 temp.push_back(indent() + "end"s + nlr(whileNode));
9520 } 9590 }
9521 out.push_back(join(temp)); 9591 out.push_back(join(temp));
@@ -9589,6 +9659,7 @@ private:
9589 void transformSwitch(Switch_t* switchNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 9659 void transformSwitch(Switch_t* switchNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
9590 auto x = switchNode; 9660 auto x = switchNode;
9591 str_list temp; 9661 str_list temp;
9662 bool needScope = !currentScope().lastStatement;
9592 std::string* funcStart = nullptr; 9663 std::string* funcStart = nullptr;
9593 if (usage == ExpUsage::Closure) { 9664 if (usage == ExpUsage::Closure) {
9594 auto simpleValue = x->new_ptr<SimpleValue_t>(); 9665 auto simpleValue = x->new_ptr<SimpleValue_t>();
@@ -9605,9 +9676,11 @@ private:
9605 auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); 9676 auto objVar = singleVariableFrom(switchNode->target, AccessType::Read);
9606 if (objVar.empty() || !isLocal(objVar)) { 9677 if (objVar.empty() || !isLocal(objVar)) {
9607 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { 9678 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) {
9608 extraScope = true; 9679 if (needScope) {
9609 temp.push_back(indent() + "do"s + nll(x)); 9680 extraScope = true;
9610 pushScope(); 9681 temp.push_back(indent() + "do"s + nll(x));
9682 pushScope();
9683 }
9611 } 9684 }
9612 objVar = getUnusedName("_exp_"sv); 9685 objVar = getUnusedName("_exp_"sv);
9613 auto expList = toAst<ExpList_t>(objVar, x); 9686 auto expList = toAst<ExpList_t>(objVar, x);
@@ -9640,7 +9713,7 @@ private:
9640 addScope++; 9713 addScope++;
9641 } 9714 }
9642 if (tabCheckVar.empty()) { 9715 if (tabCheckVar.empty()) {
9643 if (!extraScope) { 9716 if (!extraScope && needScope) {
9644 temp.push_back(indent() + "do"s + nll(branch)); 9717 temp.push_back(indent() + "do"s + nll(branch));
9645 pushScope(); 9718 pushScope();
9646 extraScope = true; 9719 extraScope = true;