Templates
authorDanilo Freitas <dsurviver@gmail.com>
Mon, 27 Jul 2009 17:24:07 +0000 (14:24 -0300)
committerDanilo Freitas <dsurviver@gmail.com>
Mon, 27 Jul 2009 17:24:07 +0000 (14:24 -0300)
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/stl.pxd [new file with mode: 0644]

index 22baffd2295dc7f75daccaf266e2889ccd9b75d8..5103149502fdadc696b55571d2705bfb2e77088a 100644 (file)
@@ -721,6 +721,9 @@ 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.complex:
@@ -913,6 +916,7 @@ class CppClassNode(CStructOrUnionDefNode):
     #  attributes    [CVarDefNode] or None
     #  entry         Entry
     #  base_classes  [string]
+    #  templates     [string] or None
 
     def analyse_declarations(self, env):
         scope = None
index e5ad6d087c2269b92f0aab0470ca7fd7a2fbda63..bf16c952149f2224a0ed1381b953f4f900cc96fd 100644 (file)
@@ -32,6 +32,7 @@ class Ctx(object):
     overridable = 0
     nogil = 0
     namespace = None
+    templates = None
 
     def __init__(self, **kwds):
         self.__dict__.update(kwds)
@@ -1379,6 +1380,29 @@ def p_with_statement(s):
         s.next()
         body = p_suite(s)
         return Nodes.GILStatNode(pos, state = state, body = body)
+    elif s.systring == 'template':
+        templates = []
+        s.next()
+        s.expect('[')
+        #s.next()
+        templates.append(s.systring)
+        s.next()
+        while s.systring == ',':
+            s.next()
+            templates.append(s.systring)
+            s.next()
+        s.expect(']')
+        if s.sy == ':':
+            s.next()
+            s.expect_newline("Syntax error in template function declaration")
+            s.expect_indent()
+            body_ctx = Ctx()
+            body_ctx.templates = templates
+            func_or_var = p_c_func_or_var_declaration(s, pos, body_ctx)
+            s.expect_dedent()
+            return func_or_var
+        else:
+            error(pos, "Syntax error in template function declaration")
     else:
         manager = p_expr(s)
         target = None
@@ -1669,13 +1693,13 @@ def p_positional_and_keyword_args(s, end_sy_set, type_positions=(), type_keyword
         s.next()
     return positional_args, keyword_args
 
-def p_c_base_type(s, self_flag = 0, nonempty = 0):
+def p_c_base_type(s, self_flag = 0, nonempty = 0, templates = None):
     # If self_flag is true, this is the base type for the
     # self argument of a C method of an extension type.
     if s.sy == '(':
         return p_c_complex_base_type(s)
     else:
-        return p_c_simple_base_type(s, self_flag, nonempty = nonempty)
+        return p_c_simple_base_type(s, self_flag, nonempty = nonempty, templates = templates)
 
 def p_calling_convention(s):
     if s.sy == 'IDENT' and s.systring in calling_convention_words:
@@ -1697,7 +1721,7 @@ def p_c_complex_base_type(s):
     return Nodes.CComplexBaseTypeNode(pos, 
         base_type = base_type, declarator = declarator)
 
-def p_c_simple_base_type(s, self_flag, nonempty):
+def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
     #print "p_c_simple_base_type: self_flag =", self_flag, nonempty
     is_basic = 0
     signed = 1
@@ -1753,7 +1777,7 @@ def p_c_simple_base_type(s, self_flag, nonempty):
         name = name, module_path = module_path,
         is_basic_c_type = is_basic, signed = signed,
         complex = complex, longness = longness, 
-        is_self_arg = self_flag)
+        is_self_arg = self_flag, templates = templates)
 
 
     # Treat trailing [] on type as buffer access if it appears in a context
@@ -2253,12 +2277,12 @@ def p_c_modifiers(s):
 def p_c_func_or_var_declaration(s, pos, ctx):
     cmethod_flag = ctx.level in ('c_class', 'c_class_pxd')
     modifiers = p_c_modifiers(s)
-    base_type = p_c_base_type(s, nonempty = 1)
+    base_type = p_c_base_type(s, nonempty = 1, templates = ctx.templates)
     declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag,
                                 assignable = 1, nonempty = 1)
     declarator.overridable = ctx.overridable
     if s.sy == ':':
