diff options
| author | Li Jin <dragon-fly@qq.com> | 2022-07-24 22:13:08 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2022-07-24 22:13:08 +0800 |
| commit | 303834e1b1e6cd9cae64b66c2ae44dcd7185238f (patch) | |
| tree | 519f6a1debcc5791d35e06dc5cbb1ce22f9cfd31 /src/yuescript/yue_compiler.cpp | |
| parent | eb367126bf3a4f5b0e51ccef93b7c7136bea170e (diff) | |
| download | yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.tar.gz yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.tar.bz2 yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.zip | |
add option --target=5.1 to generate Lua 5.1 compatible codes. add const destructure. make import item const by default.
Diffstat (limited to '')
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 232 |
1 files changed, 182 insertions, 50 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7bbf5e9..0d027a0 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <memory> | 14 | #include <memory> |
| 15 | #include <set> | 15 | #include <set> |
| 16 | #include <optional> | ||
| 16 | 17 | ||
| 17 | #include "yuescript/yue_parser.h" | 18 | #include "yuescript/yue_parser.h" |
| 18 | #include "yuescript/yue_compiler.h" | 19 | #include "yuescript/yue_compiler.h" |
| @@ -37,9 +38,6 @@ extern "C" { | |||
| 37 | #endif // YUE_NO_MACRO | 38 | #endif // YUE_NO_MACRO |
| 38 | 39 | ||
| 39 | namespace yue { | 40 | namespace yue { |
| 40 | using namespace std::string_view_literals; | ||
| 41 | using namespace std::string_literals; | ||
| 42 | using namespace parserlib; | ||
| 43 | 41 | ||
| 44 | #define BLOCK_START do { | 42 | #define BLOCK_START do { |
| 45 | #define BLOCK_END } while (false); | 43 | #define BLOCK_END } while (false); |
| @@ -56,7 +54,7 @@ using namespace parserlib; | |||
| 56 | 54 | ||
| 57 | typedef std::list<std::string> str_list; | 55 | typedef std::list<std::string> str_list; |
| 58 | 56 | ||
| 59 | const std::string_view version = "0.13.6"sv; | 57 | const std::string_view version = "0.14.0"sv; |
| 60 | const std::string_view extension = "yue"sv; | 58 | const std::string_view extension = "yue"sv; |
| 61 | 59 | ||
| 62 | class YueCompilerImpl { | 60 | class YueCompilerImpl { |
| @@ -1266,8 +1264,8 @@ private: | |||
| 1266 | 1264 | ||
| 1267 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1265 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
| 1268 | auto info = extractDestructureInfo(assignment, true, false); | 1266 | auto info = extractDestructureInfo(assignment, true, false); |
| 1269 | if (!info.first.empty()) { | 1267 | if (!info.destructures.empty()) { |
| 1270 | for (const auto& destruct : info.first) { | 1268 | for (const auto& destruct : info.destructures) { |
| 1271 | str_list defs; | 1269 | str_list defs; |
| 1272 | for (const auto& item : destruct.items) { | 1270 | for (const auto& item : destruct.items) { |
| 1273 | if (!item.targetVar.empty()) { | 1271 | if (!item.targetVar.empty()) { |
| @@ -1319,11 +1317,30 @@ private: | |||
| 1319 | return assignment; | 1317 | return assignment; |
| 1320 | } | 1318 | } |
| 1321 | 1319 | ||
| 1320 | void markDestructureConst(ExpListAssign_t* assignment) { | ||
| 1321 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 1322 | for (auto& destruct : info.destructures) { | ||
| 1323 | for (auto& item : destruct.items) { | ||
| 1324 | if (item.targetVar.empty()) { | ||
| 1325 | throw std::logic_error(_info.errorMessage("can only declare variable as const"sv, item.target)); | ||
| 1326 | } | ||
| 1327 | markVarConst(item.targetVar); | ||
| 1328 | } | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1322 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 1332 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
| 1323 | checkAssignable(assignment->expList); | 1333 | checkAssignable(assignment->expList); |
| 1324 | BLOCK_START | 1334 | BLOCK_START |
| 1325 | auto assign = ast_cast<Assign_t>(assignment->action); | 1335 | auto assign = ast_cast<Assign_t>(assignment->action); |
| 1326 | BREAK_IF(!assign); | 1336 | BREAK_IF(!assign); |
| 1337 | if (assignment->expList->exprs.size() < assign->values.size()) { | ||
| 1338 | auto num = assignment->expList->exprs.size(); | ||
| 1339 | _buf << "no more than "sv << num << " right value"sv; | ||
| 1340 | if (num > 1) _buf << 's'; | ||
| 1341 | _buf << " required"sv; | ||
| 1342 | throw std::logic_error(_info.errorMessage(clearBuf(), assign->values.front())); | ||
| 1343 | } | ||
| 1327 | auto x = assignment; | 1344 | auto x = assignment; |
| 1328 | const auto& exprs = assignment->expList->exprs.objects(); | 1345 | const auto& exprs = assignment->expList->exprs.objects(); |
| 1329 | const auto& values = assign->values.objects(); | 1346 | const auto& values = assign->values.objects(); |
| @@ -1554,15 +1571,15 @@ private: | |||
| 1554 | } | 1571 | } |
| 1555 | BLOCK_END | 1572 | BLOCK_END |
| 1556 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 1573 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
| 1557 | if (info.first.empty()) { | 1574 | if (info.destructures.empty()) { |
| 1558 | transformAssignmentCommon(assignment, out); | 1575 | transformAssignmentCommon(assignment, out); |
| 1559 | } else { | 1576 | } else { |
| 1560 | str_list temp; | 1577 | str_list temp; |
| 1561 | if (info.second) { | 1578 | if (info.assignment) { |
| 1562 | transformAssignmentCommon(info.second, temp); | 1579 | transformAssignmentCommon(info.assignment, temp); |
| 1563 | } | 1580 | } |
| 1564 | auto x = assignment; | 1581 | auto x = assignment; |
| 1565 | for (auto& destruct : info.first) { | 1582 | for (auto& destruct : info.destructures) { |
| 1566 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; | 1583 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
| 1567 | bool extraScope = false; | 1584 | bool extraScope = false; |
| 1568 | if (destruct.items.size() == 1) { | 1585 | if (destruct.items.size() == 1) { |
| @@ -2030,24 +2047,22 @@ private: | |||
| 2030 | return pairs; | 2047 | return pairs; |
| 2031 | } | 2048 | } |
| 2032 | 2049 | ||
| 2033 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 2050 | struct DestructureInfo { |
| 2034 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | 2051 | std::list<Destructure> destructures; |
| 2052 | ast_ptr<false, ExpListAssign_t> assignment; | ||
| 2053 | }; | ||
| 2054 | |||
| 2055 | DestructureInfo extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | ||
| 2035 | auto x = assignment; | 2056 | auto x = assignment; |
| 2036 | std::list<Destructure> destructs; | 2057 | std::list<Destructure> destructs; |
| 2037 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2058 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
| 2038 | auto exprs = assignment->expList->exprs.objects(); | 2059 | auto exprs = assignment->expList->exprs.objects(); |
| 2039 | auto values = assignment->action.to<Assign_t>()->values.objects(); | 2060 | auto values = assignment->action.to<Assign_t>()->values.objects(); |
| 2040 | size_t size = std::max(exprs.size(), values.size()); | 2061 | size_t size = std::max(exprs.size(), values.size()); |
| 2041 | ast_list<false, ast_node> cache; | 2062 | ast_ptr<false, Exp_t> nil; |
| 2042 | if (exprs.size() < size) { | ||
| 2043 | auto var = toAst<Exp_t>("_"sv, x); | ||
| 2044 | cache.push_back(var); | ||
| 2045 | while (exprs.size() < size) exprs.emplace_back(var); | ||
| 2046 | } | ||
| 2047 | ast_ptr<false, Exp_t> nullNode; | ||
| 2048 | if (values.size() < size) { | 2063 | if (values.size() < size) { |
| 2049 | nullNode = toAst<Exp_t>("nil"sv, x); | 2064 | nil = toAst<Exp_t>("nil"sv, x); |
| 2050 | while (values.size() < size) values.emplace_back(nullNode); | 2065 | while (values.size() < size) values.emplace_back(nil); |
| 2051 | } | 2066 | } |
| 2052 | using iter = node_container::iterator; | 2067 | using iter = node_container::iterator; |
| 2053 | std::vector<std::pair<iter, iter>> destructPairs; | 2068 | std::vector<std::pair<iter, iter>> destructPairs; |
| @@ -2059,11 +2074,11 @@ private: | |||
| 2059 | auto value = singleValueFrom(expr); | 2074 | auto value = singleValueFrom(expr); |
| 2060 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); | 2075 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); |
| 2061 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { | 2076 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { |
| 2062 | if (*j != nullNode) { | 2077 | if (*j != nil) { |
| 2063 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 2078 | if (auto ssVal = simpleSingleValueFrom(*j)) { |
| 2064 | switch (ssVal->value->getId()) { | 2079 | switch (ssVal->value->getId()) { |
| 2065 | case id<const_value_t>(): | 2080 | case id<const_value_t>(): |
| 2066 | throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); | 2081 | throw std::logic_error(_info.errorMessage("can not destructure a constant"sv, ssVal->value)); |
| 2067 | break; | 2082 | break; |
| 2068 | case id<Num_t>(): | 2083 | case id<Num_t>(): |
| 2069 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); | 2084 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); |
| @@ -2074,7 +2089,7 @@ private: | |||
| 2074 | } | 2089 | } |
| 2075 | } | 2090 | } |
| 2076 | } else { | 2091 | } else { |
| 2077 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); | 2092 | throw std::logic_error(_info.errorMessage("an explicit destructure target required"sv, destructNode)); |
| 2078 | } | 2093 | } |
| 2079 | destructPairs.push_back({i, j}); | 2094 | destructPairs.push_back({i, j}); |
| 2080 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2095 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
| @@ -2173,7 +2188,7 @@ private: | |||
| 2173 | } | 2188 | } |
| 2174 | destruct.items = std::move(pairs); | 2189 | destruct.items = std::move(pairs); |
| 2175 | if (!varDefOnly) { | 2190 | if (!varDefOnly) { |
| 2176 | if (*j == nullNode) { | 2191 | if (*j == nil) { |
| 2177 | for (auto& item : destruct.items) { | 2192 | for (auto& item : destruct.items) { |
| 2178 | item.structure.clear(); | 2193 | item.structure.clear(); |
| 2179 | } | 2194 | } |
| @@ -3104,8 +3119,8 @@ private: | |||
| 3104 | } | 3119 | } |
| 3105 | } | 3120 | } |
| 3106 | auto info = extractDestructureInfo(assignment, true, false); | 3121 | auto info = extractDestructureInfo(assignment, true, false); |
| 3107 | if (!info.first.empty()) { | 3122 | if (!info.destructures.empty()) { |
| 3108 | for (const auto& destruct : info.first) | 3123 | for (const auto& destruct : info.destructures) |
| 3109 | for (const auto& item : destruct.items) | 3124 | for (const auto& item : destruct.items) |
| 3110 | if (!item.targetVar.empty()) { | 3125 | if (!item.targetVar.empty()) { |
| 3111 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); | 3126 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); |
| @@ -3114,8 +3129,8 @@ private: | |||
| 3114 | } | 3129 | } |
| 3115 | } | 3130 | } |
| 3116 | } | 3131 | } |
| 3117 | if (info.second) { | 3132 | if (info.assignment) { |
| 3118 | auto defs = transformAssignDefs(info.second->expList, DefOp::Get); | 3133 | auto defs = transformAssignDefs(info.assignment->expList, DefOp::Get); |
| 3119 | for (const auto& def : defs) { | 3134 | for (const auto& def : defs) { |
| 3120 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); | 3135 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); |
| 3121 | } else if (any) { | 3136 | } else if (any) { |
| @@ -3236,6 +3251,49 @@ private: | |||
| 3236 | } | 3251 | } |
| 3237 | } | 3252 | } |
| 3238 | 3253 | ||
| 3254 | std::optional<std::string> getOption(std::string_view key) { | ||
| 3255 | #ifndef YUE_NO_MACRO | ||
| 3256 | if (L) { | ||
| 3257 | int top = lua_gettop(L); | ||
| 3258 | DEFER(lua_settop(L, top)); | ||
| 3259 | pushYue("options"sv); // options | ||
| 3260 | lua_pushlstring(L, &key.front(), key.size()); | ||
| 3261 | lua_gettable(L, -2); | ||
| 3262 | if (lua_isstring(L, -1) != 0) { | ||
| 3263 | size_t size = 0; | ||
| 3264 | const char* str = lua_tolstring(L, -1, &size); | ||
| 3265 | return std::string(str, size); | ||
| 3266 | } | ||
| 3267 | } | ||
| 3268 | #endif // YUE_NO_MACRO | ||
| 3269 | auto it = _config.options.find(std::string(key)); | ||
| 3270 | if (it != _config.options.end()) { | ||
| 3271 | return it->second; | ||
| 3272 | } | ||
| 3273 | return std::nullopt; | ||
| 3274 | } | ||
| 3275 | |||
| 3276 | int getLuaTarget(ast_node* x) { | ||
| 3277 | if (auto target = getOption("target")) { | ||
| 3278 | if (target.value() == "5.1"sv) { | ||
| 3279 | return 501; | ||
| 3280 | } else if (target.value() == "5.2"sv) { | ||
| 3281 | return 502; | ||
| 3282 | } else if (target.value() == "5.3"sv) { | ||
| 3283 | return 503; | ||
| 3284 | } else if (target.value() == "5.4"sv) { | ||
| 3285 | return 504; | ||
| 3286 | } else { | ||
| 3287 | throw std::logic_error(_info.errorMessage("get invalid Lua target \""s + target.value() + "\", should be 5.1, 5.2, 5.3 or 5.4"s, x)); | ||
| 3288 | } | ||
| 3289 | } | ||
| 3290 | #ifndef YUE_NO_MACRO | ||
| 3291 | return LUA_VERSION_NUM; | ||
| 3292 | #else | ||
| 3293 | return 504; | ||
| 3294 | #endif // YUE_NO_MACRO | ||
| 3295 | } | ||
| 3296 | |||
| 3239 | #ifndef YUE_NO_MACRO | 3297 | #ifndef YUE_NO_MACRO |
| 3240 | void passOptions() { | 3298 | void passOptions() { |
| 3241 | if (!_config.options.empty()) { | 3299 | if (!_config.options.empty()) { |
| @@ -5898,8 +5956,8 @@ private: | |||
| 5898 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 5956 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 5899 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 5957 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
| 5900 | auto info = extractDestructureInfo(assignment, true, false); | 5958 | auto info = extractDestructureInfo(assignment, true, false); |
| 5901 | if (!info.first.empty()) { | 5959 | if (!info.destructures.empty()) { |
| 5902 | for (const auto& destruct : info.first) | 5960 | for (const auto& destruct : info.destructures) |
| 5903 | for (const auto& item : destruct.items) | 5961 | for (const auto& item : destruct.items) |
| 5904 | if (!item.targetVar.empty() && addToScope(item.targetVar)) | 5962 | if (!item.targetVar.empty() && addToScope(item.targetVar)) |
| 5905 | varDefs.push_back(item.targetVar); | 5963 | varDefs.push_back(item.targetVar); |
| @@ -6329,8 +6387,8 @@ private: | |||
| 6329 | return traversal::Stop; | 6387 | return traversal::Stop; |
| 6330 | } | 6388 | } |
| 6331 | auto info = extractDestructureInfo(assignment, true, false); | 6389 | auto info = extractDestructureInfo(assignment, true, false); |
| 6332 | if (!info.first.empty()) { | 6390 | if (!info.destructures.empty()) { |
| 6333 | for (const auto& destruct : info.first) | 6391 | for (const auto& destruct : info.destructures) |
| 6334 | for (const auto& item : destruct.items) | 6392 | for (const auto& item : destruct.items) |
| 6335 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) | 6393 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) |
| 6336 | return traversal::Stop; | 6394 | return traversal::Stop; |
| @@ -6481,8 +6539,8 @@ private: | |||
| 6481 | transformAssignment(assignment, out); | 6539 | transformAssignment(assignment, out); |
| 6482 | str_list names = transformAssignDefs(expList, DefOp::Get); | 6540 | str_list names = transformAssignDefs(expList, DefOp::Get); |
| 6483 | auto info = extractDestructureInfo(assignment, true, false); | 6541 | auto info = extractDestructureInfo(assignment, true, false); |
| 6484 | if (!info.first.empty()) { | 6542 | if (!info.destructures.empty()) { |
| 6485 | for (const auto& destruct : info.first) | 6543 | for (const auto& destruct : info.destructures) |
| 6486 | for (const auto& item : destruct.items) | 6544 | for (const auto& item : destruct.items) |
| 6487 | if (!item.targetVar.empty()) | 6545 | if (!item.targetVar.empty()) |
| 6488 | names.push_back(item.targetVar); | 6546 | names.push_back(item.targetVar); |
| @@ -6848,6 +6906,7 @@ private: | |||
| 6848 | temp.push_back(indent() + "end"s + nlr(import)); | 6906 | temp.push_back(indent() + "end"s + nlr(import)); |
| 6849 | } | 6907 | } |
| 6850 | out.push_back(join(temp)); | 6908 | out.push_back(join(temp)); |
| 6909 | markDestructureConst(assignment); | ||
| 6851 | } | 6910 | } |
| 6852 | 6911 | ||
| 6853 | std::string moduleNameFrom(ImportLiteral_t* literal) { | 6912 | std::string moduleNameFrom(ImportLiteral_t* literal) { |
| @@ -7013,6 +7072,12 @@ private: | |||
| 7013 | assignment->expList.set(assignList); | 7072 | assignment->expList.set(assignList); |
| 7014 | assignment->action.set(assign); | 7073 | assignment->action.set(assign); |
| 7015 | transformAssignment(assignment, out); | 7074 | transformAssignment(assignment, out); |
| 7075 | if (auto var = ast_cast<Variable_t>(target)) { | ||
| 7076 | auto moduleName = _parser.toString(var); | ||
| 7077 | markVarConst(moduleName); | ||
| 7078 | } else { | ||
| 7079 | markDestructureConst(assignment); | ||
| 7080 | } | ||
| 7016 | } | 7081 | } |
| 7017 | 7082 | ||
| 7018 | void transformImport(Import_t* import, str_list& out) { | 7083 | void transformImport(Import_t* import, str_list& out) { |
| @@ -7191,7 +7256,7 @@ private: | |||
| 7191 | auto info = extractDestructureInfo(assignment, true, false); | 7256 | auto info = extractDestructureInfo(assignment, true, false); |
| 7192 | transformAssignment(assignment, temp, true); | 7257 | transformAssignment(assignment, temp, true); |
| 7193 | str_list conds; | 7258 | str_list conds; |
| 7194 | for (const auto& destruct : info.first) { | 7259 | for (const auto& destruct : info.destructures) { |
| 7195 | for (const auto& item : destruct.items) { | 7260 | for (const auto& item : destruct.items) { |
| 7196 | if (!item.defVal) { | 7261 | if (!item.defVal) { |
| 7197 | transformExp(item.target, conds, ExpUsage::Closure); | 7262 | transformExp(item.target, conds, ExpUsage::Closure); |
| @@ -7334,23 +7399,84 @@ private: | |||
| 7334 | 7399 | ||
| 7335 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { | 7400 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { |
| 7336 | auto x = localAttrib; | 7401 | auto x = localAttrib; |
| 7337 | auto attrib = _parser.toString(localAttrib->attrib); | 7402 | if (x->leftList.size() < x->assign->values.size()) { |
| 7338 | str_list vars; | 7403 | throw std::logic_error(_info.errorMessage("number of right values should not be greater than left values"sv, x->assign->values.front())); |
| 7339 | for (auto name : localAttrib->nameList->names.objects()) { | 7404 | } |
| 7340 | auto var = _parser.toString(name); | 7405 | auto listA = x->new_ptr<NameList_t>(); |
| 7341 | forceAddToScope(var); | 7406 | auto assignA = x->new_ptr<Assign_t>(); |
| 7342 | vars.push_back(var); | 7407 | auto listB = x->new_ptr<ExpList_t>(); |
| 7408 | auto assignB = x->new_ptr<Assign_t>(); | ||
| 7409 | auto i = x->leftList.objects().begin(); | ||
| 7410 | auto ie = x->leftList.objects().end(); | ||
| 7411 | auto j = x->assign->values.objects().begin(); | ||
| 7412 | auto je = x->assign->values.objects().end(); | ||
| 7413 | while (i != ie) { | ||
| 7414 | if (ast_is<Variable_t>(*i)) { | ||
| 7415 | listA->names.push_back(*i); | ||
| 7416 | if (j != je) assignA->values.push_back(*j); | ||
| 7417 | } else { | ||
| 7418 | auto item = *i; | ||
| 7419 | auto value = item->new_ptr<Value_t>(); | ||
| 7420 | switch (item->getId()) { | ||
| 7421 | case id<simple_table_t>(): | ||
| 7422 | value->item.set(item); | ||
| 7423 | break; | ||
| 7424 | case id<TableLit_t>(): { | ||
| 7425 | auto simpleValue = item->new_ptr<SimpleValue_t>(); | ||
| 7426 | simpleValue->value.set(item); | ||
| 7427 | value->item.set(simpleValue); | ||
| 7428 | break; | ||
| 7429 | } | ||
| 7430 | default: YUEE("AST node mismatch", item); break; | ||
| 7431 | } | ||
| 7432 | auto exp = newExp(value, item); | ||
| 7433 | listB->exprs.push_back(exp); | ||
| 7434 | if (j != je) assignB->values.push_back(*j); | ||
| 7435 | } | ||
| 7436 | ++i; | ||
| 7437 | if (j != je) ++j; | ||
| 7343 | } | 7438 | } |
| 7344 | attrib = " <"s + attrib + '>'; | 7439 | if (!listA->names.empty()) { |
| 7345 | for (auto& var : vars) { | 7440 | str_list vars; |
| 7346 | markVarConst(var); | 7441 | for (auto name : listA->names.objects()) { |
| 7347 | var.append(attrib); | 7442 | auto var = _parser.toString(name); |
| 7443 | forceAddToScope(var); | ||
| 7444 | vars.push_back(var); | ||
| 7445 | } | ||
| 7446 | if (getLuaTarget(x) >= 504) { | ||
| 7447 | std::string attrib; | ||
| 7448 | if (localAttrib->attrib.is<const_attrib_t>()) { | ||
| 7449 | attrib = " <const>"s; | ||
| 7450 | } else if (localAttrib->attrib.is<close_attrib_t>()) { | ||
| 7451 | attrib = " <close>"s; | ||
| 7452 | } else { | ||
| 7453 | YUEE("AST node mismatch", localAttrib->attrib); | ||
| 7454 | } | ||
| 7455 | for (auto& var : vars) { | ||
| 7456 | markVarConst(var); | ||
| 7457 | var.append(attrib); | ||
| 7458 | } | ||
| 7459 | } else { | ||
| 7460 | if (localAttrib->attrib.is<close_attrib_t>()) { | ||
| 7461 | throw std::logic_error(_info.errorMessage("close attribute is not available when not targeting Lua 5.4 or higher version"sv, x)); | ||
| 7462 | } | ||
| 7463 | for (auto& var : vars) { | ||
| 7464 | markVarConst(var); | ||
| 7465 | } | ||
| 7466 | } | ||
| 7467 | str_list temp; | ||
| 7468 | for (auto item : assignA->values.objects()) { | ||
| 7469 | transformAssignItem(item, temp); | ||
| 7470 | } | ||
| 7471 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
| 7348 | } | 7472 | } |
| 7349 | str_list temp; | 7473 | if (!listB->exprs.empty()) { |
| 7350 | for (auto item : localAttrib->assign->values.objects()) { | 7474 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 7351 | transformAssignItem(item, temp); | 7475 | assignment->expList.set(listB); |
| 7476 | assignment->action.set(assignB); | ||
| 7477 | transformAssignment(assignment, out); | ||
| 7478 | markDestructureConst(assignment); | ||
| 7352 | } | 7479 | } |
| 7353 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
| 7354 | } | 7480 | } |
| 7355 | 7481 | ||
| 7356 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 7482 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
| @@ -7372,10 +7498,16 @@ private: | |||
| 7372 | } | 7498 | } |
| 7373 | 7499 | ||
| 7374 | void transformLabel(Label_t* label, str_list& out) { | 7500 | void transformLabel(Label_t* label, str_list& out) { |
| 7501 | if (getLuaTarget(label) < 502) { | ||
| 7502 | throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua 5.2 or higher version"sv, label)); | ||
| 7503 | } | ||
| 7375 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); | 7504 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); |
| 7376 | } | 7505 | } |
| 7377 | 7506 | ||
| 7378 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 7507 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
| 7508 | if (getLuaTarget(gotoNode) < 502) { | ||
| 7509 | throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua 5.2 or higher version"sv, gotoNode)); | ||
| 7510 | } | ||
| 7379 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); | 7511 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); |
| 7380 | } | 7512 | } |
| 7381 | 7513 | ||
