--- /dev/null
+#ifndef __NEST_SCHEDULE_H__
+#define __NEST_SCHEDULE_H__
+
+#include "nest/Module.h"
+#include "nest/Level.h"
+
+#include <vector>
+
+namespace nest
+{
+
+class Schedule final
+{
+public:
+ explicit Schedule(const Module &);
+
+public:
+ const VarContext &var(void) const { return _module.var(); }
+ const DomainContext &domain(void) const { return _module.domain(); }
+ const Block &block(void) const { return _module.block(); }
+ const Ret &ret(void) const { return _module.ret(); }
+
+public:
+ Var at(const Level &) const;
+ Level level(const Var &) const;
+
+private:
+ Module _module;
+
+private:
+ std::vector<VarID> _level;
+};
+
+} // namespace nest
+
+#endif // __NEST_SCHEDULE_H___
--- /dev/null
+#include "nest/Schedule.h"
+
+#include <cassert>
+#include <stdexcept>
+
+namespace nest
+{
+
+Schedule::Schedule(const Module &module) : _module{module}
+{
+ // NOTE This implementation assumes that VarContext sequentially assigns VarID
+ for (uint32_t n = 0; n < _module.var().count(); ++n)
+ {
+ _level.emplace_back(VarID{n});
+ }
+
+ assert(_level.size() == _module.var().count());
+}
+
+Var Schedule::at(const Level &lv) const { return Var{_level.at(lv.value())}; }
+
+Level Schedule::level(const Var &var) const
+{
+ for (uint32_t lv = 0; lv < _level.size(); ++lv)
+ {
+ if (_level.at(lv) == var.id())
+ {
+ return Level{lv};
+ }
+ }
+
+ throw std::invalid_argument{"var"};
+}
+
+} // namespace nest
--- /dev/null
+#include "nest/Schedule.h"
+
+#include <gtest/gtest.h>
+
+TEST(SCHEDULE, module)
+{
+ nest::Module m;
+
+ auto var_1 = m.var().make();
+
+ nest::Schedule sch{m};
+
+ ASSERT_EQ(sch.level(var_1).value(), 0);
+}
+
+TEST(SCHEDULE, module_copy)
+{
+ nest::Module m;
+
+ m.var().make();
+
+ nest::Schedule sch{m};
+
+ // Update on 'm' does not affect the schedule
+ m.var().make();
+
+ ASSERT_EQ(sch.var().count(), 1);
+}