Templates
authorDanilo Freitas <dsurviver@gmail.com>
Tue, 11 Aug 2009 15:59:51 +0000 (12:59 -0300)
committerDanilo Freitas <dsurviver@gmail.com>
Tue, 11 Aug 2009 15:59:51 +0000 (12:59 -0300)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
Cython/Compiler/Symtab.py

index ab9b601c1684de87f77ed3e558b4a64dd293c79c..6691c7f60d6bb2bd3464276dda79553935d238f6 100755 (executable)
@@ -1123,6 +1123,7 @@ class ImagNode(AtomicNewTempExprNode):
 class NewExprNode(AtomicExprNode):
     
     def analyse_types(self, env):
+        print self.cppclass
         entry = env.lookup(self.cppclass)
         if entry is None or not entry.is_cpp_class:
             error(self.pos, "new operator can only be applied to a C++ class")
index 5103149502fdadc696b55571d2705bfb2e77088a..f0c43f011f7f0a5db20b13a74a274a039d11446f 100644 (file)
@@ -721,11 +721,13 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
                     else:
                         type = py_object_type
                     self.arg_name = self.name
-                elif self.templates:
-                    if not self.name in self.templates:
-                        error(self.pos, "'%s' is not a type identifier" % self.name) 
                 else:
-                    error(self.pos, "'%s' is not a type identifier" % self.name)
+                    if self.templates:
+                        if not self.name in self.templates:
+                            error(self.pos, "'%s' is not a type identifier" % self.name)
+                        type = PyrexTypes.TemplatedType(self.name)
+                    else:
+                        error(self.pos, "'%s' is not a type identifier" % self.name)
         if self.complex:
             if not type.is_numeric or type.is_complex:
                 error(self.pos, "can only complexify c numeric types")
@@ -736,6 +738,24 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
         else:
             return PyrexTypes.error_type
 
+class TemplatedTypeNode(CBaseTypeNode):
+    #  name
+    #  base_type_node    CSimpleBaseTypeNode
+    #  templates         [CSimpleBaseTypeNode]
+
+    child_attrs = ["base_type_node", "templates"]
+    
+    def analyse(self, env, could_be_name = False):
+        entry = env.lookup(self.base_type_node.name)
+        base_types = entry.type.templates
+        if not base_types:
+            error(self.pos, "%s type is not a template" % entry.type)
+        if len(base_types) != len(self.templates):
+            error(self.pos, "%s templated type receives %d arguments, got %d" % 
+                  (entry.type, len(base_types), len(self.templates)))
+        print entry.type
+        return entry.type
+
 class CBufferAccessTypeNode(CBaseTypeNode):
     #  After parsing:
     #  positional_args  [ExprNode]        List of positional arguments
@@ -935,7 +955,7 @@ class CppClassNode(CStructOrUnionDefNode):
                 base_class_types.append(base_class_entry.type)
         self.entry = env.declare_cpp_class(
             self.name, "cppclass", scope, 0, self.pos,
-            self.cname, base_class_types, visibility = self.visibility)
+            self.cname, base_class_types, visibility = self.visibility, templates = self.templates)
         self.entry.is_cpp_class = 1
         if self.attributes is not None:
             if self.in_pxd and not env.in_cinclude:
index bf16c952149f2224a0ed1381b953f4f900cc96fd..0b1d32798a760216575b7a77d126482f6c64dd20 100644 (file)
@@ -1787,29 +1787,50 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
     # (This means that buffers cannot occur where there can be empty declarators,
     # which is an ok restriction to make.)
     if nonempty and s.sy == '[':
-        return p_buffer_access(s, type_node)
+        return p_buffer_or_template(s, type_node)
     else:
         return type_node
 
-def p_buffer_access(s, base_type_node):
+def p_buffer_or_template(s, base_type_node):
     # s.sy == '['
     pos = s.position()
     s.next()
-    positional_args, keyword_args = (
-        p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
-    )
-    s.expect(']')
+    if s.systring == 'int' or s.systring == 'long':
+        positional_args, keyword_args = (
+            p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
+        )
+        if keyword_args:
+            error(pos, "Keyword arguments not allowed for template types")
+        s.expect(']')
 
-    keyword_dict = ExprNodes.DictNode(pos,
-        key_value_pairs = [
-            ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
-            for key, value in keyword_args
-        ])
+        result = Nodes.TemplatedTypeNode(pos, base_type_node = base_type_node,
+            templates = positional_args)
+    else:
+        positional_args, keyword_args = (
+            p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
+        )
+        if positional_args:
+            if positional_args[0] != 'int' or positional_args != 'long':
+                if keyword_args:
+                    error(pos, "Keyword arguments not allowed for template types")
+                s.expect(']')
 
