aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-12-19 11:26:23 +0800
committerLi Jin <dragon-fly@qq.com>2024-12-19 11:30:01 +0800
commitf38c4f94c9ba0499d923e59483d6381b97cce926 (patch)
tree945fd3658a9018dc2558ddf4f2c95d17e3a80091
parent8a3d78c4d5bfe2ba39173e91146025278bf0deb2 (diff)
downloadyuescript-0.26.1.tar.gz
yuescript-0.26.1.tar.bz2
yuescript-0.26.1.zip
Fixed MoonScript issue # 459.v0.26.1
Supported local/const/close hoist in class body.
-rw-r--r--spec/inputs/class.yue15
-rw-r--r--spec/outputs/class.lua60
-rw-r--r--src/yuescript/yue_ast.h2
-rw-r--r--src/yuescript/yue_compiler.cpp99
4 files changed, 169 insertions, 7 deletions
diff --git a/spec/inputs/class.yue b/spec/inputs/class.yue
index 49537c2..3c73ebc 100644
--- a/spec/inputs/class.yue
+++ b/spec/inputs/class.yue
@@ -242,4 +242,19 @@ class Foo
242 :add 242 :add
243 :<add> 243 :<add>
244 244
245do
246 global xa, xb
247 class CX
248 xa = 1
249 xb = 1
250 new: =>
251
252do
253 class CY
254 xa = 1
255 local xb = 2
256 new: => print xa, xb, xc, xd
257 const xc = 3
258 close xd = <close>: =>
259
245nil 260nil
diff --git a/spec/outputs/class.lua b/spec/outputs/class.lua
index 442ff4b..aaea33c 100644
--- a/spec/outputs/class.lua
+++ b/spec/outputs/class.lua
@@ -1229,4 +1229,64 @@ do
1229 _base_0.__class = _class_0 1229 _base_0.__class = _class_0
1230 Foo = _class_0 1230 Foo = _class_0
1231end 1231end
1232do
1233 local CX
1234 do
1235 local _class_0
1236 local _base_0 = { }
1237 if _base_0.__index == nil then
1238 _base_0.__index = _base_0
1239 end
1240 _class_0 = setmetatable({
1241 __init = function(self) end,
1242 __base = _base_0,
1243 __name = "CX"
1244 }, {
1245 __index = _base_0,
1246 __call = function(cls, ...)
1247 local _self_0 = setmetatable({ }, _base_0)
1248 cls.__init(_self_0, ...)
1249 return _self_0
1250 end
1251 })
1252 _base_0.__class = _class_0
1253 local self = _class_0;
1254 xa = 1
1255 xb = 1
1256 CX = _class_0
1257 end
1258end
1259do
1260 local CY
1261 local _class_0
1262 local xa, xb, xc, xd
1263 local _base_0 = { }
1264 if _base_0.__index == nil then
1265 _base_0.__index = _base_0
1266 end
1267 _class_0 = setmetatable({
1268 __init = function(self)
1269 return print(xa, xb, xc, xd)
1270 end,
1271 __base = _base_0,
1272 __name = "CY"
1273 }, {
1274 __index = _base_0,
1275 __call = function(cls, ...)
1276 local _self_0 = setmetatable({ }, _base_0)
1277 cls.__init(_self_0, ...)
1278 return _self_0
1279 end
1280 })
1281 _base_0.__class = _class_0
1282 local self = _class_0;
1283 xa = 1
1284 xb = 2
1285 xc = 3
1286 xd = setmetatable({ }, {
1287 __close = function(self) end
1288 })
1289 local _close_0 <close> = xd
1290 CY = _class_0
1291end
1232return nil 1292return nil
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 92d67ac..033fe30 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -52,7 +52,6 @@ std::string_view ast_name() { return {}; }
52namespace yue { 52namespace yue {
53class ExpListLow_t; 53class ExpListLow_t;
54class TableBlock_t; 54class TableBlock_t;
55class Attrib_t;
56class SimpleTable_t; 55class SimpleTable_t;
57class TableLit_t; 56class TableLit_t;
58class Assign_t; 57class Assign_t;
@@ -181,6 +180,7 @@ AST_NODE(LocalAttrib)
181 ast_ptr<true, Seperator_t> sep; 180 ast_ptr<true, Seperator_t> sep;
182 ast_sel_list<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> leftList; 181 ast_sel_list<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> leftList;
183 ast_ptr<true, Assign_t> assign; 182 ast_ptr<true, Assign_t> assign;
183 bool forceLocal = true;
184 AST_MEMBER(LocalAttrib, &attrib, &sep, &leftList, &assign) 184 AST_MEMBER(LocalAttrib, &attrib, &sep, &leftList, &assign)
185AST_END(LocalAttrib) 185AST_END(LocalAttrib)
186 186
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 240e3b5..0b5a8c1 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.26.0"sv; 78const std::string_view version = "0.26.1"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -8701,12 +8701,15 @@ private:
8701 auto classVar = getUnusedName("_class_"sv); 8701 auto classVar = getUnusedName("_class_"sv);
8702 addToScope(classVar); 8702 addToScope(classVar);
8703 temp.push_back(indent() + "local "s + classVar + nll(classDecl)); 8703 temp.push_back(indent() + "local "s + classVar + nll(classDecl));
8704 auto block = classDecl->new_ptr<Block_t>();
8705 str_list classConstVars;
8704 if (body) { 8706 if (body) {
8705 str_list varDefs; 8707 str_list varDefs;
8706 for (auto item : body->contents.objects()) { 8708 for (auto item : body->contents.objects()) {
8707 if (auto statement = ast_cast<Statement_t>(item)) { 8709 if (auto statement = ast_cast<Statement_t>(item)) {
8708 ClassDecl_t* clsDecl = nullptr; 8710 ClassDecl_t* clsDecl = nullptr;
8709 if (auto assignment = assignmentFrom(statement)) { 8711 if (auto assignment = assignmentFrom(statement)) {
8712 block->statements.push_back(statement);
8710 auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); 8713 auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark);
8711 for (const auto& name : names) { 8714 for (const auto& name : names) {
8712 varDefs.push_back(name.first); 8715 varDefs.push_back(name.first);
@@ -8736,9 +8739,85 @@ private:
8736 clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); 8739 clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>();
8737 BLOCK_END 8740 BLOCK_END
8738 } else if (auto expList = expListFrom(statement)) { 8741 } else if (auto expList = expListFrom(statement)) {
8742 block->statements.push_back(statement);
8739 if (auto value = singleValueFrom(expList)) { 8743 if (auto value = singleValueFrom(expList)) {
8740 clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); 8744 clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>();
8741 } 8745 }
8746 } else if (auto local = statement->content.as<Local_t>()) {
8747 block->statements.push_back(statement);
8748 if (auto values = local->item.as<LocalValues_t>()) {
8749 for (auto name : values->nameList->names.objects()) {
8750 auto varName = variableToString(static_cast<Variable_t*>(name));
8751 forceAddToScope(varName);
8752 varDefs.push_back(varName);
8753 }
8754 }
8755 } else if (auto localAttrib = statement->content.as<LocalAttrib_t>()) {
8756 auto explist = localAttrib->new_ptr<ExpList_t>();
8757 for (auto item : localAttrib->leftList.objects()) {
8758 auto value = item->new_ptr<Value_t>();
8759 switch (item->get_id()) {
8760 case id<Variable_t>(): {
8761 auto callable = item->new_ptr<Callable_t>();
8762 callable->item.set(item);
8763 auto chainValue = item->new_ptr<ChainValue_t>();
8764 chainValue->items.push_back(callable);
8765 value->item.set(chainValue);
8766 break;
8767 }
8768 case id<SimpleTable_t>():
8769 value->item.set(item);
8770 break;
8771 case id<TableLit_t>():
8772 case id<Comprehension_t>(): {
8773 auto simpleValue = item->new_ptr<SimpleValue_t>();
8774 simpleValue->value.set(item);
8775 value->item.set(simpleValue);
8776 break;
8777 }
8778 default: YUEE("AST node mismatch", item); break;
8779 }
8780 explist->exprs.push_back(newExp(value, value));
8781 }
8782 auto assignment = localAttrib->new_ptr<ExpListAssign_t>();
8783 assignment->expList.set(explist);
8784 assignment->action.set(localAttrib->assign);
8785 auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get);
8786 for (const auto& name : names) {
8787 forceAddToScope(name.first);
8788 markVarConst(name.first);
8789 varDefs.push_back(name.first);
8790 classConstVars.push_back(name.first);
8791 }
8792 auto info = extractDestructureInfo(assignment, true, false);
8793 if (!info.destructures.empty()) {
8794 for (const auto& des : info.destructures) {
8795 if (std::holds_alternative<AssignmentPtr>(des)) {
8796 continue;
8797 }
8798 const auto& destruct = std::get<Destructure>(des);
8799 for (const auto& item : destruct.items) {
8800 if (!item.targetVar.empty()) {
8801 forceAddToScope(item.targetVar);
8802 markVarConst(item.targetVar);
8803 varDefs.push_back(item.targetVar);
8804 classConstVars.push_back(item.targetVar);
8805 }
8806 }
8807 }
8808 }
8809 auto stmt = statement->new_ptr<Statement_t>();
8810 stmt->comments.dup(statement->comments);
8811 auto newAttrib = localAttrib->new_ptr<LocalAttrib_t>();
8812 newAttrib->attrib.set(localAttrib->attrib);
8813 newAttrib->leftList.dup(localAttrib->leftList);
8814 newAttrib->assign.set(localAttrib->assign);
8815 newAttrib->forceLocal = false;
8816 stmt->content.set(newAttrib);
8817 stmt->appendix.set(statement->appendix);
8818 block->statements.push_back(stmt);
8819 } else if (statement->content.is<Global_t>()) {
8820 throw CompileError("global statement is not allowed here"sv, statement->content);
8742 } 8821 }
8743 if (clsDecl) { 8822 if (clsDecl) {
8744 std::string clsName; 8823 std::string clsName;
@@ -8786,12 +8865,17 @@ private:
8786 } 8865 }
8787 break; 8866 break;
8788 } 8867 }
8789 case id<Statement_t>(): 8868 case id<Statement_t>(): break;
8790 transformStatement(static_cast<Statement_t*>(content), statements);
8791 break;
8792 default: YUEE("AST node mismatch", content); break; 8869 default: YUEE("AST node mismatch", content); break;
8793 } 8870 }
8794 } 8871 }
8872 for (const auto& classVar : classConstVars) {
8873 auto& scope = _scopes.back();
8874 scope.vars->insert_or_assign(classVar, VarType::Local);
8875 }
8876 for (auto stmt_ : block->statements.objects()) {
8877 transformStatement(static_cast<Statement_t*>(stmt_), statements);
8878 }
8795 for (auto& member : members) { 8879 for (auto& member : members) {
8796 switch (member.type) { 8880 switch (member.type) {
8797 case MemType::Common: 8881 case MemType::Common:
@@ -10608,6 +10692,7 @@ private:
10608 10692
10609 void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { 10693 void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) {
10610 auto x = localAttrib; 10694 auto x = localAttrib;
10695 bool forceLocal = localAttrib->forceLocal;
10611 if (x->leftList.size() < x->assign->values.size()) { 10696 if (x->leftList.size() < x->assign->values.size()) {
10612 auto num = x->leftList.size(); 10697 auto num = x->leftList.size();
10613 if (num > 1) { 10698 if (num > 1) {
@@ -10652,7 +10737,7 @@ private:
10652 ++i; 10737 ++i;
10653 if (j != je) ++j; 10738 if (j != je) ++j;
10654 } 10739 }
10655 bool checkValuesLater = false; 10740 bool checkValuesLater = !forceLocal;
10656 for (ast_node* value : assignA->values.objects()) { 10741 for (ast_node* value : assignA->values.objects()) {
10657 if (ast_is<Exp_t>(value)) { 10742 if (ast_is<Exp_t>(value)) {
10658 if (auto sVal = singleValueFrom(value)) { 10743 if (auto sVal = singleValueFrom(value)) {
@@ -10744,7 +10829,9 @@ private:
10744 } 10829 }
10745 } 10830 }
10746 str_list temp; 10831 str_list temp;
10747 temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); 10832 if (localAttrib->forceLocal) {
10833 temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x));
10834 }
10748 transformAssignment(assignment, temp); 10835 transformAssignment(assignment, temp);
10749 for (const auto& name : vars) { 10836 for (const auto& name : vars) {
10750 markVarConst(name); 10837 markVarConst(name);