aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-11-08 18:10:44 +0800
committerLi Jin <dragon-fly@qq.com>2022-11-09 11:29:32 +0800
commitb041d365b88b76418def86d13a8f946dd8a6db73 (patch)
treebca73c504d250b15fe40e1718d00f6e8516e5195
parentbd10e55e72cfd588d3ed1ef6330bc138a3fe8eff (diff)
downloadyuescript-b041d365b88b76418def86d13a8f946dd8a6db73.tar.gz
yuescript-b041d365b88b76418def86d13a8f946dd8a6db73.tar.bz2
yuescript-b041d365b88b76418def86d13a8f946dd8a6db73.zip
add chain assignment. fix issue #115.
-rw-r--r--spec/inputs/assign.yue11
-rw-r--r--spec/outputs/assign.lua26
-rwxr-xr-xsrc/yuescript/yue_ast.h9
-rw-r--r--src/yuescript/yue_compiler.cpp37
-rw-r--r--src/yuescript/yue_parser.cpp8
-rw-r--r--src/yuescript/yue_parser.h1
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
79do
80 a = b = c = d = 0
81
82do
83 a = b = c = d = f!
84
85do
86 {a} = :b = c.d = e = tab
87
88nil
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
131end) 157end)
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)
827AST_LEAF(YueMultilineComment) 827AST_LEAF(YueMultilineComment)
828AST_END(YueMultilineComment, "comment"sv) 828AST_END(YueMultilineComment, "comment"sv)
829 829
830AST_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)
835AST_END(ChainAssign, "chain_assign")
836
830AST_NODE(Statement) 837AST_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
60typedef std::list<std::string> str_list; 60typedef std::list<std::string> str_list;
61 61
62const std::string_view version = "0.15.10"sv; 62const std::string_view version = "0.15.11"sv;
63const std::string_view extension = "yue"sv; 63const std::string_view extension = "yue"sv;
64 64
65class YueCompilerImpl { 65class 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
8009const std::string YueCompilerImpl::Empty; 8044const 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)