Record statement source lines and emit #line directives to output
authorMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 11:27:32 +0000 (14:27 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 11:54:28 +0000 (14:54 +0300)
source/programcompiler.cpp
source/programcompiler.h
source/programparser.cpp
source/programparser.h
source/programsyntax.cpp
source/programsyntax.h

index 50e4f5851df3cb11aecb1277763f622bb3a8d6f1..518b31e17f0d76213f2de8c52160cb3602f346b5 100644 (file)
@@ -58,7 +58,7 @@ void ProgramCompiler::compile(const string &source, const string &src_name)
        module = new Module();
        ProgramParser parser;
        imported_names.insert(src_name);
-       append_module(parser.parse(source, src_name));
+       append_module(parser.parse(source, src_name, 1));
        process();
 }
 
@@ -69,7 +69,7 @@ void ProgramCompiler::compile(IO::Base &io, Resources *res, const string &src_na
        module = new Module();
        ProgramParser parser;
        imported_names.insert(src_name);
-       append_module(parser.parse(io, src_name));
+       append_module(parser.parse(io, src_name, 1));
        process();
 }
 
@@ -199,7 +199,7 @@ void ProgramCompiler::import(const string &name)
        if(!io)
                throw runtime_error(format("module %s not found", name));
        ProgramParser import_parser;
-       append_module(import_parser.parse(*io, fn));
+       append_module(import_parser.parse(*io, fn, imported_names.size()));
 }
 
 void ProgramCompiler::generate(Stage &stage)
@@ -307,6 +307,7 @@ void ProgramCompiler::BlockModifier::visit(Block &block)
 
 
 ProgramCompiler::Formatter::Formatter():
+       source_line(1),
        indent(0),
        parameter_list(false)
 { }
@@ -335,11 +336,34 @@ void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
 void ProgramCompiler::Formatter::append(const string &text)
 {
        formatted += text;
+       for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
+               if(*i=='\n')
+                       ++source_line;
 }
 
 void ProgramCompiler::Formatter::append(char c)
 {
        formatted += c;
+       if(c=='\n')
+               ++source_line;
+}
+
+void ProgramCompiler::Formatter::set_source(unsigned index, unsigned line)
+{
+       if(index!=source_index || (index && line!=source_line))
+       {
+               if(index==source_index && line==source_line+1)
+                       formatted += '\n';
+               else
+               {
+                       unsigned l = line;
+                       if(stage->required_version<Version(3, 30))
+                               --l;
+                       formatted += format("#line %d %d\n", l, index);
+               }
+       }
+       source_index = index;
+       source_line = line;
 }
 
 void ProgramCompiler::Formatter::visit(Literal &literal)
@@ -420,6 +444,7 @@ void ProgramCompiler::Formatter::visit(Block &block)
        {
                if(i!=block.body.begin())
                        append('\n');
+               set_source((*i)->source, (*i)->line);
                append(spaces);
                (*i)->visit(*this);
        }
@@ -549,7 +574,9 @@ void ProgramCompiler::Formatter::visit(Conditional &cond)
                Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
                if(cond.else_body.body.size()==1 && else_cond)
                {
-                       append(format("\n%selse ", string(indent*2, ' ')));
+                       append('\n');
+                       set_source(else_cond->source, else_cond->line);
+                       append(format("%selse ", string(indent*2, ' ')));
                        else_cond->visit(*this);
                }
                else
index 9c20e090980fd3d403c4574345692314a1eeff71..697c608617bc2a85c91524b04d91eff0978d74f2 100644 (file)
@@ -44,6 +44,8 @@ private:
                typedef std::string ResultType;
 
                std::string formatted;
+               unsigned source_index;
+               unsigned source_line;
                unsigned indent;
                bool parameter_list;
                std::string block_interface;
@@ -55,6 +57,7 @@ private:
                using Visitor::visit;
                void append(const std::string &);
                void append(char);
