Created
February 29, 2024 10:40
-
-
Save neworderofjamie/f8903409eb03ea3ded0ac1e9064131e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <memory> | |
#include <string> | |
#include <vector> | |
// Forward declarations | |
class NoAnnotation; | |
template<typename A = NoAnnotation> | |
class Literal; | |
template<typename A = NoAnnotation> | |
class Binary; | |
class NoAnnotation | |
{ | |
}; | |
class TypeAnnotation | |
{ | |
public: | |
TypeAnnotation(const std::string &type) : m_Type(type) | |
{} | |
const std::string &getType() const{ return m_Type; } | |
private: | |
std::string m_Type; | |
}; | |
// Visitor | |
template<typename A = NoAnnotation> | |
class Visitor | |
{ | |
public: | |
virtual void visit(const Binary<A> &binary) = 0; | |
virtual void visit(const Literal<A> &literal) = 0; | |
}; | |
//--------------------------------------------------------------------------- | |
// GeNN::Transpiler::Expression::Base | |
//--------------------------------------------------------------------------- | |
template<typename A = NoAnnotation> | |
class Base : public A | |
{ | |
public: | |
using A::A; | |
virtual void accept(Visitor<A> &visitor) const = 0; | |
}; | |
//--------------------------------------------------------------------------- | |
// GeNN::Transpiler::Expression::Acceptable | |
//--------------------------------------------------------------------------- | |
template<typename T, typename A = NoAnnotation> | |
class Acceptable : public Base<A> | |
{ | |
public: | |
using Base<A>::Base; | |
virtual void accept(Visitor<A> &visitor) const final | |
{ | |
visitor.visit(static_cast<const T&>(*this)); | |
} | |
}; | |
template<typename A = NoAnnotation> | |
using ExpressionPtr = std::unique_ptr<Base<A> const> ; | |
template<typename A = NoAnnotation> | |
using ExpressionList = std::vector<ExpressionPtr<A>>; | |
//--------------------------------------------------------------------------- | |
// GeNN::Transpiler::Expression::Binary | |
//--------------------------------------------------------------------------- | |
template<typename A> | |
class Binary : public Acceptable<Binary<A>, A> | |
{ | |
public: | |
template<typename... PolicyArgs> | |
Binary(ExpressionPtr<A> left, ExpressionPtr<A> right, PolicyArgs&&... policyArgs) | |
: Acceptable<Binary<A>, A>(std::forward<PolicyArgs>(policyArgs)...), m_Left(std::move(left)), m_Right(std::move(right)) | |
{} | |
const Base<A> *getLeft() const { return m_Left.get(); } | |
const Base<A> *getRight() const { return m_Right.get(); } | |
private: | |
ExpressionPtr<A> m_Left; | |
ExpressionPtr<A> m_Right; | |
}; | |
//--------------------------------------------------------------------------- | |
// GeNN::Transpiler::Expression::Literal | |
//--------------------------------------------------------------------------- | |
template<typename A> | |
class Literal : public Acceptable<Literal<A>, A> | |
{ | |
public: | |
template<typename... PolicyArgs> | |
Literal(int value, PolicyArgs&&... policyArgs) | |
: Acceptable<Literal<A>, A>(std::forward<PolicyArgs>(policyArgs)...), m_Value(value) | |
{} | |
int getValue() const { return m_Value; } | |
private: | |
int m_Value; | |
}; | |
class TestVisitor : public Visitor<> | |
{ | |
public: | |
virtual void visit(const Binary<> &binary) | |
{ | |
std::cout << "Visiting binary" << std::endl; | |
binary.getLeft()->accept(*this); | |
binary.getRight()->accept(*this); | |
} | |
virtual void visit(const Literal<> &literal) | |
{ | |
std::cout << "Visiting literal value:" << literal.getValue() << std::endl; | |
} | |
}; | |
class AnnotatingVisitor : public Visitor<> | |
{ | |
public: | |
virtual void visit(const Binary<> &binary) | |
{ | |
std::cout << "Annotating binary" << std::endl; | |
binary.getLeft()->accept(*this); | |
auto leftExpression = std::move(m_CurrentExpression); | |
binary.getRight()->accept(*this); | |
auto rightExpression = std::move(m_CurrentExpression); | |
m_CurrentExpression = std::make_unique<Binary<TypeAnnotation>>(std::move(leftExpression), std::move(rightExpression), "int"); | |
} | |
virtual void visit(const Literal<> &literal) | |
{ | |
std::cout << "Annotating literal" << std::endl; | |
m_CurrentExpression = std::make_unique<Literal<TypeAnnotation>>(literal.getValue(), "int"); | |
} | |
ExpressionPtr<TypeAnnotation> annotate(const Base<> *expression) | |
{ | |
expression->accept(*this); | |
return std::move(m_CurrentExpression); | |
} | |
private: | |
ExpressionPtr<TypeAnnotation> m_CurrentExpression; | |
}; | |
class TypeVisitor : public Visitor<TypeAnnotation> | |
{ | |
public: | |
virtual void visit(const Binary<TypeAnnotation> &binary) | |
{ | |
std::cout << "Visiting binary (" << binary.getType() << ")" << std::endl; | |
binary.getLeft()->accept(*this); | |
binary.getRight()->accept(*this); | |
} | |
virtual void visit(const Literal<TypeAnnotation> &literal) | |
{ | |
std::cout << "Visiting literal value:" << literal.getValue() << "(" << literal.getType() << ")" << std::endl; | |
} | |
}; | |
int main() | |
{ | |
auto a = std::make_unique<Literal<>>(1); | |
auto b = std::make_unique<Literal<>>(2); | |
auto c = std::make_unique<Binary<>>(std::move(a), std::move(b)); | |
TestVisitor visitor; | |
c->accept(visitor); | |
AnnotatingVisitor annotator; | |
auto annotated = annotator.annotate(c.get()); | |
TypeVisitor typeVisitor; | |
annotated->accept(typeVisitor); | |
/*{ | |
auto a = std::make_unique<Literal<TypeAnnotation>>(1, "int"); | |
auto b = std::make_unique<Literal<TypeAnnotation>>(2, "int"); | |
auto c = std::make_unique<Binary<TypeAnnotation>>(std::move(a), std::move(b), "int"); | |
TypeVisitor visitor; | |
visitor.visit(*c); | |
}*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment