From 09fc831f540ce3966aeff679164f37e7d40457c9 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 11 Feb 2022 10:37:35 +0800 Subject: add Lua table appending idiom: tb #= 123 --- spec/inputs/syntax.yue | 13 ++++++++- spec/outputs/syntax.lua | 18 ++++++++++++ src/yuescript/yue_compiler.cpp | 66 ++++++++++++++++++++++++++++-------------- src/yuescript/yue_parser.cpp | 3 +- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index cb947e1..67d3a27 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue @@ -184,10 +184,21 @@ a["hello#{tostring ff}"] += 10 a[four].x += 10 a.b += 1 -a.b[1].c[2+3] += 1 +a.b[1].c[2 + 3] += 1 with tb .a.c += 1 +tb #= 10 +a.b.c #= 1 +x #= if v + 1 +else + 2 +with tb + .b.c #= with vec + .x = 1 + .y = 2 + x = 0 _ = (if ntype(v) == "fndef" then x += 1) for v in *values diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index ed8ed39..4596a29 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua @@ -195,6 +195,24 @@ do local _obj_2 = _with_0.a _obj_2.c = _obj_2.c + 1 end +tb[#tb + 1] = 10 +local _obj_2 = a.b.c +_obj_2[#_obj_2 + 1] = 1 +if v then + x[#x + 1] = 1 +else + x[#x + 1] = 2 +end +do + local _with_0 = tb + local _obj_3 = _with_0.b.c + do + local _with_1 = vec + _with_1.x = 1 + _with_1.y = 2 + _obj_3[#_obj_3 + 1] = _with_1 + end +end x = 0 local _list_0 = values for _index_0 = 1, #_list_0 do diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index db225f6..33d4dcb 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -60,7 +60,7 @@ using namespace parserlib; typedef std::list str_list; -const std::string_view version = "0.9.8"sv; +const std::string_view version = "0.9.9"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -2014,7 +2014,10 @@ private: auto leftExp = static_cast(expList->exprs.objects().front()); auto leftValue = singleValueFrom(leftExp); if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); - if (auto chain = leftValue->item.as()) { + auto chain = leftValue->item.as(); + if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain)); + auto op = _parser.toString(update->op); + { auto dot = ast_cast(chain->items.back()); if (dot && dot->name.is()) { throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); @@ -2030,26 +2033,38 @@ private: BREAK_IF(var); } } - auto tmpChain = x->new_ptr(); - ast_ptr ptr(chain->items.back()); - for (auto item : chain->items.objects()) { - if (item != ptr) { - tmpChain->items.push_back(item); + if (op == "#"sv) { + auto objVar = getUnusedName("_obj_"sv); + auto newAssignment = x->new_ptr(); + newAssignment->expList.set(toAst(objVar, x)); + auto assign = x->new_ptr(); + assign->values.push_back(leftExp); + newAssignment->action.set(assign); + transformAssignment(newAssignment, temp); + chain->items.clear(); + chain->items.push_back(toAst(objVar, x)); + } else { + auto tmpChain = x->new_ptr(); + ast_ptr ptr(chain->items.back()); + for (auto item : chain->items.objects()) { + if (item != ptr) { + tmpChain->items.push_back(item); + } } + auto value = x->new_ptr(); + value->item.set(tmpChain); + auto exp = newExp(value, x); + auto objVar = getUnusedName("_obj_"sv); + auto newAssignment = x->new_ptr(); + newAssignment->expList.set(toAst(objVar, x)); + auto assign = x->new_ptr(); + assign->values.push_back(exp); + newAssignment->action.set(assign); + transformAssignment(newAssignment, temp); + chain->items.clear(); + chain->items.push_back(toAst(objVar, x)); + chain->items.push_back(ptr); } - auto value = x->new_ptr(); - value->item.set(tmpChain); - auto exp = newExp(value, x); - auto objVar = getUnusedName("_obj_"sv); - auto newAssignment = x->new_ptr(); - newAssignment->expList.set(toAst(objVar, x)); - auto assign = x->new_ptr(); - assign->values.push_back(exp); - newAssignment->action.set(assign); - transformAssignment(newAssignment, temp); - chain->items.clear(); - chain->items.push_back(toAst(objVar, x)); - chain->items.push_back(ptr); BLOCK_END auto tmpChain = x->new_ptr(); for (auto item : chain->items.objects()) { @@ -2074,7 +2089,6 @@ private: chain->items.clear(); chain->items.dup(tmpChain->items); } - auto op = _parser.toString(update->op); if (op == "??"sv) { auto defs = getPredefine(assignment); auto rightExp = x->new_ptr(); @@ -2085,6 +2099,16 @@ private: if (!defs.empty()) temp.back().insert(0, defs + nll(x)); out.push_back(join(temp)); return; + } else if (op == "#"sv) { + auto left = _parser.toString(chain->items.front()); + auto newAssignment = x->new_ptr(); + newAssignment->expList.set(toAst(left + "[#"s + left + "+1]"s, x)); + auto assign = x->new_ptr(); + assign->values.push_back(update->value); + newAssignment->action.set(assign); + transformAssignment(newAssignment, temp); + out.push_back(join(temp)); + return; } auto defs = getPredefine(assignment); transformValue(leftValue, temp); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index e171f3f..772ae08 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -324,7 +324,8 @@ YueParser::YueParser() { expr("|") | expr(">>") | expr("<<") | - expr("??"); + expr("??") | + expr("#"); Update = Space >> update_op >> expr("=") >> Exp; -- cgit v1.2.3-55-g6feb