aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-12-28 15:55:15 +0800
committerLi Jin <dragon-fly@qq.com>2022-12-28 15:55:15 +0800
commitdba662758192b41648e6c1201083d83926f07783 (patch)
tree4eca06097fce6ac52bbf5276a6ac2da4affb90d0 /src
parent5e453de810f8a5e54351609857d742481f057498 (diff)
downloadyuescript-dba662758192b41648e6c1201083d83926f07783.tar.gz
yuescript-dba662758192b41648e6c1201083d83926f07783.tar.bz2
yuescript-dba662758192b41648e6c1201083d83926f07783.zip
add metamethods checking.
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_compiler.cpp112
1 files changed, 102 insertions, 10 deletions
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
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.15.18"sv; 63static 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
74const std::string_view version = "0.15.19"sv;
64const std::string_view extension = "yue"sv; 75const std::string_view extension = "yue"sv;
65 76
66class YueCompilerImpl { 77class 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));