Refactor ProgramCompiler::Formatter
authorMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 11:24:56 +0000 (14:24 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 21 Jun 2019 11:54:28 +0000 (14:54 +0300)
This is necessary for keeping track of output lines and translating error
locations.

source/programcompiler.cpp
source/programcompiler.h

index 5027dc9b79788783c0e2cc5860fa91c39b232ef2..50e4f5851df3cb11aecb1277763f622bb3a8d6f1 100644 (file)
@@ -308,8 +308,7 @@ void ProgramCompiler::BlockModifier::visit(Block &block)
 
 ProgramCompiler::Formatter::Formatter():
        indent(0),
-       parameter_list(false),
-       else_if(0)
+       parameter_list(false)
 { }
 
 void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
@@ -319,145 +318,151 @@ void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
 
        if(ver)
        {
-               formatted += format("#version %d%02d", ver.major, ver.minor);
+               append(format("#version %d%02d", ver.major, ver.minor));
                if(api==OPENGL_ES2 && ver>=Version(3, 0))
-                       formatted += " es";
+                       append(" es");
                formatted += '\n';
        }
 
        for(vector<const Extension *>::const_iterator i=s.required_extensions.begin(); i!=s.required_extensions.end(); ++i)
-               formatted += format("#extension %s: require\n", (*i)->get_name());
+               append(format("#extension %s: require\n", (*i)->get_name()));
        if(!s.required_extensions.empty())
                formatted += '\n';
 
        Visitor::apply(s);
 }
 
+void ProgramCompiler::Formatter::append(const string &text)
+{
+       formatted += text;
+}
+
+void ProgramCompiler::Formatter::append(char c)
+{
+       formatted += c;
+}
+
 void ProgramCompiler::Formatter::visit(Literal &literal)
 {
-       formatted += literal.token;
+       append(literal.token);
 }
 
 void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr)
 {
-       formatted += '(';
+       append('(');
        parexpr.expression->visit(*this);
-       formatted += ')';
+       append(')');
 }
 
 void ProgramCompiler::Formatter::visit(VariableReference &var)
 {
-       formatted += var.name;
+       append(var.name);
 }
 
 void ProgramCompiler::Formatter::visit(MemberAccess &memacc)
 {
        memacc.left->visit(*this);
-       formatted += format(".%s", memacc.member);
+       append(format(".%s", memacc.member));
 }
 
 void ProgramCompiler::Formatter::visit(UnaryExpression &unary)
 {
        if(unary.prefix)
-               formatted += unary.oper;
+               append(unary.oper);
        unary.expression->visit(*this);
        if(!unary.prefix)
-               formatted += unary.oper;
+               append(unary.oper);
 }
 
 void ProgramCompiler::Formatter::visit(BinaryExpression &binary)
 {
        binary.left->visit(*this);
-       formatted += binary.oper;
+       append(binary.oper);
        binary.right->visit(*this);
-       formatted += binary.after;
+       append(binary.after);
 }
 
 void ProgramCompiler::Formatter::visit(Assignment &assign)
 {
        assign.left->visit(*this);
-       formatted += format(" %s ", assign.oper);
+       append(format(" %s ", assign.oper));
        assign.right->visit(*this);
 }
 
 void ProgramCompiler::Formatter::visit(FunctionCall &call)
 {
-       formatted += format("%s(", call.name);
+       append(format("%s(", call.name));
        for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
        {
                if(i!=call.arguments.begin())
-                       formatted += ", ";
+                       append(", ");
                (*i)->visit(*this);
        }
-       formatted += ')';
+       append(')');
 }
 
 void ProgramCompiler::Formatter::visit(ExpressionStatement &expr)
 {
        expr.expression->visit(*this);
-       formatted += ';';
+       append(';');
 }
 
 void ProgramCompiler::Formatter::visit(Block &block)
 {
-       if(else_if)
-               --else_if;
-
        unsigned brace_indent = indent;
        bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
        if(use_braces)
-               formatted += format("%s{\n", string(brace_indent*2, ' '));
+               append(format("%s{\n", string(brace_indent*2, ' ')));
 
        SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
        string spaces(indent*2, ' ');
        for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
        {
                if(i!=block.body.begin())
-                       formatted += '\n';
-               formatted += spaces;
+                       append('\n');
+               append(spaces);
                (*i)->visit(*this);
-               else_if = 0;
        }
 
        if(use_braces)
-               formatted += format("\n%s}", string(brace_indent*2, ' '));
+               append(format("\n%s}", string(brace_indent*2, ' ')));
 }
 
 void ProgramCompiler::Formatter::visit(Import &import)
 {
-       formatted += format("import %s;", import.module);
+       append(format("import %s;", import.module));
 }
 
 void ProgramCompiler::Formatter::visit(Precision &prec)
 {
-       formatted += format("precision %s %s;", prec.precision, prec.type);
+       append(format("precision %s %s;", prec.precision, prec.type));
 }
 
 void ProgramCompiler::Formatter::visit(Layout &layout)
 {
-       formatted += "layout(";
+       append("layout(");
        for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
        {
                if(i!=layout.qualifiers.begin())
-                       formatted += ", ";
-               formatted += i->identifier;
+                       append(", ");
+               append(i->identifier);
                if(!i->value.empty())
-                       formatted += format("=%s", i->value);
+                       append(format("=%s", i->value));
        }
-       formatted += ')';
+       append(')');
 }
 
 void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
 {
        layout.layout.visit(*this);
-       formatted += format(" %s;", layout.interface);
+       append(format(" %s;", layout.interface));
 }
 
 void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
 {
-       formatted += format("struct %s\n", strct.name);
+       append(format("struct %s\n", strct.name));
        strct.members.visit(*this);
-       formatted += ';';
+       append(';');
 }
 
 void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
