diff options
author | Li Jin <dragon-fly@qq.com> | 2022-11-08 18:10:44 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-11-09 11:29:32 +0800 |
commit | b041d365b88b76418def86d13a8f946dd8a6db73 (patch) | |
tree | bca73c504d250b15fe40e1718d00f6e8516e5195 | |
parent | bd10e55e72cfd588d3ed1ef6330bc138a3fe8eff (diff) | |
download | yuescript-b041d365b88b76418def86d13a8f946dd8a6db73.tar.gz yuescript-b041d365b88b76418def86d13a8f946dd8a6db73.tar.bz2 yuescript-b041d365b88b76418def86d13a8f946dd8a6db73.zip |
add chain assignment. fix issue #115.
-rw-r--r-- | spec/inputs/assign.yue | 11 | ||||
-rw-r--r-- | spec/outputs/assign.lua | 26 | ||||
-rwxr-xr-x | src/yuescript/yue_ast.h | 9 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 37 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 8 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 1 |
6 files changed, 87 insertions, 5 deletions
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue index da44dff..8c7848d 100644 --- a/spec/inputs/assign.yue +++ b/spec/inputs/assign.yue | |||
@@ -75,3 +75,14 @@ do | |||
75 | do | 75 | do |
76 | print 123 | 76 | print 123 |
77 | 1, f2! | 77 | 1, f2! |
78 | |||
79 | do | ||
80 | a = b = c = d = 0 | ||
81 | |||
82 | do | ||
83 | a = b = c = d = f! | ||
84 | |||
85 | do | ||
86 | {a} = :b = c.d = e = tab | ||
87 | |||
88 | nil | ||
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua index c7f2e20..e638c47 100644 --- a/spec/outputs/assign.lua +++ b/spec/outputs/assign.lua | |||
@@ -128,4 +128,30 @@ return _(function() | |||
128 | end | 128 | end |
129 | end | 129 | end |
130 | end | 130 | end |
131 | do | ||
132 | local a = 0 | ||
133 | local b = 0 | ||
134 | local c = 0 | ||
135 | local d = 0 | ||
136 | end | ||
137 | do | ||
138 | local a | ||
139 | local b | ||
140 | local c | ||
141 | local d | ||
142 | do | ||
143 | local _tmp_0 = f() | ||
144 | a = _tmp_0 | ||
145 | b = _tmp_0 | ||
146 | c = _tmp_0 | ||
147 | d = _tmp_0 | ||
148 | end | ||
149 | end | ||
150 | do | ||
151 | local a = tab[1] | ||
152 | local b = tab.b | ||
153 | c.d = tab | ||
154 | local e = tab | ||
155 | end | ||
156 | return nil | ||
131 | end) | 157 | end) |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 0925f5a..21266c9 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -827,6 +827,13 @@ AST_END(YueLineComment, "comment"sv) | |||
827 | AST_LEAF(YueMultilineComment) | 827 | AST_LEAF(YueMultilineComment) |
828 | AST_END(YueMultilineComment, "comment"sv) | 828 | AST_END(YueMultilineComment, "comment"sv) |
829 | 829 | ||
830 | AST_NODE(ChainAssign) | ||
831 | ast_ptr<true, Seperator_t> sep; | ||
832 | ast_list<true, Exp_t> exprs; | ||
833 | ast_ptr<true, Assign_t> assign; | ||
834 | AST_MEMBER(ChainAssign, &sep, &exprs, &assign) | ||
835 | AST_END(ChainAssign, "chain_assign") | ||
836 | |||
830 | AST_NODE(Statement) | 837 | AST_NODE(Statement) |
831 | ast_ptr<true, Seperator_t> sep; | 838 | ast_ptr<true, Seperator_t> sep; |
832 | ast_sel_list<false, YueLineComment_t, YueMultilineComment_t> comments; | 839 | ast_sel_list<false, YueLineComment_t, YueMultilineComment_t> comments; |
@@ -834,7 +841,7 @@ AST_NODE(Statement) | |||
834 | Import_t, While_t, Repeat_t, For_t, ForEach_t, | 841 | Import_t, While_t, Repeat_t, For_t, ForEach_t, |
835 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, | 842 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, |
836 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, | 843 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, |
837 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t | 844 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t |
838 | > content; | 845 | > content; |
839 | ast_ptr<false, statement_appendix_t> appendix; | 846 | ast_ptr<false, statement_appendix_t> appendix; |
840 | ast_ptr<false, statement_sep_t> needSep; | 847 | ast_ptr<false, statement_sep_t> needSep; |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 45a9bf6..4072974 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -59,7 +59,7 @@ namespace yue { | |||
59 | 59 | ||
60 | typedef std::list<std::string> str_list; | 60 | typedef std::list<std::string> str_list; |
61 | 61 | ||
62 | const std::string_view version = "0.15.10"sv; | 62 | const std::string_view version = "0.15.11"sv; |
63 | const std::string_view extension = "yue"sv; | 63 | const std::string_view extension = "yue"sv; |
64 | 64 | ||
65 | class YueCompilerImpl { | 65 | class YueCompilerImpl { |
@@ -1276,6 +1276,7 @@ private: | |||
1276 | } | 1276 | } |
1277 | break; | 1277 | break; |
1278 | } | 1278 | } |
1279 | case id<ChainAssign_t>(): transformChainAssign(static_cast<ChainAssign_t*>(content), out); break; | ||
1279 | default: YUEE("AST node mismatch", content); break; | 1280 | default: YUEE("AST node mismatch", content); break; |
1280 | } | 1281 | } |
1281 | if (statement->needSep && !out.empty() && !out.back().empty()) { | 1282 | if (statement->needSep && !out.empty() && !out.back().empty()) { |
@@ -8004,6 +8005,40 @@ private: | |||
8004 | assignment->action.set(tab->assign); | 8005 | assignment->action.set(tab->assign); |
8005 | transformAssignment(assignment, out); | 8006 | transformAssignment(assignment, out); |
8006 | } | 8007 | } |
8008 | |||
8009 | void transformChainAssign(ChainAssign_t* chainAssign, str_list& out) { | ||
8010 | auto x = chainAssign; | ||
8011 | str_list temp; | ||
8012 | auto value = chainAssign->assign->values.front(); | ||
8013 | bool constVal = false; | ||
8014 | if (auto simpleVal = simpleSingleValueFrom(value)) { | ||
8015 | constVal = ast_is<const_value_t, Num_t>(simpleVal->value); | ||
8016 | } | ||
8017 | if (constVal || !singleVariableFrom(value, false).empty()) { | ||
8018 | for (auto exp : chainAssign->exprs.objects()) { | ||
8019 | transformAssignment(assignmentFrom(static_cast<Exp_t*>(exp), value, exp), temp); | ||
8020 | } | ||
8021 | out.push_back(join(temp)); | ||
8022 | return; | ||
8023 | } | ||
8024 | auto valName = getUnusedName("_tmp_"); | ||
8025 | auto newValue = toAst<Exp_t>(valName, value); | ||
8026 | ast_list<false, ExpListAssign_t> assignments; | ||
8027 | for (auto exp : chainAssign->exprs.objects()) { | ||
8028 | auto assignment = assignmentFrom(static_cast<Exp_t*>(exp), newValue, exp); | ||
8029 | assignments.push_back(assignment.get()); | ||
8030 | temp.push_back(getPreDefineLine(assignment)); | ||
8031 | } | ||
8032 | assignments.push_front(assignmentFrom(newValue, value, value)); | ||
8033 | temp.push_back(indent() + "do"s + nll(x)); | ||
8034 | pushScope(); | ||
8035 | for (auto item : assignments.objects()) { | ||
8036 | transformAssignment(static_cast<ExpListAssign_t*>(item), temp); | ||
8037 | } | ||
8038 | popScope(); | ||
8039 | temp.push_back(indent() + "end"s + nll(x)); | ||
8040 | out.push_back(join(temp)); | ||
8041 | } | ||
8007 | }; | 8042 | }; |
8008 | 8043 | ||
8009 | const std::string YueCompilerImpl::Empty; | 8044 | const std::string YueCompilerImpl::Empty; |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index e755fb2..b1f29a9 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -650,7 +650,7 @@ YueParser::YueParser() { | |||
650 | unary_value | TblComprehension | TableLit | Comprehension | | 650 | unary_value | TblComprehension | TableLit | Comprehension | |
651 | FunLit | Num); | 651 | FunLit | Num); |
652 | 652 | ||
653 | ExpListAssign = ExpList >> -(Update | Assign); | 653 | ExpListAssign = ExpList >> -(Update | Assign) >> not_(Space >> expr('=')); |
654 | 654 | ||
655 | if_line = Space >> IfType >> IfCond; | 655 | if_line = Space >> IfType >> IfCond; |
656 | while_line = Space >> WhileType >> Exp; | 656 | while_line = Space >> WhileType >> Exp; |
@@ -661,13 +661,15 @@ YueParser::YueParser() { | |||
661 | yue_multiline_comment = multi_line_open >> YueMultilineComment >> multi_line_close; | 661 | yue_multiline_comment = multi_line_open >> YueMultilineComment >> multi_line_close; |
662 | yue_comment = check_indent >> (yue_multiline_comment >> *(set(" \t") | yue_multiline_comment) >> -yue_line_comment | yue_line_comment) >> and_(Break); | 662 | yue_comment = check_indent >> (yue_multiline_comment >> *(set(" \t") | yue_multiline_comment) >> -yue_line_comment | yue_line_comment) >> and_(Break); |
663 | 663 | ||
664 | ChainAssign = Seperator >> Exp >> +(sym('=') >> Exp >> Space >> and_('=')) >> Assign; | ||
665 | |||
664 | statement_appendix = (if_line | while_line | CompInner) >> Space; | 666 | statement_appendix = (if_line | while_line | CompInner) >> Space; |
665 | statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); | 667 | statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); |
666 | Statement = Seperator >> -(yue_comment >> *(Break >> yue_comment) >> Break >> CheckIndent) >> Space >> ( | 668 | Statement = Seperator >> -(yue_comment >> *(Break >> yue_comment) >> Break >> CheckIndent) >> Space >> ( |
667 | Import | While | Repeat | For | ForEach | | 669 | Import | While | Repeat | For | ForEach | |
668 | Return | Local | Global | Export | Macro | | 670 | Return | Local | Global | Export | Macro | |
669 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | 671 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | |
670 | LocalAttrib | Backcall | PipeBody | ExpListAssign | | 672 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | |
671 | statement_appendix >> empty_block_error | 673 | statement_appendix >> empty_block_error |
672 | ) >> Space >> | 674 | ) >> Space >> |
673 | -statement_appendix >> -statement_sep; | 675 | -statement_appendix >> -statement_sep; |
@@ -679,7 +681,7 @@ YueParser::YueParser() { | |||
679 | advance >> ensure(MultiLineComment >> Space | Comment, PopIndent) | | 681 | advance >> ensure(MultiLineComment >> Space | Comment, PopIndent) | |
680 | plain_space) >> and_(Break); | 682 | plain_space) >> and_(Break); |
681 | 683 | ||
682 | indentation_error = pl::user(not_(PipeOperator), [](const item_t& item) { | 684 | indentation_error = pl::user(not_(PipeOperator | eof()), [](const item_t& item) { |
683 | throw ParserError("unexpected indent", *item.begin, *item.end); | 685 | throw ParserError("unexpected indent", *item.begin, *item.end); |
684 | return false; | 686 | return false; |
685 | }); | 687 | }); |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 74281fb..88d688c 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -361,6 +361,7 @@ private: | |||
361 | AST_RULE(Statement) | 361 | AST_RULE(Statement) |
362 | AST_RULE(YueLineComment) | 362 | AST_RULE(YueLineComment) |
363 | AST_RULE(YueMultilineComment) | 363 | AST_RULE(YueMultilineComment) |
364 | AST_RULE(ChainAssign) | ||
364 | AST_RULE(Body) | 365 | AST_RULE(Body) |
365 | AST_RULE(Block) | 366 | AST_RULE(Block) |
366 | AST_RULE(BlockEnd) | 367 | AST_RULE(BlockEnd) |