aboutsummaryrefslogtreecommitdiff
path: root/src/MoonP/moon_compiler.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-02-10 14:34:08 +0800
committerLi Jin <dragon-fly@qq.com>2021-02-10 20:50:03 +0800
commitc68e11bc6d7631185749aaf0c8d89147b3ac9cc9 (patch)
treee91306fa43513f7a66022ba16abbc224a91c8bd5 /src/MoonP/moon_compiler.cpp
parent9f622c5bbd9cfb7e66a9fd3c371461af4249d566 (diff)
downloadyuescript-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.cpp104
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
56const std::string_view version = "0.5.2"sv; 56const std::string_view version = "0.6.0"sv;
57const std::string_view extension = "mp"sv; 57const std::string_view extension = "mp"sv;
58 58
59class MoonCompilerImpl { 59class 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()) {