From 0a77df1d830def01fa158579b60dfb6f06ef1684 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Tue, 30 Sep 2008 00:20:41 -0700 Subject: [PATCH] Extract last of type list dependance from parser. --- Cython/Compiler/Nodes.py | 42 ++++++++++++++++++++++++------- Cython/Compiler/Parsing.py | 42 ++++++++++++++----------------- Cython/Compiler/PyrexTypes.py | 1 - tests/compile/types_and_names.pyx | 29 +++++++++++++++++++++ tests/errors/e_argdefault.pyx | 2 +- tests/errors/e_bufaccess2.pyx | 4 +-- tests/errors/invalid_cast.pyx | 4 +-- 7 files changed, 85 insertions(+), 39 deletions(-) create mode 100644 tests/compile/types_and_names.pyx diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index baa34ae1..448aa677 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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 diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index d8e7f2e9..70f719be 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -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( diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 689a635c..c2e406d0 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -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 index 00000000..cd58910d --- /dev/null +++ b/tests/compile/types_and_names.pyx @@ -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) + diff --git a/tests/errors/e_argdefault.pyx b/tests/errors/e_argdefault.pyx index 331c1153..752e738b 100644 --- a/tests/errors/e_argdefault.pyx +++ b/tests/errors/e_argdefault.pyx @@ -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 """ diff --git a/tests/errors/e_bufaccess2.pyx b/tests/errors/e_bufaccess2.pyx index 55217ca6..83104915 100644 --- a/tests/errors/e_bufaccess2.pyx +++ b/tests/errors/e_bufaccess2.pyx @@ -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 """ diff --git a/tests/errors/invalid_cast.pyx b/tests/errors/invalid_cast.pyx index e0aa0be3..840ed344 100644 --- a/tests/errors/invalid_cast.pyx +++ b/tests/errors/invalid_cast.pyx @@ -1,6 +1,6 @@ def f(): - a = x + a = True _ERRORS = """ -2:13: Unknown type +2:9: 'foao' is not a type identifier """ \ No newline at end of file -- 2.26.2