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 --- src/yuescript/yue_compiler.cpp | 66 ++++++++++++++++++++++++++++-------------- src/yuescript/yue_parser.cpp | 3 +- 2 files changed, 47 insertions(+), 22 deletions(-) (limited to 'src') 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