InterfaceGenerator::InterfaceGenerator():
stage(0),
function_scope(false),
- iface_block(0)
+ iface_block(0),
+ copy_block(false),
+ iface_target_block(0)
{ }
string InterfaceGenerator::get_out_prefix(Stage::Type type)
void InterfaceGenerator::apply(Stage &s)
{
stage = &s;
+ iface_target_block = &stage->content;
if(stage->previous)
in_prefix = get_out_prefix(stage->previous->type);
out_prefix = get_out_prefix(stage->type);
iface_var->type = var.type;
iface_var->type_declaration = var.type_declaration;
iface_var->name = name;
- if(stage->type==Stage::GEOMETRY)
+ if(stage->type==Stage::GEOMETRY && !copy_block)
iface_var->array = ((var.array && var.interface!="in") || iface=="in");
else
iface_var->array = var.array;
iface_var->linked_declaration = &var;
var.linked_declaration = iface_var;
}
- stage->content.body.insert(iface_insert_point, iface_var);
- stage->content.variables[name] = iface_var;
+
+ iface_target_block->body.insert(iface_insert_point, iface_var);
+ iface_target_block->variables[name] = iface_var;
+
+ return true;
+}
+
+bool InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
+{
+ if(stage->content.interfaces.count(out_block.name))
+ return false;
+
+ InterfaceBlock *in_block = new InterfaceBlock;
+ in_block->interface = "in";
+ in_block->name = out_block.name;
+ in_block->instance_name = out_block.instance_name;
+ if(stage->type==Stage::GEOMETRY)
+ in_block->array = true;
+ else
+ in_block->array = out_block.array;
+ in_block->linked_block = &out_block;
+ out_block.linked_block = in_block;
+
+ {
+ SetFlag set_copy(copy_block, true);
+ SetForScope<Block *> set_target(iface_target_block, &in_block->members);
+ SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end());
+ out_block.members.visit(*this);
+ }
+
+ iface_target_block->body.insert(iface_insert_point, in_block);
+ iface_target_block->interfaces[in_block->name] = in_block;
+ if(!in_block->instance_name.empty())
+ stage->content.interfaces[in_block->instance_name] = in_block;
+
+ SetFlag set_scope(function_scope, false);
+ SetForScope<Block *> set_block(current_block, &stage->content);
+ in_block->visit(*this);
return true;
}
{
generate_interface(*i->second, "in", i->second->name);
var.name = i->second->name;
+ return;
+ }
+
+ const map<string, InterfaceBlock *> &prev_blocks = stage->previous->content.interfaces;
+ map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find(var.name);
+ if(j!=prev_blocks.end() && j->second->interface=="out" && j->second->instance_name==var.name)
+ {
+ generate_interface(*j->second);
+ return;
}
+
+ for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j)
+ if(j->second->instance_name.empty())
+ {
+ i = j->second->members.variables.find(var.name);
+ if(i!=j->second->members.variables.end())
+ {
+ generate_interface(*j->second);
+ return;
+ }
+ }
}
void InterfaceGenerator::visit(VariableDeclaration &var)
{
+ if(copy_block)
+ {
+ generate_interface(var, "in", var.name);
+ return;
+ }
+
if(iface_block)
{
if(iface_block->linked_block)
std::string out_prefix;
bool function_scope;
InterfaceBlock *iface_block;
+ bool copy_block;
+ Block *iface_target_block;
NodeList<Statement>::iterator iface_insert_point;
NodeList<Statement>::iterator assignment_insert_point;
std::set<Node *> nodes_to_remove;
std::string change_prefix(const std::string &, const std::string &) const;
virtual void visit(Block &);
bool generate_interface(VariableDeclaration &, const std::string &, const std::string &);
+ bool generate_interface(InterfaceBlock &);
ExpressionStatement &insert_assignment(const std::string &, Expression *);
virtual void visit(VariableReference &);
virtual void visit(VariableDeclaration &);