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.
Diffstat (limited to '')
| -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)); |
