]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/generate.cpp
Resolve the return types of functions
[libs/gl.git] / source / glsl / generate.cpp
index 71b35b2c59f3ef8217db37d32b93123da763d047..433d506e1a8ab762f50a0e930e314bf387c58be0 100644 (file)
@@ -114,6 +114,62 @@ void BlockHierarchyResolver::enter(Block &block)
 }
 
 
+TypeResolver::TypeResolver():
+       stage(0)
+{ }
+
+void TypeResolver::apply(Stage &s)
+{
+       stage = &s;
+       s.types.clear();
+       s.content.visit(*this);
+}
+
+void TypeResolver::visit(BasicTypeDeclaration &type)
+{
+       map<string, TypeDeclaration *>::iterator i = stage->types.find(type.base);
+       type.base_type = (i!=stage->types.end() ? i->second : 0);
+
+       if(type.kind==BasicTypeDeclaration::VECTOR && type.base_type)
+               if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
+                       if(basic_base->kind==BasicTypeDeclaration::VECTOR)
+                       {
+                               type.kind = BasicTypeDeclaration::MATRIX;
+                               type.size |= basic_base->size<<16;
+                       }
+
+       stage->types.insert(make_pair(type.name, &type));
+}
+
+void TypeResolver::visit(ImageTypeDeclaration &type)
+{
+       map<string, TypeDeclaration *>::iterator i = stage->types.find(type.base);
+       type.base_type = (i!=stage->types.end() ? i->second : 0);
+
+       stage->types.insert(make_pair(type.name, &type));
+}
+
+void TypeResolver::visit(StructDeclaration &strct)
+{
+       stage->types.insert(make_pair(strct.name, &strct));
+       TraversingVisitor::visit(strct);
+}
+
+void TypeResolver::visit(VariableDeclaration &var)
+{
+       map<string, TypeDeclaration *>::iterator i = stage->types.find(var.type);
+       if(i!=stage->types.end())
+               var.type_declaration = i->second;
+}
+
+void TypeResolver::visit(FunctionDeclaration &func)
+{
+       map<string, TypeDeclaration *>::iterator i = stage->types.find(func.return_type);
+       func.return_type_declaration = (i!=stage->types.end() ? i->second : 0);
+       TraversingVisitor::visit(func);
+}
+
+
 VariableResolver::VariableResolver():
        stage(0),
        r_members(0),
@@ -125,7 +181,6 @@ VariableResolver::VariableResolver():
 void VariableResolver::apply(Stage &s)
 {
        stage = &s;
-       s.types.clear();
        s.interface_blocks.clear();
        s.content.visit(*this);
 }
@@ -149,20 +204,17 @@ void VariableResolver::visit(VariableReference &var)
                        var.declaration = i->second;
        }
 
-       if(var.declaration)
-       {
-               if(var.declaration->type_declaration)
-                       r_members = &var.declaration->type_declaration->members.variables;
-       }
-       else
+       if(!var.declaration)
        {
                const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
-               map<string, InterfaceBlock *>::const_iterator i = blocks.find(var.name);
-               if(i!=blocks.end() && i->second->instance_name==var.name)
+               map<string, InterfaceBlock *>::const_iterator i = blocks.find("_"+var.name);
+               if(i!=blocks.end())
                {
                        /* The name refers to an interface block with an instance name rather
                        than a variable.  Prepare a new syntax tree node accordingly. */
                        r_iface_ref = new InterfaceBlockReference;
+                       r_iface_ref->source = var.source;
+                       r_iface_ref->line = var.line;
                        r_iface_ref->name = var.name;
                        r_iface_ref->declaration = i->second;
                        r_members = &i->second->members.variables;
@@ -180,6 +232,10 @@ void VariableResolver::visit(VariableReference &var)
                }
        }
 
