From a6744ed09b49b740dfc2852d655f5ed6dd471cbf Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 8 Feb 2022 16:39:20 +0800 Subject: fix a case combining the use of existential op and metatable op. raise error when use existential op in the left part in an assignment. --- src/yuescript/yue_compiler.cpp | 90 ++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 2da72da..17822c6 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.6"sv; +const std::string_view version = "0.9.7"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -800,6 +800,11 @@ private: return true; } } else { + if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) { + return ast_is(node); + }) != chainItems.end()) { + return false; + } auto lastItem = chainItems.back(); switch (lastItem->getId()) { case id(): @@ -1207,48 +1212,49 @@ private: BREAK_IF(!value); auto chainValue = value->item.as(); BREAK_IF(!chainValue); - if (specialChainValue(chainValue) == ChainType::Metatable) { - str_list args; - chainValue->items.pop_back(); - if (chainValue->items.empty()) { - if (_withVars.empty()) { - throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); - } else { - args.push_back(_withVars.top()); - } + auto dot = ast_cast(chainValue->items.back()); + BREAK_IF(!dot); + BREAK_IF(!dot->name.is()); + str_list args; + chainValue->items.pop_back(); + if (chainValue->items.empty()) { + if (_withVars.empty()) { + throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); } else { - transformExp(static_cast(*it), args, ExpUsage::Closure); + args.push_back(_withVars.top()); } - if (vit != values.end()) transformAssignItem(*vit, args); - else args.push_back("nil"s); - _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); - str_list temp; - temp.push_back(clearBuf()); - auto newExpList = x->new_ptr(); - auto newAssign = x->new_ptr(); - auto newAssignment = x->new_ptr(); - newAssignment->expList.set(newExpList); - newAssignment->action.set(newAssign); - for (auto exp : exprs) { - if (exp != *it) newExpList->exprs.push_back(exp); - } - for (auto value : values) { - if (value != *vit) newAssign->values.push_back(value); - } - if (newExpList->exprs.empty() && newAssign->values.empty()) { - out.push_back(temp.back()); - return; - } - if (newExpList->exprs.size() < newAssign->values.size()) { - auto exp = toAst("_"sv, x); - while (newExpList->exprs.size() < newAssign->values.size()) { - newExpList->exprs.push_back(exp); - } - } - transformAssignment(newAssignment, temp); - out.push_back(join(temp)); + } else { + transformExp(static_cast(*it), args, ExpUsage::Closure); + } + if (vit != values.end()) transformAssignItem(*vit, args); + else args.push_back("nil"s); + _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); + str_list temp; + temp.push_back(clearBuf()); + auto newExpList = x->new_ptr(); + auto newAssign = x->new_ptr(); + auto newAssignment = x->new_ptr(); + newAssignment->expList.set(newExpList); + newAssignment->action.set(newAssign); + for (auto exp : exprs) { + if (exp != *it) newExpList->exprs.push_back(exp); + } + for (auto value : values) { + if (value != *vit) newAssign->values.push_back(value); + } + if (newExpList->exprs.empty() && newAssign->values.empty()) { + out.push_back(temp.back()); return; } + if (newExpList->exprs.size() < newAssign->values.size()) { + auto exp = toAst("_"sv, x); + while (newExpList->exprs.size() < newAssign->values.size()) { + newExpList->exprs.push_back(exp); + } + } + transformAssignment(newAssignment, temp); + out.push_back(join(temp)); + return; BLOCK_END if (vit != values.end()) ++vit; } @@ -4287,15 +4293,15 @@ private: #endif // YUE_NO_MACRO } const auto& chainList = chainValue->items.objects(); - if (transformChainWithMetatable(chainList, out, usage, assignList)) { - return; - } if (transformChainEndWithEOP(chainList, out, usage, assignList)) { return; } if (transformChainWithEOP(chainList, out, usage, assignList)) { return; } + if (transformChainWithMetatable(chainList, out, usage, assignList)) { + return; + } if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { return; } -- cgit v1.2.3-55-g6feb