From b041d365b88b76418def86d13a8f946dd8a6db73 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 8 Nov 2022 18:10:44 +0800 Subject: add chain assignment. fix issue #115. --- spec/inputs/assign.yue | 11 +++++++++++ spec/outputs/assign.lua | 26 ++++++++++++++++++++++++++ src/yuescript/yue_ast.h | 9 ++++++++- src/yuescript/yue_compiler.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/yuescript/yue_parser.cpp | 8 +++++--- 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 do print 123 1, f2! + +do + a = b = c = d = 0 + +do + a = b = c = d = f! + +do + {a} = :b = c.d = e = tab + +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() end end end + do + local a = 0 + local b = 0 + local c = 0 + local d = 0 + end + do + local a + local b + local c + local d + do + local _tmp_0 = f() + a = _tmp_0 + b = _tmp_0 + c = _tmp_0 + d = _tmp_0 + end + end + do + local a = tab[1] + local b = tab.b + c.d = tab + local e = tab + end + return nil 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) AST_LEAF(YueMultilineComment) AST_END(YueMultilineComment, "comment"sv) +AST_NODE(ChainAssign) + ast_ptr sep; + ast_list exprs; + ast_ptr assign; + AST_MEMBER(ChainAssign, &sep, &exprs, &assign) +AST_END(ChainAssign, "chain_assign") + AST_NODE(Statement) ast_ptr sep; ast_sel_list comments; @@ -834,7 +841,7 @@ AST_NODE(Statement) Import_t, While_t, Repeat_t, For_t, ForEach_t, Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, - Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t + Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t > content; ast_ptr appendix; ast_ptr 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 { typedef std::list str_list; -const std::string_view version = "0.15.10"sv; +const std::string_view version = "0.15.11"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -1276,6 +1276,7 @@ private: } break; } + case id(): transformChainAssign(static_cast(content), out); break; default: YUEE("AST node mismatch", content); break; } if (statement->needSep && !out.empty() && !out.back().empty()) { @@ -8004,6 +8005,40 @@ private: assignment->action.set(tab->assign); transformAssignment(assignment, out); } + + void transformChainAssign(ChainAssign_t* chainAssign, str_list& out) { + auto x = chainAssign; + str_list temp; + auto value = chainAssign->assign->values.front(); + bool constVal = false; + if (auto simpleVal = simpleSingleValueFrom(value)) { + constVal = ast_is(simpleVal->value); + } + if (constVal || !singleVariableFrom(value, false).empty()) { + for (auto exp : chainAssign->exprs.objects()) { + transformAssignment(assignmentFrom(static_cast(exp), value, exp), temp); + } + out.push_back(join(temp)); + return; + } + auto valName = getUnusedName("_tmp_"); + auto newValue = toAst(valName, value); + ast_list assignments; + for (auto exp : chainAssign->exprs.objects()) { + auto assignment = assignmentFrom(static_cast(exp), newValue, exp); + assignments.push_back(assignment.get()); + temp.push_back(getPreDefineLine(assignment)); + } + assignments.push_front(assignmentFrom(newValue, value, value)); + temp.push_back(indent() + "do"s + nll(x)); + pushScope(); + for (auto item : assignments.objects()) { + transformAssignment(static_cast(item), temp); + } + popScope(); + temp.push_back(indent() + "end"s + nll(x)); + out.push_back(join(temp)); + } }; 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() { unary_value | TblComprehension | TableLit | Comprehension | FunLit | Num); - ExpListAssign = ExpList >> -(Update | Assign); + ExpListAssign = ExpList >> -(Update | Assign) >> not_(Space >> expr('=')); if_line = Space >> IfType >> IfCond; while_line = Space >> WhileType >> Exp; @@ -661,13 +661,15 @@ YueParser::YueParser() { yue_multiline_comment = multi_line_open >> YueMultilineComment >> multi_line_close; yue_comment = check_indent >> (yue_multiline_comment >> *(set(" \t") | yue_multiline_comment) >> -yue_line_comment | yue_line_comment) >> and_(Break); + ChainAssign = Seperator >> Exp >> +(sym('=') >> Exp >> Space >> and_('=')) >> Assign; + statement_appendix = (if_line | while_line | CompInner) >> Space; statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); Statement = Seperator >> -(yue_comment >> *(Break >> yue_comment) >> Break >> CheckIndent) >> Space >> ( Import | While | Repeat | For | ForEach | Return | Local | Global | Export | Macro | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | - LocalAttrib | Backcall | PipeBody | ExpListAssign | + LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | statement_appendix >> empty_block_error ) >> Space >> -statement_appendix >> -statement_sep; @@ -679,7 +681,7 @@ YueParser::YueParser() { advance >> ensure(MultiLineComment >> Space | Comment, PopIndent) | plain_space) >> and_(Break); - indentation_error = pl::user(not_(PipeOperator), [](const item_t& item) { + indentation_error = pl::user(not_(PipeOperator | eof()), [](const item_t& item) { throw ParserError("unexpected indent", *item.begin, *item.end); return false; }); 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: AST_RULE(Statement) AST_RULE(YueLineComment) AST_RULE(YueMultilineComment) + AST_RULE(ChainAssign) AST_RULE(Body) AST_RULE(Block) AST_RULE(BlockEnd) -- cgit v1.2.3-55-g6feb