diff options
Diffstat (limited to '')
| -rw-r--r-- | src/MoonP/moon_compiler.cpp | 104 |
1 files changed, 96 insertions, 8 deletions
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 73bbd60..11d4ed8 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
| @@ -53,7 +53,7 @@ inline std::string s(std::string_view sv) { | |||
| 53 | return std::string(sv); | 53 | return std::string(sv); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | const std::string_view version = "0.5.2"sv; | 56 | const std::string_view version = "0.6.0"sv; |
| 57 | const std::string_view extension = "mp"sv; | 57 | const std::string_view extension = "mp"sv; |
| 58 | 58 | ||
| 59 | class MoonCompilerImpl { | 59 | class MoonCompilerImpl { |
| @@ -429,7 +429,7 @@ private: | |||
| 429 | return result; | 429 | return result; |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | Value_t* singleValueFrom(ast_node* item) const { | 432 | unary_exp_t* singleUnaryExpFrom(ast_node* item) const { |
| 433 | Exp_t* exp = nullptr; | 433 | Exp_t* exp = nullptr; |
| 434 | switch (item->getId()) { | 434 | switch (item->getId()) { |
| 435 | case id<Exp_t>(): | 435 | case id<Exp_t>(): |
| @@ -451,8 +451,8 @@ private: | |||
| 451 | } | 451 | } |
| 452 | case id<unary_exp_t>(): { | 452 | case id<unary_exp_t>(): { |
| 453 | auto unary = static_cast<unary_exp_t*>(item); | 453 | auto unary = static_cast<unary_exp_t*>(item); |
| 454 | if (unary->ops.empty() && unary->expos.size() == 1) { | 454 | if (unary->expos.size() == 1) { |
| 455 | return static_cast<Value_t*>(unary->expos.back()); | 455 | return unary; |
| 456 | } | 456 | } |
| 457 | return nullptr; | 457 | return nullptr; |
| 458 | } | 458 | } |
| @@ -463,13 +463,21 @@ private: | |||
| 463 | BREAK_IF(!exp->opValues.empty()); | 463 | BREAK_IF(!exp->opValues.empty()); |
| 464 | BREAK_IF(exp->backcalls.size() != 1); | 464 | BREAK_IF(exp->backcalls.size() != 1); |
| 465 | auto unary = static_cast<unary_exp_t*>(exp->backcalls.back()); | 465 | auto unary = static_cast<unary_exp_t*>(exp->backcalls.back()); |
| 466 | BREAK_IF(!unary->ops.empty()); | ||
| 467 | BREAK_IF(unary->expos.size() != 1); | 466 | BREAK_IF(unary->expos.size() != 1); |
| 468 | return static_cast<Value_t*>(unary->expos.back()); | 467 | return unary; |
| 469 | BLOCK_END | 468 | BLOCK_END |
| 470 | return nullptr; | 469 | return nullptr; |
| 471 | } | 470 | } |
| 472 | 471 | ||
| 472 | Value_t* singleValueFrom(ast_node* item) const { | ||
| 473 | if (auto unary = singleUnaryExpFrom(item)) { | ||
| 474 | if (unary->ops.empty()) { | ||
| 475 | return static_cast<Value_t*>(unary->expos.back()); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | return nullptr; | ||
| 479 | } | ||
| 480 | |||
| 473 | ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) { | 481 | ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) { |
| 474 | auto unary = x->new_ptr<unary_exp_t>(); | 482 | auto unary = x->new_ptr<unary_exp_t>(); |
| 475 | unary->expos.push_back(value); | 483 | unary->expos.push_back(value); |
| @@ -522,6 +530,60 @@ private: | |||
| 522 | return stmts.empty() ? nullptr : static_cast<Statement_t*>(stmts.back()); | 530 | return stmts.empty() ? nullptr : static_cast<Statement_t*>(stmts.back()); |
| 523 | } | 531 | } |
| 524 | 532 | ||
| 533 | Exp_t* lastExpFromAssign(ast_node* action) { | ||
| 534 | switch (action->getId()) { | ||
| 535 | case id<Update_t>(): { | ||
| 536 | auto update = static_cast<Update_t*>(action); | ||
| 537 | return update->value; | ||
| 538 | } | ||
| 539 | case id<Assign_t>(): { | ||
| 540 | auto assign = static_cast<Assign_t*>(action); | ||
| 541 | return ast_cast<Exp_t>(assign->values.back()); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | return nullptr; | ||
| 545 | } | ||
| 546 | |||
| 547 | Exp_t* lastExpFromStatement(Statement_t* stmt) { | ||
| 548 | if (!stmt->content) return nullptr; | ||
| 549 | switch (stmt->content->getId()) { | ||
| 550 | case id<ExpListAssign_t>(): { | ||
| 551 | auto expListAssign = static_cast<ExpListAssign_t*>(stmt->content.get()); | ||
| 552 | if (auto action = expListAssign->action.get()) { | ||
| 553 | return lastExpFromAssign(action); | ||
| 554 | } else { | ||
| 555 | return static_cast<Exp_t*>(expListAssign->expList->exprs.back()); | ||
| 556 | } | ||
| 557 | } | ||
| 558 | case id<Export_t>(): { | ||
| 559 | auto exportNode = static_cast<Export_t*>(stmt->content.get()); | ||
| 560 | if (auto action = exportNode->assign.get()) { | ||
| 561 | return lastExpFromAssign(action); | ||
| 562 | } else { | ||
| 563 | switch (exportNode->target->getId()) { | ||
| 564 | case id<Exp_t>(): return exportNode->target.to<Exp_t>(); | ||
| 565 | case id<ExpList_t>(): return static_cast<Exp_t*>(exportNode->target.to<ExpList_t>()->exprs.back()); | ||
| 566 | } | ||
| 567 | } | ||
| 568 | } | ||
| 569 | case id<Local_t>(): { | ||
| 570 | if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<local_values_t>()) { | ||
| 571 | if (auto expList = localValues->valueList.as<ExpListLow_t>()) { | ||
| 572 | return static_cast<Exp_t*>(expList->exprs.back()); | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | case id<Global_t>(): { | ||
| 577 | if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<global_values_t>()) { | ||
| 578 | if (auto expList = globalValues->valueList.as<ExpListLow_t>()) { | ||
| 579 | return static_cast<Exp_t*>(expList->exprs.back()); | ||
| 580 | } | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | return nullptr; | ||
| 585 | } | ||
| 586 | |||
| 525 | template <class T> | 587 | template <class T> |
| 526 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 588 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
| 527 | auto res = _parser.parse<T>(s(codes)); | 589 | auto res = _parser.parse<T>(s(codes)); |
| @@ -812,6 +874,7 @@ private: | |||
| 812 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; | 874 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; |
| 813 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | 875 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; |
| 814 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; | 876 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; |
| 877 | case id<BackcallBody_t>(): throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); break; | ||
| 815 | case id<ExpListAssign_t>(): { | 878 | case id<ExpListAssign_t>(): { |
| 816 | auto expListAssign = static_cast<ExpListAssign_t*>(content); | 879 | auto expListAssign = static_cast<ExpListAssign_t*>(content); |
| 817 | if (expListAssign->action) { | 880 | if (expListAssign->action) { |
| @@ -1692,7 +1755,10 @@ private: | |||
| 1692 | auto begin = values.begin(); begin++; | 1755 | auto begin = values.begin(); begin++; |
| 1693 | for (auto it = begin; it != values.end(); ++it) { | 1756 | for (auto it = begin; it != values.end(); ++it) { |
| 1694 | auto unary = static_cast<unary_exp_t*>(*it); | 1757 | auto unary = static_cast<unary_exp_t*>(*it); |
| 1695 | auto value = singleValueFrom(unary); | 1758 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); |
| 1759 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { | ||
| 1760 | throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, x)); | ||
| 1761 | } | ||
| 1696 | if (!value) throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, *it)); | 1762 | if (!value) throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, *it)); |
| 1697 | if (auto chainValue = value->item.as<ChainValue_t>()) { | 1763 | if (auto chainValue = value->item.as<ChainValue_t>()) { |
| 1698 | if (isChainValueCall(chainValue)) { | 1764 | if (isChainValueCall(chainValue)) { |
| @@ -1936,7 +2002,29 @@ private: | |||
| 1936 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { | 2002 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { |
| 1937 | auto node = *it; | 2003 | auto node = *it; |
| 1938 | auto stmt = static_cast<Statement_t*>(node); | 2004 | auto stmt = static_cast<Statement_t*>(node); |
| 1939 | if (auto backcall = stmt->content.as<Backcall_t>()) { | 2005 | if (auto backcallBody = stmt->content.as<BackcallBody_t>()) { |
| 2006 | auto x = stmt; | ||
| 2007 | bool cond = false; | ||
| 2008 | BLOCK_START | ||
| 2009 | BREAK_IF(it == nodes.begin()); | ||
| 2010 | auto last = it; --last; | ||
| 2011 | auto lst = static_cast<Statement_t*>(*last); | ||
| 2012 | auto exp = lastExpFromStatement(lst); | ||
| 2013 | BREAK_IF(!exp); | ||
| 2014 | for (auto val : backcallBody->values.objects()) { | ||
| 2015 | exp->backcalls.push_back(val); | ||
| 2016 | } | ||
| 2017 | cond = true; | ||
| 2018 | BLOCK_END | ||
| 2019 | if (!cond) throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); | ||
| 2020 | stmt->content.set(nullptr); | ||
| 2021 | auto next = it; ++next; | ||
| 2022 | BLOCK_START | ||
| 2023 | BREAK_IF(next == nodes.end()); | ||
| 2024 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<BackcallBody_t>()); | ||
| 2025 | throw std::logic_error(_info.errorMessage("indent mismatch in backcall chain"sv, *next)); | ||
| 2026 | BLOCK_END | ||
| 2027 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { | ||
| 1940 | auto x = *nodes.begin(); | 2028 | auto x = *nodes.begin(); |
| 1941 | auto newBlock = x->new_ptr<Block_t>(); | 2029 | auto newBlock = x->new_ptr<Block_t>(); |
| 1942 | if (it != nodes.begin()) { | 2030 | if (it != nodes.begin()) { |
