From cd1d97ef0b1e5a143465a198b5a14a0275931c7f Mon Sep 17 00:00:00 2001 From: starg Date: Sun, 24 Jul 2016 19:23:52 +0900 Subject: [PATCH] =?utf8?q?Phrase2IRCompiler=20=E3=81=AE=20NoteRepeatExpres?= =?utf8?q?sion=20=E3=81=A8=20NoteRepeatEachExpression=20=E9=83=A8=E5=88=86?= =?utf8?q?=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/exceptions/messageexception.hpp | 28 +++++++++++ include/message/id.hpp | 3 +- src/ast2ir/phrase2ir.cpp | 87 +++++++++++++++++++++++++++++++-- src/ast2ir/phrase2ir.hpp | 6 ++- 4 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 include/exceptions/messageexception.hpp diff --git a/include/exceptions/messageexception.hpp b/include/exceptions/messageexception.hpp new file mode 100644 index 0000000..0c2dada --- /dev/null +++ b/include/exceptions/messageexception.hpp @@ -0,0 +1,28 @@ + +#pragma once + +#include + +#include +#include + +namespace YAMML +{ + +namespace Exceptions +{ + +class MessageException : public Exception +{ +public: + MessageException(const Message::MessageItem& item) + : Exception("MessageException: MessageID=" + std::to_string(static_cast(item.ID))), Item(item) + { + } + + Message::MessageItem Item; +}; + +} // namespace Exceptions + +} // namespace YAMML diff --git a/include/message/id.hpp b/include/message/id.hpp index ae13013..3e5e1d3 100644 --- a/include/message/id.hpp +++ b/include/message/id.hpp @@ -12,7 +12,8 @@ enum class MessageID Unknown, UnknownInPhrase2IR, DuplicatedCompositionName, - DuplicatedPhraseName + DuplicatedPhraseName, + TooLargeRepeatCount }; } // namespace Message diff --git a/src/ast2ir/phrase2ir.cpp b/src/ast2ir/phrase2ir.cpp index 64a1388..0d866d2 100644 --- a/src/ast2ir/phrase2ir.cpp +++ b/src/ast2ir/phrase2ir.cpp @@ -1,6 +1,7 @@ #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +87,8 @@ IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteSequenceBlock& a m_AttributeStack.push_back(ast.Attributes); AutoPop autoPop(m_AttributeStack); - return {}; + Compile(ast.Block, newIndex); + return newIndex; } IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteSequence& ast) @@ -93,12 +96,70 @@ IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteSequence& ast) auto newIndex = IR::BlockReference{m_IR.Blocks.size()}; m_IR.Blocks.emplace_back(); - // bounds checking - m_IR.Blocks.at(newIndex.ID); + // with bounds checking + m_IR.Blocks.at(newIndex.ID).Attributes = Concat(m_AttributeStack); for (auto&& i : ast.Notes) { - m_IR.Blocks[newIndex.ID].Events.emplace_back((*this)(i)); + for (auto&& j : i.Notes) + { + m_IR.Blocks[newIndex.ID].Events.emplace_back(j.apply_visitor(*this)); + } + } + + return newIndex; +} + +IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteAndDuration& ast) +{ + return {}; +} + +IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteRepeatExpression& ast) +{ + auto newIndex = IR::BlockReference{m_IR.Blocks.size()}; + m_IR.Blocks.emplace_back(); + + // with bounds checking + m_IR.Blocks.at(newIndex.ID).Attributes = Concat(m_AttributeStack); + + LimitRepeatCount(ast.Count, ast.Location); + + std::vector childBlockRefArray(ast.Notes.size()); + std::transform( + ast.Notes.begin(), + ast.Notes.end(), + childBlockRefArray.begin(), + [this] (auto&& x) { return x.apply_visitor(*this); } + ); + + for (std::size_t i = 0; i < ast.Count; i++) + { + auto& events = m_IR.Blocks[newIndex.ID].Events; + events.insert(events.end(), childBlockRefArray.begin(), childBlockRefArray.end()); + } + + return newIndex; +} + +IR::BlockReference Phrase2IRCompiler::operator()(const AST::NoteRepeatEachExpression& ast) +{ + auto newIndex = IR::BlockReference{m_IR.Blocks.size()}; + m_IR.Blocks.emplace_back(); + + // with bounds checking + m_IR.Blocks.at(newIndex.ID).Attributes = Concat(m_AttributeStack); + + LimitRepeatCount(ast.Count, ast.Location); + + for (auto&& i : ast.Notes) + { + auto childBlockRef = i.apply_visitor(*this); + + for (std::size_t j = 0; j < ast.Count; j++) + { + m_IR.Blocks[newIndex.ID].Events.emplace_back(childBlockRef); + } } return newIndex; @@ -115,6 +176,24 @@ void Phrase2IRCompiler::Compile(const AST::NoteSequenceBlockWithoutAttributes& a } } +void Phrase2IRCompiler::LimitRepeatCount(std::size_t count, const AST::SourceLocation& location) +{ + constexpr std::size_t MaxRepeatCount = 1024; + + if (count > MaxRepeatCount) + { + throw Exceptions::MessageException( + Message::MessageItem{ + Message::MessageKind::Error, + Message::MessageID::TooLargeRepeatCount, + m_IR.Name, + location, + {std::to_string(count), std::to_string(MaxRepeatCount)} + } + ); + } +} + } // namespace AST2IR } // namespace YAMML diff --git a/src/ast2ir/phrase2ir.hpp b/src/ast2ir/phrase2ir.hpp index 9fb63ef..2df80c6 100644 --- a/src/ast2ir/phrase2ir.hpp +++ b/src/ast2ir/phrase2ir.hpp @@ -31,10 +31,14 @@ public: IR::BlockReference operator()(const AST::NoteSequenceBlock& ast); IR::BlockReference operator()(const AST::NoteSequence& ast); - IR::BlockReference operator()(const AST::NoteAndExpression& ast); + + IR::BlockReference operator()(const AST::NoteAndDuration& ast); + IR::BlockReference operator()(const AST::NoteRepeatExpression& ast); + IR::BlockReference operator()(const AST::NoteRepeatEachExpression& ast); private: void Compile(const AST::NoteSequenceBlockWithoutAttributes& ast, IR::BlockReference index); + void LimitRepeatCount(std::size_t count, const AST::SourceLocation& location); IR::Module& m_IR; std::deque> m_AttributeStack; -- 2.11.0