aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/yue_compiler.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-07-24 22:13:08 +0800
committerLi Jin <dragon-fly@qq.com>2022-07-24 22:13:08 +0800
commit303834e1b1e6cd9cae64b66c2ae44dcd7185238f (patch)
tree519f6a1debcc5791d35e06dc5cbb1ce22f9cfd31 /src/yuescript/yue_compiler.cpp
parenteb367126bf3a4f5b0e51ccef93b7c7136bea170e (diff)
downloadyuescript-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-xsrc/yuescript/yue_compiler.cpp232
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
39namespace yue { 40namespace yue {
40using namespace std::string_view_literals;
41using namespace std::string_literals;
42using 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
57typedef std::list<std::string> str_list; 55typedef std::list<std::string> str_list;
58 56
59const std::string_view version = "0.13.6"sv; 57const std::string_view version = "0.14.0"sv;
60const std::string_view extension = "yue"sv; 58const std::string_view extension = "yue"sv;
61 59
62class YueCompilerImpl { 60class 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