Allows Nodes to be moved from one Block to another without copying them.
When targeting GLSL 1.30 LegacyConverter has a sequence where it flattens
an interface block and later checks the type of those variables through
their declaration pointer. This caused memory errors because the
original nodes were destroyed in the flatten operation.
void ProgramCompiler::inject_block(Block &target, const Block &source)
{
- list<NodePtr<Node> >::iterator insert_point = target.body.begin();
- for(list<NodePtr<Node> >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
+ list<RefPtr<Node> >::iterator insert_point = target.body.begin();
+ for(list<RefPtr<Node> >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
target.body.insert(insert_point, (*i)->clone());
}
void ProgramCompiler::Formatter::visit(FunctionCall &call)
{
formatted += format("%s(", call.name);
- for(vector<NodePtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
+ for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
{
if(i!=call.arguments.begin())
formatted += ", ";
SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
string spaces(indent*2, ' ');
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
{
if(i!=block.body.begin())
formatted += '\n';
void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
{
formatted += format("%s %s(", func.return_type, func.name);
- for(vector<NodePtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
{
if(i!=func.parameters.begin())
formatted += ", ";
return;
SetForScope<bool> set(toplevel, false);
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
{
remove_node = false;
(*i)->visit(*this);
void ProgramCompiler::BlockModifier::flatten_block(Block &block)
{
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
- insert_nodes.push_back((*i)->clone());
+ insert_nodes.insert(insert_nodes.end(), block.body.begin(), block.body.end());
remove_node = true;
}
-void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list<NodePtr<Node> >::iterator &i)
+void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list<RefPtr<Node> >::iterator &i)
{
- for(list<Node *>::iterator j=insert_nodes.begin(); j!=insert_nodes.end(); ++j)
- block.body.insert(i, *j);
+ block.body.insert(i, insert_nodes.begin(), insert_nodes.end());
insert_nodes.clear();
if(remove_node)
void ProgramCompiler::BlockModifier::visit(Block &block)
{
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
{
(*i)->visit(*this);
apply_and_increment(block, i);
void ProgramCompiler::InterfaceGenerator::visit(Block &block)
{
SetForScope<unsigned> set(scope_level, scope_level+1);
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
{
(*i)->visit(*this);
if(scope_level==1)
{
- for(map<string, VariableDeclaration *>::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
+ for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
{
- list<NodePtr<Node> >::iterator k = block.body.insert(i, j->second);
+ list<RefPtr<Node> >::iterator k = block.body.insert(i, j->second);
(*k)->visit(*this);
}
iface_declarations.clear();
for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
pass_vars.push_back(i->second);
- for(map<string, VariableDeclaration *>::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
+ for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
if(i->second->interface=="in")
- pass_vars.push_back(i->second);
+ pass_vars.push_back(i->second.get());
if(stage->previous)
{
void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
{
if(var.constant || scope_level>1)
- variable_values[&var] = &*var.init_expression;
+ variable_values[&var] = var.init_expression.get();
}
void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
{
assignments.push_back(BlockAssignmentMap());
- for(vector<NodePtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
(*i)->visit(*this);
func.body.visit(*this);
void ProgramCompiler::NodeRemover::visit(Block &block)
{
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
{
(*i)->visit(*this);
- if(to_remove.count(&**i))
+ if(to_remove.count(i->get()))
block.body.erase(i++);
else
++i;
if(var.linked_declaration)
var.linked_declaration->linked_declaration = 0;
}
- else if(var.init_expression && to_remove.count(&*var.init_expression))
+ else if(var.init_expression && to_remove.count(var.init_expression.get()))
var.init_expression = 0;
}
{
if(call.name=="texture" && !call.declaration && !check_version(Version(1, 30)))
{
- vector<NodePtr<Expression> >::iterator i = call.arguments.begin();
+ vector<RefPtr<Expression> >::iterator i = call.arguments.begin();
if(i!=call.arguments.end())
{
(*i)->visit(*this);
struct BlockModifier: Visitor
{
bool remove_node;
- std::list<ProgramSyntax::Node *> insert_nodes;
+ std::list<RefPtr<ProgramSyntax::Node> > insert_nodes;
BlockModifier();
void flatten_block(ProgramSyntax::Block &);
- void apply_and_increment(ProgramSyntax::Block &, std::list<ProgramSyntax::NodePtr<ProgramSyntax::Node> >::iterator &);
+ void apply_and_increment(ProgramSyntax::Block &, std::list<RefPtr<ProgramSyntax::Node> >::iterator &);
virtual void visit(ProgramSyntax::Block &);
};
std::string in_prefix;
std::string out_prefix;
unsigned scope_level;
- std::map<std::string, ProgramSyntax::VariableDeclaration *> iface_declarations;
+ std::map<std::string, RefPtr<ProgramSyntax::VariableDeclaration> > iface_declarations;
InterfaceGenerator();
iter = source.begin();
while(1)
{
- while(Node *statement = parse_global_declaration())
+ while(RefPtr<Node> statement = parse_global_declaration())
cur_stage->content.body.push_back(statement);
parse_token();
return re.match(token);
}
-Node *ProgramParser::parse_global_declaration()
+RefPtr<Node> ProgramParser::parse_global_declaration()
{
string token = peek_token();
if(token=="import")
iface_lo->layout.qualifiers = layout->qualifiers;
iface_lo->interface = parse_token();
expect(";");
- return iface_lo.release();
+ return iface_lo;
}
else
{
- VariableDeclaration *var = parse_variable_declaration();
- var->layout = layout.release();
+ RefPtr<VariableDeclaration> var = parse_variable_declaration();
+ var->layout = layout;
return var;
}
}
throw runtime_error(format("Syntax error at '%s': expected a global declaration", token));
}
-Node *ProgramParser::parse_statement()
+RefPtr<Node> ProgramParser::parse_statement()
{
string token = peek_token();
if(token=="if")
expr->expression = parse_expression();
expect(";");
- return expr.release();
+ return expr;
}
else
throw runtime_error(format("Syntax error at '%s': expected a statement", token));
}
-Import *ProgramParser::parse_import()
+RefPtr<Import> ProgramParser::parse_import()
{
if(cur_stage->type!=SHARED)
throw runtime_error("Imports are only allowed in the shared section");
RefPtr<Import> import = new Import;
import->module = parse_token();
expect(";");
- return import.release();
+ return import;
}
-Layout *ProgramParser::parse_layout()
+RefPtr<Layout> ProgramParser::parse_layout()
{
expect("layout");
expect("(");
}
expect(")");
- return layout.release();
+ return layout;
}
void ProgramParser::parse_block(Block &block, bool require_braces)
expect("}");
}
-Expression *ProgramParser::parse_expression(unsigned precedence)
+RefPtr<Expression> ProgramParser::parse_expression(unsigned precedence)
{
RefPtr<Expression> left;
VariableReference *left_var = 0;
if(token==";" || token==")" || token=="]" || token=="," || (oper && precedence && oper->precedence>=precedence))
{
if(left)
- return left.release();
+ return left;
else
throw runtime_error(format("Parse error at '%s': expected an expression", token));
}
{
if(!left_var)
throw runtime_error(format("Parse error at '%s': function name must be an identifier", token));
- left = parse_function_call(left_var);
+ left = parse_function_call(*left_var);
}
else if(token==".")
{
RefPtr<MemberAccess> memacc = new MemberAccess;
- memacc->left = left.release();
+ memacc->left = left;
parse_token();
memacc->member = expect_identifier();
left = memacc;
RefPtr<UnaryExpression> unary = new UnaryExpression;
unary->oper = parse_token();
unary->prefix = false;
- unary->expression = left.release();
+ unary->expression = left;
left = unary;
}
else if(oper && oper->type==BINARY)
- left = parse_binary(left.release(), oper);
+ left = parse_binary(left, oper);
else
throw runtime_error(format("Parse error at '%s': expected an operator", token));
left_var = 0;
}
}
-BinaryExpression *ProgramParser::parse_binary(Expression *left, const Operator *oper)
+RefPtr<BinaryExpression> ProgramParser::parse_binary(const RefPtr<Expression> &left, const Operator *oper)
{
RefPtr<BinaryExpression> binary = (oper->precedence==16 ? new Assignment : new BinaryExpression);
binary->left = left;
}
else
binary->right = parse_expression(oper->precedence+(oper->assoc==RIGHT_TO_LEFT));
- return binary.release();
+ return binary;
}
-FunctionCall *ProgramParser::parse_function_call(VariableReference *var)
+RefPtr<FunctionCall> ProgramParser::parse_function_call(const VariableReference &var)
{
RefPtr<FunctionCall> call = new FunctionCall;
- call->name = var->name;
+ call->name = var.name;
call->constructor = is_type(call->name);
expect("(");
while(peek_token()!=")")
call->arguments.push_back(parse_expression());
}
expect(")");
- return call.release();
+ return call;
}
-StructDeclaration *ProgramParser::parse_struct_declaration()
+RefPtr<StructDeclaration> ProgramParser::parse_struct_declaration()
{
expect("struct");
RefPtr<StructDeclaration> strct = new StructDeclaration;
expect(";");
declared_types.insert(strct->name);
- return strct.release();
+ return strct;
}
-VariableDeclaration *ProgramParser::parse_variable_declaration()
+RefPtr<VariableDeclaration> ProgramParser::parse_variable_declaration()
{
RefPtr<VariableDeclaration> var = new VariableDeclaration;
var->init_expression = parse_expression();
expect(";");
- return var.release();
+ return var;
}
-FunctionDeclaration *ProgramParser::parse_function_declaration()
+RefPtr<FunctionDeclaration> ProgramParser::parse_function_declaration()
{
RefPtr<FunctionDeclaration> func = new FunctionDeclaration;
RefPtr<VariableDeclaration> var = new VariableDeclaration;
var->type = expect_type();
var->name = expect_identifier();
- func->parameters.push_back(var.release());
+ func->parameters.push_back(var);
}
expect(")");
else
throw runtime_error(format("Parse error at '%s': expected '{' or ';'", token));
- return func.release();
+ return func;
}
-InterfaceBlock *ProgramParser::parse_interface_block()
+RefPtr<InterfaceBlock> ProgramParser::parse_interface_block()
{
RefPtr<InterfaceBlock> iface = new InterfaceBlock;
expect(";");
}
- return iface.release();
+ return iface;
}
-Conditional *ProgramParser::parse_conditional()
+RefPtr<Conditional> ProgramParser::parse_conditional()
{
expect("if");
expect("(");
parse_block(cond->else_body, false);
}
- return cond.release();
+ return cond;
}
-Iteration *ProgramParser::parse_iteration()
+RefPtr<Iteration> ProgramParser::parse_iteration()
{
expect("for");
expect("(");
RefPtr<ExpressionStatement> expr = new ExpressionStatement;
expr->expression = parse_expression();
expect(";");
- loop->init_statement = expr.release();
+ loop->init_statement = expr;
}
loop->condition = parse_expression();
expect(";");
parse_block(loop->body, false);
- return loop.release();
+ return loop;
}
-Passthrough *ProgramParser::parse_passthrough()
+RefPtr<Passthrough> ProgramParser::parse_passthrough()
{
expect("passthrough");
RefPtr<Passthrough> pass = new Passthrough;
expect("]");
}
expect(";");
- return pass.release();
+ return pass;
}
-Return *ProgramParser::parse_return()
+RefPtr<Return> ProgramParser::parse_return()
{
expect("return");
RefPtr<Return> ret = new Return;
if(peek_token()!=";")
ret->expression = parse_expression();
expect(";");
- return ret.release();
+ return ret;
}
} // namespace GL
bool is_type(const std::string &);
bool is_identifier(const std::string &);
- ProgramSyntax::Node *parse_global_declaration();
- ProgramSyntax::Node *parse_statement();
- ProgramSyntax::Import *parse_import();
- ProgramSyntax::Layout *parse_layout();
+ RefPtr<ProgramSyntax::Node> parse_global_declaration();
+ RefPtr<ProgramSyntax::Node> parse_statement();
+ RefPtr<ProgramSyntax::Import> parse_import();
+ RefPtr<ProgramSyntax::Layout> parse_layout();
void parse_block(ProgramSyntax::Block &, bool);
- ProgramSyntax::Expression *parse_expression(unsigned = 0);
- ProgramSyntax::BinaryExpression *parse_binary(ProgramSyntax::Expression *, const Operator *);
- ProgramSyntax::FunctionCall *parse_function_call(ProgramSyntax::VariableReference *);
- ProgramSyntax::StructDeclaration *parse_struct_declaration();
- ProgramSyntax::VariableDeclaration *parse_variable_declaration();
- ProgramSyntax::FunctionDeclaration *parse_function_declaration();
- ProgramSyntax::InterfaceBlock *parse_interface_block();
- ProgramSyntax::Conditional *parse_conditional();
- ProgramSyntax::Iteration *parse_iteration();
- ProgramSyntax::Passthrough *parse_passthrough();
- ProgramSyntax::Return *parse_return();
+ RefPtr<ProgramSyntax::Expression> parse_expression(unsigned = 0);
+ RefPtr<ProgramSyntax::BinaryExpression> parse_binary(const RefPtr<ProgramSyntax::Expression> &, const Operator *);
+ RefPtr<ProgramSyntax::FunctionCall> parse_function_call(const ProgramSyntax::VariableReference &);
+ RefPtr<ProgramSyntax::StructDeclaration> parse_struct_declaration();
+ RefPtr<ProgramSyntax::VariableDeclaration> parse_variable_declaration();
+ RefPtr<ProgramSyntax::FunctionDeclaration> parse_function_declaration();
+ RefPtr<ProgramSyntax::InterfaceBlock> parse_interface_block();
+ RefPtr<ProgramSyntax::Conditional> parse_conditional();
+ RefPtr<ProgramSyntax::Iteration> parse_iteration();
+ RefPtr<ProgramSyntax::Passthrough> parse_passthrough();
+ RefPtr<ProgramSyntax::Return> parse_return();
};
} // namespace GL
void TraversingVisitor::visit(Block &block)
{
- for(list<NodePtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+ for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
(*i)->visit(*this);
}
void TraversingVisitor::visit(FunctionCall &call)
{
- for(vector<NodePtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
+ for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
(*i)->visit(*this);
}
void TraversingVisitor::visit(FunctionDeclaration &func)
{
- for(vector<NodePtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
+ for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
(*i)->visit(*this);
func.body.visit(*this);
}
#include <map>
#include <string>
#include <vector>
+#include <msp/core/refptr.h>
#include "extension.h"
namespace Msp {
virtual void visit(NodeVisitor &) = 0;
};
-template<typename T>
-class NodePtr
-{
-private:
- T *node;
-
-public:
- NodePtr(T *n = 0): node(n) { }
- NodePtr(const NodePtr &p): node(clone(p.node)) { }
- NodePtr &operator=(const NodePtr &p) { delete node; node = clone(p.node); return *this; }
-#if __cplusplus>=201103L
- NodePtr(NodePtr &&p): node(p.node) { p.node = 0; }
- NodePtr &operator=(NodePtr &&p) { delete node; node = p.node; p.node = 0; return *this; }
-#endif
- ~NodePtr() { delete node; }
-
-private:
- static T *clone(T *n) { return n ? n->clone() : 0; }
-
-public:
- T *operator->() { return node; }
- const T *operator->() const { return node; }
- T &operator*() { return *node; }
- const T &operator*() const { return *node; }
- operator void *() const { return node; }
-};
-
struct StructDeclaration;
struct VariableDeclaration;
struct FunctionDeclaration;
struct Block: Node
{
- std::list<NodePtr<Node> > body;
+ std::list<RefPtr<Node> > body;
bool use_braces;
std::map<std::string, StructDeclaration *> types;
std::map<std::string, VariableDeclaration *> variables;
struct ParenthesizedExpression: Expression
{
- NodePtr<Expression> expression;
+ RefPtr<Expression> expression;
virtual ParenthesizedExpression *clone() const { return new ParenthesizedExpression(*this); }
virtual void visit(NodeVisitor &);
struct MemberAccess: Expression
{
- NodePtr<Expression> left;
+ RefPtr<Expression> left;
std::string member;
VariableDeclaration *declaration;
struct UnaryExpression: Expression
{
std::string oper;
- NodePtr<Expression> expression;
+ RefPtr<Expression> expression;
bool prefix;
UnaryExpression();
struct BinaryExpression: Expression
{
- NodePtr<Expression> left;
+ RefPtr<Expression> left;
std::string oper;
- NodePtr<Expression> right;
+ RefPtr<Expression> right;
std::string after;
virtual BinaryExpression *clone() const { return new BinaryExpression(*this); }
std::string name;
FunctionDeclaration *declaration;
bool constructor;
- std::vector<NodePtr<Expression> > arguments;
+ std::vector<RefPtr<Expression> > arguments;
FunctionCall();
struct ExpressionStatement: Node
{
- NodePtr<Expression> expression;
+ RefPtr<Expression> expression;
virtual ExpressionStatement *clone() const { return new ExpressionStatement(*this); }
virtual void visit(NodeVisitor &);
StructDeclaration *type_declaration;
std::string name;
bool array;
- NodePtr<Expression> array_size;
- NodePtr<Expression> init_expression;
+ RefPtr<Expression> array_size;
+ RefPtr<Expression> init_expression;
VariableDeclaration *linked_declaration;
- NodePtr<Layout> layout;
+ RefPtr<Layout> layout;
VariableDeclaration();
{
std::string return_type;
std::string name;
- std::vector<NodePtr<VariableDeclaration> > parameters;
+ std::vector<RefPtr<VariableDeclaration> > parameters;
FunctionDeclaration *definition;
Block body;
struct Conditional: Node
{
- NodePtr<Expression> condition;
+ RefPtr<Expression> condition;
Block body;
Block else_body;
struct Iteration: Node
{
- NodePtr<Node> init_statement;
- NodePtr<Expression> condition;
- NodePtr<Expression> loop_expression;
+ RefPtr<Node> init_statement;
+ RefPtr<Expression> condition;
+ RefPtr<Expression> loop_expression;
Block body;
virtual Iteration *clone() const { return new Iteration(*this); }
struct Passthrough: Node
{
- NodePtr<Expression> subscript;
+ RefPtr<Expression> subscript;
virtual Passthrough *clone() const { return new Passthrough(*this); }
virtual void visit(NodeVisitor &);
struct Return: Node
{
- NodePtr<Expression> expression;
+ RefPtr<Expression> expression;
virtual Return *clone() const { return new Return(*this); }
virtual void visit(NodeVisitor &);