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 '')
| -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" |
