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; |
