Extract last of type list dependance from parser.
authorRobert Bradshaw <robertwb@math.washington.edu>
Tue, 30 Sep 2008 07:20:41 +0000 (00:20 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Tue, 30 Sep 2008 07:20:41 +0000 (00:20 -0700)
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
tests/compile/types_and_names.pyx [new file with mode: 0644]
tests/errors/e_argdefault.pyx
tests/errors/e_bufaccess2.pyx
tests/errors/invalid_cast.pyx

index baa34ae1d121a9e2b20f6f80a34e6b28ad33c7e0..448aa677cf81e71e0ccdb9904f1ba40fb39ce1ae 100644 (file)
@@ -411,8 +411,10 @@ class CNameDeclaratorNode(CDeclaratorNode):
                 error(self.pos, "Missing argument name")
             elif base_type.is_void:
                 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
-            self.name = base_type.declaration_code("", for_display=1, pyrex=1)
-            base_type = py_object_type
+            else:
+                print "here"
+                self.name = base_type.declaration_code("", for_display=1, pyrex=1)
+                base_type = py_object_type
         self.type = base_type
         return self, base_type
         
@@ -570,7 +572,19 @@ class CArgDeclNode(Node):
 
     def analyse(self, env, nonempty = 0):
         #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
-        base_type = self.base_type.analyse(env)
+        # The parser may missinterpret names as types...
+        # We fix that here.
+        if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
+            if nonempty:
+                self.declarator.name = self.base_type.name
+                self.base_type.name = None
+                self.base_type.is_basic_c_type = False
+            could_be_name = True
+        else:
+            could_be_name = False
+        base_type = self.base_type.analyse(env, could_be_name = could_be_name)
+        if self.base_type.arg_name:
+            self.declarator.name = self.base_type.arg_name
         return self.declarator.analyse(base_type, env, nonempty = nonempty)
 
     def annotate(self, code):
@@ -597,8 +611,9 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
     # is_self_arg      boolean      Is self argument of C method
 
     child_attrs = []
+    arg_name = None   # in case the argument name was interpreted as a type
     
-    def analyse(self, env):
+    def analyse(self, env, could_be_name = False):
         # Return type descriptor.
         #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
         type = None
@@ -615,13 +630,22 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
             else:
                 type = py_object_type
         else:
-            scope = env.find_imported_module(self.module_path, self.pos)
+            if self.module_path:
+                scope = env.find_imported_module(self.module_path, self.pos)
+            else:
+                scope = env
             if scope:
                 if scope.is_c_class_scope:
                     scope = scope.global_scope()
-                entry = scope.find(self.name, self.pos)
+                entry = scope.lookup(self.name)
                 if entry and entry.is_type:
                     type = entry.type
+                elif could_be_name:
+                    if self.is_self_arg and env.is_c_class_scope:
+                        type = env.parent_type
+                    else:
+                        type = py_object_type
+                    self.arg_name = self.name
                 else:
                     error(self.pos, "'%s' is not a type identifier" % self.name)
         if type:
@@ -644,7 +668,7 @@ class CBufferAccessTypeNode(CBaseTypeNode):
 
     dtype_node = None
     
-    def analyse(self, env):
+    def analyse(self, env, could_be_name = False):
         base_type = self.base_type_node.analyse(env)
         if base_type.is_error: return base_type
         import Buffer
@@ -665,8 +689,8 @@ class CComplexBaseTypeNode(CBaseTypeNode):
     
     child_attrs = ["base_type", "declarator"]
 
-    def analyse(self, env):
-        base = self.base_type.analyse(env)
+    def analyse(self, env, could_be_name = False):
+        base = self.base_type.analyse(env, could_be_name)
         _, type = self.declarator.analyse(base, env)
         return type
 
index d8e7f2e9d52d5823b8eaf096a4a97dbdab9d1c1f..70f719be711dc3186a1be99cab38023347af5e16 100644 (file)
@@ -253,14 +253,14 @@ def p_sizeof(s):
     # Here we decide if we are looking at an expression or type
     # If it is actually a type, but parsable as an expression, 
     # we treat it as an expression here. 
-    if looking_at_type(s):
+    if looking_at_expr(s):
+        operand = p_simple_expr(s)
+        node = ExprNodes.SizeofVarNode(pos, operand = operand)
+    else:
         base_type = p_c_base_type(s)
         declarator = p_c_declarator(s, empty = 1)
         node = ExprNodes.SizeofTypeNode(pos, 
             base_type = base_type, declarator = declarator)
-    else:
-        operand = p_simple_expr(s)
-        node = ExprNodes.SizeofVarNode(pos, operand = operand)
     s.expect(')')
     return node
 
@@ -1034,7 +1034,6 @@ def p_from_import_statement(s, first_statement = 0):
         for (name_pos, name, as_name, kind) in imported_names:
             local_name = as_name or name
             if local_name == "*" and False:
-                print s.__dict__.keys()
                 module = s.context.find_module(dotted_name)
                 for type in module.type_entries:
                     s.add_type_name(type.name)
@@ -1613,7 +1612,7 @@ def p_c_complex_base_type(s):
         base_type = base_type, declarator = declarator)
 
 def p_c_simple_base_type(s, self_flag, nonempty):
