virtual CanonicalOpcode opcode(void) const = 0;
template <typename T> T accept(CanonicalNodeVisitorBase<T> *) const;
+ template <typename T> T accept(CanonicalNodeMutableVisitorBase<T> *);
};
template <CanonicalOpcode Code> struct CanonicalNodeImpl : public CanonicalNode
throw std::runtime_error{"NYI"};
}
+template <typename T> T CanonicalNode::accept(CanonicalNodeMutableVisitorBase<T> *v)
+{
+ switch (this->opcode())
+ {
+#define CANONICAL_NODE(OPCODE, CLASS) \
+ case CanonicalOpcode::OPCODE: \
+ return v->visit(dynamic_cast<CLASS *>(this));
+
+#include "CanonicalNodes.lst"
+#undef CANONICAL_NODE
+ default:
+ break;
+ }
+
+ throw std::runtime_error{"NYI"};
+}
+
} // namespace loco
#endif // __LOCO_IR_CANONICAL_NODE_IMPL_H__
namespace loco
{
-// NOTE This forward declaration SHOULD BE aligned with Node delcaration in "CanonicalNodeVisitor.h"
+// NOTE These forward declarations SHOULD BE aligned with "CanonicalNodeVisitor.h"
template <typename T> struct CanonicalNodeVisitorBase;
+template <typename T> struct CanonicalNodeMutableVisitorBase;
} // namespace loco
virtual T visit(const Node *) { throw std::runtime_error{"Not implemented, yet"}; }
};
+/**
+ * DO NOT use this class. Use CanonicalNodeMutableVisitor instead.
+ */
+template <typename T> struct CanonicalNodeMutableVisitorBase
+{
+ virtual ~CanonicalNodeMutableVisitorBase() = default;
+
+#define CANONICAL_NODE(OPCODE, CLASS) virtual T visit(CLASS *) = 0;
+#include "CanonicalNodes.lst"
+#undef CANONICAL_NODE
+};
+
+template <typename T> struct CanonicalNodeMutableVisitor : public CanonicalNodeMutableVisitorBase<T>
+{
+ virtual ~CanonicalNodeMutableVisitor() = default;
+
+#define CANONICAL_NODE(OPCODE, CLASS) \
+ virtual T visit(CLASS *node) { return visit(static_cast<Node *>(node)); }
+#include "CanonicalNodes.lst"
+#undef CANONICAL_NODE
+
+ /// @brief Default fallback
+ virtual T visit(Node *) { throw std::runtime_error{"Not implemented, yet"}; }
+};
+
} // namespace loco
#endif // __LOCO_IR_CANONICAL_NODE_VISITOR_H__
ASSERT_EQ(node.accept(&v), 1);
}
+
+TEST(CanonicalNodeTest, mutable_visitor)
+{
+ struct ResetForward final : public loco::CanonicalNodeMutableVisitor<void>
+ {
+ void visit(loco::Forward *node) final { node->input(nullptr); }
+ };
+
+ loco::Pull pull_node;
+ loco::Forward forward_node;
+
+ forward_node.input(&pull_node);
+
+ ResetForward v;
+ forward_node.accept(&v);
+
+ ASSERT_EQ(forward_node.input(), nullptr);
+}