--- /dev/null
+#ifndef __NEST_STMT_H__
+#define __NEST_STMT_H__
+
+#include "nest/stmt/Node.h"
+#include "nest/stmt/Visitor.h"
+
+#endif // __NEST_STMT_H__
--- /dev/null
+#ifndef __NEST_STMT_FORWARD_H__
+#define __NEST_STMT_FORWARD_H__
+
+#include "nest/stmt/Macro.h"
+
+namespace nest
+{
+namespace stmt
+{
+
+#define STMT(Tag) class NEST_STMT_CLASS_NAME(Tag);
+#include "nest/stmt/Node.def"
+#undef STMT
+
+} // namespace stmt
+} // namespace nest
+
+#endif // __NEST_STMT_FORWARD_H__
--- /dev/null
+#ifndef __NEST_STMT_MACRO_H__
+#define __NEST_STMT_MACRO_H__
+
+#ifndef NEST_STMT_CLASS_NAME
+#define NEST_STMT_CLASS_NAME(Tag) Tag##Node
+#endif // NEST_STMT_CLASS_NAME
+
+#ifndef NEST_STMT_CAST_METHOD_NAME
+#define NEST_STMT_CAST_METHOD_NAME(Tag) as##Tag
+#endif // STMT_CAST_METHOD_NAME
+
+#endif // __NEST_STMT_MACRO_H__
--- /dev/null
+#ifndef STMT
+#error STMT is should be defined before including this file
+#endif
+
+// STMT(Tag)
--- /dev/null
+#ifndef __NEST_STMT_NODE_H__
+#define __NEST_STMT_NODE_H__
+
+#include "nest/stmt/Macro.h"
+#include "nest/stmt/Forward.h"
+#include "nest/stmt/Visitor.h"
+
+#include <stdexcept>
+
+namespace nest
+{
+namespace stmt
+{
+
+struct Node
+{
+ virtual ~Node() = default;
+
+#define STMT(Tag) \
+ virtual const NEST_STMT_CLASS_NAME(Tag) * NEST_STMT_CAST_METHOD_NAME(Tag)(void) const \
+ { \
+ return nullptr; \
+ }
+#include "nest/stmt/Node.def"
+#undef STMT
+
+ template <typename T> T accept(Visitor<T> *v)
+ {
+#define STMT(Tag) \
+ if (auto s = NEST_STMT_CAST_METHOD_NAME(Tag)()) \
+ { \
+ return v->visit(s); \
+ }
+#include "nest/stmt/Node.def"
+#undef STMT
+
+ throw std::runtime_error{"unreachable"};
+ }
+
+ template <typename T> T accept(Visitor<T> &v) { return accept(&v); }
+};
+
+} // namespace stmt
+} // namespace nest
+
+#endif // __NEST_STMT_NODE_H__
--- /dev/null
+#ifndef __NEST_STMT_VISITOR_H__
+#define __NEST_STMT_VISITOR_H__
+
+#include "nest/stmt/Macro.h"
+#include "nest/stmt/Forward.h"
+
+namespace nest
+{
+namespace stmt
+{
+
+template <typename T> struct Visitor
+{
+ virtual ~Visitor() = default;
+
+#define STMT(Tag) virtual T visit(const NEST_STMT_CLASS_NAME(Tag) *) = 0;
+#include "nest/stmt/Node.def"
+#undef STMT
+};
+
+} // namespace stmt
+} // namespace nest
+
+#endif // __NEST_STMT_VISITOR_H__
--- /dev/null
+#include "nest/stmt/Macro.h"
+
+// This file checkes the self-completeness of 'nest/stmt/Macro.h'.
+//
+// NOTE Please do NOT remove this file.
--- /dev/null
+#include "nest/stmt/Node.h"
+
+// This file checkes the self-completeness of 'nest/stmt/Node.h'.
+//
+// NOTE Please do NOT remove this file.
--- /dev/null
+#include "nest/stmt/Visitor.h"
+
+// This file checkes the self-completeness of 'nest/stmt/Visitor.h'.
+//
+// NOTE Please do NOT remove this file.