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 | } |
