#include <msp/core/algorithm.h>
#include <msp/gl/extensions/ext_gpu_shader4.h>
#include <msp/strings/format.h>
-#include <msp/strings/regex.h>
-#include <msp/strings/utils.h>
#include "compatibility.h"
#include "compiler.h"
#include "error.h"
delete module;
module = new Module();
imported_names.clear();
+ module->source_map.set_name(0, "<generated>");
}
void Compiler::set_source(const string &source, const string &src_name)
}
catch(const compile_error &e)
{
- static const Regex r_message("^(([0-9]+)\\(([0-9]+)\\) :|ERROR: ([0-9]+):([0-9]+):) (.*)$");
- vector<string> lines = split(e.what(), '\n');
- string translated;
- for(vector<string>::const_iterator i=lines.begin(); i!=lines.end(); ++i)
- {
- RegMatch m = r_message.match(*i);
- if(m)
- {
- unsigned index = 0;
- unsigned line = 0;
- if(m[2])
- {
- index = lexical_cast<unsigned>(m[2].str);
- line = lexical_cast<unsigned>(m[3].str);
- }
- else if(m[4])
- {
- index = lexical_cast<unsigned>(m[4].str);
- line = lexical_cast<unsigned>(m[5].str);
- }
- const char *src = "<unknown>";
- if(index==0)
- src = "<generated>";
- else if(index-1<imported_names.size())
- src = imported_names[index-1].c_str();
- translated += format("%s:%d: %s", src, line, m[6].str);
- }
- else
- translated += *i;
- translated += '\n';
- }
-
- throw compile_error(translated);
+ throw compile_error(module->source_map.translate_errors(e.what()));
}
}
void Compiler::append_module(Module &mod, DataFile::Collection *res)
{
+ module->source_map.merge_from(mod.source_map);
+
vector<Import *> imports = NodeGatherer<Import>().apply(mod.shared);
for(vector<Import *>::iterator i=imports.begin(); i!=imports.end(); ++i)
import(res, (*i)->module);
if(!io)
throw runtime_error(format("module %s not found", name));
Parser import_parser;
- append_module(import_parser.parse(*io, fn, imported_names.size()), resources);
+ append_module(import_parser.parse(*io, fn, module->source_map.get_count()), resources);
}
void Compiler::generate(Stage &stage)
Module &Parser::parse(const string &s, const string &n, unsigned i)
{
source = s;
- source_index = i;
- parse_source(n);
+ parse_source(n, i);
return *module;
}
Module &Parser::parse(IO::Base &io, const string &n, unsigned i)
{
source = string();
- source_index = i;
while(!io.eof())
{
char buffer[4096];
unsigned len = io.read(buffer, sizeof(buffer));
source.append(buffer, len);
}
- parse_source(n);
+ parse_source(n, i);
return *module;
}
-void Parser::parse_source(const string &name)
+void Parser::parse_source(const string &name, unsigned index)
{
delete module;
module = new Module;
cur_stage = &module->shared;
+ source_index = index;
+ module->source_map.set_name(source_index, name);
tokenizer.begin(name, source);
while(RefPtr<Statement> statement = parse_global_declaration())
cur_stage->content.body.push_back(statement);
{
private:
std::string source;
- std::string source_name;
unsigned source_index;
Tokenizer tokenizer;
Preprocessor preprocessor;
Module &parse(IO::Base &, const std::string &, unsigned = 0);
private:
- void parse_source(const std::string &);
+ void parse_source(const std::string &, unsigned);
void set_required_version(const Version &);
void stage_change(Stage::Type);
--- /dev/null
+#include <msp/strings/format.h>
+#include <msp/strings/regex.h>
+#include <msp/strings/utils.h>
+#include "sourcemap.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+namespace SL {
+
+SourceMap::SourceMap():
+ base_index(0)
+{ }
+
+void SourceMap::set_name(unsigned i, const std::string &n)
+{
+ if(source_names.empty())
+ base_index = i;
+ else if(i<base_index)
+ {
+ source_names.insert(source_names.begin(), base_index-i, string());
+ base_index = i;
+ }
+ i -= base_index;
+
+ if(source_names.size()<=i)
+ source_names.resize(i+1);
+ source_names[i] = n;
+}
+
+void SourceMap::merge_from(const SourceMap &other)
+{
+ if(other.base_index<base_index)
+ {
+ source_names.insert(source_names.begin(), base_index-other.base_index, string());
+ base_index = other.base_index;
+ }
+ if(get_count()<other.get_count())
+ source_names.resize(other.get_count()-base_index);
+
+ for(unsigned i=0; i<other.source_names.size(); ++i)
+ if(!other.source_names[i].empty())
+ source_names[i+other.base_index-base_index] = other.source_names[i];
+}
+
+string SourceMap::translate_errors(const string &errors) const
+{
+ static const Regex r_message("^(([0-9]+)\\(([0-9]+)\\) :|ERROR: ([0-9]+):([0-9]+):) (.*)$");
+ vector<string> lines = split(errors, '\n');
+ string translated;
+ for(vector<string>::const_iterator i=lines.begin(); i!=lines.end(); ++i)
+ {
+ RegMatch m = r_message.match(*i);
+ if(m)
+ {
+ unsigned index = 0;
+ unsigned line = 0;
+ if(m[2])
+ {
+ index = lexical_cast<unsigned>(m[2].str);
+ line = lexical_cast<unsigned>(m[3].str);
+ }
+ else if(m[4])
+ {
+ index = lexical_cast<unsigned>(m[4].str);
+ line = lexical_cast<unsigned>(m[5].str);
+ }
+ const char *src = "<unknown>";
+ if(index<source_names.size() && !source_names[index].empty())
+ src = source_names[index].c_str();
+ translated += format("%s:%d: %s", src, line, m[6].str);
+ }
+ else
+ translated += *i;
+ translated += '\n';
+ }
+
+ return translated;
+}
+
+} // namespace SL
+} // namespace GL
+} // namespace Msp
--- /dev/null
+#ifndef MSP_GL_SL_SOURCEMAP_H_
+#define MSP_GL_SL_SOURCEMAP_H_
+
+#include <string>
+#include <vector>
+
+namespace Msp {
+namespace GL {
+namespace SL {
+
+class SourceMap
+{
+private:
+ unsigned base_index;
+ std::vector<std::string> source_names;
+
+public:
+ SourceMap();
+
+ void set_name(unsigned, const std::string &);
+ unsigned get_count() const { return base_index+source_names.size(); }
+ void merge_from(const SourceMap &);
+ std::string translate_errors(const std::string &) const;
+};
+
+} // namespace SL
+} // namespace GL
+} // namespace Msp
+
+#endif
#include <vector>
#include <msp/core/refptr.h>
#include "extension.h"
+#include "sourcemap.h"
#include "uniform.h"
#pragma push_macro("interface")
struct Module
{
+ SourceMap source_map;
Stage shared;
std::list<Stage> stages;