diff options
author | Li Jin <dragon-fly@qq.com> | 2022-12-28 15:55:15 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-12-28 15:55:15 +0800 |
commit | dba662758192b41648e6c1201083d83926f07783 (patch) | |
tree | 4eca06097fce6ac52bbf5276a6ac2da4affb90d0 | |
parent | 5e453de810f8a5e54351609857d742481f057498 (diff) | |
download | yuescript-dba662758192b41648e6c1201083d83926f07783.tar.gz yuescript-dba662758192b41648e6c1201083d83926f07783.tar.bz2 yuescript-dba662758192b41648e6c1201083d83926f07783.zip |
add metamethods checking.
-rw-r--r-- | spec/inputs/import.yue | 7 | ||||
-rw-r--r-- | spec/outputs/destructure.lua | 72 | ||||
-rw-r--r-- | spec/outputs/import.lua | 16 | ||||
-rw-r--r-- | spec/outputs/metatable.lua | 29 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 112 |
5 files changed, 169 insertions, 67 deletions
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index af5545d..fe5caf5 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue | |||
@@ -64,8 +64,9 @@ do | |||
64 | import "org.package.module" as function:func, if:ifVar | 64 | import "org.package.module" as function:func, if:ifVar |
65 | 65 | ||
66 | do | 66 | do |
67 | import "m" as {<a>: b} | 67 | import "m" as {<gc>: b} |
68 | import "m" as {e: f, <a>: c} | 68 | import "m" as {:<index>} |
69 | import "m" as {e: f, <pairs>: c} | ||
69 | import "m" as {c: d} | 70 | import "m" as {c: d} |
70 | import "m" as {g, {<h>: i}} | 71 | import "m" as {g, {<close>: i}} |
71 | 72 | ||
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 8953a2a..cb0eb3f 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
@@ -288,28 +288,31 @@ do | |||
288 | end) | 288 | end) |
289 | end | 289 | end |
290 | end | 290 | end |
291 | local _obj_0 = tb | 291 | local mtx, y, zItem, index |
292 | local mtx, y, zItem = getmetatable(_obj_0.x), _obj_0.y, _obj_0.z | 292 | do |
293 | if mtx == nil then | 293 | local _obj_0 = tb |
294 | mtx = { } | 294 | mtx, y, zItem = getmetatable(_obj_0.x), _obj_0.y, _obj_0.z |
295 | end | 295 | if mtx == nil then |
296 | local index = getmetatable(_obj_0).__index | 296 | mtx = { } |
297 | if index == nil then | 297 | end |
298 | index = function() | 298 | index = getmetatable(_obj_0).__index |
299 | return nil | 299 | if index == nil then |
300 | index = function() | ||
301 | return nil | ||
302 | end | ||
300 | end | 303 | end |
301 | end | 304 | end |
302 | do | 305 | do |
303 | local _tmp_0 | 306 | local _tmp_0 |
304 | do | 307 | do |
305 | local _obj_1 = getmetatable(tb) | 308 | local _obj_0 = getmetatable(tb) |
306 | _tmp_0 = _obj_1.func | 309 | _tmp_0 = _obj_0.func |
307 | end | 310 | end |
308 | if _tmp_0 == nil then | 311 | if _tmp_0 == nil then |
309 | do | 312 | do |
310 | local _obj_1 = item | 313 | local _obj_0 = item |
311 | if _obj_1 ~= nil then | 314 | if _obj_0 ~= nil then |
312 | _tmp_0 = _obj_1.defVal | 315 | _tmp_0 = _obj_0.defVal |
313 | end | 316 | end |
314 | end | 317 | end |
315 | end | 318 | end |
@@ -455,9 +458,12 @@ do | |||
455 | end | 458 | end |
456 | end | 459 | end |
457 | do | 460 | do |
458 | local _obj_0 = tb | 461 | local value, value_meta |
459 | local value = _obj_0[name] | 462 | do |
460 | local value_meta = getmetatable(_obj_0)[name] | 463 | local _obj_0 = tb |
464 | value = _obj_0[name] | ||
465 | value_meta = getmetatable(_obj_0)[name] | ||
466 | end | ||
461 | end | 467 | end |
462 | do | 468 | do |
463 | local tostring, add | 469 | local tostring, add |
@@ -492,16 +498,15 @@ do | |||
492 | end | 498 | end |
493 | do | 499 | do |
494 | local tb = { } | 500 | local tb = { } |
495 | local _obj_0 = tb | ||
496 | do | 501 | do |
497 | local _tmp_0 = c() | 502 | local _tmp_0 = c() |
498 | local v2 = _obj_0[_tmp_0] | 503 | local v2 = tb[_tmp_0] |
499 | end | 504 | end |
500 | local v1 | 505 | local v1 |
501 | do | 506 | do |
502 | local _obj_1 = getmetatable(_obj_0) | 507 | local _obj_0 = getmetatable(tb) |
503 | local _tmp_1 = a + b | 508 | local _tmp_1 = a + b |
504 | v1 = _obj_1[_tmp_1] | 509 | v1 = _obj_0[_tmp_1] |
505 | end | 510 | end |
506 | end | 511 | end |
507 | do | 512 | do |
@@ -575,16 +580,15 @@ do | |||
575 | local _tab_0 = type(_exp_0) | 580 | local _tab_0 = type(_exp_0) |
576 | _tab_0 = "table" == _tab_0 or "userdata" == _tab_0 | 581 | _tab_0 = "table" == _tab_0 or "userdata" == _tab_0 |
577 | if _tab_0 then | 582 | if _tab_0 then |
578 | local _obj_0 = _exp_0 | ||
579 | do | 583 | do |
580 | local _obj_1 = _obj_0.c | 584 | local _obj_0 = _exp_0.c |
581 | local _type_0 = type(_obj_1) | 585 | local _type_0 = type(_obj_0) |
582 | if "table" == _type_0 or "userdata" == _type_0 then | 586 | if "table" == _type_0 or "userdata" == _type_0 then |
583 | do | 587 | do |
584 | local _obj_2 = getmetatable(_obj_1) | 588 | local _obj_1 = getmetatable(_obj_0) |
585 | local _type_1 = type(_obj_2) | 589 | local _type_1 = type(_obj_1) |
586 | if "table" == _type_1 or "userdata" == _type_1 then | 590 | if "table" == _type_1 or "userdata" == _type_1 then |
587 | meta_field = _obj_2["abc"] | 591 | meta_field = _obj_1["abc"] |
588 | end | 592 | end |
589 | end | 593 | end |
590 | end | 594 | end |
@@ -593,19 +597,19 @@ do | |||
593 | meta_field = "def" | 597 | meta_field = "def" |
594 | end | 598 | end |
595 | do | 599 | do |
596 | local _obj_1 = getmetatable(_obj_0) | 600 | local _obj_0 = getmetatable(_exp_0) |
597 | do | 601 | do |
598 | local _obj_2 = _obj_1[ [[any string]]] | 602 | local _obj_1 = _obj_0[ [[any string]]] |
599 | local _type_0 = type(_obj_2) | 603 | local _type_0 = type(_obj_1) |
600 | if "table" == _type_0 or "userdata" == _type_0 then | 604 | if "table" == _type_0 or "userdata" == _type_0 then |
601 | abc = _obj_2.d | 605 | abc = _obj_1.d |
602 | end | 606 | end |
603 | end | 607 | end |
604 | do | 608 | do |
605 | local _obj_2 = _obj_1['str'] | 609 | local _obj_1 = _obj_0['str'] |
606 | local _type_0 = type(_obj_2) | 610 | local _type_0 = type(_obj_1) |
607 | if "table" == _type_0 or "userdata" == _type_0 then | 611 | if "table" == _type_0 or "userdata" == _type_0 then |
608 | def = _obj_2.e | 612 | def = _obj_1.e |
609 | end | 613 | end |
610 | end | 614 | end |
611 | if abc == nil then | 615 | if abc == nil then |
diff --git a/spec/outputs/import.lua b/spec/outputs/import.lua index edb7c44..f8d6ef0 100644 --- a/spec/outputs/import.lua +++ b/spec/outputs/import.lua | |||
@@ -89,14 +89,18 @@ do | |||
89 | end | 89 | end |
90 | end | 90 | end |
91 | do | 91 | do |
92 | local b = getmetatable(require("m")).__a | 92 | local b = getmetatable(require("m")).__gc |
93 | local _obj_0 = require("m") | 93 | local index = getmetatable(require("m")).__index |
94 | local f = _obj_0.e | 94 | local f, c |
95 | local c = getmetatable(_obj_0).__a | 95 | do |
96 | local _obj_0 = require("m") | ||
97 | f = _obj_0.e | ||
98 | c = getmetatable(_obj_0).__pairs | ||
99 | end | ||
96 | local d = require("m").c | 100 | local d = require("m").c |
97 | local g, i | 101 | local g, i |
98 | do | 102 | do |
99 | local _obj_1 = require("m") | 103 | local _obj_0 = require("m") |
100 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__h | 104 | g, i = _obj_0[1], getmetatable(_obj_0[2]).__close |
101 | end | 105 | end |
102 | end | 106 | end |
diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua index 937136f..907a584 100644 --- a/spec/outputs/metatable.lua +++ b/spec/outputs/metatable.lua | |||
@@ -38,28 +38,29 @@ getmetatable(a).__add = function(x, y) | |||
38 | return x + y | 38 | return x + y |
39 | end | 39 | end |
40 | do | 40 | do |
41 | local _obj_0 = a | 41 | local new = a.new |
42 | local new = _obj_0.new | ||
43 | local close, closeA | 42 | local close, closeA |
44 | do | 43 | do |
45 | local _obj_1 = getmetatable(_obj_0) | 44 | local _obj_0 = getmetatable(a) |
46 | close, closeA = _obj_1.__close, _obj_1.__close | 45 | close, closeA = _obj_0.__close, _obj_0.__close |
47 | end | 46 | end |
48 | print(new, close, closeA) | 47 | print(new, close, closeA) |
49 | end | 48 | end |
50 | do | 49 | do |
51 | local x, new, var, close, closeA, num, add, sub | 50 | local x, new, var, close, closeA, num, add, sub |
52 | local _obj_0, _obj_1 | ||
53 | x, _obj_0, _obj_1 = 123, a.b.c, func() | ||
54 | new, var = _obj_0.new, _obj_0.var | ||
55 | do | ||
56 | local _obj_2 = getmetatable(_obj_0) | ||
57 | close, closeA = _obj_2.__close, _obj_2.__close | ||
58 | end | ||
59 | num = _obj_1.num | ||
60 | do | 51 | do |
61 | local _obj_2 = getmetatable(_obj_1) | 52 | local _obj_0, _obj_1 |
62 | add, sub = _obj_2.__add, _obj_2.__sub | 53 | x, _obj_0, _obj_1 = 123, a.b.c, func() |
54 | new, var = _obj_0.new, _obj_0.var | ||
55 | do | ||
56 | local _obj_2 = getmetatable(_obj_0) | ||
57 | close, closeA = _obj_2.__close, _obj_2.__close | ||
58 | end | ||
59 | num = _obj_1.num | ||
60 | do | ||
61 | local _obj_2 = getmetatable(_obj_1) | ||
62 | add, sub = _obj_2.__add, _obj_2.__sub | ||
63 | end | ||
63 | end | 64 | end |
64 | end | 65 | end |
65 | setmetatable(a.b, { }) | 66 | setmetatable(a.b, { }) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 0d674f8..42310b2 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -60,7 +60,18 @@ namespace yue { | |||
60 | 60 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.15.18"sv; | 63 | static std::unordered_set<std::string> Metamethods = { |
64 | "add"s, "sub"s, "mul"s, "div"s, "mod"s, | ||
65 | "pow"s, "unm"s, "concat"s, "len"s, "eq"s, | ||
66 | "lt"s, "le"s, "index"s, "newindex"s, "call"s, | ||
67 | "gc"s, "mode"s, "tostring"s, "metatable"s, // Lua 5.1 | ||
68 | "pairs"s, "ipairs"s, // Lua 5.2 | ||
69 | "name"s, "idiv"s, "band"s, "bor"s, "bxor"s, | ||
70 | "bnot"s, "shl"s, "shr"s, // Lua 5.3 ipairs deprecated | ||
71 | "close"s // Lua 5.4 | ||
72 | }; | ||
73 | |||
74 | const std::string_view version = "0.15.19"sv; | ||
64 | const std::string_view extension = "yue"sv; | 75 | const std::string_view extension = "yue"sv; |
65 | 76 | ||
66 | class YueCompilerImpl { | 77 | class YueCompilerImpl { |
@@ -1089,6 +1100,46 @@ private: | |||
1089 | return str; | 1100 | return str; |
1090 | } | 1101 | } |
1091 | 1102 | ||
1103 | void checkMetamethod(const std::string& name, ast_node* x) { | ||
1104 | if (Metamethods.find(name) == Metamethods.end()) { | ||
1105 | throw std::logic_error(_info.errorMessage("invalid metamethod name"sv, x)); | ||
1106 | } | ||
1107 | int target = getLuaTarget(x); | ||
1108 | switch (target) { | ||
1109 | case 501: goto metamethod51; | ||
1110 | case 502: goto metamethod52; | ||
1111 | case 503: { | ||
1112 | if (name == "ipairs"sv) { | ||
1113 | throw std::logic_error(_info.errorMessage("metamethod is deprecated since Lua 5.3"sv, x)); | ||
1114 | } | ||
1115 | goto metamethod53; | ||
1116 | } | ||
1117 | case 504: { | ||
1118 | if (name == "ipairs"sv) { | ||
1119 | throw std::logic_error(_info.errorMessage("metamethod is not supported since Lua 5.4"sv, x)); | ||
1120 | } | ||
1121 | goto metamethod54; | ||
1122 | } | ||
1123 | } | ||
1124 | metamethod51: | ||
1125 | if (name == "pairs"sv || name == "ipairs"sv) { | ||
1126 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.2"sv, x)); | ||
1127 | } | ||
1128 | metamethod52: | ||
1129 | if (name == "name"sv || name == "idiv"sv || | ||
1130 | name == "band"sv || name == "bor"sv || | ||
1131 | name == "bxor"sv || name == "bnot"sv || | ||
1132 | name == "shl"sv || name == "shr"sv) { | ||
1133 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.3"sv, x)); | ||
1134 | } | ||
1135 | metamethod53: | ||
1136 | if (name == "close"sv) { | ||
1137 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.4"sv, x)); | ||
1138 | } | ||
1139 | metamethod54: | ||
1140 | return; | ||
1141 | } | ||
1142 | |||
1092 | void transformStatement(Statement_t* statement, str_list& out) { | 1143 | void transformStatement(Statement_t* statement, str_list& out) { |
1093 | auto x = statement; | 1144 | auto x = statement; |
1094 | if (statement->appendix) { | 1145 | if (statement->appendix) { |
@@ -1825,11 +1876,32 @@ private: | |||
1825 | if (info.destructures.empty()) { | 1876 | if (info.destructures.empty()) { |
1826 | transformAssignmentCommon(assignment, out); | 1877 | transformAssignmentCommon(assignment, out); |
1827 | } else { | 1878 | } else { |
1879 | auto x = assignment; | ||
1828 | str_list temp; | 1880 | str_list temp; |
1881 | if (info.extraScope) { | ||
1882 | str_list defs; | ||
1883 | for (auto& destruct : info.destructures) { | ||
1884 | for (auto& item : destruct.items) { | ||
1885 | if (!item.targetVar.empty()) { | ||
1886 | if (!isDefined(item.targetVar)) { | ||
1887 | defs.push_back(item.targetVar); | ||
1888 | } | ||
1889 | } | ||
1890 | } | ||
1891 | } | ||
1892 | if (!defs.empty()) { | ||
1893 | for (const auto& def : defs) { | ||
1894 | checkConst(def, x); | ||
1895 | addToScope(def); | ||
1896 | } | ||
1897 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | ||
1898 | } | ||
1899 | temp.push_back(indent() + "do"s + nll(x)); | ||
1900 | pushScope(); | ||
1901 | } | ||
1829 | if (info.assignment) { | 1902 | if (info.assignment) { |
1830 | transformAssignmentCommon(info.assignment, temp); | 1903 | transformAssignmentCommon(info.assignment, temp); |
1831 | } | 1904 | } |
1832 | auto x = assignment; | ||
1833 | for (auto& destruct : info.destructures) { | 1905 | for (auto& destruct : info.destructures) { |
1834 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; | 1906 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
1835 | bool extraScope = false; | 1907 | bool extraScope = false; |
@@ -1861,7 +1933,7 @@ private: | |||
1861 | } | 1933 | } |
1862 | } | 1934 | } |
1863 | if (!isNil) { | 1935 | if (!isNil) { |
1864 | auto stmt = toAst<Statement_t>(pair.targetVar + "=nil if "s + pair.targetVar + "==nil", pair.defVal); | 1936 | auto stmt = toAst<Statement_t>(pair.targetVar + "=nil if "s + pair.targetVar + "==nil"s, pair.defVal); |
1865 | auto defAssign = stmt->content.as<ExpListAssign_t>(); | 1937 | auto defAssign = stmt->content.as<ExpListAssign_t>(); |
1866 | auto assign = defAssign->action.as<Assign_t>(); | 1938 | auto assign = defAssign->action.as<Assign_t>(); |
1867 | assign->values.clear(); | 1939 | assign->values.clear(); |
@@ -2035,6 +2107,10 @@ private: | |||
2035 | temp.push_back(clearBuf()); | 2107 | temp.push_back(clearBuf()); |
2036 | } | 2108 | } |
2037 | } | 2109 | } |
2110 | if (info.extraScope) { | ||
2111 | popScope(); | ||
2112 | temp.push_back(indent() + "end"s + nlr(x)); | ||
2113 | } | ||
2038 | out.push_back(join(temp)); | 2114 | out.push_back(join(temp)); |
2039 | } | 2115 | } |
2040 | } | 2116 | } |
@@ -2247,6 +2323,7 @@ private: | |||
2247 | } | 2323 | } |
2248 | auto mp = static_cast<meta_variable_pair_t*>(pair); | 2324 | auto mp = static_cast<meta_variable_pair_t*>(pair); |
2249 | auto name = _parser.toString(mp->name); | 2325 | auto name = _parser.toString(mp->name); |
2326 | checkMetamethod(name, mp->name); | ||
2250 | _buf << "__"sv << name << ':' << name; | 2327 | _buf << "__"sv << name << ':' << name; |
2251 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), pair); | 2328 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), pair); |
2252 | newPairDef->defVal.set(defVal); | 2329 | newPairDef->defVal.set(defVal); |
@@ -2266,6 +2343,7 @@ private: | |||
2266 | switch (mp->key->getId()) { | 2343 | switch (mp->key->getId()) { |
2267 | case id<Name_t>(): { | 2344 | case id<Name_t>(): { |
2268 | auto key = _parser.toString(mp->key); | 2345 | auto key = _parser.toString(mp->key); |
2346 | checkMetamethod(key, mp->key); | ||
2269 | _buf << "__"sv << key; | 2347 | _buf << "__"sv << key; |
2270 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | 2348 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); |
2271 | newPair->key.set(newKey); | 2349 | newPair->key.set(newKey); |
@@ -2309,10 +2387,12 @@ private: | |||
2309 | struct DestructureInfo { | 2387 | struct DestructureInfo { |
2310 | std::list<Destructure> destructures; | 2388 | std::list<Destructure> destructures; |
2311 | ast_ptr<false, ExpListAssign_t> assignment; | 2389 | ast_ptr<false, ExpListAssign_t> assignment; |
2390 | bool extraScope = false; | ||
2312 | }; | 2391 | }; |
2313 | 2392 | ||
2314 | DestructureInfo extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | 2393 | DestructureInfo extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { |
2315 | auto x = assignment; | 2394 | auto x = assignment; |
2395 | bool extraScope = false; | ||
2316 | std::list<Destructure> destructs; | 2396 | std::list<Destructure> destructs; |
2317 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2397 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
2318 | auto exprs = assignment->expList->exprs.objects(); | 2398 | auto exprs = assignment->expList->exprs.objects(); |
@@ -2367,6 +2447,7 @@ private: | |||
2367 | auto mvp = static_cast<meta_variable_pair_def_t*>(item); | 2447 | auto mvp = static_cast<meta_variable_pair_def_t*>(item); |
2368 | auto mp = mvp->pair.get(); | 2448 | auto mp = mvp->pair.get(); |
2369 | auto name = _parser.toString(mp->name); | 2449 | auto name = _parser.toString(mp->name); |
2450 | checkMetamethod(name, mp->name); | ||
2370 | _buf << "__"sv << name << ':' << name; | 2451 | _buf << "__"sv << name << ':' << name; |
2371 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), item); | 2452 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), item); |
2372 | newPairDef->defVal.set(mvp->defVal); | 2453 | newPairDef->defVal.set(mvp->defVal); |
@@ -2381,6 +2462,7 @@ private: | |||
2381 | switch (mp->key->getId()) { | 2462 | switch (mp->key->getId()) { |
2382 | case id<Name_t>(): { | 2463 | case id<Name_t>(): { |
2383 | auto key = _parser.toString(mp->key); | 2464 | auto key = _parser.toString(mp->key); |
2465 | checkMetamethod(key, mp->key); | ||
2384 | _buf << "__"sv << key; | 2466 | _buf << "__"sv << key; |
2385 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | 2467 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); |
2386 | newPair->key.set(newKey); | 2468 | newPair->key.set(newKey); |
@@ -2406,6 +2488,7 @@ private: | |||
2406 | case id<meta_variable_pair_t>(): { | 2488 | case id<meta_variable_pair_t>(): { |
2407 | auto mp = static_cast<meta_variable_pair_t*>(item); | 2489 | auto mp = static_cast<meta_variable_pair_t*>(item); |
2408 | auto name = _parser.toString(mp->name); | 2490 | auto name = _parser.toString(mp->name); |
2491 | checkMetamethod(name, mp->name); | ||
2409 | _buf << "__"sv << name << ':' << name; | 2492 | _buf << "__"sv << name << ':' << name; |
2410 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), item); | 2493 | auto newPairDef = toAst<normal_pair_def_t>(clearBuf(), item); |
2411 | subMetaDestruct->values.push_back(newPairDef); | 2494 | subMetaDestruct->values.push_back(newPairDef); |
@@ -2418,6 +2501,7 @@ private: | |||
2418 | switch (mp->key->getId()) { | 2501 | switch (mp->key->getId()) { |
2419 | case id<Name_t>(): { | 2502 | case id<Name_t>(): { |
2420 | auto key = _parser.toString(mp->key); | 2503 | auto key = _parser.toString(mp->key); |
2504 | checkMetamethod(key, mp->key); | ||
2421 | _buf << "__"sv << key; | 2505 | _buf << "__"sv << key; |
2422 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | 2506 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); |
2423 | newPair->key.set(newKey); | 2507 | newPair->key.set(newKey); |
@@ -2462,12 +2546,16 @@ private: | |||
2462 | } | 2546 | } |
2463 | valueItems.push_back(*j); | 2547 | valueItems.push_back(*j); |
2464 | if (!varDefOnly && !subDestruct->values.empty() && !subMetaDestruct->values.empty()) { | 2548 | if (!varDefOnly && !subDestruct->values.empty() && !subMetaDestruct->values.empty()) { |
2465 | auto objVar = getUnusedName("_obj_"sv); | 2549 | auto var = singleVariableFrom(*j, false); |
2466 | addToScope(objVar); | 2550 | if (var.empty() || !isLocal(var)) { |
2467 | valueItems.pop_back(); | 2551 | auto objVar = getUnusedName("_obj_"sv); |
2468 | valueItems.push_back(toAst<Exp_t>(objVar, *j)); | 2552 | addToScope(objVar); |
2469 | exprs.push_back(valueItems.back()); | 2553 | valueItems.pop_back(); |
2470 | values.push_back(*j); | 2554 | valueItems.push_back(toAst<Exp_t>(objVar, *j)); |
2555 | exprs.push_back(valueItems.back()); | ||
2556 | values.push_back(*j); | ||
2557 | extraScope = true; | ||
2558 | } | ||
2471 | } | 2559 | } |
2472 | TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()}; | 2560 | TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()}; |
2473 | for (auto tab : tabs) { | 2561 | for (auto tab : tabs) { |
@@ -2573,7 +2661,7 @@ private: | |||
2573 | } | 2661 | } |
2574 | } | 2662 | } |
2575 | popScope(); | 2663 | popScope(); |
2576 | return {std::move(destructs), newAssignment}; | 2664 | return {std::move(destructs), newAssignment, extraScope}; |
2577 | } | 2665 | } |
2578 | 2666 | ||
2579 | void transformAssignmentCommon(ExpListAssign_t* assignment, str_list& out) { | 2667 | void transformAssignmentCommon(ExpListAssign_t* assignment, str_list& out) { |
@@ -5513,6 +5601,7 @@ private: | |||
5513 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); | 5601 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); |
5514 | } | 5602 | } |
5515 | auto name = _parser.toString(mp->name); | 5603 | auto name = _parser.toString(mp->name); |
5604 | checkMetamethod(name, mp->name); | ||
5516 | _buf << "__"sv << name << ':' << name; | 5605 | _buf << "__"sv << name << ':' << name; |
5517 | auto newPair = toAst<normal_pair_t>(clearBuf(), item); | 5606 | auto newPair = toAst<normal_pair_t>(clearBuf(), item); |
5518 | metatable->pairs.push_back(newPair); | 5607 | metatable->pairs.push_back(newPair); |
@@ -5529,6 +5618,7 @@ private: | |||
5529 | switch (mp->key->getId()) { | 5618 | switch (mp->key->getId()) { |
5530 | case id<Name_t>(): { | 5619 | case id<Name_t>(): { |
5531 | auto key = _parser.toString(mp->key); | 5620 | auto key = _parser.toString(mp->key); |
5621 | checkMetamethod(key, mp->key); | ||
5532 | _buf << "__"sv << key; | 5622 | _buf << "__"sv << key; |
5533 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | 5623 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); |
5534 | newPair->key.set(newKey); | 5624 | newPair->key.set(newKey); |
@@ -6739,6 +6829,7 @@ private: | |||
6739 | case id<meta_variable_pair_t>(): { | 6829 | case id<meta_variable_pair_t>(): { |
6740 | auto mtPair = static_cast<meta_variable_pair_t*>(keyValue); | 6830 | auto mtPair = static_cast<meta_variable_pair_t*>(keyValue); |
6741 | auto nameStr = _parser.toString(mtPair->name); | 6831 | auto nameStr = _parser.toString(mtPair->name); |
6832 | checkMetamethod(nameStr, mtPair->name); | ||
6742 | ref.set(toAst<normal_pair_t>("__"s + nameStr + ':' + nameStr, keyValue)); | 6833 | ref.set(toAst<normal_pair_t>("__"s + nameStr + ':' + nameStr, keyValue)); |
6743 | keyValue = ref.get(); | 6834 | keyValue = ref.get(); |
6744 | break; | 6835 | break; |
@@ -6748,6 +6839,7 @@ private: | |||
6748 | auto normal_pair = keyValue->new_ptr<normal_pair_t>(); | 6839 | auto normal_pair = keyValue->new_ptr<normal_pair_t>(); |
6749 | if (auto name = mtPair->key.as<Name_t>()) { | 6840 | if (auto name = mtPair->key.as<Name_t>()) { |
6750 | auto nameStr = _parser.toString(name); | 6841 | auto nameStr = _parser.toString(name); |
6842 | checkMetamethod(nameStr, name); | ||
6751 | normal_pair->key.set(toAst<KeyName_t>("__"s + nameStr, keyValue)); | 6843 | normal_pair->key.set(toAst<KeyName_t>("__"s + nameStr, keyValue)); |
6752 | } else if (auto str = mtPair->key.as<String_t>()) { | 6844 | } else if (auto str = mtPair->key.as<String_t>()) { |
6753 | normal_pair->key.set(newExp(str, str)); | 6845 | normal_pair->key.set(newExp(str, str)); |