From 07a64933f8d956a8bba401db2200e6f7d8244dc9 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 9 Feb 2022 10:14:25 +0800 Subject: fix the way update assignment is implemented. --- spec/inputs/syntax.yue | 5 +++++ spec/outputs/syntax.lua | 12 +++++++++++- src/yuescript/yue_compiler.cpp | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index aed4144..cb947e1 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue @@ -183,6 +183,11 @@ a["hello"] += 10 a["hello#{tostring ff}"] += 10 a[four].x += 10 +a.b += 1 +a.b[1].c[2+3] += 1 +with tb + .a.c += 1 + 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 3187898..ed8ed39 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua @@ -184,7 +184,17 @@ local _update_0 = "hello" a[_update_0] = a[_update_0] + 10 local _update_1 = "hello" .. tostring(tostring(ff)) a[_update_1] = a[_update_1] + 10 -a[four].x = a[four].x + 10 +local _obj_0 = a[four] +_obj_0.x = _obj_0.x + 10 +a.b = a.b + 1 +local _obj_1 = a.b[1].c +local _update_2 = 2 + 3 +_obj_1[_update_2] = _obj_1[_update_2] + 1 +do + local _with_0 = tb + local _obj_2 = _with_0.a + _obj_2.c = _obj_2.c + 1 +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 17822c6..852a0f4 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -2015,9 +2015,42 @@ private: 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()) { - if (specialChainValue(chain) == ChainType::Metatable) { + 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)); } + BLOCK_START + BREAK_IF(chain->items.size() < 2); + if (chain->items.size() == 2) { + if (auto callable = ast_cast(chain->items.front())) { + ast_node* var = callable->item.as(); + if (auto self = callable->item.as()) { + var = self->name.as(); + } + 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); + } + } + 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()) { bool itemAdded = false; -- cgit v1.2.3-55-g6feb