diff options
author | Li Jin <dragon-fly@qq.com> | 2022-02-08 16:39:20 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-02-08 16:39:20 +0800 |
commit | a6744ed09b49b740dfc2852d655f5ed6dd471cbf (patch) | |
tree | 4209b5f16c67f79259ad4c6bf116a8428b589ad3 /src/yuescript/yue_compiler.cpp | |
parent | d22ae154b57ac80107020e98f04f76fffaa9cd90 (diff) | |
download | yuescript-a6744ed09b49b740dfc2852d655f5ed6dd471cbf.tar.gz yuescript-a6744ed09b49b740dfc2852d655f5ed6dd471cbf.tar.bz2 yuescript-a6744ed09b49b740dfc2852d655f5ed6dd471cbf.zip |
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.
Diffstat (limited to '')
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 90 |
1 files changed, 48 insertions, 42 deletions
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; | |||
60 | 60 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.9.6"sv; | 63 | const std::string_view version = "0.9.7"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
@@ -800,6 +800,11 @@ private: | |||
800 | return true; | 800 | return true; |
801 | } | 801 | } |
802 | } else { | 802 | } else { |
803 | if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) { | ||
804 | return ast_is<existential_op_t>(node); | ||
805 | }) != chainItems.end()) { | ||
806 | return false; | ||
807 | } | ||
803 | auto lastItem = chainItems.back(); | 808 | auto lastItem = chainItems.back(); |
804 | switch (lastItem->getId()) { | 809 | switch (lastItem->getId()) { |
805 | case id<DotChainItem_t>(): | 810 | case id<DotChainItem_t>(): |
@@ -1207,48 +1212,49 @@ private: | |||
1207 | BREAK_IF(!value); | 1212 | BREAK_IF(!value); |
1208 | auto chainValue = value->item.as<ChainValue_t>(); | 1213 | auto chainValue = value->item.as<ChainValue_t>(); |
1209 | BREAK_IF(!chainValue); | 1214 | BREAK_IF(!chainValue); |
1210 | if (specialChainValue(chainValue) == ChainType::Metatable) { | 1215 | auto dot = ast_cast<DotChainItem_t>(chainValue->items.back()); |
1211 | str_list args; | 1216 | BREAK_IF(!dot); |
1212 | chainValue->items.pop_back(); | 1217 | BREAK_IF(!dot->name.is<Metatable_t>()); |
1213 | if (chainValue->items.empty()) { | 1218 | str_list args; |
1214 | if (_withVars.empty()) { | 1219 | chainValue->items.pop_back(); |
1215 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); | 1220 | if (chainValue->items.empty()) { |
1216 | } else { | 1221 | if (_withVars.empty()) { |
1217 | args.push_back(_withVars.top()); | 1222 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); |
1218 | } | ||
1219 | } else { | 1223 | } else { |
1220 | transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); | 1224 | args.push_back(_withVars.top()); |
1221 | } | 1225 | } |
1222 | if (vit != values.end()) transformAssignItem(*vit, args); | 1226 | } else { |
1223 | else args.push_back("nil"s); | 1227 | transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); |
1224 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); | 1228 | } |
1225 | str_list temp; | 1229 | if (vit != values.end()) transformAssignItem(*vit, args); |
1226 | temp.push_back(clearBuf()); | 1230 | else args.push_back("nil"s); |
1227 | auto newExpList = x->new_ptr<ExpList_t>(); | 1231 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); |
1228 | auto newAssign = x->new_ptr<Assign_t>(); | 1232 | str_list temp; |
1229 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 1233 | temp.push_back(clearBuf()); |
1230 | newAssignment->expList.set(newExpList); | 1234 | auto newExpList = x->new_ptr<ExpList_t>(); |
1231 | newAssignment->action.set(newAssign); | 1235 | auto newAssign = x->new_ptr<Assign_t>(); |
1232 | for (auto exp : exprs) { | 1236 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
1233 | if (exp != *it) newExpList->exprs.push_back(exp); | 1237 | newAssignment->expList.set(newExpList); |
1234 | } | 1238 | newAssignment->action.set(newAssign); |
1235 | for (auto value : values) { | 1239 | for (auto exp : exprs) { |
1236 | if (value != *vit) newAssign->values.push_back(value); | 1240 | if (exp != *it) newExpList->exprs.push_back(exp); |
1237 | } | 1241 | } |
1238 | if (newExpList->exprs.empty() && newAssign->values.empty()) { | 1242 | for (auto value : values) { |
1239 | out.push_back(temp.back()); | 1243 | if (value != *vit) newAssign->values.push_back(value); |
1240 | return; | 1244 | } |
1241 | } | 1245 | if (newExpList->exprs.empty() && newAssign->values.empty()) { |
1242 | if (newExpList->exprs.size() < newAssign->values.size()) { | 1246 | out.push_back(temp.back()); |
1243 | auto exp = toAst<Exp_t>("_"sv, x); | ||
1244 | while (newExpList->exprs.size() < newAssign->values.size()) { | ||
1245 | newExpList->exprs.push_back(exp); | ||
1246 | } | ||
1247 | } | ||
1248 | transformAssignment(newAssignment, temp); | ||
1249 | out.push_back(join(temp)); | ||
1250 | return; | 1247 | return; |
1251 | } | 1248 | } |
1249 | if (newExpList->exprs.size() < newAssign->values.size()) { | ||
1250 | auto exp = toAst<Exp_t>("_"sv, x); | ||
1251 | while (newExpList->exprs.size() < newAssign->values.size()) { | ||
1252 | newExpList->exprs.push_back(exp); | ||
1253 | } | ||
1254 | } | ||
1255 | transformAssignment(newAssignment, temp); | ||
1256 | out.push_back(join(temp)); | ||
1257 | return; | ||
1252 | BLOCK_END | 1258 | BLOCK_END |
1253 | if (vit != values.end()) ++vit; | 1259 | if (vit != values.end()) ++vit; |
1254 | } | 1260 | } |
@@ -4287,15 +4293,15 @@ private: | |||
4287 | #endif // YUE_NO_MACRO | 4293 | #endif // YUE_NO_MACRO |
4288 | } | 4294 | } |
4289 | const auto& chainList = chainValue->items.objects(); | 4295 | const auto& chainList = chainValue->items.objects(); |
4290 | if (transformChainWithMetatable(chainList, out, usage, assignList)) { | ||
4291 | return; | ||
4292 | } | ||
4293 | if (transformChainEndWithEOP(chainList, out, usage, assignList)) { | 4296 | if (transformChainEndWithEOP(chainList, out, usage, assignList)) { |
4294 | return; | 4297 | return; |
4295 | } | 4298 | } |
4296 | if (transformChainWithEOP(chainList, out, usage, assignList)) { | 4299 | if (transformChainWithEOP(chainList, out, usage, assignList)) { |
4297 | return; | 4300 | return; |
4298 | } | 4301 | } |
4302 | if (transformChainWithMetatable(chainList, out, usage, assignList)) { | ||
4303 | return; | ||
4304 | } | ||
4299 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 4305 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
4300 | return; | 4306 | return; |
4301 | } | 4307 | } |