-    #print "p_c_simple_base_type: self_flag =", self_flag
+    #print "p_c_simple_base_type: self_flag =", self_flag, nonempty
     is_basic = 0
     signed = 1
     longness = 0
@@ -1636,12 +1635,11 @@ def p_c_simple_base_type(s, self_flag, nonempty):
             module_path.append(name)
             s.next()
             name = p_ident(s)
-    elif s.looking_at_type_name(): # looking_at_type(s):
+    else:
         name = s.systring
         s.next()
         if nonempty and s.sy != 'IDENT':
-            # Make sure this is not a declaration of a variable or 
-            # function with the same name as a type.  
+            # Make sure this is not a declaration of a variable or function.  
             if s.sy == '(':
                 s.next()
                 if s.sy == '*' or s.sy == '**':
@@ -1653,10 +1651,7 @@ def p_c_simple_base_type(s, self_flag, nonempty):
             elif s.sy not in ('*', '**', '['):
                 s.put_back('IDENT', name)
                 name = None
-    else:
-        #print "p_c_simple_base_type: not looking at type at", s.position()
-        name = None
-
+    
     type_node = Nodes.CSimpleBaseTypeNode(pos, 
         name = name, module_path = module_path,
         is_basic_c_type = is_basic, signed = signed,
@@ -1696,13 +1691,12 @@ def p_buffer_access(s, base_type_node):
     return result
     
 
-def looking_at_possible_type(s):
+def looking_at_name(s):
     return s.sy == 'IDENT' and not s.systring in calling_convention_words
-#    return looking_at_base_type(s) or s.looking_at_type_name()
 
-def looking_at_type(s):
+def looking_at_expr(s):
     if s.systring in base_type_start_words:
-        return True
+        return False
     elif s.sy == 'IDENT':
         is_type = False
         name = s.systring
@@ -1713,7 +1707,9 @@ def looking_at_type(s):
             dotted_path.append(s.systring)
             s.expect('IDENT')
         saved = s.sy, s.systring
-        if s.sy == '*' or s.sy == '**':
+        if s.sy == 'IDENT':
+            is_type = True
+        elif s.sy == '*' or s.sy == '**':
             s.next()
             is_type = s.sy == ')'
             s.put_back(*saved)
@@ -1725,16 +1721,14 @@ def looking_at_type(s):
             s.next()
             is_type = s.sy == ']'
             s.put_back(*saved)
-        elif s.sy == 'IDENT':
-            is_type = True
         dotted_path.reverse()
         for p in dotted_path:
             s.put_back('IDENT', p)
             s.put_back('.', '.')
         s.put_back('IDENT', name)
-        return is_type
+        return not is_type
     else:
-        return False
+        return True
 
 def looking_at_base_type(s):
     #print "looking_at_base_type?", s.sy, s.systring, s.position()
@@ -1790,7 +1784,7 @@ def p_c_declarator(s, ctx = Ctx(), empty = 0, is_type = 0, cmethod_flag = 0,
     pos = s.position()
     if s.sy == '(':
         s.next()
-        if s.sy == ')' or looking_at_possible_type(s):
+        if s.sy == ')' or looking_at_name(s):
             base = Nodes.CNameDeclaratorNode(pos, name = EncodedString(u""), cname = None)
             result = p_c_func_declarator(s, pos, ctx, base, cmethod_flag)
         else:
@@ -2195,6 +2189,8 @@ def p_ctypedef_statement(s, ctx):
             return p_c_struct_or_union_definition(s, pos, ctx)
     else:
         base_type = p_c_base_type(s, nonempty = 1)
+        if base_type.name is None:
+            s.error("Syntax error in ctypedef statement")
         declarator = p_c_declarator(s, ctx, is_type = 1, nonempty = 1)
         s.expect_newline("Syntax error in ctypedef statement")
         return Nodes.CTypeDefNode(
index 689a635c88b43b781449a836caf5ab698971aebf..c2e406d07654504a5e7ca52850da345f0ba5a705 100644 (file)
@@ -280,7 +280,6 @@ class BuiltinObjectType(PyObjectType):
         return "<%s>"% self.cname
         
     def assignable_from(self, src_type):
-
         if isinstance(src_type, BuiltinObjectType):
             return src_type.name == self.name
         else:
diff --git a/tests/compile/types_and_names.pyx b/tests/compile/types_and_names.pyx
new file mode 100644 (file)
index 0000000..cd58910
--- /dev/null
@@ -0,0 +1,29 @@
+cdef struct point:
+    double x
+    double y
+    double z
+
+print sizeof(point*)
+
+cdef extern from *:
+    cdef foo(int, int i, 
+             list, list L, 
+             point, point p, point* ps)
+             
+cdef class A:
+    cdef list
+    cdef list L
+    cdef point(self, int, int i, list, list L, point, point p, point* ps):
+        pass
+    
+cdef class B(A):
+    cdef point(self, o, int i, oo, list L, ooo, point p, point* ps):
+        pass
+
+cdef point P
+cdef point *Ps
+cdef A a
+
+foo(2, 3, [], [], P, P, &P)
+a.point("something", 3, "anything", [], "an object", P, &P)
+
index 331c1153307d6d4fd3036c5a236a7987409ba18e..752e738bc49bbe4abcf0237c2acaad84e53db2ff 100644 (file)
@@ -10,7 +10,7 @@ cdef class Grail:
                pass
 
 _ERRORS = u"""
-1:9: Non-default argument follows default argument
+1:10: Non-default argument follows default argument
 9:16: This argument cannot have a default value
 4:23: Non-default argument following default argument
 """
index 55217ca6d0c047831886a87789149d3a702450ef..8310491525e4ca4cc921d005345f9b5eb908be84 100644 (file)
@@ -4,7 +4,5 @@ def f():
     cdef object[e_bufaccess_pxd.T] buf
 
 _ERRORS = u"""
-3:17: Syntax error in ctypedef statement
-4:31: 'T' is not a type identifier
-4:31: 'T' is not declared
+3:9: 'nothing' is not a type identifier
 """
index e0aa0be38d8f871fa10ccc818da32a3fdfdecbfd..840ed344c0b6a7e82ac8b1562d33e9f7c41c89f8 100644 (file)
@@ -1,6 +1,6 @@
 def f():
-    a = <foao>x
+    a = <foao>True
 
 _ERRORS = """
-2:13: Unknown type
+2:9: 'foao' is not a type identifier
 """
\ No newline at end of file