#pragma once
+#include <deque>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <boost/variant.hpp>
+
+#include <ast/attribute.hpp>
#include <compiler/base.hpp>
#include <ir/module.hpp>
+#include <irprocessor/attrprocfactory.hpp>
namespace YAMML
{
namespace IRProcessor
{
-class IRCompiler : public Compiler::CompilerBase
+class IRCompiler : public Compiler::CompilerBase, public boost::static_visitor<>
{
public:
template<typename T>
std::string GetSourceName() const;
const IR::Module& GetIR() const;
+ void operator()(IR::TrackList& trackList);
+ void operator()(AST::Command& command);
+
+ void operator()(IR::Event& ev);
+ void operator()(IR::BlockReference& blockRef);
+
+ void CompileBlock(IR::BlockReference blockRef);
+
private:
void CompileTrackBlock(std::size_t index);
+ void AddAttributeProcessorFactory(std::unique_ptr<IAttributeProcessorFactory> pAttributeProcessorFactory);
+ void InitializeAttributeProcessorFactories();
+
+ void RegisterAttributeProcessors(const std::vector<AST::Attribute>& attributes);
+
+ IR::BlockReference DuplicateBlock(IR::BlockReference blockRef);
+
IR::Module m_IR;
+ std::unordered_map<std::string, std::unique_ptr<IAttributeProcessorFactory>> m_AttributeProcessorFactoryMap;
+ std::deque<std::vector<std::unique_ptr<IAttributeProcessor>>> m_AttributeProcessorStack;
};
} // namespace IRProcessor
+#include <algorithm>
#include <exception>
+#include <utility>
+#include <common/containerutil.hpp>
#include <exceptions/messageexception.hpp>
#include <irprocessor/irprocessor.hpp>
#include <message/message.hpp>
return m_IR;
}
+void IRCompiler::InitializeAttributeProcessorFactories()
+{
+
+}
+
+void IRCompiler::AddAttributeProcessorFactory(std::unique_ptr<IAttributeProcessorFactory> pAttributeProcessorFactory)
+{
+ auto name = pAttributeProcessorFactory->GetAttributeName();
+ m_AttributeProcessorFactoryMap[name] = std::move(pAttributeProcessorFactory);
+}
+
+void IRCompiler::RegisterAttributeProcessors(const std::vector<AST::Attribute>& attributes)
+{
+ std::vector<std::unique_ptr<IAttributeProcessor>> attrProcessors;
+ attrProcessors.reserve(attributes.size());
+
+ for (auto&& i : attributes)
+ {
+ auto itFactory = m_AttributeProcessorFactoryMap.find(i.Name);
+
+ if (itFactory == m_AttributeProcessorFactoryMap.end())
+ {
+ throw Exceptions::MessageException(
+ Message::MessageItem{
+ Message::MessageKind::Error,
+ Message::MessageID::InvalidAttributeName,
+ GetSourceName(),
+ i.Location,
+ {i.Name}
+ }
+ );
+ }
+ else
+ {
+ attrProcessors.push_back(itFactory->second->CreateProcessor(i));
+ }
+ }
+
+ m_AttributeProcessorStack.push_back(std::move(attrProcessors));
+}
+
+IR::BlockReference IRCompiler::DuplicateBlock(IR::BlockReference blockRef)
+{
+ IR::BlockReference newRef{m_IR.Blocks.size()};
+ m_IR.Blocks.push_back(m_IR.Blocks.at(blockRef.ID));
+ return newRef;
+}
+
void IRCompiler::CompileTrackBlock(std::size_t index)
{
- // TODO
+ RegisterAttributeProcessors(m_IR.TrackBlocks.at(index).Attributes);
+ Common::AutoPop<decltype(m_AttributeProcessorStack)> autoPop(m_AttributeProcessorStack);
- if (!m_IR.TrackBlocks[index].Attributes.empty())
+ for (auto&& i : m_IR.TrackBlocks[index].Blocks)
{
- auto attribute = m_IR.TrackBlocks[index].Attributes.at(0);
+ i.apply_visitor(*this);
+ }
+}
- throw Exceptions::MessageException(
- Message::MessageItem{
- Message::MessageKind::Error,
- Message::MessageID::InvalidAttributeName,
- GetSourceName(),
- attribute.Location,
- {attribute.Name}
- }
- );
+void IRCompiler::operator()(IR::TrackList& trackList)
+{
+ RegisterAttributeProcessors(trackList.Attributes);
+ Common::AutoPop<decltype(m_AttributeProcessorStack)> autoPop(m_AttributeProcessorStack);
+
+ for (auto&& i : trackList.Tracks)
+ {
+ RegisterAttributeProcessors(i.Attributes);
+ Common::AutoPop<decltype(m_AttributeProcessorStack)> autoPop2(m_AttributeProcessorStack);
+
+ for (auto&& j : i.Items)
+ {
+ RegisterAttributeProcessors(j.Attributes);
+ Common::AutoPop<decltype(m_AttributeProcessorStack)> autoPop3(m_AttributeProcessorStack);
+
+ auto dupRef = DuplicateBlock(j.Block);
+ j.Block = dupRef;
+
+ CompileBlock(dupRef);
+ }
}
}
+void IRCompiler::operator()(AST::Command&)
+{
+ // no-op
+}
+
+void IRCompiler::CompileBlock(IR::BlockReference blockRef)
+{
+ RegisterAttributeProcessors(m_IR.Blocks.at(blockRef.ID).Attributes);
+ Common::AutoPop<decltype(m_AttributeProcessorStack)> autoPop(m_AttributeProcessorStack);
+
+ for (auto&& i : m_IR.Blocks[blockRef.ID].Events)
+ {
+ i.apply_visitor(*this);
+ }
+}
+
+void IRCompiler::operator()(IR::Event& ev)
+{
+ std::for_each(
+ m_AttributeProcessorStack.rbegin(),
+ m_AttributeProcessorStack.rend(),
+ [&ev] (auto&& x)
+ {
+ for (auto&& i : x)
+ {
+ i->TransformEvent(ev);
+ }
+ }
+ );
+}
+
+void IRCompiler::operator()(IR::BlockReference& blockRef)
+{
+ // 'blockRef' here should be referenced by a single block, thus no need to duplicate it.
+ // blockRef = DuplicateBlock(blockRef);
+ CompileBlock(blockRef);
+}
+
} // namespace IRProcessor
} // namespace YAMML