diff options
author | Li Jin <dragon-fly@qq.com> | 2021-02-10 14:34:08 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-02-10 20:50:03 +0800 |
commit | c68e11bc6d7631185749aaf0c8d89147b3ac9cc9 (patch) | |
tree | e91306fa43513f7a66022ba16abbc224a91c8bd5 /src/MoonP/moon_compiler.cpp | |
parent | 9f622c5bbd9cfb7e66a9fd3c371461af4249d566 (diff) | |
download | yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.tar.gz yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.tar.bz2 yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.zip |
update backcall operator syntax, fix issue #31.
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()) { |