fix locals directive in pxd files
authorHaoyu Bai <baihaoyu@gmail.com>
Thu, 7 Apr 2011 12:08:23 +0000 (20:08 +0800)
committerHaoyu Bai <baihaoyu@gmail.com>
Thu, 7 Apr 2011 12:32:07 +0000 (20:32 +0800)
Cython/Compiler/Nodes.py
tests/run/directive_locals_in_pxd.pxd [new file with mode: 0644]
tests/run/directive_locals_in_pxd.py [new file with mode: 0644]

index e7c3bd4f4f9280273d0248b33ce1ead71762b2e9..a8ed64e67f119c4df0b99c675a079633662f8bcb 100644 (file)
@@ -535,7 +535,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
     overridable = 0
     optional_arg_count = 0
 
-    def analyse(self, return_type, env, nonempty = 0):
+    def analyse(self, return_type, env, nonempty = 0, directive_locals = {}):
         if nonempty:
             nonempty -= 1
         func_type_args = []
@@ -543,6 +543,17 @@ class CFuncDeclaratorNode(CDeclaratorNode):
             name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
                                                      is_self_arg = (i == 0 and env.is_c_class_scope))
             name = name_declarator.name
+            if name in directive_locals:
+                type_node = directive_locals[name]
+                other_type = type_node.analyse_as_type(env)
+                if other_type is None:
+                    error(type_node.pos, "Not a type")
+                elif (type is not PyrexTypes.py_object_type 
+                      and not type.same_as(other_type)):
+                    error(self.base.pos, "Signature does not agree with previous declaration")
+                    error(type_node.pos, "Previous declaration here")
+                else:
+                    type = other_type
             if name_declarator.cname:
                 error(self.pos,
                     "Function argument cannot have C name specification")
@@ -946,7 +957,10 @@ class CVarDefNode(StatNode):
         visibility = self.visibility
 
         for declarator in self.declarators:
-            name_declarator, type = declarator.analyse(base_type, env)
+            if isinstance(declarator, CFuncDeclaratorNode):
+                name_declarator, type = declarator.analyse(base_type, env, directive_locals=self.directive_locals)
+            else:
+                name_declarator, type = declarator.analyse(base_type, env)
             if not type.is_complete():
                 if not (self.visibility == 'extern' and type.is_array):
                     error(declarator.pos,
diff --git a/tests/run/directive_locals_in_pxd.pxd b/tests/run/directive_locals_in_pxd.pxd
new file mode 100644 (file)
index 0000000..2b5678c
--- /dev/null
@@ -0,0 +1,4 @@
+cimport cython
+
+@cython.locals(egg=double)
+cdef foo(egg)
diff --git a/tests/run/directive_locals_in_pxd.py b/tests/run/directive_locals_in_pxd.py
new file mode 100644 (file)
index 0000000..8614fdf
--- /dev/null
@@ -0,0 +1,17 @@
+import cython
+
+# @cython.locals(x=double)
+# cdef func_defval(x=0):
+    # return x**2
+
+def foo(egg):
+    if not cython.compiled:
+        egg = float(egg)
+    return egg
+
+def test_pxd_locals():
+    """
+    >>> isinstance(test_pxd_locals(), float)
+    True
+    """
+    return foo(1)