+               void set_source(unsigned, unsigned);
                virtual void visit(ProgramSyntax::Block &);
                virtual void visit(ProgramSyntax::Literal &);
                virtual void visit(ProgramSyntax::ParenthesizedExpression &);
index 393936624556df0a0c9fe5b2fef6a8576a1f5b0c..ca554f427464b8863b03ed8211c0f8598e2c7c03 100644 (file)
@@ -70,18 +70,20 @@ ProgramParser::~ProgramParser()
        delete module;
 }
 
-Module &ProgramParser::parse(const string &s, const string &n)
+Module &ProgramParser::parse(const string &s, const string &n, unsigned i)
 {
        source = s;
        source_name = n;
+       source_index = i;
        parse_source();
        return *module;
 }
 
-Module &ProgramParser::parse(IO::Base &io, const string &n)
+Module &ProgramParser::parse(IO::Base &io, const string &n, unsigned i)
 {
        source = string();
        source_name = n;
+       source_index = i;
        while(!io.eof())
        {
                char buffer[4096];
@@ -443,6 +445,8 @@ RefPtr<Statement> ProgramParser::parse_global_declaration()
                if(is_interface_qualifier(token) && peek_token(1)==";")
                {
                        RefPtr<InterfaceLayout> iface_lo = new InterfaceLayout;
+                       iface_lo->source = source_index;
+                       iface_lo->line = current_line;
                        iface_lo->layout.qualifiers = layout->qualifiers;
                        iface_lo->interface = parse_token();
                        expect(";");
@@ -496,6 +500,8 @@ RefPtr<Statement> ProgramParser::parse_statement()
        else if(token=="break" || token=="continue" || token=="discard")
        {
                RefPtr<Jump> jump = new Jump;
+               jump->source = source_index;
+               jump->line = current_line;
                jump->keyword = parse_token();
                expect(";");
 
@@ -506,6 +512,8 @@ RefPtr<Statement> ProgramParser::parse_statement()
        else if(!token.empty())
        {
                RefPtr<ExpressionStatement> expr = new ExpressionStatement;
+               expr->source = source_index;
+               expr->line = current_line;
                expr->expression = parse_expression();
                expect(";");
 
@@ -522,6 +530,8 @@ RefPtr<Import> ProgramParser::parse_import()
 
        expect("import");
        RefPtr<Import> import = new Import;
+       import->source = source_index;
+       import->line = current_line;
        import->module = expect_identifier();
        expect(";");
        return import;
@@ -531,6 +541,8 @@ RefPtr<Precision> ProgramParser::parse_precision()
 {
        expect("precision");
        RefPtr<Precision> precision = new Precision;
+       precision->source = source_index;
+       precision->line = current_line;
 
        precision->precision = parse_token();
        if(!is_precision_qualifier(precision->precision))
@@ -717,6 +729,8 @@ RefPtr<StructDeclaration> ProgramParser::parse_struct_declaration()
 {
        expect("struct");
        RefPtr<StructDeclaration> strct = new StructDeclaration;
+       strct->source = source_index;
+       strct->line = current_line;
 
        strct->name = expect_identifier();
        parse_block(strct->members, true);
@@ -729,6 +743,8 @@ RefPtr<StructDeclaration> ProgramParser::parse_struct_declaration()
 RefPtr<VariableDeclaration> ProgramParser::parse_variable_declaration()
 {
        RefPtr<VariableDeclaration> var = new VariableDeclaration;
+       var->source = source_index;
+       var->line = current_line;
 
        string token = peek_token();
        while(is_qualifier(token))
@@ -770,6 +786,8 @@ RefPtr<VariableDeclaration> ProgramParser::parse_variable_declaration()
 RefPtr<FunctionDeclaration> ProgramParser::parse_function_declaration()
 {
        RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
+       func->source = source_index;
+       func->line = current_line;
 
        func->return_type = expect_type();
        func->name = expect_identifier();
@@ -806,6 +824,8 @@ RefPtr<FunctionDeclaration> ProgramParser::parse_function_declaration()
 RefPtr<InterfaceBlock> ProgramParser::parse_interface_block()
 {
        RefPtr<InterfaceBlock> iface = new InterfaceBlock;
+       iface->source = source_index;
+       iface->line = current_line;
 
        iface->interface = parse_token();
        if(!is_interface_qualifier(iface->interface))
@@ -830,8 +850,10 @@ RefPtr<InterfaceBlock> ProgramParser::parse_interface_block()
 RefPtr<Conditional> ProgramParser::parse_conditional()
 {
        expect("if");
-       expect("(");
        RefPtr<Conditional> cond = new Conditional;
+       cond->source = source_index;
+       cond->line = current_line;
+       expect("(");
        cond->condition = parse_expression();
        expect(")");
 
@@ -850,8 +872,10 @@ RefPtr<Conditional> ProgramParser::parse_conditional()
 RefPtr<Iteration> ProgramParser::parse_for()
 {
        expect("for");
-       expect("(");
        RefPtr<Iteration> loop = new Iteration;
+       loop->source = source_index;
+       loop->line = current_line;
+       expect("(");
        string token = peek_token();
        if(is_type(token))
                loop->init_statement = parse_statement();
@@ -880,8 +904,10 @@ RefPtr<Iteration> ProgramParser::parse_for()
 RefPtr<Iteration> ProgramParser::parse_while()
 {
        expect("while");
-       expect("(");
        RefPtr<Iteration> loop = new Iteration;
+       loop->source = source_index;
+       loop->line = current_line;
+       expect("(");
        loop->condition = parse_expression();
        expect(")");
 
@@ -894,6 +920,8 @@ RefPtr<Passthrough> ProgramParser::parse_passthrough()
 {
        expect("passthrough");
        RefPtr<Passthrough> pass = new Passthrough;
+       pass->source = source_index;
+       pass->line = current_line;
        if(cur_stage->type==GEOMETRY)
        {
                expect("[");
@@ -908,6 +936,8 @@ RefPtr<Return> ProgramParser::parse_return()
 {
        expect("return");
        RefPtr<Return> ret = new Return;
+       ret->source = source_index;
+       ret->line = current_line;
        if(peek_token()!=";")
                ret->expression = parse_expression();
        expect(";");
index 72817e7ede06f8fe9607a2c17d8d99a503ea6c8e..dc94bd0044443bd01ca862584e6784a58da4fb9f 100644 (file)
@@ -38,6 +38,7 @@ private:
 
        std::string source;
        std::string source_name;
+       unsigned source_index;
        unsigned current_line;
        std::string::const_iterator iter;
        std::string::const_iterator source_end;
@@ -55,8 +56,8 @@ public:
        ProgramParser();
        ~ProgramParser();
 
-       ProgramSyntax::Module &parse(const std::string &, const std::string &);
-       ProgramSyntax::Module &parse(IO::Base &, const std::string &);
+       ProgramSyntax::Module &parse(const std::string &, const std::string &, unsigned = 0);
+       ProgramSyntax::Module &parse(IO::Base &, const std::string &, unsigned = 0);
 
 private:
        void parse_source();
index edd38eaa84285c5924699d9671bc8fb3178a287b..6dea029f2fe024d1fed301a20cf93bd2fc80f430 100644 (file)
@@ -15,6 +15,12 @@ NodeContainer<C>::NodeContainer(const NodeContainer &c):
 }
 
 
+Statement::Statement():
+       source(0),
+       line(1)
+{ }
+
+
 Block::Block():
        use_braces(false)
 { }
index 3db059c4f4d79c4e6252537c5a1cfc27b90e223e..590429519118614f6a59a83796da97f50693ff9c 100644 (file)
@@ -66,6 +66,11 @@ struct FunctionDeclaration;
 
 struct Statement: Node
 {
+       unsigned source;
+       unsigned line;
+
+       Statement();
+
        virtual Statement *clone() const = 0;
 };