diff options
author | Li Jin <dragon-fly@qq.com> | 2024-05-17 16:38:44 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2024-05-17 16:38:44 +0800 |
commit | 06bf167924d04aaefe80d6e4ead40989a447ea34 (patch) | |
tree | ccd2c3b62797d378ee7cc1872440483d328980ca /src | |
parent | fe317e2bdd9cb60b3c7cd347e21ce65cf90396e7 (diff) | |
download | yuescript-06bf167924d04aaefe80d6e4ead40989a447ea34.tar.gz yuescript-06bf167924d04aaefe80d6e4ead40989a447ea34.tar.bz2 yuescript-06bf167924d04aaefe80d6e4ead40989a447ea34.zip |
fix more cases in try-catch syntax.v0.23.6
Diffstat (limited to 'src')
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 326 |
1 files changed, 310 insertions, 16 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index c205031..7f6a042 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 | ||
78 | const std::string_view version = "0.23.4"sv; | 78 | const std::string_view version = "0.23.6"sv; |
79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
80 | 80 | ||
81 | class CompileError : public std::logic_error { | 81 | class CompileError : public std::logic_error { |
@@ -577,6 +577,273 @@ private: | |||
577 | } | 577 | } |
578 | } | 578 | } |
579 | 579 | ||
580 | bool isConstTableItem(ast_node* item) { | ||
581 | switch (item->get_id()) { | ||
582 | case id<VariablePairDef_t>(): { | ||
583 | auto pair = static_cast<VariablePairDef_t*>(item); | ||
584 | if (pair->defVal) return false; | ||
585 | return isConstTableItem(pair->pair); | ||
586 | } | ||
587 | case id<NormalPairDef_t>(): { | ||
588 | auto pair = static_cast<NormalPairDef_t*>(item); | ||
589 | if (pair->defVal) return false; | ||
590 | return isConstTableItem(pair->pair); | ||
591 | } | ||
592 | case id<MetaVariablePairDef_t>(): { | ||
593 | auto pair = static_cast<MetaVariablePairDef_t*>(item); | ||
594 | if (pair->defVal) return false; | ||
595 | return isConstTableItem(pair->pair); | ||
596 | } | ||
597 | case id<MetaNormalPairDef_t>(): { | ||
598 | auto pair = static_cast<MetaNormalPairDef_t*>(item); | ||
599 | if (pair->defVal) return false; | ||
600 | return isConstTableItem(pair->pair); | ||
601 | } | ||
602 | case id<NormalDef_t>(): { | ||
603 | auto pair = static_cast<NormalDef_t*>(item); | ||
604 | if (pair->defVal) return false; | ||
605 | return isConstTableItem(pair->item); | ||
606 | } | ||
607 | case id<Exp_t>(): { | ||
608 | auto pair = static_cast<Exp_t*>(item); | ||
609 | return isConstExp(pair); | ||
610 | } | ||
611 | case id<VariablePair_t>(): { | ||
612 | auto pair = static_cast<VariablePair_t*>(item); | ||
613 | return isLocal(variableToString(pair->name)); | ||
614 | } | ||
615 | case id<NormalPair_t>(): { | ||
616 | auto pair = static_cast<NormalPair_t*>(item); | ||
617 | if (auto exp = pair->key.as<Exp_t>()) { | ||
618 | if (!isConstExp(exp)) { | ||
619 | return false; | ||
620 | } | ||
621 | } | ||
622 | if (auto exp = pair->value.as<Exp_t>()) { | ||
623 | if (!isConstExp(exp)) { | ||
624 | return false; | ||
625 | } | ||
626 | } else if (auto tbBlock = pair->value.as<TableBlock_t>()) { | ||
627 | if (!isConstTable(tbBlock)) { | ||
628 | return false; | ||
629 | } | ||
630 | } else { | ||
631 | return false; | ||
632 | } | ||
633 | return true; | ||
634 | } | ||
635 | case id<TableBlockIndent_t>(): { | ||
636 | auto pair = static_cast<TableBlockIndent_t*>(item); | ||
637 | return isConstTable(pair); | ||
638 | } | ||
639 | case id<TableBlock_t>(): { | ||
640 | auto pair = static_cast<TableBlock_t*>(item); | ||
641 | return isConstTable(pair); | ||
642 | break; | ||
643 | } | ||
644 | case id<MetaVariablePair_t>(): { | ||
645 | auto pair = static_cast<MetaVariablePair_t*>(item); | ||
646 | return isLocal(variableToString(pair->name)); | ||
647 | } | ||
648 | case id<MetaNormalPair_t>(): { | ||
649 | auto pair = static_cast<MetaNormalPair_t*>(item); | ||
650 | if (auto str = pair->key.as<String_t>()) { | ||
651 | if (!ast_is<SingleString_t, LuaString_t>(str)) { | ||
652 | return false; | ||
653 | } | ||
654 | } else if (auto exp = pair->key.as<Exp_t>()) { | ||
655 | if (!isConstExp(exp)) { | ||
656 | return false; | ||
657 | } | ||
658 | } else if (pair->key.is<Name_t>()) { | ||
659 | return true; | ||
660 | } else { | ||
661 | return false; | ||
662 | } | ||
663 | if (auto exp = pair->value.as<Exp_t>()) { | ||
664 | if (!isConstExp(exp)) { | ||
665 | return false; | ||
666 | } | ||
667 | } else if (auto tbBlock = pair->value.as<TableBlock_t>()) { | ||
668 | if (!isConstTable(tbBlock)) { | ||
669 | return false; | ||
670 | } | ||
671 | } else { | ||
672 | return false; | ||
673 | } | ||
674 | return true; | ||
675 | } | ||
676 | } | ||
677 | return false; | ||
678 | } | ||
679 | |||
680 | bool isConstTable(TableLit_t* tableLit) { | ||
681 | for (auto value : tableLit->values.objects()) { | ||
682 | if (!isConstTableItem(value)) { | ||
683 | return false; | ||
684 | } | ||
685 | } | ||
686 | return true; | ||
687 | } | ||
688 | |||
689 | bool isConstTable(TableBlock_t* tableBlock) { | ||
690 | for (auto value : tableBlock->values.objects()) { | ||
691 | if (!isConstTableItem(value)) { | ||
692 | return false; | ||
693 | } | ||
694 | } | ||
695 | return true; | ||
696 | } | ||
697 | |||
698 | bool isConstTable(SimpleTable_t* stable) { | ||
699 | for (auto value : stable->pairs.objects()) { | ||
700 | if (!isConstTableItem(value)) { | ||
701 | return false; | ||
702 | } | ||
703 | } | ||
704 | return true; | ||
705 | } | ||
706 | |||
707 | bool isConstTable(TableBlockIndent_t* table) { | ||
708 | for (auto value : table->values.objects()) { | ||
709 | if (!isConstTableItem(value)) { | ||
710 | return false; | ||
711 | } | ||
712 | } | ||
713 | return true; | ||
714 | } | ||
715 | |||
716 | bool isConstChainValue(ChainValue_t* value) { | ||
717 | auto var = singleVariableFrom(value, AccessType::None); | ||
718 | return isLocal(var); | ||
719 | } | ||
720 | |||
721 | bool isConstUnaryValue(UnaryValue_t* value) { | ||
722 | if (value->ops.size() > 1) { | ||
723 | return false; | ||
724 | } | ||
725 | auto unaryStr = _parser.toString(value->ops.front()); | ||
726 | if (unaryStr == "-"sv) { | ||
727 | return value->value->item->get_by_path<SimpleValue_t, Num_t>(); | ||
728 | } else if (unaryStr == "#"sv) { | ||
729 | return false; | ||
730 | } else if (unaryStr == "not"sv) { | ||
731 | return isConstValue(value->value); | ||
732 | } | ||
733 | return false; | ||
734 | } | ||
735 | |||
736 | bool isConstNum(Value_t* value) { | ||
737 | return value->get_by_path<SimpleValue_t, Num_t>(); | ||
738 | } | ||
739 | |||
740 | bool isConstUnaryExp(UnaryExp_t* value) { | ||
741 | if (value->inExp) return false; | ||
742 | if (value->ops.size() == 0) { | ||
743 | if (value->expos.size() == 1) { | ||
744 | return isConstValue(static_cast<Value_t*>(value->expos.front())); | ||
745 | } | ||
746 | for (auto expo : value->expos.objects()) { | ||
747 | if (!isConstNum(static_cast<Value_t*>(expo))) { | ||
748 | return false; | ||
749 | } | ||
750 | } | ||
751 | return true; | ||
752 | } | ||
753 | if (value->ops.size() > 1) { | ||
754 | return false; | ||
755 | } | ||
756 | auto unaryStr = _parser.toString(value->ops.front()); | ||
757 | if (unaryStr == "-"sv) { | ||
758 | for (auto expo : value->expos.objects()) { | ||
759 | if (!isConstNum(static_cast<Value_t*>(expo))) { | ||
760 | return false; | ||
761 | } | ||
762 | } | ||
763 | return true; | ||
764 | } else if (unaryStr == "#"sv) { | ||
765 | return false; | ||
766 | } else if (unaryStr == "not"sv) { | ||
767 | if (value->expos.size() == 1) { | ||
768 | return isConstValue(static_cast<Value_t*>(value->expos.front())); | ||
769 | } | ||
770 | for (auto expo : value->expos.objects()) { | ||
771 | if (!isConstNum(static_cast<Value_t*>(expo))) { | ||
772 | return false; | ||
773 | } | ||
774 | } | ||
775 | return true; | ||
776 | } | ||
777 | return false; | ||
778 | } | ||
779 | |||
780 | bool isConstValue(Value_t* value) { | ||
781 | if (auto strNode = value->item.as<String_t>()) { | ||
782 | switch (strNode->str->get_id()) { | ||
783 | case id<SingleString_t>(): | ||
784 | case id<LuaString_t>(): | ||
785 | return true; | ||
786 | case id<DoubleString_t>(): | ||
787 | return false; | ||
788 | default: | ||
789 | YUEE("AST node mismatch", strNode->str); | ||
790 | return false; | ||
791 | } | ||
792 | } else if (auto chainValue = value->item.as<ChainValue_t>()) { | ||
793 | return isConstChainValue(chainValue); | ||
794 | } else if (auto simpleValue = value->item.as<SimpleValue_t>()) { | ||
795 | if (ast_is<ConstValue_t, Num_t, VarArg_t, FunLit_t>(simpleValue->value.get())) { | ||
796 | return true; | ||
797 | } else if (auto uValue = simpleValue->value.as<UnaryValue_t>()) { | ||
798 | return isConstUnaryValue(uValue); | ||
799 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { | ||
800 | for (auto item : comp->items.objects()) { | ||
801 | if (auto ndef = ast_cast<NormalDef_t>(item)) { | ||
802 | if (ndef->defVal) { | ||
803 | return false; | ||
804 | } | ||
805 | if (!isConstExp(ndef->item)) { | ||
806 | return false; | ||
807 | } | ||
808 | } else { | ||
809 | return false; | ||
810 | } | ||
811 | } | ||
812 | return true; | ||
813 | } else if (auto tableLit = simpleValue->value.as<TableLit_t>()) { | ||
814 | return isConstTable(tableLit); | ||
815 | } else { | ||
816 | return false; | ||
817 | } | ||
818 | } else if (auto simpleTable = value->item.as<SimpleTable_t>()) { | ||
819 | return isConstTable(simpleTable); | ||
820 | } | ||
821 | return false; | ||
822 | } | ||
823 | |||
824 | bool isConstUnaryExps(const ast_list<true, UnaryExp_t>& list) { | ||
825 | if (list.size() > 1) { | ||
826 | return false; | ||
827 | } | ||
828 | if (!isConstUnaryExp(static_cast<UnaryExp_t*>(list.front()))) { | ||
829 | return false; | ||
830 | } | ||
831 | return true; | ||
832 | } | ||
833 | |||
834 | bool isConstExp(Exp_t* exp) { | ||
835 | if (exp->nilCoalesed) { | ||
836 | return false; | ||
837 | } | ||
838 | if (!isConstUnaryExps(exp->pipeExprs)) { | ||
839 | return false; | ||
840 | } | ||
841 | if (exp->opValues.empty()) { | ||
842 | return true; | ||
843 | } | ||
844 | return false; | ||
845 | } | ||
846 | |||
580 | void markVarConst(const std::string& name) { | 847 | void markVarConst(const std::string& name) { |
581 | auto& scope = _scopes.back(); | 848 | auto& scope = _scopes.back(); |
582 | scope.vars->insert_or_assign(name, VarType::Const); | 849 | scope.vars->insert_or_assign(name, VarType::Const); |
@@ -3691,7 +3958,7 @@ private: | |||
3691 | }) != traversal::Stop; | 3958 | }) != traversal::Stop; |
3692 | } | 3959 | } |
3693 | 3960 | ||
3694 | std::optional<std::pair<std::string, str_list>> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd) { | 3961 | std::optional<std::pair<std::string, str_list>> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing) { |
3695 | if (_funcLevel <= 1) return std::nullopt; | 3962 | if (_funcLevel <= 1) return std::nullopt; |
3696 | auto result = block->traverse([&](ast_node* node) { | 3963 | auto result = block->traverse([&](ast_node* node) { |
3697 | switch (node->get_id()) { | 3964 | switch (node->get_id()) { |
@@ -3754,6 +4021,9 @@ private: | |||
3754 | } else if (std::find(args.begin(), args.end(), global.name) == args.end()) { | 4021 | } else if (std::find(args.begin(), args.end(), global.name) == args.end()) { |
3755 | args.push_back(global.name); | 4022 | args.push_back(global.name); |
3756 | } | 4023 | } |
4024 | if (noGlobalVarPassing && !isLocal(global.name)) { | ||
4025 | return std::nullopt; | ||
4026 | } | ||
3757 | } | 4027 | } |
3758 | } | 4028 | } |
3759 | } | 4029 | } |
@@ -3809,9 +4079,9 @@ private: | |||
3809 | } | 4079 | } |
3810 | 4080 | ||
3811 | 4081 | ||
3812 | std::optional<std::pair<std::string, str_list>> upValueFuncFrom(Block_t* block, str_list* ensureArgListInTheEnd = nullptr) { | 4082 | std::optional<std::pair<std::string, str_list>> upValueFuncFrom(Block_t* block, str_list* ensureArgListInTheEnd = nullptr, bool noGlobalVarPassing = false) { |
3813 | if (checkUpValueFuncAvailable(block)) { | 4083 | if (checkUpValueFuncAvailable(block)) { |
3814 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd); | 4084 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, noGlobalVarPassing); |
3815 | } | 4085 | } |
3816 | return std::nullopt; | 4086 | return std::nullopt; |
3817 | } | 4087 | } |
@@ -3826,7 +4096,7 @@ private: | |||
3826 | auto stmt = exp->new_ptr<Statement_t>(); | 4096 | auto stmt = exp->new_ptr<Statement_t>(); |
3827 | stmt->content.set(returnNode); | 4097 | stmt->content.set(returnNode); |
3828 | block->statements.push_back(stmt); | 4098 | block->statements.push_back(stmt); |
3829 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd); | 4099 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false); |
3830 | } | 4100 | } |
3831 | return std::nullopt; | 4101 | return std::nullopt; |
3832 | } | 4102 | } |
@@ -9135,23 +9405,47 @@ private: | |||
9135 | BREAK_IF(var.empty()); | 9405 | BREAK_IF(var.empty()); |
9136 | tryFunc.set(expListAssign->expList->exprs.front()); | 9406 | tryFunc.set(expListAssign->expList->exprs.front()); |
9137 | BLOCK_END | 9407 | BLOCK_END |
9138 | } else { | 9408 | } |
9139 | auto tryExp = tryFunc.as<Exp_t>(); | 9409 | if (auto tryExp = tryFunc.as<Exp_t>()) { |
9140 | bool needWrap = singleVariableFrom(tryExp, AccessType::None).empty(); | 9410 | bool wrapped = true; |
9141 | BLOCK_START | 9411 | BLOCK_START |
9142 | auto value = singleValueFrom(tryExp); | 9412 | auto value = singleValueFrom(tryExp); |
9143 | BREAK_IF(!value); | 9413 | BREAK_IF(!value); |
9144 | auto chainValue = value->item.as<ChainValue_t>(); | 9414 | auto chainValue = value->item.as<ChainValue_t>(); |
9145 | BREAK_IF(!chainValue); | 9415 | BREAK_IF(!chainValue); |
9146 | BREAK_IF(!isChainValueCall(chainValue)); | 9416 | BREAK_IF(!isChainValueCall(chainValue)); |
9147 | auto tmpChain = chainValue->new_ptr<ChainValue_t>(); | 9417 | auto chainCaller = chainValue->new_ptr<ChainValue_t>(); |
9148 | tmpChain->items.dup(chainValue->items); | 9418 | chainCaller->items.dup(chainValue->items); |
9149 | tmpChain->items.pop_back(); | 9419 | chainCaller->items.pop_back(); |
9150 | auto var = singleVariableFrom(tmpChain, AccessType::None); | 9420 | BREAK_IF(!isConstChainValue(chainCaller)); |
9151 | BREAK_IF(var.empty()); | 9421 | _ast_list* args = nullptr; |
9152 | needWrap = false; | 9422 | if (auto invoke = ast_cast<InvokeArgs_t>(chainValue->items.back())) { |
9423 | args = &invoke->args; | ||
9424 | } else { | ||
9425 | args = &(ast_to<Invoke_t>(chainValue->items.back())->args); | ||
9426 | } | ||
9427 | wrapped = false; | ||
9428 | for (auto arg : args->objects()) { | ||
9429 | switch (arg->get_id()) { | ||
9430 | case id<Exp_t>(): | ||
9431 | if (isConstExp(static_cast<Exp_t*>(arg))) continue; | ||
9432 | break; | ||
9433 | case id<SingleString_t>(): | ||
9434 | case id<LuaString_t>(): | ||
9435 | continue; | ||
9436 | case id<DoubleString_t>(): | ||
9437 | break; | ||
9438 | case id<TableLit_t>(): | ||
9439 | if (isConstTable(static_cast<TableLit_t*>(arg))) continue; | ||
9440 | break; | ||
9441 | case id<TableBlock_t>(): | ||
9442 | if (isConstTable(static_cast<TableBlock_t*>(arg))) continue; | ||
9443 | break; | ||
9444 | } | ||
9445 | wrapped = true; | ||
9446 | } | ||
9153 | BLOCK_END | 9447 | BLOCK_END |
9154 | if (needWrap) { | 9448 | if (wrapped) { |
9155 | auto expList = x->new_ptr<ExpList_t>(); | 9449 | auto expList = x->new_ptr<ExpList_t>(); |
9156 | expList->exprs.push_back(tryFunc); | 9450 | expList->exprs.push_back(tryFunc); |
9157 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 9451 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); |
@@ -9165,7 +9459,7 @@ private: | |||
9165 | } | 9459 | } |
9166 | if (auto tryBlock = tryFunc.as<Block_t>()) { | 9460 | if (auto tryBlock = tryFunc.as<Block_t>()) { |
9167 | if (getLuaTarget(tryBlock) >= 502 || !errHandler) { | 9461 | if (getLuaTarget(tryBlock) >= 502 || !errHandler) { |
9168 | if (auto result = upValueFuncFrom(tryBlock)) { | 9462 | if (auto result = upValueFuncFrom(tryBlock, nullptr, true)) { |
9169 | auto [funcName, args] = std::move(*result); | 9463 | auto [funcName, args] = std::move(*result); |
9170 | if (errHandler) { | 9464 | if (errHandler) { |
9171 | auto xpcall = toAst<ChainValue_t>("xpcall()", x); | 9465 | auto xpcall = toAst<ChainValue_t>("xpcall()", x); |