@@ -465,14 +470,14 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
        if(var.layout)
        {
                var.layout->visit(*this);
-               formatted += ' ';
+               append(' ');
        }
        if(var.constant)
-               formatted += "const ";
+               append("const ");
        if(!var.interpolation.empty())
-               formatted += format("%s ", var.interpolation);
+               append(format("%s ", var.interpolation));
        if(!var.sampling.empty())
-               formatted += format("%s ", var.sampling);
+               append(format("%s ", var.sampling));
        if(!var.interface.empty() && var.interface!=block_interface)
        {
                string interface = var.interface;
@@ -483,72 +488,75 @@ void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
                        else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
                                interface = "varying";
                }
-               formatted += format("%s ", interface);
+               append(format("%s ", interface));
        }
        if(!var.precision.empty())
-               formatted += format("%s ", var.precision);
-       formatted += format("%s %s", var.type, var.name);
+               append(format("%s ", var.precision));
+       append(format("%s %s", var.type, var.name));
        if(var.array)
        {
-               formatted += '[';
+               append('[');
                if(var.array_size)
                        var.array_size->visit(*this);
-               formatted += ']';
+               append(']');
        }
        if(var.init_expression)
        {
-               formatted += " = ";
+               append(" = ");
                var.init_expression->visit(*this);
        }
        if(!parameter_list)
-               formatted += ';';
+               append(';');
 }
 
 void ProgramCompiler::Formatter::visit(InterfaceBlock &iface)
 {
        SetForScope<string> set(block_interface, iface.interface);
-       formatted += format("%s %s\n", iface.interface, iface.name);
+       append(format("%s %s\n", iface.interface, iface.name));
        iface.members.visit(*this);
-       formatted += ';';
+       append(';');
 }
 
 void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
 {
-       formatted += format("%s %s(", func.return_type, func.name);
+       append(format("%s %s(", func.return_type, func.name));
        for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
        {
                if(i!=func.parameters.begin())
-                       formatted += ", ";
+                       append(", ");
                SetFlag set(parameter_list);
                (*i)->visit(*this);
        }
-       formatted += ')';
+       append(')');
        if(func.definition==&func)
        {
-               formatted += '\n';
+               append('\n');
                func.body.visit(*this);
        }
        else
-               formatted += ';';
+               append(';');
 }
 
 void ProgramCompiler::Formatter::visit(Conditional &cond)
 {
-       if(else_if)
-               formatted.replace(formatted.rfind('\n'), string::npos, 1, ' ');
-
-       indent -= else_if;
-
-       formatted += "if(";
+       append("if(");
        cond.condition->visit(*this);
-       formatted += ")\n";
+       append(")\n");
 
        cond.body.visit(*this);
        if(!cond.else_body.body.empty())
        {
-               formatted += format("\n%selse\n", string(indent*2, ' '));
-               SetForScope<unsigned> set(else_if, 2);
-               cond.else_body.visit(*this);
+               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, ' ')));
+                       else_cond->visit(*this);
+               }
+               else
+               {
+                       append(format("\n%selse\n", string(indent*2, ' ')));
+                       cond.else_body.visit(*this);
+               }
        }
 }
 
@@ -556,55 +564,55 @@ void ProgramCompiler::Formatter::visit(Iteration &iter)
 {
        if(!iter.init_statement && iter.condition && !iter.loop_expression)
        {
-               formatted += "while(";
+               append("while(");
                iter.condition->visit(*this);
-               formatted += ')';
+               append(')');
        }
        else
        {
-               formatted += "for(";
+               append("for(");
                if(iter.init_statement)
                        iter.init_statement->visit(*this);
                else
-                       formatted += ';';
+                       append(';');
                if(iter.condition)
                {
-                       formatted += ' ';
+                       append(' ');
                        iter.condition->visit(*this);
                }
-               formatted += ';';
+               append(';');
                if(iter.loop_expression)
                {
-                       formatted += ' ';
+                       append(' ');
                        iter.loop_expression->visit(*this);
                }
-               formatted += ')';
+               append(')');
        }
 
        if(iter.body.body.empty())
-               formatted += " { }";
+               append(" { }");
        else
        {
-               formatted += '\n';
+               append('\n');
                iter.body.visit(*this);
        }
 }
 
 void ProgramCompiler::Formatter::visit(Return &ret)
 {
-       formatted += "return";
+       append("return");
        if(ret.expression)
        {
-               formatted += ' ';
+               append(' ');
                ret.expression->visit(*this);
        }
-       formatted += ';';
+       append(';');
 }
 
 void ProgramCompiler::Formatter::visit(Jump &jump)
 {
-       formatted += jump.keyword;
-       formatted += ';';
+       append(jump.keyword);
+       append(';');
 }
 
 
index 8c4f54537c7bc0da9f70ce9a744acf154157bb5d..9c20e090980fd3d403c4574345692314a1eeff71 100644 (file)
@@ -46,7 +46,6 @@ private:
                std::string formatted;
                unsigned indent;
                bool parameter_list;
-               unsigned else_if;
                std::string block_interface;
 
                Formatter();
@@ -54,6 +53,8 @@ private:
                virtual void apply(ProgramSyntax::Stage &);
                const std::string &get_result() const { return formatted; }
                using Visitor::visit;
+               void append(const std::string &);
+               void append(char);
                virtual void visit(ProgramSyntax::Block &);
                virtual void visit(ProgramSyntax::Literal &);
                virtual void visit(ProgramSyntax::ParenthesizedExpression &);