diff options
author | Li Jin <dragon-fly@qq.com> | 2022-04-25 13:19:26 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-04-25 13:19:45 +0800 |
commit | 10afeaf30bfe03774c12908235520eebf0c192ee (patch) | |
tree | ca266b04aaea63ea0710a51708d6ef806008b34e /src | |
parent | 249e1de1d32dda2b60b9116c5a4e538475de0192 (diff) | |
download | yuescript-10afeaf30bfe03774c12908235520eebf0c192ee.tar.gz yuescript-10afeaf30bfe03774c12908235520eebf0c192ee.tar.bz2 yuescript-10afeaf30bfe03774c12908235520eebf0c192ee.zip |
add spread syntax support for table block. fix a gcc compiler issue. update doc.
Diffstat (limited to 'src')
-rwxr-xr-x | src/yuescript/yue_ast.h | 6 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 351 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.cpp | 9 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.h | 1 |
4 files changed, 227 insertions, 140 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index ed6f7d2..06896b8 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -221,9 +221,11 @@ AST_NODE(ExpList) | |||
221 | AST_MEMBER(ExpList, &sep, &exprs) | 221 | AST_MEMBER(ExpList, &sep, &exprs) |
222 | AST_END(ExpList) | 222 | AST_END(ExpList) |
223 | 223 | ||
224 | class TableBlock_t; | ||
225 | |||
224 | AST_NODE(Return) | 226 | AST_NODE(Return) |
225 | bool allowBlockMacroReturn = false; | 227 | bool allowBlockMacroReturn = false; |
226 | ast_ptr<false, ExpListLow_t> valueList; | 228 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; |
227 | AST_MEMBER(Return, &valueList) | 229 | AST_MEMBER(Return, &valueList) |
228 | AST_END(Return) | 230 | AST_END(Return) |
229 | 231 | ||
@@ -628,7 +630,7 @@ AST_END(TableBlockIndent) | |||
628 | 630 | ||
629 | AST_NODE(TableBlock) | 631 | AST_NODE(TableBlock) |
630 | ast_ptr<true, Seperator_t> sep; | 632 | ast_ptr<true, Seperator_t> sep; |
631 | ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t, default_pair_t, | 633 | ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t, SpreadExp_t, default_pair_t, |
632 | meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values; | 634 | meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values; |
633 | AST_MEMBER(TableBlock, &sep, &values) | 635 | AST_MEMBER(TableBlock, &sep, &values) |
634 | AST_END(TableBlock) | 636 | AST_END(TableBlock) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 6a0fba6..476494e 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -60,7 +60,7 @@ using namespace parserlib; | |||
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.10.14"sv; | 63 | const std::string_view version = "0.10.15"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
@@ -1355,10 +1355,20 @@ private: | |||
1355 | } | 1355 | } |
1356 | case id<TableLit_t>(): { | 1356 | case id<TableLit_t>(): { |
1357 | auto tableLit = static_cast<TableLit_t*>(value); | 1357 | auto tableLit = static_cast<TableLit_t*>(value); |
1358 | if (hasSpreadExp(tableLit)) { | 1358 | if (hasSpreadExp(tableLit->values.objects())) { |
1359 | auto expList = assignment->expList.get(); | 1359 | auto expList = assignment->expList.get(); |
1360 | std::string preDefine = getPredefine(assignment); | 1360 | std::string preDefine = getPredefine(assignment); |
1361 | transformSpreadTableLit(tableLit, out, ExpUsage::Assignment, expList); | 1361 | transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList); |
1362 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | ||
1363 | return; | ||
1364 | } | ||
1365 | } | ||
1366 | case id<TableBlock_t>(): { | ||
1367 | auto tableBlock = static_cast<TableBlock_t*>(value); | ||
1368 | if (hasSpreadExp(tableBlock->values.objects())) { | ||
1369 | auto expList = assignment->expList.get(); | ||
1370 | std::string preDefine = getPredefine(assignment); | ||
1371 | transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList); | ||
1362 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1372 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); |
1363 | return; | 1373 | return; |
1364 | } | 1374 | } |
@@ -3239,7 +3249,7 @@ private: | |||
3239 | if (!target) target = returnNode; | 3249 | if (!target) target = returnNode; |
3240 | throw std::logic_error(_info.errorMessage("illegal return statement here"sv, target)); | 3250 | throw std::logic_error(_info.errorMessage("illegal return statement here"sv, target)); |
3241 | } | 3251 | } |
3242 | if (auto valueList = returnNode->valueList.get()) { | 3252 | if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { |
3243 | if (valueList->exprs.size() == 1) { | 3253 | if (valueList->exprs.size() == 1) { |
3244 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); | 3254 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); |
3245 | if (isPureBackcall(exp)) { | 3255 | if (isPureBackcall(exp)) { |
@@ -3286,8 +3296,8 @@ private: | |||
3286 | return; | 3296 | return; |
3287 | case id<TableLit_t>(): { | 3297 | case id<TableLit_t>(): { |
3288 | auto tableLit = static_cast<TableLit_t*>(value); | 3298 | auto tableLit = static_cast<TableLit_t*>(value); |
3289 | if (hasSpreadExp(tableLit)) { | 3299 | if (hasSpreadExp(tableLit->values.objects())) { |
3290 | transformSpreadTableLit(tableLit, out, ExpUsage::Return); | 3300 | transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Return); |
3291 | return; | 3301 | return; |
3292 | } | 3302 | } |
3293 | } | 3303 | } |
@@ -3306,6 +3316,14 @@ private: | |||
3306 | transformExpListLow(valueList, temp); | 3316 | transformExpListLow(valueList, temp); |
3307 | out.push_back(indent() + "return "s + temp.back() + nlr(returnNode)); | 3317 | out.push_back(indent() + "return "s + temp.back() + nlr(returnNode)); |
3308 | } | 3318 | } |
3319 | } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { | ||
3320 | const auto& values = tableBlock->values.objects(); | ||
3321 | if (hasSpreadExp(values)) { | ||
3322 | transformSpreadTable(values, out, ExpUsage::Return); | ||
3323 | } else { | ||
3324 | transformTable(values, out); | ||
3325 | out.back() = indent() + "return "s + out.back() + nlr(returnNode); | ||
3326 | } | ||
3309 | } else { | 3327 | } else { |
3310 | out.push_back(indent() + "return"s + nll(returnNode)); | 3328 | out.push_back(indent() + "return"s + nll(returnNode)); |
3311 | } | 3329 | } |
@@ -4495,23 +4513,15 @@ private: | |||
4495 | out.push_back(_parser.toString(num)); | 4513 | out.push_back(_parser.toString(num)); |
4496 | } | 4514 | } |
4497 | 4515 | ||
4498 | bool hasSpreadExp(TableLit_t* table) { | 4516 | bool hasSpreadExp(const node_container& items) { |
4499 | for (auto item : table->values.objects()) { | 4517 | for (auto item : items) { |
4500 | if (ast_is<SpreadExp_t>(item)) return true; | 4518 | if (ast_is<SpreadExp_t>(item)) return true; |
4501 | } | 4519 | } |
4502 | return false; | 4520 | return false; |
4503 | } | 4521 | } |
4504 | 4522 | ||
4505 | void transformTableLit(TableLit_t* table, str_list& out) { | 4523 | void transformSpreadTable(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
4506 | if (hasSpreadExp(table)) { | 4524 | auto x = values.front(); |
4507 | transformSpreadTableLit(table, out, ExpUsage::Closure); | ||
4508 | } else { | ||
4509 | transformTable(table, table->values.objects(), out); | ||
4510 | } | ||
4511 | } | ||
4512 | |||
4513 | void transformSpreadTableLit(TableLit_t* table, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | ||
4514 | auto x = table; | ||
4515 | switch (usage) { | 4525 | switch (usage) { |
4516 | case ExpUsage::Closure: | 4526 | case ExpUsage::Closure: |
4517 | _enableReturn.push(true); | 4527 | _enableReturn.push(true); |
@@ -4527,19 +4537,19 @@ private: | |||
4527 | str_list temp; | 4537 | str_list temp; |
4528 | std::string tableVar = getUnusedName("_tab_"sv); | 4538 | std::string tableVar = getUnusedName("_tab_"sv); |
4529 | forceAddToScope(tableVar); | 4539 | forceAddToScope(tableVar); |
4530 | auto it = table->values.objects().begin(); | 4540 | auto it = values.begin(); |
4531 | if (ast_is<SpreadExp_t>(*it)) { | 4541 | if (ast_is<SpreadExp_t>(*it)) { |
4532 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 4542 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); |
4533 | } else { | 4543 | } else { |
4534 | auto initialTab = x->new_ptr<TableLit_t>(); | 4544 | auto initialTab = x->new_ptr<TableLit_t>(); |
4535 | while (it != table->values.objects().end() && !ast_is<SpreadExp_t>(*it)) { | 4545 | while (it != values.end() && !ast_is<SpreadExp_t>(*it)) { |
4536 | initialTab->values.push_back(*it); | 4546 | initialTab->values.push_back(*it); |
4537 | ++it; | 4547 | ++it; |
4538 | } | 4548 | } |
4539 | transformTable(table, initialTab->values.objects(), temp); | 4549 | transformTable(initialTab->values.objects(), temp); |
4540 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); | 4550 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); |
4541 | } | 4551 | } |
4542 | for (; it != table->values.objects().end(); ++it) { | 4552 | for (; it != values.end(); ++it) { |
4543 | auto item = *it; | 4553 | auto item = *it; |
4544 | switch (item->getId()) { | 4554 | switch (item->getId()) { |
4545 | case id<SpreadExp_t>(): { | 4555 | case id<SpreadExp_t>(): { |
@@ -4623,7 +4633,7 @@ private: | |||
4623 | case id<Exp_t>(): { | 4633 | case id<Exp_t>(): { |
4624 | bool lastVarArg = false; | 4634 | bool lastVarArg = false; |
4625 | BLOCK_START | 4635 | BLOCK_START |
4626 | BREAK_IF(item != table->values.back()); | 4636 | BREAK_IF(item != values.back()); |
4627 | auto value = singleValueFrom(item); | 4637 | auto value = singleValueFrom(item); |
4628 | BREAK_IF(!value); | 4638 | BREAK_IF(!value); |
4629 | auto chainValue = value->item.as<ChainValue_t>(); | 4639 | auto chainValue = value->item.as<ChainValue_t>(); |
@@ -4644,6 +4654,66 @@ private: | |||
4644 | } | 4654 | } |
4645 | break; | 4655 | break; |
4646 | } | 4656 | } |
4657 | case id<TableBlockIndent_t>(): { | ||
4658 | auto tbIndent = static_cast<TableBlockIndent_t*>(item); | ||
4659 | auto tableBlock = item->new_ptr<TableBlock_t>(); | ||
4660 | tableBlock->values.dup(tbIndent->values); | ||
4661 | auto assignment = toAst<ExpListAssign_t>(tableVar + "[]=nil"s, item); | ||
4662 | auto assign = assignment->action.to<Assign_t>(); | ||
4663 | assign->values.clear(); | ||
4664 | assign->values.push_back(tableBlock); | ||
4665 | transformAssignment(assignment, temp); | ||
4666 | break; | ||
4667 | } | ||
4668 | case id<TableBlock_t>(): { | ||
4669 | auto assignment = toAst<ExpListAssign_t>(tableVar + "[]=nil"s, item); | ||
4670 | auto assign = assignment->action.to<Assign_t>(); | ||
4671 | assign->values.clear(); | ||
4672 | assign->values.push_back(item); | ||
4673 | transformAssignment(assignment, temp); | ||
4674 | break; | ||
4675 | } | ||
4676 | case id<meta_variable_pair_t>(): { | ||
4677 | auto metaVarPair = static_cast<meta_variable_pair_t*>(item); | ||
4678 | auto nameStr = _parser.toString(metaVarPair->name); | ||
4679 | auto assignment = toAst<ExpListAssign_t>(tableVar + '.' + nameStr + "#="s + nameStr, item); | ||
4680 | transformAssignment(assignment, temp); | ||
4681 | break; | ||
4682 | } | ||
4683 | case id<meta_normal_pair_t>(): { | ||
4684 | auto metaNormalPair = static_cast<meta_normal_pair_t*>(item); | ||
4685 | auto assignment = toAst<ExpListAssign_t>(tableVar + "=nil"s, item); | ||
4686 | auto chainValue = singleValueFrom(ast_to<Exp_t>(assignment->expList->exprs.front()))->item.to<ChainValue_t>(); | ||
4687 | auto key = metaNormalPair->key.get(); | ||
4688 | switch (key->getId()) { | ||
4689 | case id<Name_t>(): { | ||
4690 | auto dotItem = x->new_ptr<DotChainItem_t>(); | ||
4691 | dotItem->name.set(key); | ||
4692 | chainValue->items.push_back(dotItem); | ||
4693 | break; | ||
4694 | } | ||
4695 | case id<Exp_t>(): { | ||
4696 | auto dotItem = toAst<DotChainItem_t>(".#"sv, key); | ||
4697 | chainValue->items.push_back(dotItem); | ||
4698 | chainValue->items.push_back(key); | ||
4699 | break; | ||
4700 | } | ||
4701 | default: YUEE("AST node mismatch", key); break; | ||
4702 | } | ||
4703 | auto assign = assignment->action.to<Assign_t>(); | ||
4704 | assign->values.clear(); | ||
4705 | assign->values.push_back(metaNormalPair->value); | ||
4706 | transformAssignment(assignment, temp); | ||
4707 | break; | ||
4708 | } | ||
4709 | case id<default_pair_t>(): { | ||
4710 | throw std::logic_error(_info.errorMessage("invalid default value"sv, static_cast<default_pair_t*>(item)->defVal)); | ||
4711 | break; | ||
4712 | } | ||
4713 | case id<meta_default_pair_t>(): { | ||
4714 | throw std::logic_error(_info.errorMessage("invalid default value"sv, static_cast<meta_default_pair_t*>(item)->defVal)); | ||
4715 | break; | ||
4716 | } | ||
4647 | default: YUEE("AST node mismatch", item); break; | 4717 | default: YUEE("AST node mismatch", item); break; |
4648 | } | 4718 | } |
4649 | } | 4719 | } |
@@ -4682,6 +4752,123 @@ private: | |||
4682 | } | 4752 | } |
4683 | } | 4753 | } |
4684 | 4754 | ||
4755 | void transformTable(const node_container& values, str_list& out) { | ||
4756 | if (values.empty()) { | ||
4757 | out.push_back("{ }"s); | ||
4758 | return; | ||
4759 | } | ||
4760 | auto x = values.front(); | ||
4761 | str_list temp; | ||
4762 | incIndentOffset(); | ||
4763 | auto metatable = x->new_ptr<simple_table_t>(); | ||
4764 | ast_sel<false, Exp_t, TableBlock_t> metatableItem; | ||
4765 | for (auto item : values) { | ||
4766 | bool isMetamethod = false; | ||
4767 | switch (item->getId()) { | ||
4768 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); break; | ||
4769 | case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(item), temp); break; | ||
4770 | case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(item), temp, false); break; | ||
4771 | case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(item), temp); break; | ||
4772 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(item), temp); break; | ||
4773 | case id<meta_variable_pair_t>(): { | ||
4774 | isMetamethod = true; | ||
4775 | auto mp = static_cast<meta_variable_pair_t*>(item); | ||
4776 | if (metatableItem) { | ||
4777 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); | ||
4778 | } | ||
4779 | auto name = _parser.toString(mp->name); | ||
4780 | _buf << "__"sv << name << ':' << name; | ||
4781 | auto newPair = toAst<normal_pair_t>(clearBuf(), item); | ||
4782 | metatable->pairs.push_back(newPair); | ||
4783 | break; | ||
4784 | } | ||
4785 | case id<meta_normal_pair_t>(): { | ||
4786 | isMetamethod = true; | ||
4787 | auto mp = static_cast<meta_normal_pair_t*>(item); | ||
4788 | auto newPair = item->new_ptr<normal_pair_t>(); | ||
4789 | if (mp->key) { | ||
4790 | if (metatableItem) { | ||
4791 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); | ||
4792 | } | ||
4793 | switch (mp->key->getId()) { | ||
4794 | case id<Name_t>(): { | ||
4795 | auto key = _parser.toString(mp->key); | ||
4796 | _buf << "__"sv << key; | ||
4797 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | ||
4798 | newPair->key.set(newKey); | ||
4799 | break; | ||
4800 | } | ||
4801 | case id<Exp_t>(): | ||
4802 | newPair->key.set(mp->key); | ||
4803 | break; | ||
4804 | default: YUEE("AST node mismatch", mp->key); break; | ||
4805 | } | ||
4806 | newPair->value.set(mp->value); | ||
4807 | metatable->pairs.push_back(newPair); | ||
4808 | } else { | ||
4809 | if (!metatable->pairs.empty()) { | ||
4810 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); | ||
4811 | } | ||
4812 | metatableItem.set(mp->value); | ||
4813 | } | ||
4814 | break; | ||
4815 | } | ||
4816 | case id<default_pair_t>(): { | ||
4817 | throw std::logic_error(_info.errorMessage("invalid default value"sv, static_cast<default_pair_t*>(item)->defVal)); | ||
4818 | break; | ||
4819 | } | ||
4820 | case id<meta_default_pair_t>(): { | ||
4821 | throw std::logic_error(_info.errorMessage("invalid default value"sv, static_cast<meta_default_pair_t*>(item)->defVal)); | ||
4822 | break; | ||
4823 | } | ||
4824 | default: YUEE("AST node mismatch", item); break; | ||
4825 | } | ||
4826 | if (!isMetamethod) { | ||
4827 | temp.back() = indent() + (item == values.back() ? temp.back() : temp.back() + ',') + nll(item); | ||
4828 | } | ||
4829 | } | ||
4830 | if (metatable->pairs.empty() && !metatableItem) { | ||
4831 | out.push_back('{' + nll(x) + join(temp)); | ||
4832 | decIndentOffset(); | ||
4833 | out.back() += (indent() + '}'); | ||
4834 | } else { | ||
4835 | auto tabStr = globalVar("setmetatable"sv, x); | ||
4836 | tabStr += '('; | ||
4837 | if (temp.empty()) { | ||
4838 | decIndentOffset(); | ||
4839 | tabStr += "{ }"sv; | ||
4840 | } else { | ||
4841 | tabStr += ('{' + nll(x) + join(temp)); | ||
4842 | decIndentOffset(); | ||
4843 | tabStr += (indent() + '}'); | ||
4844 | } | ||
4845 | tabStr += ", "sv; | ||
4846 | str_list tmp; | ||
4847 | if (!metatable->pairs.empty()) { | ||
4848 | transform_simple_table(metatable, tmp); | ||
4849 | } else switch (metatableItem->getId()) { | ||
4850 | case id<Exp_t>(): | ||
4851 | transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure); | ||
4852 | break; | ||
4853 | case id<TableBlock_t>(): | ||
4854 | transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp); | ||
4855 | break; | ||
4856 | } | ||
4857 | tabStr += tmp.back(); | ||
4858 | tabStr += ')'; | ||
4859 | out.push_back(tabStr); | ||
4860 | } | ||
4861 | } | ||
4862 | |||
4863 | void transformTableLit(TableLit_t* table, str_list& out) { | ||
4864 | const auto& values = table->values.objects(); | ||
4865 | if (hasSpreadExp(values)) { | ||
4866 | transformSpreadTable(values, out, ExpUsage::Closure); | ||
4867 | } else { | ||
4868 | transformTable(values, out); | ||
4869 | } | ||
4870 | } | ||
4871 | |||
4685 | void transformCompCommon(Comprehension_t* comp, str_list& out) { | 4872 | void transformCompCommon(Comprehension_t* comp, str_list& out) { |
4686 | str_list temp; | 4873 | str_list temp; |
4687 | auto x = comp; | 4874 | auto x = comp; |
@@ -6079,115 +6266,8 @@ private: | |||
6079 | } | 6266 | } |
6080 | } | 6267 | } |
6081 | 6268 | ||
6082 | void transformTable(ast_node* table, const node_container& pairs, str_list& out) { | ||
6083 | if (pairs.empty()) { | ||
6084 | out.push_back("{ }"s); | ||
6085 | return; | ||
6086 | } | ||
6087 | str_list temp; | ||
6088 | incIndentOffset(); | ||
6089 | auto metatable = table->new_ptr<simple_table_t>(); | ||
6090 | ast_sel<false, Exp_t, TableBlock_t> metatableItem; | ||
6091 | for (auto pair : pairs) { | ||
6092 | bool isMetamethod = false; | ||
6093 | switch (pair->getId()) { | ||
6094 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(pair), temp, ExpUsage::Closure); break; | ||
6095 | case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(pair), temp); break; | ||
6096 | case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(pair), temp, false); break; | ||
6097 | case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(pair), temp); break; | ||
6098 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(pair), temp); break; | ||
6099 | case id<meta_variable_pair_t>(): { | ||
6100 | isMetamethod = true; | ||
6101 | auto mp = static_cast<meta_variable_pair_t*>(pair); | ||
6102 | if (metatableItem) { | ||
6103 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); | ||
6104 | } | ||
6105 | auto name = _parser.toString(mp->name); | ||
6106 | _buf << "__"sv << name << ':' << name; | ||
6107 | auto newPair = toAst<normal_pair_t>(clearBuf(), pair); | ||
6108 | metatable->pairs.push_back(newPair); | ||
6109 | break; | ||
6110 | } | ||
6111 | case id<meta_normal_pair_t>(): { | ||
6112 | isMetamethod = true; | ||
6113 | auto mp = static_cast<meta_normal_pair_t*>(pair); | ||
6114 | auto newPair = pair->new_ptr<normal_pair_t>(); | ||
6115 | if (mp->key) { | ||
6116 | if (metatableItem) { | ||
6117 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); | ||
6118 | } | ||
6119 | switch (mp->key->getId()) { | ||
6120 | case id<Name_t>(): { | ||
6121 | auto key = _parser.toString(mp->key); | ||
6122 | _buf << "__"sv << key; | ||
6123 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | ||
6124 | newPair->key.set(newKey); | ||
6125 | break; | ||
6126 | } | ||
6127 | case id<Exp_t>(): | ||
6128 | newPair->key.set(mp->key); | ||
6129 | break; | ||
6130 | default: YUEE("AST node mismatch", mp->key); break; | ||
6131 | } | ||
6132 | newPair->value.set(mp->value); | ||
6133 | metatable->pairs.push_back(newPair); | ||
6134 | } else { | ||
6135 | if (!metatable->pairs.empty()) { | ||
6136 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); | ||
6137 | } | ||
6138 | metatableItem.set(mp->value); | ||
6139 | } | ||
6140 | break; | ||
6141 | } | ||
6142 | case id<default_pair_t>(): { | ||
6143 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, static_cast<default_pair_t*>(pair)->defVal)); | ||
6144 | break; | ||
6145 | } | ||
6146 | case id<meta_default_pair_t>(): { | ||
6147 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, static_cast<meta_default_pair_t*>(pair)->defVal)); | ||
6148 | break; | ||
6149 | } | ||
6150 | default: YUEE("AST node mismatch", pair); break; | ||
6151 | } | ||
6152 | if (!isMetamethod) { | ||
6153 | temp.back() = indent() + (pair == pairs.back() ? temp.back() : temp.back() + ',') + nll(pair); | ||
6154 | } | ||
6155 | } | ||
6156 | if (metatable->pairs.empty() && !metatableItem) { | ||
6157 | out.push_back('{' + nll(table) + join(temp)); | ||
6158 | decIndentOffset(); | ||
6159 | out.back() += (indent() + '}'); | ||
6160 | } else { | ||
6161 | auto tabStr = globalVar("setmetatable"sv, table); | ||
6162 | tabStr += '('; | ||
6163 | if (temp.empty()) { | ||
6164 | decIndentOffset(); | ||
6165 | tabStr += "{ }"sv; | ||
6166 | } else { | ||
6167 | tabStr += ('{' + nll(table) + join(temp)); | ||
6168 | decIndentOffset(); | ||
6169 | tabStr += (indent() + '}'); | ||
6170 | } | ||
6171 | tabStr += ", "sv; | ||
6172 | str_list tmp; | ||
6173 | if (!metatable->pairs.empty()) { | ||
6174 | transform_simple_table(metatable, tmp); | ||
6175 | } else switch (metatableItem->getId()) { | ||
6176 | case id<Exp_t>(): | ||
6177 | transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure); | ||
6178 | break; | ||
6179 | case id<TableBlock_t>(): | ||
6180 | transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp); | ||
6181 | break; | ||
6182 | } | ||
6183 | tabStr += tmp.back(); | ||
6184 | tabStr += ')'; | ||
6185 | out.push_back(tabStr); | ||
6186 | } | ||
6187 | } | ||
6188 | |||
6189 | void transform_simple_table(simple_table_t* table, str_list& out) { | 6269 | void transform_simple_table(simple_table_t* table, str_list& out) { |
6190 | transformTable(table, table->pairs.objects(), out); | 6270 | transformTable(table->pairs.objects(), out); |
6191 | } | 6271 | } |
6192 | 6272 | ||
6193 | void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 6273 | void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
@@ -6284,11 +6364,16 @@ private: | |||
6284 | } | 6364 | } |
6285 | 6365 | ||
6286 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { | 6366 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { |
6287 | transformTable(table, table->values.objects(), out); | 6367 | transformTable(table->values.objects(), out); |
6288 | } | 6368 | } |
6289 | 6369 | ||
6290 | void transformTableBlock(TableBlock_t* table, str_list& out) { | 6370 | void transformTableBlock(TableBlock_t* table, str_list& out) { |
6291 | transformTable(table, table->values.objects(), out); | 6371 | const auto& values = table->values.objects(); |
6372 | if (hasSpreadExp(values)) { | ||
6373 | transformSpreadTable(values, out, ExpUsage::Closure); | ||
6374 | } else { | ||
6375 | transformTable(values, out); | ||
6376 | } | ||
6292 | } | 6377 | } |
6293 | 6378 | ||
6294 | void transformDo(Do_t* doNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 6379 | void transformDo(Do_t* doNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 0c08d4f..1f1b57c 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -28,9 +28,8 @@ std::unordered_set<std::string> Keywords = { | |||
28 | "or", "repeat", "return", "then", "true", | 28 | "or", "repeat", "return", "then", "true", |
29 | "until", "while", // Lua keywords | 29 | "until", "while", // Lua keywords |
30 | "as", "class", "continue", "export", "extends", | 30 | "as", "class", "continue", "export", "extends", |
31 | "from", "global", "import", "is", "macro", | 31 | "from", "global", "import", "macro", "switch", |
32 | "switch", "try", "unless", "using", "when", | 32 | "try", "unless", "using", "when", "with" // Yue keywords |
33 | "with" // Yue keywords | ||
34 | }; | 33 | }; |
35 | 34 | ||
36 | YueParser::YueParser() { | 35 | YueParser::YueParser() { |
@@ -219,7 +218,7 @@ YueParser::YueParser() { | |||
219 | 218 | ||
220 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | 219 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); |
221 | 220 | ||
222 | Return = key("return") >> -ExpListLow; | 221 | Return = key("return") >> -(TableBlock | ExpListLow); |
223 | 222 | ||
224 | WithExp = ExpList >> -Assign; | 223 | WithExp = ExpList >> -Assign; |
225 | 224 | ||
@@ -556,7 +555,7 @@ YueParser::YueParser() { | |||
556 | 555 | ||
557 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; | 556 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; |
558 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 557 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); |
559 | KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock)); | 558 | KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (SpreadExp | Exp | TableBlock)); |
560 | 559 | ||
561 | FnArgDef = (Variable | SelfName >> -existential_op) >> -(sym('=') >> Space >> Exp); | 560 | FnArgDef = (Variable | SelfName >> -existential_op) >> -(sym('=') >> Space >> Exp); |
562 | 561 | ||
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index eeadaf6..159bbca 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
15 | #include <list> | 15 | #include <list> |
16 | #include <sstream> | 16 | #include <sstream> |
17 | #include <string_view> | 17 | #include <string_view> |
18 | #include <memory> | ||
18 | 19 | ||
19 | #include "yuescript/ast.hpp" | 20 | #include "yuescript/ast.hpp" |
20 | #include "yuescript/yue_ast.h" | 21 | #include "yuescript/yue_ast.h" |