Cython has moved to github.
cython-devel
view Cython/Compiler/Symtab.py @ 2771:8094c672a0b9
Less strict type checking on non-subclassed extern types.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Tue Dec 08 23:10:36 2009 -0800 (2 years ago) |
| parents | 430db09b246f |
| children | ca9ea011aca4 dde8beab2d1e |
line source
1 #
2 # Symbol Table
3 #
5 import re
6 from Cython import Utils
7 from Errors import warning, error, InternalError
8 from StringEncoding import EncodedString
9 import Options, Naming
10 import PyrexTypes
11 from PyrexTypes import py_object_type, unspecified_type
12 import TypeSlots
13 from TypeSlots import \
14 pyfunction_signature, pymethod_signature, \
15 get_special_method_signature, get_property_accessor_signature
16 import ControlFlow
17 import Code
18 import __builtin__ as builtins
19 try:
20 set
21 except NameError:
22 from sets import Set as set
24 possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
25 nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
27 iso_c99_keywords = set(
28 ['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do',
29 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if',
30 'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof',
31 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void',
32 'volatile', 'while',
33 '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict'])
35 def c_safe_identifier(cname):
36 # There are some C limitations on struct entry names.
37 if ((cname[:2] == '__'
38 and not (cname.startswith(Naming.pyrex_prefix)
39 or cname == '__weakref__'))
40 or cname in iso_c99_keywords):
41 cname = Naming.pyrex_prefix + cname
42 return cname
44 class BufferAux(object):
45 writable_needed = False
47 def __init__(self, buffer_info_var, stridevars, shapevars,
48 suboffsetvars):
49 self.buffer_info_var = buffer_info_var
50 self.stridevars = stridevars
51 self.shapevars = shapevars
52 self.suboffsetvars = suboffsetvars
54 def __repr__(self):
55 return "<BufferAux %r>" % self.__dict__
57 class Entry(object):
58 # A symbol table entry in a Scope or ModuleNamespace.
59 #
60 # name string Python name of entity
61 # cname string C name of entity
62 # type PyrexType Type of entity
63 # doc string Doc string
64 # init string Initial value
65 # visibility 'private' or 'public' or 'extern'
66 # is_builtin boolean Is an entry in the Python builtins dict
67 # is_cglobal boolean Is a C global variable
68 # is_pyglobal boolean Is a Python module-level variable
69 # or class attribute during
70 # class construction
71 # is_member boolean Is an assigned class member
72 # is_variable boolean Is a variable
73 # is_cfunction boolean Is a C function
74 # is_cmethod boolean Is a C method of an extension type
75 # is_unbound_cmethod boolean Is an unbound C method of an extension type
76 # is_type boolean Is a type definition
77 # is_cclass boolean Is an extension class
78 # is_const boolean Is a constant
79 # is_property boolean Is a property of an extension type:
80 # doc_cname string or None C const holding the docstring
81 # getter_cname string C func for getting property
82 # setter_cname string C func for setting or deleting property
83 # is_self_arg boolean Is the "self" arg of an exttype method
84 # is_arg boolean Is the arg of a method
85 # is_local boolean Is a local variable
86 # in_closure boolean Is referenced in an inner scope
87 # is_readonly boolean Can't be assigned to
88 # func_cname string C func implementing Python func
89 # func_modifiers [string] C function modifiers ('inline')
90 # pos position Source position where declared
91 # namespace_cname string If is_pyglobal, the C variable
92 # holding its home namespace
93 # pymethdef_cname string PyMethodDef structure
94 # signature Signature Arg & return types for Python func
95 # init_to_none boolean True if initial value should be None
96 # as_variable Entry Alternative interpretation of extension
97 # type name or builtin C function as a variable
98 # xdecref_cleanup boolean Use Py_XDECREF for error cleanup
99 # in_cinclude boolean Suppress C declaration code
100 # enum_values [Entry] For enum types, list of values
101 # qualified_name string "modname.funcname" or "modname.classname"
102 # or "modname.classname.funcname"
103 # is_declared_generic boolean Is declared as PyObject * even though its
104 # type is an extension type
105 # as_module None Module scope, if a cimported module
106 # is_inherited boolean Is an inherited attribute of an extension type
107 # pystring_cname string C name of Python version of string literal
108 # is_interned boolean For string const entries, value is interned
109 # is_identifier boolean For string const entries, value is an identifier
110 # used boolean
111 # is_special boolean Is a special method or property accessor
112 # of an extension type
113 # defined_in_pxd boolean Is defined in a .pxd file (not just declared)
114 # api boolean Generate C API for C class or function
115 # utility_code string Utility code needed when this entry is used
116 #
117 # buffer_aux BufferAux or None Extra information needed for buffer variables
118 # inline_func_in_pxd boolean Hacky special case for inline function in pxd file.
119 # Ideally this should not be necesarry.
120 # assignments [ExprNode] List of expressions that get assigned to this entry.
122 inline_func_in_pxd = False
123 borrowed = 0
124 init = ""
125 visibility = 'private'
126 is_builtin = 0
127 is_cglobal = 0
128 is_pyglobal = 0
129 is_member = 0
130 is_variable = 0
131 is_cfunction = 0
132 is_cmethod = 0
133 is_unbound_cmethod = 0
134 is_type = 0
135 is_cclass = 0
136 is_const = 0
137 is_property = 0
138 doc_cname = None
139 getter_cname = None
140 setter_cname = None
141 is_self_arg = 0
142 is_arg = 0
143 is_local = 0
144 in_closure = 0
145 is_declared_generic = 0
146 is_readonly = 0
147 func_cname = None
148 func_modifiers = []
149 doc = None
150 init_to_none = 0
151 as_variable = None
152 xdecref_cleanup = 0
153 in_cinclude = 0
154 as_module = None
155 is_inherited = 0
156 pystring_cname = None
157 is_identifier = 0
158 is_interned = 0
159 used = 0
160 is_special = 0
161 defined_in_pxd = 0
162 is_implemented = 0
163 api = 0
164 utility_code = None
165 is_overridable = 0
166 buffer_aux = None
167 prev_entry = None
169 def __init__(self, name, cname, type, pos = None, init = None):
170 self.name = name
171 self.cname = cname
172 self.type = type
173 self.pos = pos
174 self.init = init
175 self.assignments = []
177 def __repr__(self):
178 return "Entry(name=%s, type=%s)" % (self.name, self.type)
180 def redeclared(self, pos):
181 error(pos, "'%s' does not match previous declaration" % self.name)
182 error(self.pos, "Previous declaration is here")
184 class Scope(object):
185 # name string Unqualified name
186 # outer_scope Scope or None Enclosing scope
187 # entries {string : Entry} Python name to entry, non-types
188 # const_entries [Entry] Constant entries
189 # type_entries [Entry] Struct/union/enum/typedef/exttype entries
190 # sue_entries [Entry] Struct/union/enum entries
191 # arg_entries [Entry] Function argument entries
192 # var_entries [Entry] User-defined variable entries
193 # pyfunc_entries [Entry] Python function entries
194 # cfunc_entries [Entry] C function entries
195 # c_class_entries [Entry] All extension type entries
196 # cname_to_entry {string : Entry} Temp cname to entry mapping
197 # int_to_entry {int : Entry} Temp cname to entry mapping
198 # return_type PyrexType or None Return type of function owning scope
199 # is_py_class_scope boolean Is a Python class scope
200 # is_c_class_scope boolean Is an extension type scope
201 # scope_prefix string Disambiguator for C names
202 # in_cinclude boolean Suppress C declaration code
203 # qualified_name string "modname" or "modname.classname"
204 # pystring_entries [Entry] String const entries newly used as
205 # Python strings in this scope
206 # control_flow ControlFlow Used for keeping track of environment state
207 # nogil boolean In a nogil section
208 # directives dict Helper variable for the recursive
209 # analysis, contains directive values.
211 is_py_class_scope = 0
212 is_c_class_scope = 0
213 is_module_scope = 0
214 scope_prefix = ""
215 in_cinclude = 0
216 nogil = 0
218 def __init__(self, name, outer_scope, parent_scope):
219 # The outer_scope is the next scope in the lookup chain.
220 # The parent_scope is used to derive the qualified name of this scope.
221 self.name = name
222 self.outer_scope = outer_scope
223 self.parent_scope = parent_scope
224 mangled_name = "%d%s_" % (len(name), name)
225 qual_scope = self.qualifying_scope()
226 if qual_scope:
227 self.qualified_name = qual_scope.qualify_name(name)
228 self.scope_prefix = qual_scope.scope_prefix + mangled_name
229 else:
230 self.qualified_name = name
231 self.scope_prefix = mangled_name
232 self.entries = {}
233 self.const_entries = []
234 self.type_entries = []
235 self.sue_entries = []
236 self.arg_entries = []
237 self.var_entries = []
238 self.pyfunc_entries = []
239 self.cfunc_entries = []
240 self.c_class_entries = []
241 self.defined_c_classes = []
242 self.imported_c_classes = {}
243 self.cname_to_entry = {}
244 self.string_to_entry = {}
245 self.identifier_to_entry = {}
246 self.num_to_entry = {}
247 self.obj_to_entry = {}
248 self.pystring_entries = []
249 self.buffer_entries = []
250 self.control_flow = ControlFlow.LinearControlFlow()
251 self.return_type = None
253 def start_branching(self, pos):
254 self.control_flow = self.control_flow.start_branch(pos)
256 def next_branch(self, pos):
257 self.control_flow = self.control_flow.next_branch(pos)
259 def finish_branching(self, pos):
260 self.control_flow = self.control_flow.finish_branch(pos)
262 def __str__(self):
263 return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
265 def qualifying_scope(self):
266 return self.parent_scope
268 def mangle(self, prefix, name = None):
269 if name:
270 return "%s%s%s" % (prefix, self.scope_prefix, name)
271 else:
272 return self.parent_scope.mangle(prefix, self.name)
274 def mangle_internal(self, name):
275 # Mangle an internal name so as not to clash with any
276 # user-defined name in this scope.
277 prefix = "%s%s_" % (Naming.pyrex_prefix, name)
278 return self.mangle(prefix)
279 #return self.parent_scope.mangle(prefix, self.name)
281 def global_scope(self):
282 # Return the module-level scope containing this scope.
283 return self.outer_scope.global_scope()
285 def builtin_scope(self):
286 # Return the module-level scope containing this scope.
287 return self.outer_scope.builtin_scope()
289 def declare(self, name, cname, type, pos, visibility):
290 # Create new entry, and add to dictionary if
291 # name is not None. Reports a warning if already
292 # declared.
293 if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
294 # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
295 warning(pos, "'%s' is a reserved name in C." % cname, -1)
296 entries = self.entries
297 if name and name in entries:
298 if visibility == 'extern':
299 warning(pos, "'%s' redeclared " % name, 0)
300 elif visibility != 'ignore':
301 error(pos, "'%s' redeclared " % name)
302 entry = Entry(name, cname, type, pos = pos)
303 entry.in_cinclude = self.in_cinclude
304 if name:
305 entry.qualified_name = self.qualify_name(name)
306 entries[name] = entry
307 entry.scope = self
308 entry.visibility = visibility
309 return entry
311 def qualify_name(self, name):
312 return "%s.%s" % (self.qualified_name, name)
314 def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
315 # Add an entry for a named constant.
316 if not cname:
317 if self.in_cinclude or visibility == 'public':
318 cname = name
319 else:
320 cname = self.mangle(Naming.enum_prefix, name)
321 entry = self.declare(name, cname, type, pos, visibility)
322 entry.is_const = 1
323 entry.value_node = value
324 return entry
326 def declare_type(self, name, type, pos,
327 cname = None, visibility = 'private', defining = 1):
328 # Add an entry for a type definition.
329 if not cname:
330 cname = name
331 entry = self.declare(name, cname, type, pos, visibility)
332 entry.is_type = 1
333 if defining:
334 self.type_entries.append(entry)
335 # here we would set as_variable to an object representing this type
336 return entry
338 def declare_typedef(self, name, base_type, pos, cname = None,
339 visibility = 'private'):
340 if not cname:
341 if self.in_cinclude or visibility == 'public':
342 cname = name
343 else:
344 cname = self.mangle(Naming.type_prefix, name)
345 try:
346 type = PyrexTypes.create_typedef_type(cname, base_type, (visibility == 'extern'))
347 except ValueError, e:
348 error(pos, e.message)
349 type = PyrexTypes.error_type
350 entry = self.declare_type(name, type, pos, cname, visibility)
351 type.qualified_name = entry.qualified_name
352 return entry
354 def declare_struct_or_union(self, name, kind, scope,
355 typedef_flag, pos, cname = None, visibility = 'private',
356 packed = False):
357 # Add an entry for a struct or union definition.
358 if not cname:
359 if self.in_cinclude or visibility == 'public':
360 cname = name
361 else:
362 cname = self.mangle(Naming.type_prefix, name)
363 entry = self.lookup_here(name)
364 if not entry:
365 type = PyrexTypes.CStructOrUnionType(
366 name, kind, scope, typedef_flag, cname, packed)
367 entry = self.declare_type(name, type, pos, cname,
368 visibility = visibility, defining = scope is not None)
369 self.sue_entries.append(entry)
370 type.entry = entry
371 else:
372 if not (entry.is_type and entry.type.is_struct_or_union
373 and entry.type.kind == kind):
374 warning(pos, "'%s' redeclared " % name, 0)
375 elif scope and entry.type.scope:
376 warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
377 else:
378 self.check_previous_typedef_flag(entry, typedef_flag, pos)
379 self.check_previous_visibility(entry, visibility, pos)
380 if scope:
381 entry.type.scope = scope
382 self.type_entries.append(entry)
383 if not scope and not entry.type.scope:
384 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
385 return entry
387 def check_previous_typedef_flag(self, entry, typedef_flag, pos):
388 if typedef_flag != entry.type.typedef_flag:
389 error(pos, "'%s' previously declared using '%s'" % (
390 entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
392 def check_previous_visibility(self, entry, visibility, pos):
393 if entry.visibility != visibility:
394 error(pos, "'%s' previously declared as '%s'" % (
395 entry.name, entry.visibility))
397 def declare_enum(self, name, pos, cname, typedef_flag,
398 visibility = 'private'):
399 if name:
400 if not cname:
401 if self.in_cinclude or visibility == 'public':
402 cname = name
403 else:
404 cname = self.mangle(Naming.type_prefix, name)
405 type = PyrexTypes.CEnumType(name, cname, typedef_flag)
406 else:
407 type = PyrexTypes.c_anon_enum_type
408 entry = self.declare_type(name, type, pos, cname = cname,
409 visibility = visibility)
410 entry.enum_values = []
411 self.sue_entries.append(entry)
412 return entry
414 def declare_var(self, name, type, pos,
415 cname = None, visibility = 'private', is_cdef = 0):
416 # Add an entry for a variable.
417 if not cname:
418 if visibility != 'private':
419 cname = name
420 else:
421 cname = self.mangle(Naming.var_prefix, name)
422 entry = self.declare(name, cname, type, pos, visibility)
423 entry.is_variable = 1
424 self.control_flow.set_state((), (name, 'initalized'), False)
425 return entry
427 def declare_builtin(self, name, pos):
428 return self.outer_scope.declare_builtin(name, pos)
430 def declare_pyfunction(self, name, pos):
431 # Add an entry for a Python function.
432 entry = self.lookup_here(name)
433 if entry and not entry.type.is_cfunction:
434 # This is legal Python, but for now will produce invalid C.
435 error(pos, "'%s' already declared" % name)
436 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
437 entry.signature = pyfunction_signature
438 self.pyfunc_entries.append(entry)
439 return entry
441 def register_pyfunction(self, entry):
442 self.pyfunc_entries.append(entry)
444 def declare_cfunction(self, name, type, pos,
445 cname = None, visibility = 'private', defining = 0,
446 api = 0, in_pxd = 0, modifiers = ()):
447 # Add an entry for a C function.
448 entry = self.lookup_here(name)
449 if entry:
450 if visibility != 'private' and visibility != entry.visibility:
451 warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
452 if not entry.type.same_as(type):
453 if visibility == 'extern' and entry.visibility == 'extern':
454 warning(pos, "Function signature does not match previous declaration", 1)
455 entry.type = type
456 else:
457 error(pos, "Function signature does not match previous declaration")
458 else:
459 if not cname:
460 if api or visibility != 'private':
461 cname = name
462 else:
463 cname = self.mangle(Naming.func_prefix, name)
464 entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
465 entry.func_cname = cname
466 if in_pxd and visibility != 'extern':
467 entry.defined_in_pxd = 1
468 if api:
469 entry.api = 1
470 if not defining and not in_pxd and visibility != 'extern':
471 error(pos, "Non-extern C function '%s' declared but not defined" % name)
472 if defining:
473 entry.is_implemented = True
474 if modifiers:
475 entry.func_modifiers = modifiers
476 return entry
478 def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
479 # Add a C function entry without giving it a func_cname.
480 entry = self.declare(name, cname, type, pos, visibility)
481 entry.is_cfunction = 1
482 if modifiers:
483 entry.func_modifiers = modifiers
484 self.cfunc_entries.append(entry)
485 return entry
487 def find(self, name, pos):
488 # Look up name, report error if not found.
489 entry = self.lookup(name)
490 if entry:
491 return entry
492 else:
493 error(pos, "'%s' is not declared" % name)
495 def find_imported_module(self, path, pos):
496 # Look up qualified name, must be a module, report error if not found.
497 # Path is a list of names.
498 scope = self
499 for name in path:
500 entry = scope.find(name, pos)
501 if not entry:
502 return None
503 if entry.as_module:
504 scope = entry.as_module
505 else:
506 error(pos, "'%s' is not a cimported module" % '.'.join(path))
507 return None
508 return scope
510 def lookup(self, name):
511 # Look up name in this scope or an enclosing one.
512 # Return None if not found.
513 return (self.lookup_here(name)
514 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
515 or None)
517 def lookup_from_inner(self, name):
518 # Look up name in this scope or an enclosing one.
519 # This is only called from enclosing scopes.
520 return (self.lookup_here(name)
521 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
522 or None)
524 def lookup_here(self, name):
525 # Look up in this scope only, return None if not found.
526 return self.entries.get(name, None)
528 def lookup_target(self, name):
529 # Look up name in this scope only. Declare as Python
530 # variable if not found.
531 entry = self.lookup_here(name)
532 if not entry:
533 entry = self.declare_var(name, py_object_type, None)
534 return entry
536 def lookup_type(self, name):
537 entry = self.lookup(name)
538 if entry and entry.is_type:
539 return entry.type
541 def use_utility_code(self, new_code):
542 self.global_scope().use_utility_code(new_code)
544 def generate_library_function_declarations(self, code):
545 # Generate extern decls for C library funcs used.
546 pass
548 def defines_any(self, names):
549 # Test whether any of the given names are
550 # defined in this scope.
551 for name in names:
552 if name in self.entries:
553 return 1
554 return 0
556 def infer_types(self):
557 from TypeInference import get_type_inferer
558 get_type_inferer().infer_types(self)
560 class PreImportScope(Scope):
562 namespace_cname = Naming.preimport_cname
564 def __init__(self):
565 Scope.__init__(self, Options.pre_import, None, None)
567 def declare_builtin(self, name, pos):
568 entry = self.declare(name, name, py_object_type, pos, 'private')
569 entry.is_variable = True
570 entry.is_pyglobal = True
571 return entry
574 class BuiltinScope(Scope):
575 # The builtin namespace.
577 def __init__(self):
578 if Options.pre_import is None:
579 Scope.__init__(self, "__builtin__", None, None)
580 else:
581 Scope.__init__(self, "__builtin__", PreImportScope(), None)
582 self.type_names = {}
584 for name, definition in self.builtin_entries.iteritems():
585 cname, type = definition
586 self.declare_var(name, type, None, cname)
588 def declare_builtin(self, name, pos):
589 if not hasattr(builtins, name):
590 if self.outer_scope is not None:
591 return self.outer_scope.declare_builtin(name, pos)
592 else:
593 error(pos, "undeclared name not builtin: %s"%name)
595 def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
596 utility_code = None):
597 # If python_equiv == "*", the Python equivalent has the same name
598 # as the entry, otherwise it has the name specified by python_equiv.
599 name = EncodedString(name)
600 entry = self.declare_cfunction(name, type, None, cname, visibility='extern')
601 entry.utility_code = utility_code
602 if python_equiv:
603 if python_equiv == "*":
604 python_equiv = name
605 else:
606 python_equiv = EncodedString(python_equiv)
607 var_entry = Entry(python_equiv, python_equiv, py_object_type)
608 var_entry.is_variable = 1
609 var_entry.is_builtin = 1
610 entry.as_variable = var_entry
611 return entry
613 def declare_builtin_type(self, name, cname, utility_code = None):
614 name = EncodedString(name)
615 type = PyrexTypes.BuiltinObjectType(name, cname)
616 type.set_scope(CClassScope(name, outer_scope=None, visibility='extern'))
617 self.type_names[name] = 1
618 entry = self.declare_type(name, type, None, visibility='extern')
620 var_entry = Entry(name = entry.name,
621 type = self.lookup('type').type, # make sure "type" is the first type declared...
622 pos = entry.pos,
623 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
624 var_entry.is_variable = 1
625 var_entry.is_cglobal = 1
626 var_entry.is_readonly = 1
627 var_entry.is_builtin = 1
628 var_entry.utility_code = utility_code
629 entry.as_variable = var_entry
631 return type
633 def builtin_scope(self):
634 return self
636 builtin_entries = {
638 "type": ["((PyObject*)&PyType_Type)", py_object_type],
640 "bool": ["((PyObject*)&PyBool_Type)", py_object_type],
641 "int": ["((PyObject*)&PyInt_Type)", py_object_type],
642 "long": ["((PyObject*)&PyLong_Type)", py_object_type],
643 "float": ["((PyObject*)&PyFloat_Type)", py_object_type],
644 "complex":["((PyObject*)&PyComplex_Type)", py_object_type],
646 "bytes": ["((PyObject*)&PyBytes_Type)", py_object_type],
647 "str": ["((PyObject*)&PyString_Type)", py_object_type],
648 "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type],
650 "tuple": ["((PyObject*)&PyTuple_Type)", py_object_type],
651 "list": ["((PyObject*)&PyList_Type)", py_object_type],
652 "dict": ["((PyObject*)&PyDict_Type)", py_object_type],
653 "set": ["((PyObject*)&PySet_Type)", py_object_type],
654 "frozenset": ["((PyObject*)&PyFrozenSet_Type)", py_object_type],
656 "slice": ["((PyObject*)&PySlice_Type)", py_object_type],
657 "file": ["((PyObject*)&PyFile_Type)", py_object_type],
659 "None": ["Py_None", py_object_type],
660 "False": ["Py_False", py_object_type],
661 "True": ["Py_True", py_object_type],
662 }
664 const_counter = 1 # As a temporary solution for compiling code in pxds
666 class ModuleScope(Scope):
667 # module_name string Python name of the module
668 # module_cname string C name of Python module object
669 # #module_dict_cname string C name of module dict object
670 # method_table_cname string C name of method table
671 # doc string Module doc string
672 # doc_cname string C name of module doc string
673 # utility_code_list [UtilityCode] Queuing utility codes for forwarding to Code.py
674 # python_include_files [string] Standard Python headers to be included
675 # include_files [string] Other C headers to be included
676 # string_to_entry {string : Entry} Map string const to entry
677 # identifier_to_entry {string : Entry} Map identifier string const to entry
678 # context Context
679 # parent_module Scope Parent in the import namespace
680 # module_entries {string : Entry} For cimport statements
681 # type_names {string : 1} Set of type names (used during parsing)
682 # included_files [string] Cython sources included with 'include'
683 # pxd_file_loaded boolean Corresponding .pxd file has been processed
684 # cimported_modules [ModuleScope] Modules imported with cimport
685 # types_imported {PyrexType : 1} Set of types for which import code generated
686 # has_import_star boolean Module contains import *
688 is_module_scope = 1
689 has_import_star = 0
691 def __init__(self, name, parent_module, context):
692 self.parent_module = parent_module
693 outer_scope = context.find_submodule("__builtin__")
694 Scope.__init__(self, name, outer_scope, parent_module)
695 if name != "__init__":
696 self.module_name = name
697 else:
698 # Treat Spam/__init__.pyx specially, so that when Python loads
699 # Spam/__init__.so, initSpam() is defined.
700 self.module_name = parent_module.module_name
701 self.context = context
702 self.module_cname = Naming.module_cname
703 self.module_dict_cname = Naming.moddict_cname
704 self.method_table_cname = Naming.methtable_cname
705 self.doc = ""
706 self.doc_cname = Naming.moddoc_cname
707 self.utility_code_list = []
708 self.module_entries = {}
709 self.python_include_files = ["Python.h", "structmember.h"]
710 self.include_files = []
711 self.type_names = dict(outer_scope.type_names)
712 self.pxd_file_loaded = 0
713 self.cimported_modules = []
714 self.types_imported = {}
715 self.included_files = []
716 self.has_extern_class = 0
717 self.cached_builtins = []
718 self.undeclared_cached_builtins = []
719 self.namespace_cname = self.module_cname
720 for name in ['__builtins__', '__name__', '__file__', '__doc__']:
721 self.declare_var(EncodedString(name), py_object_type, None)
723 def qualifying_scope(self):
724 return self.parent_module
726 def global_scope(self):
727 return self
729 def declare_builtin(self, name, pos):
730 if not hasattr(builtins, name):
731 if self.has_import_star:
732 entry = self.declare_var(name, py_object_type, pos)
733 return entry
734 elif self.outer_scope is not None:
735 return self.outer_scope.declare_builtin(name, pos)
736 else:
737 error(pos, "undeclared name not builtin: %s"%name)
738 if Options.cache_builtins:
739 for entry in self.cached_builtins:
740 if entry.name == name:
741 return entry
742 entry = self.declare(None, None, py_object_type, pos, 'private')
743 if Options.cache_builtins:
744 entry.is_builtin = 1
745 entry.is_const = 1
746 entry.name = name
747 entry.cname = Naming.builtin_prefix + name
748 self.cached_builtins.append(entry)
749 self.undeclared_cached_builtins.append(entry)
750 else:
751 entry.is_builtin = 1
752 return entry
754 def find_module(self, module_name, pos):
755 # Find a module in the import namespace, interpreting
756 # relative imports relative to this module's parent.
757 # Finds and parses the module's .pxd file if the module
758 # has not been referenced before.
759 return self.global_scope().context.find_module(
760 module_name, relative_to = self.parent_module, pos = pos)
762 def find_submodule(self, name):
763 # Find and return scope for a submodule of this module,
764 # creating a new empty one if necessary. Doesn't parse .pxd.
765 scope = self.lookup_submodule(name)
766 if not scope:
767 scope = ModuleScope(name,
768 parent_module = self, context = self.context)
769 self.module_entries[name] = scope
770 return scope
772 def lookup_submodule(self, name):
773 # Return scope for submodule of this module, or None.
774 return self.module_entries.get(name, None)
776 def add_include_file(self, filename):
777 if filename not in self.python_include_files \
778 and filename not in self.include_files:
779 self.include_files.append(filename)
781 def add_imported_module(self, scope):
782 if scope not in self.cimported_modules:
783 for filename in scope.include_files:
784 self.add_include_file(filename)
785 self.cimported_modules.append(scope)
786 for m in scope.cimported_modules:
787 self.add_imported_module(m)
789 def add_imported_entry(self, name, entry, pos):
790 if entry not in self.entries:
791 self.entries[name] = entry
792 else:
793 warning(pos, "'%s' redeclared " % name, 0)
795 def declare_module(self, name, scope, pos):
796 # Declare a cimported module. This is represented as a
797 # Python module-level variable entry with a module
798 # scope attached to it. Reports an error and returns
799 # None if previously declared as something else.
800 entry = self.lookup_here(name)
801 if entry:
802 if entry.is_pyglobal and entry.as_module is scope:
803 return entry # Already declared as the same module
804 if not (entry.is_pyglobal and not entry.as_module):
805 # SAGE -- I put this here so Pyrex
806 # cimport's work across directories.
807 # Currently it tries to multiply define
808 # every module appearing in an import list.
809 # It shouldn't be an error for a module
810 # name to appear again, and indeed the generated
811 # code compiles fine.
812 return entry
813 warning(pos, "'%s' redeclared " % name, 0)
814 return None
815 else:
816 entry = self.declare_var(name, py_object_type, pos)
817 entry.as_module = scope
818 self.add_imported_module(scope)
819 return entry
821 def declare_var(self, name, type, pos,
822 cname = None, visibility = 'private', is_cdef = 0):
823 # Add an entry for a global variable. If it is a Python
824 # object type, and not declared with cdef, it will live
825 # in the module dictionary, otherwise it will be a C
826 # global variable.
827 entry = Scope.declare_var(self, name, type, pos,
828 cname, visibility, is_cdef)
829 if not visibility in ('private', 'public', 'extern'):
830 error(pos, "Module-level variable cannot be declared %s" % visibility)
831 if not is_cdef:
832 if type is unspecified_type:
833 type = py_object_type
834 if not (type.is_pyobject and not type.is_extension_type):
835 raise InternalError(
836 "Non-cdef global variable is not a generic Python object")
837 entry.is_pyglobal = 1
838 else:
839 entry.is_cglobal = 1
840 if entry.type.is_pyobject:
841 entry.init = 0
842 self.var_entries.append(entry)
843 return entry
845 def declare_global(self, name, pos):
846 entry = self.lookup_here(name)
847 if not entry:
848 self.declare_var(name, py_object_type, pos)
850 def use_utility_code(self, new_code):
851 if new_code is not None:
852 self.utility_code_list.append(new_code)
854 def declare_c_class(self, name, pos, defining = 0, implementing = 0,
855 module_name = None, base_type = None, objstruct_cname = None,
856 typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
857 buffer_defaults = None):
858 # If this is a non-extern typedef class, expose the typedef, but use
859 # the non-typedef struct internally to avoid needing forward
860 # declarations for anonymous structs.
861 if typedef_flag and visibility != 'extern':
862 if visibility != 'public':
863 warning(pos, "ctypedef only valid for public and extern classes", 2)
864 objtypedef_cname = objstruct_cname
865 objstruct_cname = None
866 typedef_flag = 0
867 else:
868 objtypedef_cname = None
869 #
870 # Look for previous declaration as a type
871 #
872 entry = self.lookup_here(name)
873 if entry:
874 type = entry.type
875 if not (entry.is_type and type.is_extension_type):
876 entry = None # Will cause redeclaration and produce an error
877 else:
878 scope = type.scope
879 if typedef_flag and (not scope or scope.defined):
880 self.check_previous_typedef_flag(entry, typedef_flag, pos)
881 if (scope and scope.defined) or (base_type and type.base_type):
882 if base_type and base_type is not type.base_type:
883 error(pos, "Base type does not match previous declaration")
884 if base_type and not type.base_type:
885 type.base_type = base_type
886 #
887 # Make a new entry if needed
888 #
889 if not entry:
890 type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern')
891 type.pos = pos
892 type.buffer_defaults = buffer_defaults
893 if objtypedef_cname is not None:
894 type.objtypedef_cname = objtypedef_cname
895 if visibility == 'extern':
896 type.module_name = module_name
897 else:
898 type.module_name = self.qualified_name
899 type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
900 entry = self.declare_type(name, type, pos, visibility = visibility,
901 defining = 0)
902 entry.is_cclass = True
903 if objstruct_cname:
904 type.objstruct_cname = objstruct_cname
905 elif not entry.in_cinclude:
906 type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
907 else:
908 error(entry.pos,
909 "Object name required for 'public' or 'extern' C class")
910 self.attach_var_entry_to_c_class(entry)
911 self.c_class_entries.append(entry)
912 #
913 # Check for re-definition and create scope if needed
914 #
915 if not type.scope:
916 if defining or implementing:
917 scope = CClassScope(name = name, outer_scope = self,
918 visibility = visibility)
919 if base_type and base_type.scope:
920 scope.declare_inherited_c_attributes(base_type.scope)
921 type.set_scope(scope)
922 self.type_entries.append(entry)
923 else:
924 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
925 else:
926 if defining and type.scope.defined:
927 error(pos, "C class '%s' already defined" % name)
928 elif implementing and type.scope.implemented:
929 error(pos, "C class '%s' already implemented" % name)
930 #
931 # Fill in options, checking for compatibility with any previous declaration
932 #
933 if defining:
934 entry.defined_in_pxd = 1
935 if implementing: # So that filenames in runtime exceptions refer to
936 entry.pos = pos # the .pyx file and not the .pxd file
937 if visibility != 'private' and entry.visibility != visibility:
938 error(pos, "Class '%s' previously declared as '%s'"
939 % (name, entry.visibility))
940 if api:
941 entry.api = 1
942 if objstruct_cname:
943 if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
944 error(pos, "Object struct name differs from previous declaration")
945 type.objstruct_cname = objstruct_cname
946 if typeobj_cname:
947 if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
948 error(pos, "Type object name differs from previous declaration")
949 type.typeobj_cname = typeobj_cname
950 #
951 # Return new or existing entry
952 #
953 return entry
955 def check_for_illegal_incomplete_ctypedef(self, typedef_flag, pos):
956 if typedef_flag and not self.in_cinclude:
957 error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
959 def allocate_vtable_names(self, entry):
960 # If extension type has a vtable, allocate vtable struct and
961 # slot names for it.
962 type = entry.type
963 if type.base_type and type.base_type.vtabslot_cname:
964 #print "...allocating vtabslot_cname because base type has one" ###
965 type.vtabslot_cname = "%s.%s" % (
966 Naming.obj_base_cname, type.base_type.vtabslot_cname)
967 elif type.scope and type.scope.cfunc_entries:
968 #print "...allocating vtabslot_cname because there are C methods" ###
969 type.vtabslot_cname = Naming.vtabslot_cname
970 if type.vtabslot_cname:
971 #print "...allocating other vtable related cnames" ###
972 type.vtabstruct_cname = self.mangle(Naming.vtabstruct_prefix, entry.name)
973 type.vtabptr_cname = self.mangle(Naming.vtabptr_prefix, entry.name)
975 def check_c_classes_pxd(self):
976 # Performs post-analysis checking and finishing up of extension types
977 # being implemented in this module. This is called only for the .pxd.
978 #
979 # Checks all extension types declared in this scope to
980 # make sure that:
981 #
982 # * The extension type is fully declared
983 #
984 # Also allocates a name for the vtable if needed.
985 #
986 for entry in self.c_class_entries:
987 # Check defined
988 if not entry.type.scope:
989 error(entry.pos, "C class '%s' is declared but not defined" % entry.name)
991 def check_c_classes(self):
992 # Performs post-analysis checking and finishing up of extension types
993 # being implemented in this module. This is called only for the main
994 # .pyx file scope, not for cimported .pxd scopes.
995 #
996 # Checks all extension types declared in this scope to
997 # make sure that:
998 #
999 # * The extension type is implemented
1000 # * All required object and type names have been specified or generated
1001 # * All non-inherited C methods are implemented
1002 #
1003 # Also allocates a name for the vtable if needed.
1004 #
1005 debug_check_c_classes = 0
1006 if debug_check_c_classes:
1007 print("Scope.check_c_classes: checking scope " + self.qualified_name)
1008 for entry in self.c_class_entries:
1009 if debug_check_c_classes:
1010 print("...entry %s %s" % (entry.name, entry))
1011 print("......type = ", entry.type)
1012 print("......visibility = ", entry.visibility)
1013 type = entry.type
1014 name = entry.name
1015 visibility = entry.visibility
1016 # Check defined
1017 if not type.scope:
1018 error(entry.pos, "C class '%s' is declared but not defined" % name)
1019 # Generate typeobj_cname
1020 if visibility != 'extern' and not type.typeobj_cname:
1021 type.typeobj_cname = self.mangle(Naming.typeobj_prefix, name)
1022 ## Generate typeptr_cname
1023 #type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1024 # Check C methods defined
1025 if type.scope:
1026 for method_entry in type.scope.cfunc_entries:
1027 if not method_entry.is_inherited and not method_entry.func_cname:
1028 error(method_entry.pos, "C method '%s' is declared but not defined" %
1029 method_entry.name)
1030 # Allocate vtable name if necessary
1031 if type.vtabslot_cname:
1032 #print "ModuleScope.check_c_classes: allocating vtable cname for", self ###
1033 type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name)
1035 def check_c_functions(self):
1036 # Performs post-analysis checking making sure all
1037 # defined c functions are actually implemented.
1038 for name, entry in self.entries.items():
1039 if entry.is_cfunction:
1040 if (entry.defined_in_pxd
1041 and entry.scope is self
1042 and entry.visibility != 'extern'
1043 and not entry.in_cinclude
1044 and not entry.is_implemented):
1045 error(entry.pos, "Non-extern C function '%s' declared but not defined" % name)
1047 def attach_var_entry_to_c_class(self, entry):
1048 # The name of an extension class has to serve as both a type
1049 # name and a variable name holding the type object. It is
1050 # represented in the symbol table by a type entry with a
1051 # variable entry attached to it. For the variable entry,
1052 # we use a read-only C global variable whose name is an
1053 # expression that refers to the type object.
1054 import Builtin
1055 var_entry = Entry(name = entry.name,
1056 type = Builtin.type_type,
1057 pos = entry.pos,
1058 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
1059 var_entry.is_variable = 1
1060 var_entry.is_cglobal = 1
1061 var_entry.is_readonly = 1
1062 entry.as_variable = var_entry
1064 def infer_types(self):
1065 from TypeInference import PyObjectTypeInferer
1066 PyObjectTypeInferer().infer_types(self)
1068 class LocalScope(Scope):
1070 def __init__(self, name, outer_scope, parent_scope = None):
1071 if parent_scope is None:
1072 parent_scope = outer_scope
1073 Scope.__init__(self, name, outer_scope, parent_scope)
1075 def mangle(self, prefix, name):
1076 return prefix + name
1078 def declare_arg(self, name, type, pos):
1079 # Add an entry for an argument of a function.
1080 cname = self.mangle(Naming.var_prefix, name)
1081 entry = self.declare(name, cname, type, pos, 'private')
1082 entry.is_variable = 1
1083 if type.is_pyobject:
1084 entry.init = "0"
1085 entry.is_arg = 1
1086 #entry.borrowed = 1 # Not using borrowed arg refs for now
1087 self.arg_entries.append(entry)
1088 self.control_flow.set_state((), (name, 'source'), 'arg')
1089 return entry
1091 def declare_var(self, name, type, pos,
1092 cname = None, visibility = 'private', is_cdef = 0):
1093 # Add an entry for a local variable.
1094 if visibility in ('public', 'readonly'):
1095 error(pos, "Local variable cannot be declared %s" % visibility)
1096 entry = Scope.declare_var(self, name, type, pos,
1097 cname, visibility, is_cdef)
1098 if type.is_pyobject and not Options.init_local_none:
1099 entry.init = "0"
1100 entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
1101 entry.is_local = 1
1102 self.var_entries.append(entry)
1103 return entry
1105 def declare_global(self, name, pos):
1106 # Pull entry from global scope into local scope.
1107 if self.lookup_here(name):
1108 warning(pos, "'%s' redeclared ", 0)
1109 else:
1110 entry = self.global_scope().lookup_target(name)
1111 self.entries[name] = entry
1113 def lookup_from_inner(self, name):
1114 entry = self.lookup_here(name)
1115 if entry:
1116 entry.in_closure = 1
1117 return entry
1118 else:
1119 return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
1121 def mangle_closure_cnames(self, scope_var):
1122 for entry in self.entries.values():
1123 if entry.in_closure:
1124 if not hasattr(entry, 'orig_cname'):
1125 entry.orig_cname = entry.cname
1126 entry.cname = scope_var + "->" + entry.cname
1129 class GeneratorLocalScope(LocalScope):
1131 def mangle_closure_cnames(self, scope_var):
1132 # for entry in self.entries.values() + self.temp_entries:
1133 # entry.in_closure = 1
1134 LocalScope.mangle_closure_cnames(self, scope_var)
1136 # def mangle(self, prefix, name):
1137 # return "%s->%s" % (Naming.scope_obj_cname, name)
1139 class StructOrUnionScope(Scope):
1140 # Namespace of a C struct or union.
1142 def __init__(self, name="?"):
1143 Scope.__init__(self, name, None, None)
1145 def declare_var(self, name, type, pos,
1146 cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
1147 # Add an entry for an attribute.
1148 if not cname:
1149 cname = name
1150 if visibility == 'private':
1151 cname = c_safe_identifier(cname)
1152 if type.is_cfunction:
1153 type = PyrexTypes.CPtrType(type)
1154 entry = self.declare(name, cname, type, pos, visibility)
1155 entry.is_variable = 1
1156 self.var_entries.append(entry)
1157 if type.is_pyobject and not allow_pyobject:
1158 error(pos,
1159 "C struct/union member cannot be a Python object")
1160 if visibility != 'private':
1161 error(pos,
1162 "C struct/union member cannot be declared %s" % visibility)
1163 return entry
1165 def declare_cfunction(self, name, type, pos,
1166 cname = None, visibility = 'private', defining = 0,
1167 api = 0, in_pxd = 0, modifiers = ()):
1168 return self.declare_var(name, type, pos, cname, visibility)
1170 class ClassScope(Scope):
1171 # Abstract base class for namespace of
1172 # Python class or extension type.
1173 #
1174 # class_name string Pyrex name of the class
1175 # scope_prefix string Additional prefix for names
1176 # declared in the class
1177 # doc string or None Doc string
1179 def __init__(self, name, outer_scope):
1180 Scope.__init__(self, name, outer_scope, outer_scope)
1181 self.class_name = name
1182 self.doc = None
1184 def add_string_const(self, value, identifier = False):
1185 return self.outer_scope.add_string_const(value, identifier)
1187 def lookup(self, name):
1188 entry = Scope.lookup(self, name)
1189 if entry:
1190 return entry
1191 if name == "classmethod":
1192 # We don't want to use the builtin classmethod here 'cause it won't do the
1193 # right thing in this scope (as the class memebers aren't still functions).
1194 # Don't want to add a cfunction to this scope 'cause that would mess with
1195 # the type definition, so we just return the right entry.
1196 self.use_utility_code(classmethod_utility_code)
1197 entry = Entry(
1198 "classmethod",
1199 "__Pyx_Method_ClassMethod",
1200 PyrexTypes.CFuncType(
1201 py_object_type,
1202 [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0))
1203 entry.is_cfunction = 1
1204 return entry
1207 class PyClassScope(ClassScope):
1208 # Namespace of a Python class.
1209 #
1210 # class_obj_cname string C variable holding class object
1212 is_py_class_scope = 1
1214 def declare_var(self, name, type, pos,
1215 cname = None, visibility = 'private', is_cdef = 0):
1216 if type is unspecified_type:
1217 type = py_object_type
1218 # Add an entry for a class attribute.
1219 entry = Scope.declare_var(self, name, type, pos,
1220 cname, visibility, is_cdef)
1221 entry.is_pyglobal = 1
1222 return entry
1224 def add_default_value(self, type):
1225 return self.outer_scope.add_default_value(type)
1228 class CClassScope(ClassScope):
1229 # Namespace of an extension type.
1230 #
1231 # parent_type CClassType
1232 # #typeobj_cname string or None
1233 # #objstruct_cname string
1234 # method_table_cname string
1235 # member_table_cname string
1236 # getset_table_cname string
1237 # has_pyobject_attrs boolean Any PyObject attributes?
1238 # public_attr_entries boolean public/readonly attrs
1239 # property_entries [Entry]
1240 # defined boolean Defined in .pxd file
1241 # implemented boolean Defined in .pyx file
1242 # inherited_var_entries [Entry] Adapted var entries from base class
1244 is_c_class_scope = 1
1246 def __init__(self, name, outer_scope, visibility):
1247 ClassScope.__init__(self, name, outer_scope)
1248 if visibility != 'extern':
1249 self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
1250 self.member_table_cname = outer_scope.mangle(Naming.memtab_prefix, name)
1251 self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
1252 self.has_pyobject_attrs = 0
1253 self.public_attr_entries = []
1254 self.property_entries = []
1255 self.inherited_var_entries = []
1256 self.defined = 0
1257 self.implemented = 0
1259 def needs_gc(self):
1260 # If the type or any of its base types have Python-valued
1261 # C attributes, then it needs to participate in GC.
1262 return self.has_pyobject_attrs or \
1263 (self.parent_type.base_type and
1264 self.parent_type.base_type.scope is not None and
1265 self.parent_type.base_type.scope.needs_gc())
1267 def declare_var(self, name, type, pos,
1268 cname = None, visibility = 'private', is_cdef = 0):
1269 if is_cdef:
1270 # Add an entry for an attribute.
1271 if self.defined:
1272 error(pos,
1273 "C attributes cannot be added in implementation part of"
1274 " extension type defined in a pxd")
1275 if get_special_method_signature(name):
1276 error(pos,
1277 "The name '%s' is reserved for a special method."
1278 % name)
1279 if not cname:
1280 cname = name
1281 if visibility == 'private':
1282 cname = c_safe_identifier(cname)
1283 entry = self.declare(name, cname, type, pos, visibility)
1284 entry.is_variable = 1
1285 self.var_entries.append(entry)
1286 if type.is_pyobject:
1287 self.has_pyobject_attrs = 1
1288 if visibility not in ('private', 'public', 'readonly'):
1289 error(pos,
1290 "Attribute of extension type cannot be declared %s" % visibility)
1291 if visibility in ('public', 'readonly'):
1292 if type.pymemberdef_typecode:
1293 self.public_attr_entries.append(entry)
1294 if name == "__weakref__":
1295 error(pos, "Special attribute __weakref__ cannot be exposed to Python")
1296 else:
1297 error(pos,
1298 "C attribute of type '%s' cannot be accessed from Python" % type)
1299 if visibility == 'public' and type.is_extension_type:
1300 error(pos,
1301 "Non-generic Python attribute cannot be exposed for writing from Python")
1302 return entry
1303 else:
1304 if type is unspecified_type:
1305 type = py_object_type
1306 # Add an entry for a class attribute.
1307 entry = Scope.declare_var(self, name, type, pos,
1308 cname, visibility, is_cdef)
1309 entry.is_member = 1
1310 entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
1311 # I keep it in for now. is_member should be enough
1312 # later on
1313 self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
1314 return entry
1317 def declare_pyfunction(self, name, pos):
1318 # Add an entry for a method.
1319 if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
1320 error(pos, "Special method %s must be implemented via __richcmp__" % name)
1321 if name == "__new__":
1322 warning(pos, "__new__ method of extension type will change semantics "
1323 "in a future version of Pyrex and Cython. Use __cinit__ instead.")
1324 name = EncodedString("__cinit__")
1325 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
1326 special_sig = get_special_method_signature(name)
1327 if special_sig:
1328 # Special methods get put in the method table with a particular
1329 # signature declared in advance.
1330 entry.signature = special_sig
1331 entry.is_special = 1
1332 else:
1333 entry.signature = pymethod_signature
1334 entry.is_special = 0
1336 self.pyfunc_entries.append(entry)
1337 return entry
1339 def lookup_here(self, name):
1340 if name == "__new__":
1341 name = EncodedString("__cinit__")
1342 return ClassScope.lookup_here(self, name)
1344 def declare_cfunction(self, name, type, pos,
1345 cname = None, visibility = 'private',
1346 defining = 0, api = 0, in_pxd = 0, modifiers = ()):
1347 if get_special_method_signature(name):
1348 error(pos, "Special methods must be declared with 'def', not 'cdef'")
1349 args = type.args
1350 if not args:
1351 error(pos, "C method has no self argument")
1352 elif not args[0].type.same_as(self.parent_type):
1353 error(pos, "Self argument (%s) of C method '%s' does not match parent type (%s)" %
1354 (args[0].type, name, self.parent_type))
1355 entry = self.lookup_here(name)
1356 if entry:
1357 if not entry.is_cfunction:
1358 warning(pos, "'%s' redeclared " % name, 0)
1359 else:
1360 if defining and entry.func_cname:
1361 error(pos, "'%s' already defined" % name)
1362 #print "CClassScope.declare_cfunction: checking signature" ###
1363 if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1364 pass
1365 elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1366 entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore', modifiers=modifiers)
1367 defining = 1
1368 else:
1369 error(pos, "Signature not compatible with previous declaration")
1370 error(entry.pos, "Previous declaration is here")
1371 else:
1372 if self.defined:
1373 error(pos,
1374 "C method '%s' not previously declared in definition part of"
1375 " extension type" % name)
1376 entry = self.add_cfunction(name, type, pos, cname or name,
1377 visibility, modifiers)
1378 if defining:
1379 entry.func_cname = self.mangle(Naming.func_prefix, name)
1380 return entry
1382 def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
1383 # Add a cfunction entry without giving it a func_cname.
1384 prev_entry = self.lookup_here(name)
1385 entry = ClassScope.add_cfunction(self, name, type, pos, cname,
1386 visibility, modifiers)
1387 entry.is_cmethod = 1
1388 entry.prev_entry = prev_entry
1389 return entry
1391 def declare_property(self, name, doc, pos):
1392 entry = self.lookup_here(name)
1393 if entry is None:
1394 entry = self.declare(name, name, py_object_type, pos, 'private')
1395 entry.is_property = 1
1396 entry.doc = doc
1397 entry.scope = PropertyScope(name,
1398 outer_scope = self.global_scope(), parent_scope = self)
1399 entry.scope.parent_type = self.parent_type
1400 self.property_entries.append(entry)
1401 return entry
1403 def declare_inherited_c_attributes(self, base_scope):
1404 # Declare entries for all the C attributes of an
1405 # inherited type, with cnames modified appropriately
1406 # to work with this type.
1407 def adapt(cname):
1408 return "%s.%s" % (Naming.obj_base_cname, base_entry.cname)
1409 for base_entry in \
1410 base_scope.inherited_var_entries + base_scope.var_entries:
1411 entry = self.declare(base_entry.name, adapt(base_entry.cname),
1412 base_entry.type, None, 'private')
1413 entry.is_variable = 1
1414 self.inherited_var_entries.append(entry)
1415 for base_entry in base_scope.cfunc_entries:
1416 entry = self.add_cfunction(base_entry.name, base_entry.type,
1417 base_entry.pos, adapt(base_entry.cname),
1418 base_entry.visibility, base_entry.func_modifiers)
1419 entry.is_inherited = 1
1422 class PropertyScope(Scope):
1423 # Scope holding the __get__, __set__ and __del__ methods for
1424 # a property of an extension type.
1425 #
1426 # parent_type PyExtensionType The type to which the property belongs
1428 def declare_pyfunction(self, name, pos):
1429 # Add an entry for a method.
1430 signature = get_property_accessor_signature(name)
1431 if signature:
1432 entry = self.declare(name, name, py_object_type, pos, 'private')
1433 entry.is_special = 1
1434 entry.signature = signature
1435 return entry
1436 else:
1437 error(pos, "Only __get__, __set__ and __del__ methods allowed "
1438 "in a property declaration")
1439 return None
1442 # Should this go elsewhere (and then get imported)?
1443 #------------------------------------------------------------------------------------
1445 classmethod_utility_code = Code.UtilityCode(
1446 proto = """
1447 #include "descrobject.h"
1448 static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
1449 """,
1450 impl = """
1451 static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
1452 /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
1453 static PyTypeObject *methoddescr_type = NULL;
1454 if (methoddescr_type == NULL) {
1455 PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
1456 if (!meth) return NULL;
1457 methoddescr_type = Py_TYPE(meth);
1458 Py_DECREF(meth);
1459 }
1460 if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
1461 PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
1462 #if PY_VERSION_HEX < 0x03020000
1463 PyTypeObject *d_type = descr->d_type;
1464 #else
1465 PyTypeObject *d_type = descr->d_common.d_type;
1466 #endif
1467 return PyDescr_NewClassMethod(d_type, descr->d_method);
1468 }
1469 else if (PyMethod_Check(method)) { /* python classes */
1470 return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
1471 }
1472 else if (PyCFunction_Check(method)) {
1473 return PyClassMethod_New(method);
1474 }
1475 PyErr_Format(PyExc_TypeError,
1476 "Class-level classmethod() can only be called on"
1477 "a method_descriptor or instance method.");
1478 return NULL;
1479 }
1480 """)
