X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fsyntax.cpp;h=38a7f003be8b239f360df2a143cf214ed50a43b8;hb=77f6973f58167d94059d3f324c29ab2ca8de4544;hp=9705c989370d87b6672c7fc543a8fc9710c46502;hpb=c1b0303f65ee966a973197cbdbf177c571478674;p=libs%2Fgl.git diff --git a/source/glsl/syntax.cpp b/source/glsl/syntax.cpp index 9705c989..38a7f003 100644 --- a/source/glsl/syntax.cpp +++ b/source/glsl/syntax.cpp @@ -1,4 +1,7 @@ +#include +#include #include "syntax.h" +#include "visitor.h" using namespace std; @@ -6,23 +9,76 @@ namespace Msp { namespace GL { namespace SL { +const Operator Operator::operators[] = +{ + { "[", "]", 2, BINARY, LEFT_TO_RIGHT }, + { "(", ")", 2, POSTFIX, LEFT_TO_RIGHT }, + { ".", { }, 2, POSTFIX, LEFT_TO_RIGHT }, + { "++", { }, 2, POSTFIX, LEFT_TO_RIGHT }, + { "--", { }, 2, POSTFIX, LEFT_TO_RIGHT }, + { "++", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "--", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "+", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "-", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "~", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "!", { }, 3, PREFIX, RIGHT_TO_LEFT }, + { "*", { }, 4, BINARY, ASSOCIATIVE }, + { "/", { }, 4, BINARY, LEFT_TO_RIGHT }, + { "%", { }, 4, BINARY, LEFT_TO_RIGHT }, + { "+", { }, 5, BINARY, ASSOCIATIVE }, + { "-", { }, 5, BINARY, LEFT_TO_RIGHT }, + { "<<", { }, 6, BINARY, LEFT_TO_RIGHT }, + { ">>", { }, 6, BINARY, LEFT_TO_RIGHT }, + { "<", { }, 7, BINARY, LEFT_TO_RIGHT }, + { ">", { }, 7, BINARY, LEFT_TO_RIGHT }, + { "<=", { }, 7, BINARY, LEFT_TO_RIGHT }, + { ">=", { }, 7, BINARY, LEFT_TO_RIGHT }, + { "==", { }, 8, BINARY, LEFT_TO_RIGHT }, + { "!=", { }, 8, BINARY, LEFT_TO_RIGHT }, + { "&", { }, 9, BINARY, ASSOCIATIVE }, + { "^", { }, 10, BINARY, ASSOCIATIVE }, + { "|", { }, 11, BINARY, ASSOCIATIVE }, + { "&&", { }, 12, BINARY, ASSOCIATIVE }, + { "^^", { }, 13, BINARY, ASSOCIATIVE }, + { "||", { }, 14, BINARY, ASSOCIATIVE }, + { "?", ":", 15, TERNARY, RIGHT_TO_LEFT }, + { "=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "+=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "-=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "*=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "/=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "%=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "<<=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { ">>=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "&=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "^=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { "|=", { }, 16, BINARY, RIGHT_TO_LEFT }, + { ",", { }, 17, BINARY, LEFT_TO_RIGHT }, + { { 0 }, { }, 18, NO_OPERATOR, LEFT_TO_RIGHT } +}; + +const Operator &Operator::get_operator(const string &token, Type type) +{ + for(const Operator *i=operators; i->type; ++i) + if(i->type==type && i->token==token) + return *i; + throw key_error(token); +} + + template NodeContainer::NodeContainer(const NodeContainer &c): C(c) { - for(typename C::iterator i=this->begin(); i!=this->end(); ++i) - *i = (*i)->clone(); + for(auto &i: *this) + i = i->clone(); } -Statement::Statement(): - source(0), - line(1) -{ } - - -Block::Block(): - use_braces(false) +Block::Block(const Block &other): + Node(other), + body(other.body), + use_braces(other.use_braces) { } void Block::visit(NodeVisitor &visitor) @@ -37,32 +93,36 @@ void Literal::visit(NodeVisitor &visitor) } -void ParenthesizedExpression::visit(NodeVisitor &visitor) +VariableReference::VariableReference(const VariableReference &other): + Expression(other), + name(other.name) +{ } + +void VariableReference::visit(NodeVisitor &visitor) { visitor.visit(*this); } -VariableReference::VariableReference(): - declaration(0) +MemberAccess::MemberAccess(const MemberAccess &other): + Expression(other), + left(other.left), + member(other.member) + // Do not copy declaration { } -void VariableReference::visit(NodeVisitor &visitor) +void MemberAccess::visit(NodeVisitor &visitor) { visitor.visit(*this); } -void MemberAccess::visit(NodeVisitor &visitor) +void Swizzle::visit(NodeVisitor &visitor) { visitor.visit(*this); } -UnaryExpression::UnaryExpression(): - prefix(true) -{ } - void UnaryExpression::visit(NodeVisitor &visitor) { visitor.visit(*this); @@ -75,9 +135,10 @@ void BinaryExpression::visit(NodeVisitor &visitor) } -Assignment::Assignment(): - self_referencing(false), - target_declaration(0) +Assignment::Assignment(const Assignment &other): + BinaryExpression(other), + self_referencing(other.self_referencing) + // Do not copy target { } void Assignment::visit(NodeVisitor &visitor) @@ -86,9 +147,29 @@ void Assignment::visit(NodeVisitor &visitor) } -FunctionCall::FunctionCall(): - declaration(0), - constructor(false) +bool Assignment::Target::operator<(const Target &other) const +{ + if(declaration!=other.declaration) + return declarationlinked_declaration==this) + linked_declaration->linked_declaration = 0; } -void InterfaceBlock::visit(NodeVisitor &visitor) +void VariableDeclaration::visit(NodeVisitor &visitor) { visitor.visit(*this); } -FunctionDeclaration::FunctionDeclaration(): - definition(0) -{ } - FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other): + Statement(other), return_type(other.return_type), name(other.name), parameters(other.parameters), - definition(other.definition==&other ? this : other.definition), - body(other.body) + virtua(other.virtua), + overrd(other.overrd), + body(other.body), + signature(other.signature), + definition(other.definition==&other ? this : 0) + // Do not copy return type declaration { } void FunctionDeclaration::visit(NodeVisitor &visitor) @@ -211,123 +326,111 @@ void Jump::visit(NodeVisitor &visitor) } -void NodeVisitor::visit(Assignment &assign) -{ - visit(static_cast(assign)); -} - - -void TraversingVisitor::visit(Block &block) -{ - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - (*i)->visit(*this); -} - -void TraversingVisitor::visit(ParenthesizedExpression &parexpr) -{ - parexpr.expression->visit(*this); -} +Stage::Stage(Stage::Type t): + type(t) +{ } -void TraversingVisitor::visit(MemberAccess &memacc) +const char *Stage::get_stage_name(Type type) { - memacc.left->visit(*this); + static const char *const names[] = { "shared", "vertex", "geometry", "fragment" }; + return names[type]; } -void TraversingVisitor::visit(UnaryExpression &unary) -{ - unary.expression->visit(*this); -} -void TraversingVisitor::visit(BinaryExpression &binary) -{ - binary.left->visit(*this); - binary.right->visit(*this); -} +Module::Module(): + shared(Stage::SHARED) +{ } -void TraversingVisitor::visit(FunctionCall &call) -{ - for(NodeArray::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - (*i)->visit(*this); -} -void TraversingVisitor::visit(ExpressionStatement &expr) +string get_unused_variable_name(const Block &block, const string &base) { - expr.expression->visit(*this); -} + string name = base; -void TraversingVisitor::visit(InterfaceLayout &layout) -{ - layout.layout.visit(*this); -} + unsigned number = 1; + unsigned base_size = name.size(); + while(1) + { + bool unused = true; + for(const Block *b=█ (unused && b); b=b->parent) + unused = !b->variables.count(name); + if(unused) + return name; -void TraversingVisitor::visit(StructDeclaration &strct) -{ - strct.members.visit(*this); + name.erase(base_size); + name += format("_%d", number); + ++number; + } } -void TraversingVisitor::visit(VariableDeclaration &var) +TypeDeclaration *get_ultimate_base_type(TypeDeclaration *type) { - if(var.layout) - var.layout->visit(*this); - if(var.init_expression) - var.init_expression->visit(*this); - if(var.array_size) - var.array_size->visit(*this); + if(!type) + return 0; + while(const BasicTypeDeclaration *basic = dynamic_cast(type)) + { + if(!basic->base_type) + break; + type = basic->base_type; + } + return type; } -void TraversingVisitor::visit(InterfaceBlock &iface) +bool has_layout_qualifier(const Layout *layout, const string &name) { - iface.members.visit(*this); + if(!layout) + return false; + auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name); + return i!=layout->qualifiers.end(); } -void TraversingVisitor::visit(FunctionDeclaration &func) +int get_layout_value(const Layout *layout, const string &name, int def_value) { - for(NodeArray::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - (*i)->visit(*this); - func.body.visit(*this); + if(!layout) + return def_value; + auto i = find_member(layout->qualifiers, name, &Layout::Qualifier::name); + return (i!=layout->qualifiers.end() ? i->value : def_value); } -void TraversingVisitor::visit(Conditional &cond) +void add_layout_qualifier(RefPtr &layout, const Layout::Qualifier &q) { - cond.condition->visit(*this); - cond.body.visit(*this); - cond.else_body.visit(*this); + if(!layout) + layout = new Layout; + layout->qualifiers.push_back(q); } -void TraversingVisitor::visit(Iteration &iter) +void add_to_chain(Assignment::Target &target, Assignment::Target::ChainType type, unsigned index) { - if(iter.init_statement) - iter.init_statement->visit(*this); - if(iter.condition) - iter.condition->visit(*this); - if(iter.loop_expression) - iter.loop_expression->visit(*this); - iter.body.visit(*this); + if(target.chain_len<7) + target.chain[target.chain_len] = type | min(index, 0x3F); + ++target.chain_len; } -void TraversingVisitor::visit(Passthrough &pass) +bool targets_overlap(const Assignment::Target &target1, const Assignment::Target &target2) { - if(pass.subscript) - pass.subscript->visit(*this); -} + bool overlap = (target1.declaration==target2.declaration); + for(unsigned i=0; (overlap && i(target1.chain[i]&0xC0); + Assignment::Target::ChainType type2 = static_cast(target2.chain[i]&0xC0); + unsigned index1 = target1.chain[i]&0x3F; + unsigned index2 = target2.chain[i]&0x3F; + if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE) + { + if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE) + overlap = index1&index2; + else if(type1==Assignment::Target::ARRAY && index1<4) + overlap = index2&(1<visit(*this); + return overlap; } - -Stage::Stage(StageType t): - type(t), - previous(0) -{ } - - -Module::Module(): - shared(SHARED) -{ } - } // namespace SL } // namespace GL } // namespace Msp