diff options
| author | Li Jin <dragon-fly@qq.com> | 2023-01-29 10:29:19 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2023-01-29 10:29:19 +0800 |
| commit | e10b1b163a9a173f32b956bf1fb9be00194352b5 (patch) | |
| tree | 4692fe729bbb588c0565ce78426c932e8b360f22 /src/yuescript/yue_compiler.cpp | |
| parent | 32f2a579ec15e6204e44d67ab2b8b4a1796e9a84 (diff) | |
| download | yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.gz yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.bz2 yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.zip | |
fix cases from issue #120.
Diffstat (limited to '')
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 5443c61..c7f0f27 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -71,7 +71,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 71 | "close"s // Lua 5.4 | 71 | "close"s // Lua 5.4 |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | const std::string_view version = "0.15.23"sv; | 74 | const std::string_view version = "0.15.24"sv; |
| 75 | const std::string_view extension = "yue"sv; | 75 | const std::string_view extension = "yue"sv; |
| 76 | 76 | ||
| 77 | class YueCompilerImpl { | 77 | class YueCompilerImpl { |
| @@ -1224,6 +1224,8 @@ private: | |||
| 1224 | } | 1224 | } |
| 1225 | default: YUEE("AST node mismatch", appendix->item.get()); break; | 1225 | default: YUEE("AST node mismatch", appendix->item.get()); break; |
| 1226 | } | 1226 | } |
| 1227 | } else if (statement->content.is<Return_t>() && !statement->appendix->item.is<IfLine_t>()) { | ||
| 1228 | throw std::logic_error(_info.errorMessage("loop line decorator can not be used in a return statement"sv, statement->appendix->item)); | ||
| 1227 | } | 1229 | } |
| 1228 | auto appendix = statement->appendix.get(); | 1230 | auto appendix = statement->appendix.get(); |
| 1229 | switch (appendix->item->getId()) { | 1231 | switch (appendix->item->getId()) { |
| @@ -1357,7 +1359,7 @@ private: | |||
| 1357 | break; | 1359 | break; |
| 1358 | } | 1360 | } |
| 1359 | } | 1361 | } |
| 1360 | throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, expList)); | 1362 | throw std::logic_error(_info.errorMessage("unexpected expression"sv, expList)); |
| 1361 | } | 1363 | } |
| 1362 | break; | 1364 | break; |
| 1363 | } | 1365 | } |
| @@ -3029,7 +3031,7 @@ private: | |||
| 3029 | auto unary = static_cast<UnaryExp_t*>(*it); | 3031 | auto unary = static_cast<UnaryExp_t*>(*it); |
| 3030 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); | 3032 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); |
| 3031 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { | 3033 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { |
| 3032 | throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, x)); | 3034 | throw std::logic_error(_info.errorMessage("unexpected expression"sv, x)); |
| 3033 | } | 3035 | } |
| 3034 | if (!value) throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, *it)); | 3036 | if (!value) throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, *it)); |
| 3035 | if (auto chainValue = value->item.as<ChainValue_t>()) { | 3037 | if (auto chainValue = value->item.as<ChainValue_t>()) { |
| @@ -3275,13 +3277,6 @@ private: | |||
| 3275 | globalVar("self"sv, item); | 3277 | globalVar("self"sv, item); |
| 3276 | break; | 3278 | break; |
| 3277 | } | 3279 | } |
| 3278 | case id<VarArg_t>(): | ||
| 3279 | if (_varArgs.empty() || !_varArgs.top().hasVar) { | ||
| 3280 | throw std::logic_error(_info.errorMessage("cannot use '...' outside a vararg function near '...'"sv, item)); | ||
| 3281 | } | ||
| 3282 | _varArgs.top().usedVar = true; | ||
| 3283 | out.push_back("..."s); | ||
| 3284 | break; | ||
| 3285 | case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break; | 3280 | case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break; |
| 3286 | default: YUEE("AST node mismatch", item); break; | 3281 | default: YUEE("AST node mismatch", item); break; |
| 3287 | } | 3282 | } |
| @@ -3312,6 +3307,7 @@ private: | |||
| 3312 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; | 3307 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; |
| 3313 | case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break; | 3308 | case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break; |
| 3314 | case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break; | 3309 | case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break; |
| 3310 | case id<VarArg_t>(): transformVarArg(static_cast<VarArg_t*>(value), out); break; | ||
| 3315 | default: YUEE("AST node mismatch", value); break; | 3311 | default: YUEE("AST node mismatch", value); break; |
| 3316 | } | 3312 | } |
| 3317 | } | 3313 | } |
| @@ -3638,8 +3634,19 @@ private: | |||
| 3638 | } | 3634 | } |
| 3639 | case ExpUsage::Assignment: { | 3635 | case ExpUsage::Assignment: { |
| 3640 | auto last = lastStatementFrom(block); | 3636 | auto last = lastStatementFrom(block); |
| 3641 | if (!last) return; | 3637 | if (!last) throw std::logic_error(_info.errorMessage("block is not assignable"sv, block)); |
| 3642 | bool lastAssignable = expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content); | 3638 | if (last->appendix) { |
| 3639 | auto appendix = last->appendix->item.get(); | ||
| 3640 | switch (appendix->getId()) { | ||
| 3641 | case id<WhileLine_t>(): | ||
| 3642 | throw std::logic_error(_info.errorMessage("while-loop line decorator is not supported here"sv, appendix)); | ||
| 3643 | break; | ||
| 3644 | case id<CompFor_t>(): | ||
| 3645 | throw std::logic_error(_info.errorMessage("for-loop line decorator is not supported here"sv, appendix)); | ||
| 3646 | break; | ||
| 3647 | } | ||
| 3648 | } | ||
| 3649 | bool lastAssignable = (expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content)); | ||
| 3643 | if (lastAssignable) { | 3650 | if (lastAssignable) { |
| 3644 | auto x = last; | 3651 | auto x = last; |
| 3645 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 3652 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -3660,6 +3667,8 @@ private: | |||
| 3660 | if (bLast != nodes.rend()) { | 3667 | if (bLast != nodes.rend()) { |
| 3661 | static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); | 3668 | static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); |
| 3662 | } | 3669 | } |
| 3670 | } else if (!last->content.is<BreakLoop_t>()) { | ||
| 3671 | throw std::logic_error(_info.errorMessage("expecting assignable statement or break loop"sv, last)); | ||
| 3663 | } | 3672 | } |
| 3664 | break; | 3673 | break; |
| 3665 | } | 3674 | } |
| @@ -4627,12 +4636,6 @@ private: | |||
| 4627 | 4636 | ||
| 4628 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 4637 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 4629 | auto x = chainList.front(); | 4638 | auto x = chainList.front(); |
| 4630 | if (chainList.size() > 1) { | ||
| 4631 | auto callable = ast_cast<Callable_t>(x); | ||
| 4632 | if (callable && callable->item.is<VarArg_t>()) { | ||
| 4633 | throw std::logic_error(_info.errorMessage("can not access variadic arguments directly"sv, x)); | ||
| 4634 | } | ||
| 4635 | } | ||
| 4636 | str_list temp; | 4639 | str_list temp; |
| 4637 | switch (x->getId()) { | 4640 | switch (x->getId()) { |
| 4638 | case id<DotChainItem_t>(): | 4641 | case id<DotChainItem_t>(): |
| @@ -5277,6 +5280,14 @@ private: | |||
| 5277 | out.push_back(numStr); | 5280 | out.push_back(numStr); |
| 5278 | } | 5281 | } |
| 5279 | 5282 | ||
| 5283 | void transformVarArg(VarArg_t* varArg, str_list& out) { | ||
| 5284 | if (_varArgs.empty() || !_varArgs.top().hasVar) { | ||
| 5285 | throw std::logic_error(_info.errorMessage("cannot use '...' outside a vararg function near '...'"sv, varArg)); | ||
| 5286 | } | ||
| 5287 | _varArgs.top().usedVar = true; | ||
| 5288 | out.push_back("..."s); | ||
| 5289 | } | ||
| 5290 | |||
| 5280 | bool hasSpreadExp(const node_container& items) { | 5291 | bool hasSpreadExp(const node_container& items) { |
| 5281 | for (auto item : items) { | 5292 | for (auto item : items) { |
| 5282 | if (ast_is<SpreadExp_t>(item)) return true; | 5293 | if (ast_is<SpreadExp_t>(item)) return true; |
| @@ -5420,10 +5431,9 @@ private: | |||
| 5420 | BREAK_IF(current != values.back()); | 5431 | BREAK_IF(current != values.back()); |
| 5421 | auto value = singleValueFrom(item); | 5432 | auto value = singleValueFrom(item); |
| 5422 | BREAK_IF(!value); | 5433 | BREAK_IF(!value); |
| 5423 | auto chainValue = value->item.as<ChainValue_t>(); | 5434 | auto simpleValue = value->item.as<SimpleValue_t>(); |
| 5424 | BREAK_IF(!chainValue); | 5435 | BREAK_IF(!simpleValue); |
| 5425 | BREAK_IF(chainValue->items.size() != 1); | 5436 | BREAK_IF(!simpleValue->value.is<VarArg_t>()); |
| 5426 | BREAK_IF((!chainValue->getByPath<Callable_t, VarArg_t>())); | ||
| 5427 | auto indexVar = getUnusedName("_index_"); | 5437 | auto indexVar = getUnusedName("_index_"); |
| 5428 | _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; | 5438 | _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; |
| 5429 | transformFor(toAst<For_t>(clearBuf(), item), temp); | 5439 | transformFor(toAst<For_t>(clearBuf(), item), temp); |