-    result = Nodes.CBufferAccessTypeNode(pos,
-        positional_args = positional_args,
-        keyword_args = keyword_dict,
-        base_type_node = base_type_node)
+                result = Nodes.TemplatedTypeNode(pos, base_type_node = base_type_node,
+                    templates = positional_args)
+            else:
+                s.expect(']')
+
+                keyword_dict = ExprNodes.DictNode(pos,
+                    key_value_pairs = [
+                        ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
+                        for key, value in keyword_args
+                    ])
+
+                result = Nodes.CBufferAccessTypeNode(pos,
+                    positional_args = positional_args,
+                    keyword_args = keyword_dict,
+                    base_type_node = base_type_node)
+                
     return result
     
 
index 5c1c136f14443596f68fae11075613690b28ec18..103e7524570b311ede56e610190c54861a0c8dcf 100755 (executable)
@@ -1015,13 +1015,15 @@ class CFuncType(CType):
     #  calling_convention  string  Function calling convention
     #  nogil            boolean    Can be called without gil
     #  with_gil         boolean    Acquire gil around function body
+    #  templates        [string] or None
     
     is_cfunction = 1
     original_sig = None
     
     def __init__(self, return_type, args, has_varargs = 0,
             exception_value = None, exception_check = 0, calling_convention = "",
-            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0):
+            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
+            templates = None):
         self.return_type = return_type
         self.args = args
         self.has_varargs = has_varargs
@@ -1032,6 +1034,7 @@ class CFuncType(CType):
         self.nogil = nogil
         self.with_gil = with_gil
         self.is_overridable = is_overridable
+        self.templates = templates
     
     def __repr__(self):
         arg_reprs = map(repr, self.args)
@@ -1370,12 +1373,14 @@ class CppClassType(CType):
     #  scope         CppClassScope
     #  typedef_flag  boolean
     #  packed        boolean
+    #  templates     [string] or None
     
     is_cpp_class = 1
     has_attributes = 1
     base_classes = []
     
-    def __init__(self, name, kind, scope, typedef_flag, cname, base_classes, packed=False):
+    def __init__(self, name, kind, scope, typedef_flag, cname, base_classes, packed=False,
+                 templates = None):
         self.name = name
         self.cname = cname
         self.kind = kind
@@ -1386,13 +1391,24 @@ class CppClassType(CType):
         self.packed = packed
         self.base_classes = base_classes
         self.operators = []
+        self.templates = templates
 
     def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+        templates = ""
+        if self.templates:
+            templates = "<"
+            for i in range(len(self.templates)-1):
+                templates += "class "
+                templates += self.templates[i]
+                templates += ','
+            templates += "class "
+            templates += self.templates[-1]
+            templates += ">"
         if for_display or pyrex:
             name = self.name
         else:
             name = self.cname
-        return "%s %s" % (name, entity_code)
+        return "%s %s%s" % (name, entity_code, templates)
 
     def is_subclass(self, other_type):
         if self.same_as_resolved_type(other_type):
@@ -1405,6 +1421,14 @@ class CppClassType(CType):
     def attributes_known(self):
         return self.scope is not None
 
+class TemplatedType(CType):
+    
+    def __init__(self, name):
+        self.name = name
+    
+    def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+        return ""
+
 class CEnumType(CType):
     #  name           string
     #  cname          string or None
index d3ecd3f6b5ba4946d3ac8c0928eee37af10cbb18..f33ab037bff93a01371e779cf2c95d3c12c923b4 100644 (file)
@@ -473,10 +473,6 @@ class Scope(object):
         else:
             entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
             entry.func_cname = cname
-            #try:
-            #    print entry.name, entry.type, entry.overloaded_alternatives
-            #except:
-            #    pass
         if in_pxd and visibility != 'extern':
             entry.defined_in_pxd = 1
         if api:
@@ -1116,7 +1112,7 @@ class ModuleScope(Scope):
     
     def declare_cpp_class(self, name, kind, scope,
             typedef_flag, pos, cname = None, base_classes = [],
-            visibility = 'extern', packed = False):
+            visibility = 'extern', packed = False, templates = None):
         if visibility != 'extern':
             error(pos, "C++ classes may only be extern")
         if cname is None:
@@ -1124,7 +1120,7 @@ class ModuleScope(Scope):
         entry = self.lookup(name)
         if not entry:
             type = PyrexTypes.CppClassType(
-                name, kind, scope, typedef_flag, cname, base_classes, packed)
+                name, kind, scope, typedef_flag, cname, base_classes, packed, templates = templates)
             entry = self.declare_type(name, type, pos, cname,
                 visibility = visibility, defining = scope is not None)
         else: