+#include <msp/io/seekable.h>
+#include "modulecache.h"
+#include "parser.h"
+#include "resources.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+namespace SL {
+
+ModuleCache::ModuleCache(DataFile::Collection *r):
+ resources(r),
+ next_source(1)
+{ }
+
+ModuleCache::ModuleCache(const ModuleCache &other)
+{
+ for(map<string, Module *>::const_iterator i=other.modules.begin(); i!=other.modules.end(); ++i)
+ modules[i->first] = new Module(*i->second);
+}
+
+ModuleCache &ModuleCache::operator=(const ModuleCache &other)
+{
+ for(map<string, Module *>::iterator i=modules.begin(); i!=modules.end(); ++i)
+ delete i->second;
+ modules.clear();
+ for(map<string, Module *>::const_iterator i=other.modules.begin(); i!=other.modules.end(); ++i)
+ modules[i->first] = new Module(*i->second);
+ return *this;
+}
+
+ModuleCache::~ModuleCache()
+{
+ for(map<string, Module *>::iterator i=modules.begin(); i!=modules.end(); ++i)
+ delete i->second;
+}
+
+const Module &ModuleCache::add_module(const string &source, const string &src_name)
+{
+ RefPtr<Module> module = new Module;
+ Parser parser(this);
+ unsigned src_index = next_source++;
+ parser.parse(*module, source, src_name, src_index);
+ return *(modules[src_name] = module.release());
+}
+
+const Module &ModuleCache::add_module(IO::Base &io, const string &src_name)
+{
+ RefPtr<Module> module = new Module;
+ Parser parser(this);
+ unsigned src_index = next_source++;
+ parser.parse(*module, io, src_name, src_index);
+ return *(modules[src_name] = module.release());
+}
+
+const Module &ModuleCache::get_module(const string &name)
+{
+ string fn = name+".glsl";
+ map<string, Module *>::const_iterator i = modules.find(fn);
+ if(i!=modules.end())
+ return *i->second;
+
+ RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
+ if(!io)
+ throw runtime_error(format("module %s not found", name));
+
+ return add_module(*io, fn);
+}
+
+} // namespace SL
+} // namespace GL
+} // namespace Msp