diff options
author | Li Jin <dragon-fly@qq.com> | 2024-03-21 09:14:34 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2024-03-21 09:14:34 +0800 |
commit | 4a3cc26c6dfd74e61c8b6480038d6a292ea86e47 (patch) | |
tree | 9554b94cfc15e4acee0c2e60b63af16f1b828207 /src | |
parent | 80b65520da432843f0c63431a1867bd2620bc4ac (diff) | |
download | yuescript-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.cpp | 325 |
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 | ||
78 | const std::string_view version = "0.23.0"sv; | 78 | const std::string_view version = "0.23.1"sv; |
79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
80 | 80 | ||
81 | class CompileError : public std::logic_error { | 81 | class 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; |