summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-01-28 18:43:14 +0800
committerLi Jin <dragon-fly@qq.com>2026-01-28 18:43:14 +0800
commitdd64edd58fe25ec74ae5958128cf3f74b0692f3b (patch)
tree0f2de1df55897e2713977c5a53936757e14b477a /src
parent7c2a92b82e9808d3c5ea29b47d1c59d663fe984a (diff)
downloadyuescript-dd64edd58fe25ec74ae5958128cf3f74b0692f3b.tar.gz
yuescript-dd64edd58fe25ec74ae5958128cf3f74b0692f3b.tar.bz2
yuescript-dd64edd58fe25ec74ae5958128cf3f74b0692f3b.zip
Fixed compiler issues and added 800+ test cases.
Diffstat (limited to 'src')
-rw-r--r--src/yue.cpp26
-rw-r--r--src/yuescript/yue_ast.h6
-rw-r--r--src/yuescript/yue_compiler.cpp31
-rw-r--r--src/yuescript/yue_parser.cpp37
4 files changed, 54 insertions, 46 deletions
diff --git a/src/yue.cpp b/src/yue.cpp
index ee4eb38..a30075d 100644
--- a/src/yue.cpp
+++ b/src/yue.cpp
@@ -201,8 +201,13 @@ static std::string compileFile(const fs::path& file, yue::YueConfig conf, const
201 conf.module = modulePath.string(); 201 conf.module = modulePath.string();
202 if (!workPath.empty()) { 202 if (!workPath.empty()) {
203 auto it = conf.options.find("path"); 203 auto it = conf.options.find("path");
204 if (it == conf.options.end()) { 204 if (it != conf.options.end()) {
205 conf.options["path"] = (workPath / "?.lua"sv).string(); 205 if (!it->second.empty()) {
206 it->second += ';';
207 }
208 it->second += (fs::path(workPath) / "?.lua"sv).string();
209 } else {
210 conf.options["path"] = (fs::path(workPath) / "?.lua"sv).string();
206 } 211 }
207 } 212 }
208 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, conf); 213 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, conf);
@@ -852,7 +857,6 @@ int main(int narg, const char** args) {
852 std::list<std::future<std::tuple<int, std::string, std::string>>> results; 857 std::list<std::future<std::tuple<int, std::string, std::string>>> results;
853 for (const auto& file : files) { 858 for (const auto& file : files) {
854 auto task = async<std::tuple<int, std::string, std::string>>([=]() { 859 auto task = async<std::tuple<int, std::string, std::string>>([=]() {
855 try {
856 std::ifstream input(file.first, std::ios::in); 860 std::ifstream input(file.first, std::ios::in);
857 if (input) { 861 if (input) {
858 std::string s( 862 std::string s(
@@ -862,7 +866,12 @@ int main(int narg, const char** args) {
862 conf.module = file.first; 866 conf.module = file.first;
863 if (!workPath.empty()) { 867 if (!workPath.empty()) {
864 auto it = conf.options.find("path"); 868 auto it = conf.options.find("path");
865 if (it == conf.options.end()) { 869 if (it != conf.options.end()) {
870 if (!it->second.empty()) {
871 it->second += ';';
872 }
873 it->second += (fs::path(workPath) / "?.lua"sv).string();
874 } else {
866 conf.options["path"] = (fs::path(workPath) / "?.lua"sv).string(); 875 conf.options["path"] = (fs::path(workPath) / "?.lua"sv).string();
867 } 876 }
868 } 877 }
@@ -942,15 +951,6 @@ int main(int narg, const char** args) {
942 } else { 951 } else {
943 return std::tuple{1, std::string(), "Failed to read file: "s + file.first + '\n'}; 952 return std::tuple{1, std::string(), "Failed to read file: "s + file.first + '\n'};
944 } 953 }
945 } catch (const std::length_error& e) {
946 std::ostringstream buf;
947 buf << "std::length_error: " << e.what() << " for file: " << file.first << '\n';
948 return std::tuple{1, std::string(), buf.str()};
949 } catch (const std::exception& e) {
950 std::ostringstream buf;
951 buf << "Exception: " << e.what() << " for file: " << file.first << '\n';
952 return std::tuple{1, std::string(), buf.str()};
953 }
954 }); 954 });
955 results.push_back(std::move(task)); 955 results.push_back(std::move(task));
956 } 956 }
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 5043526..5faeed5 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -689,12 +689,12 @@ AST_END(ChainValue)
689 689
690AST_NODE(AssignableChain) 690AST_NODE(AssignableChain)
691 ast_ptr<true, Seperator_t> sep; 691 ast_ptr<true, Seperator_t> sep;
692 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Exp_t, String_t> items; 692 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Exp_t> items;
693 AST_MEMBER(AssignableChain, &sep, &items) 693 AST_MEMBER(AssignableChain, &sep, &items)
694AST_END(AssignableChain) 694AST_END(AssignableChain)
695 695
696AST_NODE(Value) 696AST_NODE(Value)
697 ast_sel<true, SimpleValue_t, SimpleTable_t, ChainValue_t, String_t> item; 697 ast_sel<true, SimpleValue_t, SimpleTable_t, ChainValue_t> item;
698 AST_MEMBER(Value, &item) 698 AST_MEMBER(Value, &item)
699AST_END(Value) 699AST_END(Value)
700 700
@@ -782,7 +782,7 @@ AST_NODE(Export)
782AST_END(Export) 782AST_END(Export)
783 783
784AST_NODE(FnArgDef) 784AST_NODE(FnArgDef)
785 ast_sel<true, Variable_t, SelfItem_t, SimpleTable_t, TableLit_t> name; 785 ast_sel<true, Variable_t, SelfItem_t, SimpleTable_t, TableLit_t, Comprehension_t> name;
786 ast_ptr<false, ExistentialOp_t> op; 786 ast_ptr<false, ExistentialOp_t> op;
787 ast_ptr<false, Name_t> label; 787 ast_ptr<false, Name_t> label;
788 ast_ptr<false, Exp_t> defaultValue; 788 ast_ptr<false, Exp_t> defaultValue;
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index c5e4a78..835a70a 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.32.5"sv; 81const std::string_view version = "0.32.6"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -865,7 +865,7 @@ private:
865 } 865 }
866 866
867 bool isConstValue(Value_t* value) { 867 bool isConstValue(Value_t* value) {
868 if (auto strNode = value->item.as<String_t>()) { 868 if (auto strNode = value->get_by_path<ChainValue_t, String_t>()) {
869 switch (strNode->str->get_id()) { 869 switch (strNode->str->get_id()) {
870 case id<SingleString_t>(): 870 case id<SingleString_t>():
871 case id<LuaString_t>(): 871 case id<LuaString_t>():
@@ -1154,7 +1154,9 @@ private:
1154 1154
1155 ast_ptr<false, Exp_t> newExp(String_t* string, ast_node* x) { 1155 ast_ptr<false, Exp_t> newExp(String_t* string, ast_node* x) {
1156 auto value = x->new_ptr<Value_t>(); 1156 auto value = x->new_ptr<Value_t>();
1157 value->item.set(string); 1157 auto chainValue = x->new_ptr<ChainValue_t>();
1158 chainValue->items.push_back(string);
1159 value->item.set(chainValue);
1158 return newExp(value, x); 1160 return newExp(value, x);
1159 } 1161 }
1160 1162
@@ -3487,9 +3489,7 @@ private:
3487 newPair->key.set(mp->key); 3489 newPair->key.set(mp->key);
3488 break; 3490 break;
3489 case id<String_t>(): { 3491 case id<String_t>(): {
3490 auto value = mp->new_ptr<Value_t>(); 3492 newPair->key.set(newExp(mp->key.to<String_t>(), mp));
3491 value->item.set(mp->key);
3492 newPair->key.set(newExp(value, mp));
3493 break; 3493 break;
3494 } 3494 }
3495 default: YUEE("AST node mismatch", mp->key); break; 3495 default: YUEE("AST node mismatch", mp->key); break;
@@ -3622,7 +3622,7 @@ private:
3622 continue; 3622 continue;
3623 } 3623 }
3624 } 3624 }
3625 if (auto value = singleValueFrom(exp); !value || !value->item.is<String_t>()) { 3625 if (auto value = singleValueFrom(exp); !value || !value->item->get_by_path<String_t>()) {
3626 auto var = singleVariableFrom(exp, AccessType::None); 3626 auto var = singleVariableFrom(exp, AccessType::None);
3627 if (var.empty()) { 3627 if (var.empty()) {
3628 if (!des.inlineAssignment) { 3628 if (!des.inlineAssignment) {
@@ -4664,7 +4664,6 @@ private:
4664 case id<SimpleValue_t>(): transformSimpleValue(static_cast<SimpleValue_t*>(item), out); break; 4664 case id<SimpleValue_t>(): transformSimpleValue(static_cast<SimpleValue_t*>(item), out); break;
4665 case id<SimpleTable_t>(): transform_simple_table(static_cast<SimpleTable_t*>(item), out); break; 4665 case id<SimpleTable_t>(): transform_simple_table(static_cast<SimpleTable_t*>(item), out); break;
4666 case id<ChainValue_t>(): transformChainValue(static_cast<ChainValue_t*>(item), out, ExpUsage::Closure); break; 4666 case id<ChainValue_t>(): transformChainValue(static_cast<ChainValue_t*>(item), out, ExpUsage::Closure); break;
4667 case id<String_t>(): transformString(static_cast<String_t*>(item), out); break;
4668 default: YUEE("AST node mismatch", value); break; 4667 default: YUEE("AST node mismatch", value); break;
4669 } 4668 }
4670 } 4669 }
@@ -5931,6 +5930,14 @@ private:
5931 arg.assignment = asmt; 5930 arg.assignment = asmt;
5932 break; 5931 break;
5933 } 5932 }
5933 case id<Comprehension_t>(): {
5934 arg.name = getUnusedName("_arg_"sv);
5935 auto simpleValue = def->new_ptr<SimpleValue_t>();
5936 simpleValue->value.set(def->name);
5937 auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def);
5938 arg.assignment = asmt;
5939 break;
5940 }
5934 default: YUEE("AST node mismatch", def->name.get()); break; 5941 default: YUEE("AST node mismatch", def->name.get()); break;
5935 } 5942 }
5936 forceAddToScope(arg.name); 5943 forceAddToScope(arg.name);
@@ -6883,7 +6890,9 @@ private:
6883 } 6890 }
6884 case id<String_t>(): 6891 case id<String_t>():
6885 transformString(static_cast<String_t*>(item), temp); 6892 transformString(static_cast<String_t*>(item), temp);
6886 temp.back() = '(' + temp.back() + ')'; 6893 if (chainList.size() > 1) {
6894 temp.back() = '(' + temp.back() + ')';
6895 }
6887 break; 6896 break;
6888 case id<Exp_t>(): 6897 case id<Exp_t>():
6889 transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); 6898 transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure);
@@ -7007,7 +7016,7 @@ private:
7007 BREAK_IF(!exp); 7016 BREAK_IF(!exp);
7008 auto value = singleValueFrom(exp); 7017 auto value = singleValueFrom(exp);
7009 BREAK_IF(!value); 7018 BREAK_IF(!value);
7010 auto lstr = value->get_by_path<String_t, LuaString_t>(); 7019 auto lstr = value->get_by_path<ChainValue_t, String_t, LuaString_t>();
7011 BREAK_IF(!lstr); 7020 BREAK_IF(!lstr);
7012 str = _parser.toString(lstr->content); 7021 str = _parser.toString(lstr->content);
7013 rawString = true; 7022 rawString = true;
@@ -9606,7 +9615,7 @@ private:
9606 if (auto dotChain = ast_cast<DotChainItem_t>(chain->items.back())) { 9615 if (auto dotChain = ast_cast<DotChainItem_t>(chain->items.back())) {
9607 classTextName = '\"' + _parser.toString(dotChain->name) + '\"'; 9616 classTextName = '\"' + _parser.toString(dotChain->name) + '\"';
9608 } else if (auto index = ast_cast<Exp_t>(chain->items.back())) { 9617 } else if (auto index = ast_cast<Exp_t>(chain->items.back())) {
9609 if (auto name = index->get_by_path<UnaryExp_t, Value_t, String_t>()) { 9618 if (auto name = index->get_by_path<UnaryExp_t, Value_t, ChainValue_t, String_t>()) {
9610 transformString(name, temp); 9619 transformString(name, temp);
9611 classTextName = std::move(temp.back()); 9620 classTextName = std::move(temp.back());
9612 temp.pop_back(); 9621 temp.pop_back();
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index ad76517..194d04d 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -358,7 +358,7 @@ YueParser::YueParser() {
358 }); 358 });
359 advance_match = and_(advance); 359 advance_match = and_(advance);
360 360
361 push_indent = pl::user(plain_space, [](const item_t& item) { 361 push_indent = pl::user(plain_space >> not_(stop), [](const item_t& item) {
362 int indent = 0; 362 int indent = 0;
363 for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { 363 for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) {
364 switch (*i) { 364 switch (*i) {
@@ -738,12 +738,18 @@ YueParser::YueParser() {
738 return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); 738 return st->noChainBlockStack.empty() || !st->noChainBlockStack.back();
739 }) >> +space_break >> advance_match >> ensure( 739 }) >> +space_break >> advance_match >> ensure(
740 chain_line >> *(+space_break >> chain_line), pop_indent); 740 chain_line >> *(+space_break >> chain_line), pop_indent);
741 ChainValue = 741 ChainValue = Seperator >> (
742 Seperator >> 742 (
743 chain >> 743 chain >>
744 -ExistentialOp >> 744 -ExistentialOp >>
745 -(InvokeArgs | chain_block) >> 745 -(InvokeArgs | chain_block) >> -TableAppendingOp
746 -TableAppendingOp; 746 ) | String >> -(
747 and_(white >> set(".\\:")) >> (
748 chain_items >> -(InvokeArgs | chain_block) >> -TableAppendingOp |
749 chain_block >> -TableAppendingOp
750 )
751 )
752 );
747 753
748 inc_exp_level = pl::user(true_(), [](const item_t& item) { 754 inc_exp_level = pl::user(true_(), [](const item_t& item) {
749 State* st = reinterpret_cast<State*>(item.user_data); 755 State* st = reinterpret_cast<State*>(item.user_data);
@@ -762,7 +768,7 @@ YueParser::YueParser() {
762 }); 768 });
763 769
764 SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); 770 SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value);
765 Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); 771 Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue, dec_exp_level);
766 772
767 single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; 773 single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char;
768 SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error); 774 SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error);
@@ -828,21 +834,13 @@ YueParser::YueParser() {
828 TableAppendingOp = and_('[') >> "[]"; 834 TableAppendingOp = and_('[') >> "[]";
829 PlainItem = +any_char; 835 PlainItem = +any_char;
830 836
831 chain_call = ( 837 chain_call = Callable >> -ExistentialOp >> -chain_items;
832 Callable >> -ExistentialOp >> -chain_items
833 ) | (
834 String >> chain_items
835 );
836 chain_index_chain = index >> -ExistentialOp >> -chain_items; 838 chain_index_chain = index >> -ExistentialOp >> -chain_items;
837 chain_dot_chain = DotChainItem >> -ExistentialOp >> -chain_items; 839 chain_dot_chain = DotChainItem >> -ExistentialOp >> -chain_items;
838 840
839 chain = chain_call | chain_dot_chain | colon_chain | chain_index_chain; 841 chain = chain_call | chain_dot_chain | colon_chain | chain_index_chain;
840 842
841 chain_call_list = ( 843 chain_call_list = Callable >> -ExistentialOp >> chain_items;
842 Callable >> -ExistentialOp >> chain_items
843 ) | (
844 String >> chain_items
845 );
846 chain_list = chain_call_list | chain_dot_chain | colon_chain | chain_index_chain; 844 chain_list = chain_call_list | chain_dot_chain | colon_chain | chain_index_chain;
847 845
848 AssignableChain = Seperator >> chain_list; 846 AssignableChain = Seperator >> chain_list;
@@ -1030,7 +1028,7 @@ YueParser::YueParser() {
1030 1028
1031 fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); 1029 fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line);
1032 1030
1033 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; 1031 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable | Comprehension;
1034 1032
1035 check_vararg_position = and_(white >> (')' | key("using"))) | white >> -(',' >> white) >> vararg_position_error; 1033 check_vararg_position = and_(white >> (')' | key("using"))) | white >> -(',' >> white) >> vararg_position_error;
1036 1034
@@ -1391,6 +1389,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo
1391 } 1389 }
1392 errorDisplayCol = displayCol; 1390 errorDisplayCol = displayCol;
1393 } 1391 }
1392 errorDisplayCol = std::max(errorDisplayCol, 1);
1394 1393
1395 for (int lineNum = startLine; lineNum <= endLine; ++lineNum) { 1394 for (int lineNum = startLine; lineNum <= endLine; ++lineNum) {
1396 int displayLineNum = lineNum + lineOffset; 1395 int displayLineNum = lineNum + lineOffset;