From 60f8f00a022ac08701792b2897b72d8c99b50f52 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 11 Nov 2022 17:19:24 +0800 Subject: fix default value issue when doing metatable destructuring. --- spec/inputs/destructure.yue | 10 ++++ spec/outputs/destructure.lua | 105 +++++++++++++++++++++++++++++++++++++++++ src/yuescript/yue_compiler.cpp | 32 ++++++++++--- 3 files changed, 141 insertions(+), 6 deletions(-) diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 403923a..d161fd8 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue @@ -214,5 +214,15 @@ do tb = {} <[a + b]>: v1, [c!]: v2 = tb +do + {a: {: = addFunc}, b: {<[fieldName]>: field = 123}} = tb + {<"abc">: meta_field = "def", <[[any string]]>: abc = 123, <'str'>: def = {}} = tb + + switch tb + when {a: {: = addFunc}, b: {<[fieldName]>: field = 123}} + print add, field + switch tb + when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} + print meta_field, abc, def nil diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 10ad2d0..f40a658 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua @@ -503,4 +503,109 @@ do v1 = _obj_1[_tmp_1] end end +do + local add, field + do + local _obj_0 = tb + add, field = getmetatable(_obj_0.a).__add, getmetatable(_obj_0.b)[fieldName] + if add == nil then + add = addFunc + end + if field == nil then + field = 123 + end + end + local meta_field, abc, def + do + local _obj_0 = getmetatable(tb) + meta_field, abc, def = _obj_0["abc"], _obj_0[ [[any string]]], _obj_0['str'] + if meta_field == nil then + meta_field = "def" + end + if abc == nil then + abc = 123 + end + if def == nil then + def = { } + end + end + do + local _exp_0 = tb + local _tab_0 = "table" == type(_exp_0) + if _tab_0 then + do + local _obj_0 = _exp_0.a + if _obj_0 ~= nil then + do + local _obj_1 = getmetatable(_obj_0) + if _obj_1 ~= nil then + add = _obj_1.__add + end + end + end + end + do + local _obj_0 = _exp_0.b + if _obj_0 ~= nil then + do + local _obj_1 = getmetatable(_obj_0) + if _obj_1 ~= nil then + field = _obj_1[fieldName] + end + end + end + end + if add == nil then + add = addFunc + end + if field == nil then + field = 123 + end + print(add, field) + end + end + do + local _exp_0 = tb + local _tab_0 = "table" == type(_exp_0) + if _tab_0 then + local _obj_0 = _exp_0 + do + local _obj_1 = _obj_0.c + if _obj_1 ~= nil then + do + local _obj_2 = getmetatable(_obj_1) + if _obj_2 ~= nil then + meta_field = _obj_2["abc"] + end + end + end + end + if meta_field == nil then + meta_field = "def" + end + do + local _obj_1 = getmetatable(_obj_0) + do + local _obj_2 = _obj_1[ [[any string]]] + if _obj_2 ~= nil then + abc = _obj_2.d + end + end + do + local _obj_2 = _obj_1['str'] + if _obj_2 ~= nil then + def = _obj_2.e + end + end + if abc == nil then + abc = 123 + end + if def == nil then + def = { } + end + end + print(meta_field, abc, def) + end + end +end return nil diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index c359e02..9d84f43 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -2109,6 +2109,11 @@ private: auto item = value->item.get(); if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(pair, optional); + if (!subPairs.empty()) { + if (defVal) { + throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); + } + } for (auto& p : subPairs) { if (sep) p.structure->items.push_front(sep); p.structure->items.push_front( @@ -2171,14 +2176,20 @@ private: keyIndex = key; } else if (auto key = np->key.as()) { keyIndex = newExp(key, np->key).get(); - } else + } else { throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, np)); + } } if (auto exp = np->value.as()) { if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't do destructure value"sv, exp)); auto item = singleValueFrom(exp)->item.get(); if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(exp, optional); + if (!subPairs.empty()) { + if (defVal) { + throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); + } + } for (auto& p : subPairs) { if (keyIndex) { if (sep) p.structure->items.push_front(sep); @@ -2199,6 +2210,11 @@ private: } if (np->value.is()) { auto subPairs = destructFromExp(np->value, optional); + if (!subPairs.empty()) { + if (defVal) { + throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); + } + } for (auto& p : subPairs) { if (keyIndex) { if (sep) p.structure->items.push_front(sep); @@ -2253,6 +2269,7 @@ private: newPair->key.set(newKey); break; } + case id(): case id(): newPair->key.set(mp->key); break; @@ -5220,7 +5237,7 @@ private: case id(): { if (auto pair = ast_cast(item)) { if (pair->defVal) { - throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); + throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); } item = pair->pair.get(); } @@ -5234,7 +5251,7 @@ private: case id(): { if (auto pair = ast_cast(item)) { if (pair->defVal) { - throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); + throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); } item = pair->pair.get(); } @@ -5286,7 +5303,7 @@ private: auto current = item; if (auto pair = ast_cast(item)) { if (pair->defVal) { - throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); + throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); } item = pair->item.get(); } @@ -5336,7 +5353,7 @@ private: case id(): { if (auto pair = ast_cast(item)) { if (pair->defVal) { - throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); + throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); } item = pair->pair.get(); } @@ -5350,7 +5367,7 @@ private: case id(): { if (auto pair = ast_cast(item)) { if (pair->defVal) { - throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); + throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); } item = pair->pair.get(); } @@ -5373,6 +5390,9 @@ private: chainValue->items.push_back(key); break; } + case id(): + chainValue->items.push_back(key); + break; default: YUEE("AST node mismatch", key); break; } auto assign = assignment->action.to(); -- cgit v1.2.3-55-g6feb