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