-        if ctx.level not in ('module', 'c_class', 'module_pxd', 'c_class_pxd'):
+        if ctx.level not in ('module', 'c_class', 'module_pxd', 'c_class_pxd') and not ctx.templates:
             s.error("C function definition not allowed here")
         doc, suite = p_suite(s, Ctx(level = 'function'), with_doc = 1)
         result = Nodes.CFuncDefNode(pos,
@@ -2559,6 +2583,17 @@ def p_cpp_class_definition(s, pos,  ctx):
         cname = ctx.namespace + "::" + class_name
     if s.sy == '.':
         error(pos, "Qualified class name not allowed C++ class")
+    templates = None
+    if s.sy == '[':
+        s.next()
+        templates = []
+        templates.append(s.systring)
+        s.next()
+        while s.sy == ',':
+            s.next()
+            templates.append(s.systring)
+            s.next()
+        s.expect(']')
     base_classes = []
     objstruct_name = None
     typeobj_name = None
@@ -2585,6 +2620,7 @@ def p_cpp_class_definition(s, pos,  ctx):
         s.expect_indent()
         attributes = []
         body_ctx = Ctx()
+        body_ctx.templates = templates
         while s.sy != 'DEDENT':
             if s.sy != 'pass':
                 attributes.append(
@@ -2601,7 +2637,8 @@ def p_cpp_class_definition(s, pos,  ctx):
         base_classes = base_classes,
         visibility = ctx.visibility,
         in_pxd = ctx.level == 'module_pxd',
-        attributes = attributes)
+        attributes = attributes,
+        templates = templates)
 
 
 
diff --git a/Cython/Compiler/stl.pxd b/Cython/Compiler/stl.pxd
new file mode 100644 (file)
index 0000000..76f6422
--- /dev/null
@@ -0,0 +1,91 @@
+cdef extern from "<vector>" namespace std:\r
+\r
+       cdef cppclass vector[TYPE]:\r
+               #constructors\r
+               __init__()\r
+               __init__(vector&)\r
+               __init__(int)\r
+               __init__(int, TYPE&)\r
+               __init__(iterator, iterator)\r
+               #operators\r
+               TYPE& __getitem__(int)\r
+               TYPE& __setitem__(int, TYPE&)\r
+               vector __new__(vector&)\r
+               bool __eq__(vector&, vector&)\r
+               bool __ne__(vector&, vector&)\r
+               bool __lt__(vector&, vector&)\r
+               bool __gt__(vector&, vector&)\r
+               bool __le__(vector&, vector&)\r
+               bool _­_ge__(vector&, vector&)\r
+               #others\r
+               void assign(int, TYPE)\r
+               #void assign(iterator, iterator)\r
+               TYPE& at(int)\r
+               TYPE& back()\r
+               iterator begin()\r
+               int capacity()\r
+               void clear()\r
+               bool empty()\r
+               iterator end()\r
+               iterator erase(iterator)\r
+               iterator erase(iterator, iterator)\r
+               TYPE& front()\r
+               iterator insert(iterator, TYPE&)\r
+               void insert(iterator, int, TYPE&)\r
+               void insert(iterator, iterator)\r
+               int max_size()\r
+               void pop_back()\r
+               void push_back(TYPE&)\r
+               iterator rbegin()\r
+               iterator rend()\r
+               void reserve(int)\r
+               void resize(int)\r
+               void resize(int, TYPE&) #void resize(size_type num, const TYPE& = TYPE())\r
+               int size()\r
+               void swap(container&)\r
+\r
+cdef extern from "<deque>" namespace std:\r
+\r
+       cdef cppclass deque[TYPE]:\r
+               #constructors\r
+               __init__()\r
+               __init__(deque&)\r
+               __init__(int)\r
+               __init__(int, TYPE&)\r
+               __init__(iterator, iterator)\r
+               #operators\r
+               TYPE& operator[]( size_type index );\r
+               const TYPE& operator[]( size_type index ) const;\r
+               deque __new__(deque&);\r
+               bool __eq__(deque&, deque&);\r
+               bool __ne__(deque&, deque&);\r
+               bool __lt__(deque&, deque&);\r
+               bool __gt__(deque&, deque&);\r
+               bool __le__(deque&, deque&);\r
+               bool __ge__(deque&, deque&);\r
+               #others\r
+               void assign(int, TYPE&)\r
+               void assign(iterator, iterator)\r
+               TYPE& at(int)\r
+               TYPE& back()\r
+               iterator begin()\r
+               void clear()\r
+               bool empty()\r
+               iterator end()\r
+               iterator erase(iterator)\r
+               iterator erase(iterator, iterator)\r
+               TYPE& front()\r
+               iterator insert(iterator, TYPE&)\r
+               void insert(iterator, int, TYPE&)\r
+               void insert(iterator, iterator, iterator)\r
+               int max_size()\r
+               void pop_back()\r
+               void pop_front()\r
+               void push_back(TYPE&)\r
+               void push_front(TYPE&)\r
+               iterator rbegin()\r
+               iterator rend()\r
+               void resize(int)\r
+               void resize(int, TYPE&)\r
+               int size()\r
+               void swap(container&)\r