+       if(var.declaration)
+               if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(var.declaration->type_declaration))
+                       r_members = &strct->members.variables;
+
        if(record_target)
        {
                if(r_assignment_target)
@@ -201,7 +257,7 @@ void VariableResolver::visit(InterfaceBlockReference &iface)
        iface.declaration = 0;
        for(Block *block=current_block; block; block=block->parent)
        {
-               map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find(iface.name);
+               map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find("_"+iface.name);
                if(i!=stage->interface_blocks.end())
                {
                        iface.declaration = i->second;
@@ -228,8 +284,8 @@ void VariableResolver::visit(MemberAccess &memacc)
                if(i!=r_members->end())
                {
                        memacc.declaration = i->second;
-                       if(i->second->type_declaration)
-                               r_members = &i->second->type_declaration->members.variables;
+                       if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(i->second->type_declaration))
+                               r_members = &strct->members.variables;
                }
                else
                        r_members = 0;
@@ -292,32 +348,22 @@ void VariableResolver::visit(FunctionCall &call)
        r_iface_ref = 0;
 }
 
-void VariableResolver::visit(StructDeclaration &strct)
-{
-       TraversingVisitor::visit(strct);
-       stage->types[strct.name] = &strct;
-}
-
 void VariableResolver::visit(VariableDeclaration &var)
 {
-       map<string, StructDeclaration *>::iterator i = stage->types.find(var.type);
-       if(i!=stage->types.end())
-               var.type_declaration = i->second;
-
        if(!block_interface.empty() && var.interface.empty())
                var.interface = block_interface;
 
        TraversingVisitor::visit(var);
-       current_block->variables[var.name] = &var;
+       current_block->variables.insert(make_pair(var.name, &var));
 }
 
 void VariableResolver::visit(InterfaceBlock &iface)
 {
-       /* Block names can't be used for any other identifiers so we can put them
-       in the same map with instance names. */
-       stage->interface_blocks[iface.name] = &iface;
+       /* Block names can be reused in different interfaces.  Prefix the name with
+       the first character of the interface to avoid conflicts. */
+       stage->interface_blocks.insert(make_pair(iface.interface+iface.name, &iface));
        if(!iface.instance_name.empty())
-               stage->interface_blocks[iface.instance_name] = &iface;
+               stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface));
 
        SetForScope<string> set_iface(block_interface, iface.interface);
        TraversingVisitor::visit(iface);
@@ -443,14 +489,14 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
        }
 
        iface_target_block->body.insert(iface_insert_point, iface_var);
-       iface_target_block->variables[name] = iface_var;
+       iface_target_block->variables.insert(make_pair(name, iface_var));
 
        return iface_var;
 }
 
 InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
 {
-       if(stage->interface_blocks.count(out_block.name))
+       if(stage->interface_blocks.count("in"+out_block.name))
                return 0;
 
        InterfaceBlock *in_block = new InterfaceBlock;
@@ -472,9 +518,9 @@ InterfaceBlock *InterfaceGenerator::generate_interface(InterfaceBlock &out_block
        }
 
        iface_target_block->body.insert(iface_insert_point, in_block);
-       stage->interface_blocks[in_block->name] = in_block;
+       stage->interface_blocks.insert(make_pair("in"+in_block->name, in_block));
        if(!in_block->instance_name.empty())
-               stage->interface_blocks[in_block->instance_name] = in_block;
+               stage->interface_blocks.insert(make_pair("_"+in_block->instance_name, in_block));
 
        SetFlag set_scope(function_scope, false);
        SetForScope<Block *> set_block(current_block, &stage->content);
@@ -521,10 +567,12 @@ void InterfaceGenerator::visit(VariableReference &var)
        }
 
        const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
-       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)
+       map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find("_"+var.name);
+       if(j!=prev_blocks.end() && j->second->interface=="out")
        {
                generate_interface(*j->second);
+               /* Let VariableResolver convert the variable reference into an interface
+               block reference. */
                return;
        }
 
@@ -556,7 +604,10 @@ void InterfaceGenerator::visit(VariableDeclaration &var)
                        const map<string, VariableDeclaration *> &linked_vars = iface_block->linked_block->members.variables;
                        map<string, VariableDeclaration *>::const_iterator i = linked_vars.find(var.name);
                        if(i!=linked_vars.end())
+                       {
                                var.linked_declaration = i->second;
+                               var.linked_declaration->linked_declaration = &var;
+                       }
                }
                return;
        }
@@ -608,8 +659,8 @@ void InterfaceGenerator::visit(InterfaceBlock &iface)
                if(!iface.linked_block && stage->previous)
                {
                        const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
-                       map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find(iface.name);
-                       if(i!=prev_blocks.end() && i->second->interface=="out" && i->second->name==iface.name)
+                       map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find("out"+iface.name);
+                       if(i!=prev_blocks.end())
                        {
                                iface.linked_block = i->second;
                                i->second->linked_block = &iface;