Cython has moved to github.
cython-devel
view Cython/Compiler/Symtab.py @ 1241:b23f31007194
fix the declaration/initilization/cleanup of module global cdef Python objects
| author | Lisandro Dalcin <dalcinl@gmail.com> |
|---|---|
| date | Thu Oct 16 20:26:34 2008 -0300 (3 years ago) |
| parents | 234d7128643b |
| children | 303c79051806 |
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
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 __builtin__
18 try:
19 set
20 except NameError:
21 from sets import Set as set
23 possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
24 nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
26 class BufferAux:
27 writable_needed = False
29 def __init__(self, buffer_info_var, stridevars, shapevars,
30 suboffsetvars):
31 self.buffer_info_var = buffer_info_var
32 self.stridevars = stridevars
33 self.shapevars = shapevars
34 self.suboffsetvars = suboffsetvars
36 def __repr__(self):
37 return "<BufferAux %r>" % self.__dict__
39 class Entry:
40 # A symbol table entry in a Scope or ModuleNamespace.
41 #
42 # name string Python name of entity
43 # cname string C name of entity
44 # type PyrexType Type of entity
45 # doc string Doc string
46 # init string Initial value
47 # visibility 'private' or 'public' or 'extern'
48 # is_builtin boolean Is an entry in the Python builtins dict
49 # is_cglobal boolean Is a C global variable
50 # is_pyglobal boolean Is a Python module-level variable
51 # or class attribute during
52 # class construction
53 # is_member boolean Is an assigned class member
54 # is_variable boolean Is a variable
55 # is_cfunction boolean Is a C function
56 # is_cmethod boolean Is a C method of an extension type
57 # is_unbound_cmethod boolean Is an unbound C method of an extension type
58 # is_type boolean Is a type definition
59 # is_cclass boolean Is an extension class
60 # is_const boolean Is a constant
61 # is_property boolean Is a property of an extension type:
62 # doc_cname string or None C const holding the docstring
63 # getter_cname string C func for getting property
64 # setter_cname string C func for setting or deleting property
65 # is_self_arg boolean Is the "self" arg of an exttype method
66 # is_arg boolean Is the arg of a method
67 # is_local boolean Is a local variable
68 # in_closure boolean Is referenced in an inner scope
69 # is_readonly boolean Can't be assigned to
70 # func_cname string C func implementing Python func
71 # pos position Source position where declared
72 # namespace_cname string If is_pyglobal, the C variable
73 # holding its home namespace
74 # pymethdef_cname string PyMethodDef structure
75 # signature Signature Arg & return types for Python func
76 # init_to_none boolean True if initial value should be None
77 # as_variable Entry Alternative interpretation of extension
78 # type name or builtin C function as a variable
79 # xdecref_cleanup boolean Use Py_XDECREF for error cleanup
80 # in_cinclude boolean Suppress C declaration code
81 # enum_values [Entry] For enum types, list of values
82 # qualified_name string "modname.funcname" or "modname.classname"
83 # or "modname.classname.funcname"
84 # is_declared_generic boolean Is declared as PyObject * even though its
85 # type is an extension type
86 # as_module None Module scope, if a cimported module
87 # is_inherited boolean Is an inherited attribute of an extension type
88 # pystring_cname string C name of Python version of string literal
89 # is_interned boolean For string const entries, value is interned
90 # is_identifier boolean For string const entries, value is an identifier
91 # used boolean
92 # is_special boolean Is a special method or property accessor
93 # of an extension type
94 # defined_in_pxd boolean Is defined in a .pxd file (not just declared)
95 # api boolean Generate C API for C class or function
96 # utility_code string Utility code needed when this entry is used
97 #
98 # buffer_aux BufferAux or None Extra information needed for buffer variables
100 borrowed = 0
101 init = ""
102 visibility = 'private'
103 is_builtin = 0
104 is_cglobal = 0
105 is_pyglobal = 0
106 is_member = 0
107 is_variable = 0
108 is_cfunction = 0
109 is_cmethod = 0
110 is_unbound_cmethod = 0
111 is_type = 0
112 is_cclass = 0
113 is_const = 0
114 is_property = 0
115 doc_cname = None
116 getter_cname = None
117 setter_cname = None
118 is_self_arg = 0
119 is_arg = 0
120 is_local = 0
121 in_closure = 0
122 is_declared_generic = 0
123 is_readonly = 0
124 func_cname = None
125 doc = None
126 init_to_none = 0
127 as_variable = None
128 xdecref_cleanup = 0
129 in_cinclude = 0
130 as_module = None
131 is_inherited = 0
132 pystring_cname = None
133 is_identifier = 0
134 is_interned = 0
135 used = 0
136 is_special = 0
137 defined_in_pxd = 0
138 api = 0
139 utility_code = None
140 is_overridable = 0
141 buffer_aux = None
142 prev_entry = None
144 def __init__(self, name, cname, type, pos = None, init = None):
145 self.name = name
146 self.cname = cname
147 self.type = type
148 self.pos = pos
149 self.init = init
151 def redeclared(self, pos):
152 error(pos, "'%s' does not match previous declaration" % self.name)
153 error(self.pos, "Previous declaration is here")
155 class Scope:
156 # name string Unqualified name
157 # outer_scope Scope or None Enclosing scope
158 # entries {string : Entry} Python name to entry, non-types
159 # const_entries [Entry] Constant entries
160 # type_entries [Entry] Struct/union/enum/typedef/exttype entries
161 # sue_entries [Entry] Struct/union/enum entries
162 # arg_entries [Entry] Function argument entries
163 # var_entries [Entry] User-defined variable entries
164 # pyfunc_entries [Entry] Python function entries
165 # cfunc_entries [Entry] C function entries
166 # c_class_entries [Entry] All extension type entries
167 # temp_entries [Entry] Temporary variable entries
168 # free_temp_entries [Entry] Temp variables currently unused
169 # temp_counter integer Counter for naming temp vars
170 # cname_to_entry {string : Entry} Temp cname to entry mapping
171 # int_to_entry {int : Entry} Temp cname to entry mapping
172 # return_type PyrexType or None Return type of function owning scope
173 # is_py_class_scope boolean Is a Python class scope
174 # is_c_class_scope boolean Is an extension type scope
175 # scope_prefix string Disambiguator for C names
176 # in_cinclude boolean Suppress C declaration code
177 # qualified_name string "modname" or "modname.classname"
178 # pystring_entries [Entry] String const entries newly used as
179 # Python strings in this scope
180 # control_flow ControlFlow Used for keeping track of environment state
181 # nogil boolean In a nogil section
182 # directives dict Helper variable for the recursive
183 # analysis, contains directive values.
185 is_py_class_scope = 0
186 is_c_class_scope = 0
187 is_module_scope = 0
188 scope_prefix = ""
189 in_cinclude = 0
190 nogil = 0
191 directives = {}
193 temp_prefix = Naming.pyrex_prefix
195 def __init__(self, name, outer_scope, parent_scope):
196 # The outer_scope is the next scope in the lookup chain.
197 # The parent_scope is used to derive the qualified name of this scope.
198 self.name = name
199 self.outer_scope = outer_scope
200 self.parent_scope = parent_scope
201 mangled_name = "%d%s_" % (len(name), name)
202 qual_scope = self.qualifying_scope()
203 if qual_scope:
204 self.qualified_name = qual_scope.qualify_name(name)
205 self.scope_prefix = qual_scope.scope_prefix + mangled_name
206 else:
207 self.qualified_name = name
208 self.scope_prefix = mangled_name
209 self.entries = {}
210 self.const_entries = []
211 self.type_entries = []
212 self.sue_entries = []
213 self.arg_entries = []
214 self.var_entries = []
215 self.pyfunc_entries = []
216 self.cfunc_entries = []
217 self.c_class_entries = []
218 self.defined_c_classes = []
219 self.imported_c_classes = {}
220 self.temp_entries = []
221 self.free_temp_entries = []
222 #self.pending_temp_entries = [] # TEMPORARY
223 self.temp_counter = 1
224 self.cname_to_entry = {}
225 self.string_to_entry = {}
226 self.identifier_to_entry = {}
227 self.num_to_entry = {}
228 self.obj_to_entry = {}
229 self.pystring_entries = []
230 self.buffer_entries = []
231 self.control_flow = ControlFlow.LinearControlFlow()
233 def start_branching(self, pos):
234 self.control_flow = self.control_flow.start_branch(pos)
236 def next_branch(self, pos):
237 self.control_flow = self.control_flow.next_branch(pos)
239 def finish_branching(self, pos):
240 self.control_flow = self.control_flow.finish_branch(pos)
242 def __str__(self):
243 return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
245 def intern_identifier(self, name):
246 return self.global_scope().intern_identifier(name)
248 def qualifying_scope(self):
249 return self.parent_scope
251 def mangle(self, prefix, name = None):
252 if name:
253 return "%s%s%s" % (prefix, self.scope_prefix, name)
254 else:
255 return self.parent_scope.mangle(prefix, self.name)
257 def mangle_internal(self, name):
258 # Mangle an internal name so as not to clash with any
259 # user-defined name in this scope.
260 prefix = "%s%s_" % (Naming.pyrex_prefix, name)
261 return self.mangle(prefix)
262 #return self.parent_scope.mangle(prefix, self.name)
264 def global_scope(self):
265 # Return the module-level scope containing this scope.
266 return self.outer_scope.global_scope()
268 def builtin_scope(self):
269 # Return the module-level scope containing this scope.
270 return self.outer_scope.builtin_scope()
272 def declare(self, name, cname, type, pos, visibility):
273 # Create new entry, and add to dictionary if
274 # name is not None. Reports a warning if already
275 # declared.
276 if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
277 # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
278 warning(pos, "'%s' is a reserved name in C." % cname, -1)
279 dict = self.entries
280 if name and dict.has_key(name):
281 if visibility == 'extern':
282 warning(pos, "'%s' redeclared " % name, 0)
283 elif visibility != 'ignore':
284 error(pos, "'%s' redeclared " % name)
285 entry = Entry(name, cname, type, pos = pos)
286 entry.in_cinclude = self.in_cinclude
287 if name:
288 entry.qualified_name = self.qualify_name(name)
289 dict[name] = entry
290 entry.scope = self
291 entry.visibility = visibility
292 return entry
294 def qualify_name(self, name):
295 return "%s.%s" % (self.qualified_name, name)
297 def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
298 # Add an entry for a named constant.
299 if not cname:
300 if self.in_cinclude:
301 cname = name
302 else:
303 cname = self.mangle(Naming.enum_prefix, name)
304 entry = self.declare(name, cname, type, pos, visibility)
305 entry.is_const = 1
306 entry.value = value
307 return entry
309 def declare_type(self, name, type, pos,
310 cname = None, visibility = 'private', defining = 1):
311 # Add an entry for a type definition.
312 if not cname:
313 cname = name
314 entry = self.declare(name, cname, type, pos, visibility)
315 entry.is_type = 1
316 if defining:
317 self.type_entries.append(entry)
318 # here we would set as_variable to an object representing this type
319 return entry
321 def declare_typedef(self, name, base_type, pos, cname = None,
322 visibility = 'private'):
323 if not cname:
324 if self.in_cinclude or visibility == 'public':
325 cname = name
326 else:
327 cname = self.mangle(Naming.type_prefix, name)
328 type = PyrexTypes.CTypedefType(cname, base_type)
329 entry = self.declare_type(name, type, pos, cname, visibility)
330 type.qualified_name = entry.qualified_name
331 return entry
333 def declare_struct_or_union(self, name, kind, scope,
334 typedef_flag, pos, cname = None, visibility = 'private'):
335 # Add an entry for a struct or union definition.
336 if not cname:
337 if self.in_cinclude or visibility == 'public':
338 cname = name
339 else:
340 cname = self.mangle(Naming.type_prefix, name)
341 entry = self.lookup_here(name)
342 if not entry:
343 type = PyrexTypes.CStructOrUnionType(
344 name, kind, scope, typedef_flag, cname)
345 entry = self.declare_type(name, type, pos, cname,
346 visibility = visibility, defining = scope is not None)
347 self.sue_entries.append(entry)
348 else:
349 if not (entry.is_type and entry.type.is_struct_or_union
350 and entry.type.kind == kind):
351 warning(pos, "'%s' redeclared " % name, 0)
352 elif scope and entry.type.scope:
353 warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
354 else:
355 self.check_previous_typedef_flag(entry, typedef_flag, pos)
356 self.check_previous_visibility(entry, visibility, pos)
357 if scope:
358 entry.type.scope = scope
359 self.type_entries.append(entry)
360 if not scope and not entry.type.scope:
361 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
362 return entry
364 def check_previous_typedef_flag(self, entry, typedef_flag, pos):
365 if typedef_flag != entry.type.typedef_flag:
366 error(pos, "'%s' previously declared using '%s'" % (
367 entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
369 def check_previous_visibility(self, entry, visibility, pos):
370 if entry.visibility != visibility:
371 error(pos, "'%s' previously declared as '%s'" % (
372 entry.name, entry.visibility))
374 def declare_enum(self, name, pos, cname, typedef_flag,
375 visibility = 'private'):
376 if name:
377 if not cname:
378 if self.in_cinclude or visibility == 'public':
379 cname = name
380 else:
381 cname = self.mangle(Naming.type_prefix, name)
382 type = PyrexTypes.CEnumType(name, cname, typedef_flag)
383 else:
384 type = PyrexTypes.c_anon_enum_type
385 entry = self.declare_type(name, type, pos, cname = cname,
386 visibility = visibility)
387 entry.enum_values = []
388 self.sue_entries.append(entry)
389 return entry
391 def declare_var(self, name, type, pos,
392 cname = None, visibility = 'private', is_cdef = 0):
393 # Add an entry for a variable.
394 if not cname:
395 if visibility != 'private':
396 cname = name
397 else:
398 cname = self.mangle(Naming.var_prefix, name)
399 entry = self.declare(name, cname, type, pos, visibility)
400 entry.is_variable = 1
401 self.control_flow.set_state((), (name, 'initalized'), False)
402 return entry
404 def declare_builtin(self, name, pos):
405 return self.outer_scope.declare_builtin(name, pos)
407 def declare_pyfunction(self, name, pos):
408 # Add an entry for a Python function.
409 entry = self.lookup_here(name)
410 if entry and not entry.type.is_cfunction:
411 # This is legal Python, but for now will produce invalid C.
412 error(pos, "'%s' already declared" % name)
413 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
414 entry.signature = pyfunction_signature
415 self.pyfunc_entries.append(entry)
416 return entry
418 def register_pyfunction(self, entry):
419 self.pyfunc_entries.append(entry)
421 def declare_cfunction(self, name, type, pos,
422 cname = None, visibility = 'private', defining = 0, api = 0, in_pxd = 0):
423 # Add an entry for a C function.
424 entry = self.lookup_here(name)
425 if entry:
426 if visibility != 'private' and visibility != entry.visibility:
427 warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
428 if not entry.type.same_as(type):
429 if visibility == 'extern' and entry.visibility == 'extern':
430 warning(pos, "Function signature does not match previous declaration", 1)
431 entry.type = type
432 else:
433 error(pos, "Function signature does not match previous declaration")
434 else:
435 if not cname:
436 if api or visibility != 'private':
437 cname = name
438 else:
439 cname = self.mangle(Naming.func_prefix, name)
440 entry = self.add_cfunction(name, type, pos, cname, visibility)
441 entry.func_cname = cname
442 if in_pxd and visibility != 'extern':
443 entry.defined_in_pxd = 1
444 if api:
445 entry.api = 1
446 if not defining and not in_pxd and visibility != 'extern':
447 error(pos, "Non-extern C function '%s' declared but not defined" % name)
448 return entry
450 def add_cfunction(self, name, type, pos, cname, visibility):
451 # Add a C function entry without giving it a func_cname.
452 entry = self.declare(name, cname, type, pos, visibility)
453 entry.is_cfunction = 1
454 self.cfunc_entries.append(entry)
455 return entry
457 def find(self, name, pos):
458 # Look up name, report error if not found.
459 entry = self.lookup(name)
460 if entry:
461 return entry
462 else:
463 error(pos, "'%s' is not declared" % name)
465 def find_imported_module(self, path, pos):
466 # Look up qualified name, must be a module, report error if not found.
467 # Path is a list of names.
468 scope = self
469 for name in path:
470 entry = scope.find(name, pos)
471 if not entry:
472 return None
473 if entry.as_module:
474 scope = entry.as_module
475 else:
476 error(pos, "'%s' is not a cimported module" % scope.qualified_name)
477 return None
478 return scope
480 def lookup(self, name):
481 # Look up name in this scope or an enclosing one.
482 # Return None if not found.
483 return (self.lookup_here(name)
484 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
485 or None)
487 def lookup_from_inner(self, name):
488 # Look up name in this scope or an enclosing one.
489 # This is only called from enclosing scopes.
490 return (self.lookup_here(name)
491 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
492 or None)
494 def lookup_here(self, name):
495 # Look up in this scope only, return None if not found.
496 return self.entries.get(name, None)
498 def lookup_target(self, name):
499 # Look up name in this scope only. Declare as Python
500 # variable if not found.
501 entry = self.lookup_here(name)
502 if not entry:
503 entry = self.declare_var(name, py_object_type, None)
504 return entry
506 def lookup_type(self, name):
507 entry = self.lookup(name)
508 if entry and entry.is_type:
509 return entry.type
511 def add_string_const(self, value, identifier = False):
512 # Add an entry for a string constant.
513 if identifier:
514 cname = self.new_string_const_cname(value)
515 else:
516 cname = self.new_const_cname()
517 if value.is_unicode:
518 c_type = PyrexTypes.c_utf8_char_array_type
519 value = value.utf8encode()
520 else:
521 c_type = PyrexTypes.c_char_array_type
522 value = value.byteencode()
523 entry = Entry("", cname, c_type, init = value)
524 entry.used = 1
525 self.const_entries.append(entry)
526 return entry
528 def get_string_const(self, value, identifier = False):
529 # Get entry for string constant. Returns an existing
530 # one if possible, otherwise creates a new one.
531 genv = self.global_scope()
532 if identifier:
533 string_map = genv.identifier_to_entry
534 else:
535 string_map = genv.string_to_entry
536 entry = string_map.get(value)
537 if not entry:
538 entry = self.add_string_const(value, identifier)
539 entry.is_identifier = identifier
540 string_map[value] = entry
541 return entry
543 def add_py_string(self, entry, identifier = None):
544 # If not already done, allocate a C name for a Python version of
545 # a string literal, and add it to the list of Python strings to
546 # be created at module init time. If the string resembles a
547 # Python identifier, it will be interned.
548 if entry.pystring_cname:
549 return
550 value = entry.init
551 entry.pystring_cname = Naming.py_const_prefix + entry.cname[len(Naming.const_prefix):]
552 self.pystring_entries.append(entry)
553 self.global_scope().all_pystring_entries.append(entry)
554 if identifier or (identifier is None and possible_identifier(value)):
555 entry.is_interned = 1
556 self.global_scope().new_interned_string_entries.append(entry)
558 def add_py_num(self, value):
559 # Add an entry for an int constant.
560 cname = "%s%s" % (Naming.interned_num_prefix, value)
561 cname = cname.replace('-', 'neg_').replace('.','_')
562 entry = Entry("", cname, py_object_type, init = value)
563 entry.used = 1
564 entry.is_interned = 1
565 self.const_entries.append(entry)
566 self.interned_nums.append(entry)
567 return entry
569 def get_py_num(self, value, longness):
570 # Get entry for int constant. Returns an existing
571 # one if possible, otherwise creates a new one.
572 if longness or Utils.long_literal(value):
573 value += "L"
574 genv = self.global_scope()
575 entry = genv.num_to_entry.get(value)
576 if not entry:
577 entry = genv.add_py_num(value)
578 genv.num_to_entry[value] = entry
579 genv.pynum_entries.append(entry)
580 return entry
582 def get_py_obj(self, obj, c_prefix=''):
583 # Get entry for a generic constant. Returns an existing
584 # one if possible, otherwise creates a new one.
585 genv = self.global_scope()
586 entry = genv.obj_to_entry.get(obj)
587 if not entry:
588 entry = genv.add_py_num(obj, c_prefix)
589 genv.obj_to_entry[obj] = entry
590 return entry
592 def new_string_const_cname(self, value):
593 # Create a new globally-unique nice name for a string constant.
594 if len(value) < 20 and nice_identifier(value):
595 return "%s%s" % (Naming.const_prefix, value)
596 else:
597 return self.global_scope().new_const_cname()
599 def new_const_cname(self):
600 # Create a new globally-unique name for a constant.
601 return self.global_scope().new_const_cname()
603 def allocate_temp(self, type):
604 # Allocate a temporary variable of the given type from the
605 # free list if available, otherwise create a new one.
606 # Returns the cname of the variable.
607 for entry in self.free_temp_entries:
608 if entry.type == type:
609 self.free_temp_entries.remove(entry)
610 return entry.cname
611 n = self.temp_counter
612 self.temp_counter = n + 1
613 cname = "%s%d" % (self.temp_prefix, n)
614 entry = Entry("", cname, type)
615 entry.used = 1
616 if type.is_pyobject or type == PyrexTypes.c_py_ssize_t_type:
617 entry.init = "0"
618 self.cname_to_entry[entry.cname] = entry
619 self.temp_entries.append(entry)
620 return entry.cname
622 def allocate_temp_pyobject(self):
623 # Allocate a temporary PyObject variable.
624 return self.allocate_temp(py_object_type)
626 def release_temp(self, cname):
627 # Release a temporary variable for re-use.
628 if not cname: # can happen when type of an expr is void
629 return
630 entry = self.cname_to_entry[cname]
631 if entry in self.free_temp_entries:
632 raise InternalError("Temporary variable %s released more than once"
633 % cname)
634 self.free_temp_entries.append(entry)
636 def temps_in_use(self):
637 # Return a new list of temp entries currently in use.
638 return [entry for entry in self.temp_entries
639 if entry not in self.free_temp_entries]
641 def use_utility_code(self, new_code, name=None):
642 self.global_scope().use_utility_code(new_code, name)
644 def generate_library_function_declarations(self, code):
645 # Generate extern decls for C library funcs used.
646 pass
648 def defines_any(self, names):
649 # Test whether any of the given names are
650 # defined in this scope.
651 for name in names:
652 if name in self.entries:
653 return 1
654 return 0
656 class PreImportScope(Scope):
658 namespace_cname = Naming.preimport_cname
660 def __init__(self):
661 Scope.__init__(self, Options.pre_import, None, None)
663 def declare_builtin(self, name, pos):
664 entry = self.declare(name, name, py_object_type, pos, 'private')
665 entry.is_variable = True
666 entry.is_pyglobal = True
667 return entry
670 class BuiltinScope(Scope):
671 # The builtin namespace.
673 def __init__(self):
674 if Options.pre_import is None:
675 Scope.__init__(self, "__builtin__", None, None)
676 else:
677 Scope.__init__(self, "__builtin__", PreImportScope(), None)
678 self.type_names = {}
680 for name, definition in self.builtin_entries.iteritems():
681 cname, type = definition
682 self.declare_var(name, type, None, cname)
684 def declare_builtin(self, name, pos):
685 if not hasattr(__builtin__, name):
686 if self.outer_scope is not None:
687 return self.outer_scope.declare_builtin(name, pos)
688 else:
689 error(pos, "undeclared name not builtin: %s"%name)
691 def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
692 utility_code = None):
693 # If python_equiv == "*", the Python equivalent has the same name
694 # as the entry, otherwise it has the name specified by python_equiv.
695 name = EncodedString(name)
696 entry = self.declare_cfunction(name, type, None, cname, visibility='extern')
697 entry.utility_code = utility_code
698 if python_equiv:
699 if python_equiv == "*":
700 python_equiv = name
701 else:
702 python_equiv = EncodedString(python_equiv)
703 var_entry = Entry(python_equiv, python_equiv, py_object_type)
704 var_entry.is_variable = 1
705 var_entry.is_builtin = 1
706 entry.as_variable = var_entry
707 return entry
709 def declare_builtin_type(self, name, cname):
710 name = EncodedString(name)
711 type = PyrexTypes.BuiltinObjectType(name, cname)
712 type.set_scope(CClassScope(name, outer_scope=None, visibility='extern'))
713 self.type_names[name] = 1
714 entry = self.declare_type(name, type, None, visibility='extern')
716 var_entry = Entry(name = entry.name,
717 type = self.lookup('type').type, # make sure "type" is the first type declared...
718 pos = entry.pos,
719 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
720 var_entry.is_variable = 1
721 var_entry.is_cglobal = 1
722 var_entry.is_readonly = 1
723 entry.as_variable = var_entry
725 return type
727 def builtin_scope(self):
728 return self
730 builtin_entries = {
732 "type": ["((PyObject*)&PyType_Type)", py_object_type],
734 "bool": ["((PyObject*)&PyBool_Type)", py_object_type],
735 "int": ["((PyObject*)&PyInt_Type)", py_object_type],
736 "long": ["((PyObject*)&PyLong_Type)", py_object_type],
737 "float": ["((PyObject*)&PyFloat_Type)", py_object_type],
738 "complex":["((PyObject*)&PyComplex_Type)", py_object_type],
740 "bytes": ["((PyObject*)&PyBytes_Type)", py_object_type],
741 "str": ["((PyObject*)&PyString_Type)", py_object_type],
742 "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type],
744 "tuple": ["((PyObject*)&PyTuple_Type)", py_object_type],
745 "list": ["((PyObject*)&PyList_Type)", py_object_type],
746 "dict": ["((PyObject*)&PyDict_Type)", py_object_type],
747 "set": ["((PyObject*)&PySet_Type)", py_object_type],
748 "frozenset": ["((PyObject*)&PyFrozenSet_Type)", py_object_type],
750 "slice": ["((PyObject*)&PySlice_Type)", py_object_type],
751 "file": ["((PyObject*)&PyFile_Type)", py_object_type],
753 "None": ["Py_None", py_object_type],
754 "False": ["Py_False", py_object_type],
755 "True": ["Py_True", py_object_type],
756 }
758 const_counter = 1 # As a temporary solution for compiling code in pxds
760 class ModuleScope(Scope):
761 # module_name string Python name of the module
762 # module_cname string C name of Python module object
763 # #module_dict_cname string C name of module dict object
764 # method_table_cname string C name of method table
765 # doc string Module doc string
766 # doc_cname string C name of module doc string
767 # const_counter integer Counter for naming constants (PS: MOVED TO GLOBAL)
768 # utility_code_list [((string, string), string)] Queuing utility codes for forwarding to Code.py
769 # default_entries [Entry] Function argument default entries
770 # python_include_files [string] Standard Python headers to be included
771 # include_files [string] Other C headers to be included
772 # string_to_entry {string : Entry} Map string const to entry
773 # identifier_to_entry {string : Entry} Map identifier string const to entry
774 # context Context
775 # parent_module Scope Parent in the import namespace
776 # module_entries {string : Entry} For cimport statements
777 # type_names {string : 1} Set of type names (used during parsing)
778 # included_files [string] Cython sources included with 'include'
779 # pxd_file_loaded boolean Corresponding .pxd file has been processed
780 # cimported_modules [ModuleScope] Modules imported with cimport
781 # new_interned_string_entries [Entry] New interned strings waiting to be declared
782 # interned_nums [int/long] Interned numeric constants
783 # all_pystring_entries [Entry] Python string consts from all scopes
784 # types_imported {PyrexType : 1} Set of types for which import code generated
785 # has_import_star boolean Module contains import *
787 is_module_scope = 1
788 has_import_star = 0
790 def __init__(self, name, parent_module, context):
791 self.parent_module = parent_module
792 outer_scope = context.find_submodule("__builtin__")
793 Scope.__init__(self, name, outer_scope, parent_module)
794 self.module_name = name
795 self.context = context
796 self.module_cname = Naming.module_cname
797 self.module_dict_cname = Naming.moddict_cname
798 self.method_table_cname = Naming.methtable_cname
799 self.doc = ""
800 self.doc_cname = Naming.moddoc_cname
801 self.utility_code_list = []
802 self.default_entries = []
803 self.module_entries = {}
804 self.python_include_files = ["Python.h", "structmember.h"]
805 self.include_files = []
806 self.type_names = dict(outer_scope.type_names)
807 self.pxd_file_loaded = 0
808 self.cimported_modules = []
809 self.new_interned_string_entries = []
810 self.interned_nums = []
811 self.interned_objs = []
812 self.all_pystring_entries = []
813 self.types_imported = {}
814 self.included_files = []
815 self.pynum_entries = []
816 self.has_extern_class = 0
817 self.cached_builtins = []
818 self.undeclared_cached_builtins = []
819 self.namespace_cname = self.module_cname
821 def qualifying_scope(self):
822 return self.parent_module
824 def global_scope(self):
825 return self
827 def declare_builtin(self, name, pos):
828 if not hasattr(__builtin__, name):
829 if self.has_import_star:
830 entry = self.declare_var(name, py_object_type, pos)
831 return entry
832 elif self.outer_scope is not None:
833 return self.outer_scope.declare_builtin(name, pos)
834 else:
835 error(pos, "undeclared name not builtin: %s"%name)
836 if Options.cache_builtins:
837 for entry in self.cached_builtins:
838 if entry.name == name:
839 return entry
840 entry = self.declare(None, None, py_object_type, pos, 'private')
841 if Options.cache_builtins:
842 entry.is_builtin = 1
843 entry.is_const = 1
844 entry.name = name
845 entry.cname = Naming.builtin_prefix + name
846 self.cached_builtins.append(entry)
847 self.undeclared_cached_builtins.append(entry)
848 else:
849 entry.is_builtin = 1
850 return entry
852 def intern_identifier(self, name):
853 string_entry = self.get_string_const(name, identifier = True)
854 self.add_py_string(string_entry, identifier = 1)
855 return string_entry.pystring_cname
857 def find_module(self, module_name, pos):
858 # Find a module in the import namespace, interpreting
859 # relative imports relative to this module's parent.
860 # Finds and parses the module's .pxd file if the module
861 # has not been referenced before.
862 return self.global_scope().context.find_module(
863 module_name, relative_to = self.parent_module, pos = pos)
865 def find_submodule(self, name):
866 # Find and return scope for a submodule of this module,
867 # creating a new empty one if necessary. Doesn't parse .pxd.
868 scope = self.lookup_submodule(name)
869 if not scope:
870 scope = ModuleScope(name,
871 parent_module = self, context = self.context)
872 self.module_entries[name] = scope
873 return scope
875 def lookup_submodule(self, name):
876 # Return scope for submodule of this module, or None.
877 return self.module_entries.get(name, None)
879 def add_include_file(self, filename):
880 if filename not in self.python_include_files \
881 and filename not in self.include_files:
882 self.include_files.append(filename)
884 def add_imported_module(self, scope):
885 if scope not in self.cimported_modules:
886 self.cimported_modules.append(scope)
888 def add_imported_entry(self, name, entry, pos):
889 if entry not in self.entries:
890 self.entries[name] = entry
891 else:
892 warning(pos, "'%s' redeclared " % name, 0)
894 def declare_module(self, name, scope, pos):
895 # Declare a cimported module. This is represented as a
896 # Python module-level variable entry with a module
897 # scope attached to it. Reports an error and returns
898 # None if previously declared as something else.
899 entry = self.lookup_here(name)
900 if entry:
901 if entry.is_pyglobal and entry.as_module is scope:
902 return entry # Already declared as the same module
903 if not (entry.is_pyglobal and not entry.as_module):
904 # SAGE -- I put this here so Pyrex
905 # cimport's work across directories.
906 # Currently it tries to multiply define
907 # every module appearing in an import list.
908 # It shouldn't be an error for a module
909 # name to appear again, and indeed the generated
910 # code compiles fine.
911 return entry
912 warning(pos, "'%s' redeclared " % name, 0)
913 return None
914 else:
915 entry = self.declare_var(name, py_object_type, pos)
916 entry.as_module = scope
917 self.cimported_modules.append(scope)
918 return entry
920 def declare_var(self, name, type, pos,
921 cname = None, visibility = 'private', is_cdef = 0):
922 # Add an entry for a global variable. If it is a Python
923 # object type, and not declared with cdef, it will live
924 # in the module dictionary, otherwise it will be a C
925 # global variable.
926 entry = Scope.declare_var(self, name, type, pos,
927 cname, visibility, is_cdef)
928 if not visibility in ('private', 'public', 'extern'):
929 error(pos, "Module-level variable cannot be declared %s" % visibility)
930 if not is_cdef:
931 if not (type.is_pyobject and not type.is_extension_type):
932 raise InternalError(
933 "Non-cdef global variable is not a generic Python object")
934 entry.is_pyglobal = 1
935 else:
936 entry.is_cglobal = 1
937 if entry.type.is_pyobject:
938 entry.init = 0
939 self.var_entries.append(entry)
940 return entry
942 def declare_global(self, name, pos):
943 entry = self.lookup_here(name)
944 if not entry:
945 self.declare_var(name, py_object_type, pos)
947 def add_default_value(self, type):
948 # Add an entry for holding a function argument
949 # default value.
950 cname = self.new_const_cname()
951 entry = Entry("", cname, type)
952 self.default_entries.append(entry)
953 return entry
955 def new_const_cname(self):
956 global const_counter
957 # Create a new globally-unique name for a constant.
958 prefix=''
959 n = const_counter
960 const_counter = n + 1
961 return "%s%s%d" % (Naming.const_prefix, prefix, n)
963 def use_utility_code(self, new_code, name=None):
964 if new_code is not None:
965 self.utility_code_list.append((new_code, name))
967 def declare_c_class(self, name, pos, defining = 0, implementing = 0,
968 module_name = None, base_type = None, objstruct_cname = None,
969 typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
970 buffer_defaults = None):
971 #
972 # Look for previous declaration as a type
973 #
974 entry = self.lookup_here(name)
975 if entry:
976 type = entry.type
977 if not (entry.is_type and type.is_extension_type):
978 entry = None # Will cause redeclaration and produce an error
979 else:
980 scope = type.scope
981 if typedef_flag and (not scope or scope.defined):
982 self.check_previous_typedef_flag(entry, typedef_flag, pos)
983 if (scope and scope.defined) or (base_type and type.base_type):
984 if base_type and base_type is not type.base_type:
985 error(pos, "Base type does not match previous declaration")
986 if base_type and not type.base_type:
987 type.base_type = base_type
988 #
989 # Make a new entry if needed
990 #
991 if not entry:
992 type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type)
993 type.pos = pos
994 type.buffer_defaults = buffer_defaults
995 if visibility == 'extern':
996 type.module_name = module_name
997 else:
998 type.module_name = self.qualified_name
999 type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1000 entry = self.declare_type(name, type, pos, visibility = visibility,
1001 defining = 0)
1002 entry.is_cclass = True
1003 if objstruct_cname:
1004 type.objstruct_cname = objstruct_cname
1005 elif not entry.in_cinclude:
1006 type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
1007 else:
1008 error(entry.pos,
1009 "Object name required for 'public' or 'extern' C class")
1010 self.attach_var_entry_to_c_class(entry)
1011 self.c_class_entries.append(entry)
1012 #
1013 # Check for re-definition and create scope if needed
1014 #
1015 if not type.scope:
1016 if defining or implementing:
1017 scope = CClassScope(name = name, outer_scope = self,
1018 visibility = visibility)
1019 if base_type:
1020 scope.declare_inherited_c_attributes(base_type.scope)
1021 type.set_scope(scope)
1022 self.type_entries.append(entry)
1023 else:
1024 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
1025 else:
1026 if defining and type.scope.defined:
1027 error(pos, "C class '%s' already defined" % name)
1028 elif implementing and type.scope.implemented:
1029 error(pos, "C class '%s' already implemented" % name)
1030 #
1031 # Fill in options, checking for compatibility with any previous declaration
1032 #
1033 if defining:
1034 entry.defined_in_pxd = 1
1035 if implementing: # So that filenames in runtime exceptions refer to
1036 entry.pos = pos # the .pyx file and not the .pxd file
1037 if visibility != 'private' and entry.visibility != visibility:
1038 error(pos, "Class '%s' previously declared as '%s'"
1039 % (name, entry.visibility))
1040 if api:
1041 entry.api = 1
1042 if objstruct_cname:
1043 if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
1044 error(pos, "Object struct name differs from previous declaration")
1045 type.objstruct_cname = objstruct_cname
1046 if typeobj_cname:
1047 if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
1048 error(pos, "Type object name differs from previous declaration")
1049 type.typeobj_cname = typeobj_cname
1050 #
1051 # Return new or existing entry
1052 #
1053 return entry
1055 def check_for_illegal_incomplete_ctypedef(self, typedef_flag, pos):
1056 if typedef_flag and not self.in_cinclude:
1057 error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
1059 def allocate_vtable_names(self, entry):
1060 # If extension type has a vtable, allocate vtable struct and
1061 # slot names for it.
1062 type = entry.type
1063 if type.base_type and type.base_type.vtabslot_cname:
1064 #print "...allocating vtabslot_cname because base type has one" ###
1065 type.vtabslot_cname = "%s.%s" % (
1066 Naming.obj_base_cname, type.base_type.vtabslot_cname)
1067 elif type.scope and type.scope.cfunc_entries:
1068 #print "...allocating vtabslot_cname because there are C methods" ###
1069 type.vtabslot_cname = Naming.vtabslot_cname
1070 if type.vtabslot_cname:
1071 #print "...allocating other vtable related cnames" ###
1072 type.vtabstruct_cname = self.mangle(Naming.vtabstruct_prefix, entry.name)
1073 type.vtabptr_cname = self.mangle(Naming.vtabptr_prefix, entry.name)
1075 def check_c_classes(self):
1076 # Performs post-analysis checking and finishing up of extension types
1077 # being implemented in this module. This is called only for the main
1078 # .pyx file scope, not for cimported .pxd scopes.
1079 #
1080 # Checks all extension types declared in this scope to
1081 # make sure that:
1082 #
1083 # * The extension type is implemented
1084 # * All required object and type names have been specified or generated
1085 # * All non-inherited C methods are implemented
1086 #
1087 # Also allocates a name for the vtable if needed.
1088 #
1089 debug_check_c_classes = 0
1090 if debug_check_c_classes:
1091 print("Scope.check_c_classes: checking scope " + self.qualified_name)
1092 for entry in self.c_class_entries:
1093 if debug_check_c_classes:
1094 print("...entry %s %s" % (entry.name, entry))
1095 print("......type = " + entry.type)
1096 print("......visibility = " + entry.visibility)
1097 type = entry.type
1098 name = entry.name
1099 visibility = entry.visibility
1100 # Check defined
1101 if not type.scope:
1102 error(entry.pos, "C class '%s' is declared but not defined" % name)
1103 # Generate typeobj_cname
1104 if visibility != 'extern' and not type.typeobj_cname:
1105 type.typeobj_cname = self.mangle(Naming.typeobj_prefix, name)
1106 ## Generate typeptr_cname
1107 #type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1108 # Check C methods defined
1109 if type.scope:
1110 for method_entry in type.scope.cfunc_entries:
1111 if not method_entry.is_inherited and not method_entry.func_cname:
1112 error(method_entry.pos, "C method '%s' is declared but not defined" %
1113 method_entry.name)
1114 # Allocate vtable name if necessary
1115 if type.vtabslot_cname:
1116 #print "ModuleScope.check_c_classes: allocating vtable cname for", self ###
1117 type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name)
1119 def attach_var_entry_to_c_class(self, entry):
1120 # The name of an extension class has to serve as both a type
1121 # name and a variable name holding the type object. It is
1122 # represented in the symbol table by a type entry with a
1123 # variable entry attached to it. For the variable entry,
1124 # we use a read-only C global variable whose name is an
1125 # expression that refers to the type object.
1126 import Builtin
1127 var_entry = Entry(name = entry.name,
1128 type = Builtin.type_type,
1129 pos = entry.pos,
1130 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
1131 var_entry.is_variable = 1
1132 var_entry.is_cglobal = 1
1133 var_entry.is_readonly = 1
1134 entry.as_variable = var_entry
1136 class LocalScope(Scope):
1138 def __init__(self, name, outer_scope):
1139 Scope.__init__(self, name, outer_scope, outer_scope)
1141 def mangle(self, prefix, name):
1142 return prefix + name
1144 def declare_arg(self, name, type, pos):
1145 # Add an entry for an argument of a function.
1146 cname = self.mangle(Naming.var_prefix, name)
1147 entry = self.declare(name, cname, type, pos, 'private')
1148 entry.is_variable = 1
1149 if type.is_pyobject:
1150 entry.init = "0"
1151 entry.is_arg = 1
1152 #entry.borrowed = 1 # Not using borrowed arg refs for now
1153 self.arg_entries.append(entry)
1154 self.control_flow.set_state((), (name, 'source'), 'arg')
1155 return entry
1157 def declare_var(self, name, type, pos,
1158 cname = None, visibility = 'private', is_cdef = 0):
1159 # Add an entry for a local variable.
1160 if visibility in ('public', 'readonly'):
1161 error(pos, "Local variable cannot be declared %s" % visibility)
1162 entry = Scope.declare_var(self, name, type, pos,
1163 cname, visibility, is_cdef)
1164 if type.is_pyobject and not Options.init_local_none:
1165 entry.init = "0"
1166 entry.init_to_none = type.is_pyobject and Options.init_local_none
1167 entry.is_local = 1
1168 self.var_entries.append(entry)
1169 return entry
1171 def declare_global(self, name, pos):
1172 # Pull entry from global scope into local scope.
1173 if self.lookup_here(name):
1174 warning(pos, "'%s' redeclared ", 0)
1175 else:
1176 entry = self.global_scope().lookup_target(name)
1177 self.entries[name] = entry
1179 def lookup_from_inner(self, name):
1180 entry = self.lookup_here(name)
1181 if entry:
1182 entry.in_closure = 1
1183 return entry
1184 else:
1185 return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
1187 def mangle_closure_cnames(self, scope_var):
1188 for entry in self.entries.values():
1189 if entry.in_closure:
1190 if not hasattr(entry, 'orig_cname'):
1191 entry.orig_cname = entry.cname
1192 entry.cname = scope_var + "->" + entry.cname
1195 class GeneratorLocalScope(LocalScope):
1197 temp_prefix = Naming.cur_scope_cname + "->" + LocalScope.temp_prefix
1199 def mangle_closure_cnames(self, scope_var):
1200 for entry in self.entries.values() + self.temp_entries:
1201 entry.in_closure = 1
1202 LocalScope.mangle_closure_cnames(self, scope_var)
1204 # def mangle(self, prefix, name):
1205 # return "%s->%s" % (Naming.scope_obj_cname, name)
1207 class StructOrUnionScope(Scope):
1208 # Namespace of a C struct or union.
1210 def __init__(self, name="?"):
1211 Scope.__init__(self, name, None, None)
1213 def declare_var(self, name, type, pos,
1214 cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
1215 # Add an entry for an attribute.
1216 if not cname:
1217 cname = name
1218 if type.is_cfunction:
1219 type = PyrexTypes.CPtrType(type)
1220 entry = self.declare(name, cname, type, pos, visibility)
1221 entry.is_variable = 1
1222 self.var_entries.append(entry)
1223 if type.is_pyobject and not allow_pyobject:
1224 error(pos,
1225 "C struct/union member cannot be a Python object")
1226 if visibility != 'private':
1227 error(pos,
1228 "C struct/union member cannot be declared %s" % visibility)
1229 return entry
1231 def declare_cfunction(self, name, type, pos,
1232 cname = None, visibility = 'private', defining = 0, api = 0, in_pxd = 0):
1233 self.declare_var(name, type, pos, cname, visibility)
1235 class ClassScope(Scope):
1236 # Abstract base class for namespace of
1237 # Python class or extension type.
1238 #
1239 # class_name string Pyrex name of the class
1240 # scope_prefix string Additional prefix for names
1241 # declared in the class
1242 # doc string or None Doc string
1244 def __init__(self, name, outer_scope):
1245 Scope.__init__(self, name, outer_scope, outer_scope)
1246 self.class_name = name
1247 self.doc = None
1249 def add_string_const(self, value, identifier = False):
1250 return self.outer_scope.add_string_const(value, identifier)
1252 def lookup(self, name):
1253 if name == "classmethod":
1254 # We don't want to use the builtin classmethod here 'cause it won't do the
1255 # right thing in this scope (as the class memebers aren't still functions).
1256 # Don't want to add a cfunction to this scope 'cause that would mess with
1257 # the type definition, so we just return the right entry.
1258 self.use_utility_code(classmethod_utility_code)
1259 entry = Entry(
1260 "classmethod",
1261 "__Pyx_Method_ClassMethod",
1262 PyrexTypes.CFuncType(
1263 py_object_type,
1264 [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0))
1265 entry.is_cfunction = 1
1266 return entry
1267 else:
1268 return Scope.lookup(self, name)
1271 class PyClassScope(ClassScope):
1272 # Namespace of a Python class.
1273 #
1274 # class_dict_cname string C variable holding class dict
1275 # class_obj_cname string C variable holding class object
1277 is_py_class_scope = 1
1279 def declare_var(self, name, type, pos,
1280 cname = None, visibility = 'private', is_cdef = 0):
1281 # Add an entry for a class attribute.
1282 entry = Scope.declare_var(self, name, type, pos,
1283 cname, visibility, is_cdef)
1284 entry.is_pyglobal = 1
1285 return entry
1287 def allocate_temp(self, type):
1288 return self.outer_scope.allocate_temp(type)
1290 def release_temp(self, cname):
1291 self.outer_scope.release_temp(cname)
1293 #def recycle_pending_temps(self):
1294 # self.outer_scope.recycle_pending_temps()
1296 def add_default_value(self, type):
1297 return self.outer_scope.add_default_value(type)
1300 class CClassScope(ClassScope):
1301 # Namespace of an extension type.
1302 #
1303 # parent_type CClassType
1304 # #typeobj_cname string or None
1305 # #objstruct_cname string
1306 # method_table_cname string
1307 # member_table_cname string
1308 # getset_table_cname string
1309 # has_pyobject_attrs boolean Any PyObject attributes?
1310 # public_attr_entries boolean public/readonly attrs
1311 # property_entries [Entry]
1312 # defined boolean Defined in .pxd file
1313 # implemented boolean Defined in .pyx file
1314 # inherited_var_entries [Entry] Adapted var entries from base class
1316 is_c_class_scope = 1
1318 def __init__(self, name, outer_scope, visibility):
1319 ClassScope.__init__(self, name, outer_scope)
1320 if visibility != 'extern':
1321 self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
1322 self.member_table_cname = outer_scope.mangle(Naming.memtab_prefix, name)
1323 self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
1324 self.has_pyobject_attrs = 0
1325 self.public_attr_entries = []
1326 self.property_entries = []
1327 self.inherited_var_entries = []
1328 self.defined = 0
1329 self.implemented = 0
1331 def needs_gc(self):
1332 # If the type or any of its base types have Python-valued
1333 # C attributes, then it needs to participate in GC.
1334 return self.has_pyobject_attrs or \
1335 (self.parent_type.base_type and \
1336 self.parent_type.base_type.scope.needs_gc())
1338 def declare_var(self, name, type, pos,
1339 cname = None, visibility = 'private', is_cdef = 0):
1340 if is_cdef:
1341 # Add an entry for an attribute.
1342 if self.defined:
1343 error(pos,
1344 "C attributes cannot be added in implementation part of"
1345 " extension type")
1346 if get_special_method_signature(name):
1347 error(pos,
1348 "The name '%s' is reserved for a special method."
1349 % name)
1350 if not cname:
1351 cname = name
1352 entry = self.declare(name, cname, type, pos, visibility)
1353 entry.is_variable = 1
1354 self.var_entries.append(entry)
1355 if type.is_pyobject:
1356 self.has_pyobject_attrs = 1
1357 if visibility not in ('private', 'public', 'readonly'):
1358 error(pos,
1359 "Attribute of extension type cannot be declared %s" % visibility)
1360 if visibility in ('public', 'readonly'):
1361 if type.pymemberdef_typecode:
1362 self.public_attr_entries.append(entry)
1363 if name == "__weakref__":
1364 error(pos, "Special attribute __weakref__ cannot be exposed to Python")
1365 else:
1366 error(pos,
1367 "C attribute of type '%s' cannot be accessed from Python" % type)
1368 if visibility == 'public' and type.is_extension_type:
1369 error(pos,
1370 "Non-generic Python attribute cannot be exposed for writing from Python")
1371 return entry
1372 else:
1373 # Add an entry for a class attribute.
1374 entry = Scope.declare_var(self, name, type, pos,
1375 cname, visibility, is_cdef)
1376 entry.is_member = 1
1377 entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
1378 # I keep it in for now. is_member should be enough
1379 # later on
1380 self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
1381 entry.interned_cname = self.intern_identifier(name)
1382 return entry
1385 def declare_pyfunction(self, name, pos):
1386 # Add an entry for a method.
1387 if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
1388 error(pos, "Special method %s must be implemented via __richcmp__" % name)
1389 if name == "__new__":
1390 warning(pos, "__new__ method of extension type will change semantics "
1391 "in a future version of Pyrex and Cython. Use __cinit__ instead.")
1392 name = EncodedString("__cinit__")
1393 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
1394 special_sig = get_special_method_signature(name)
1395 if special_sig:
1396 # Special methods get put in the method table with a particular
1397 # signature declared in advance.
1398 entry.signature = special_sig
1399 entry.is_special = 1
1400 else:
1401 entry.signature = pymethod_signature
1402 entry.is_special = 0
1404 self.pyfunc_entries.append(entry)
1405 return entry
1407 def lookup_here(self, name):
1408 if name == "__new__":
1409 name = EncodedString("__cinit__")
1410 return ClassScope.lookup_here(self, name)
1412 def declare_cfunction(self, name, type, pos,
1413 cname = None, visibility = 'private', defining = 0, api = 0, in_pxd = 0):
1414 if get_special_method_signature(name):
1415 error(pos, "Special methods must be declared with 'def', not 'cdef'")
1416 args = type.args
1417 if not args:
1418 error(pos, "C method has no self argument")
1419 elif not args[0].type.same_as(self.parent_type):
1420 error(pos, "Self argument of C method does not match parent type")
1421 entry = self.lookup_here(name)
1422 if entry:
1423 if not entry.is_cfunction:
1424 warning(pos, "'%s' redeclared " % name, 0)
1425 else:
1426 if defining and entry.func_cname:
1427 error(pos, "'%s' already defined" % name)
1428 #print "CClassScope.declare_cfunction: checking signature" ###
1429 if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1430 pass
1431 elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1432 entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore')
1433 defining = 1
1434 else:
1435 error(pos, "Signature not compatible with previous declaration")
1436 error(entry.pos, "Previous declaration is here")
1437 else:
1438 if self.defined:
1439 error(pos,
1440 "C method '%s' not previously declared in definition part of"
1441 " extension type" % name)
1442 entry = self.add_cfunction(name, type, pos, cname or name, visibility)
1443 if defining:
1444 entry.func_cname = self.mangle(Naming.func_prefix, name)
1445 return entry
1447 def add_cfunction(self, name, type, pos, cname, visibility):
1448 # Add a cfunction entry without giving it a func_cname.
1449 prev_entry = self.lookup_here(name)
1450 entry = ClassScope.add_cfunction(self, name, type, pos, cname, visibility)
1451 entry.is_cmethod = 1
1452 entry.prev_entry = prev_entry
1453 return entry
1455 def declare_property(self, name, doc, pos):
1456 entry = self.lookup_here(name)
1457 if entry is None:
1458 entry = self.declare(name, name, py_object_type, pos, 'private')
1459 entry.is_property = 1
1460 entry.doc = doc
1461 entry.scope = PropertyScope(name,
1462 outer_scope = self.global_scope(), parent_scope = self)
1463 entry.scope.parent_type = self.parent_type
1464 self.property_entries.append(entry)
1465 return entry
1467 def declare_inherited_c_attributes(self, base_scope):
1468 # Declare entries for all the C attributes of an
1469 # inherited type, with cnames modified appropriately
1470 # to work with this type.
1471 def adapt(cname):
1472 return "%s.%s" % (Naming.obj_base_cname, base_entry.cname)
1473 for base_entry in \
1474 base_scope.inherited_var_entries + base_scope.var_entries:
1475 entry = self.declare(base_entry.name, adapt(base_entry.cname),
1476 base_entry.type, None, 'private')
1477 entry.is_variable = 1
1478 self.inherited_var_entries.append(entry)
1479 for base_entry in base_scope.cfunc_entries:
1480 entry = self.add_cfunction(base_entry.name, base_entry.type,
1481 base_entry.pos, adapt(base_entry.cname), base_entry.visibility)
1482 entry.is_inherited = 1
1484 def allocate_temp(self, type):
1485 return Scope.allocate_temp(self.global_scope(), type)
1487 def release_temp(self, cname):
1488 return Scope.release_temp(self.global_scope(), cname)
1491 class PropertyScope(Scope):
1492 # Scope holding the __get__, __set__ and __del__ methods for
1493 # a property of an extension type.
1494 #
1495 # parent_type PyExtensionType The type to which the property belongs
1497 def declare_pyfunction(self, name, pos):
1498 # Add an entry for a method.
1499 signature = get_property_accessor_signature(name)
1500 if signature:
1501 entry = self.declare(name, name, py_object_type, pos, 'private')
1502 entry.is_special = 1
1503 entry.signature = signature
1504 return entry
1505 else:
1506 error(pos, "Only __get__, __set__ and __del__ methods allowed "
1507 "in a property declaration")
1508 return None
1511 # Should this go elsewhere (and then get imported)?
1512 #------------------------------------------------------------------------------------
1514 classmethod_utility_code = [
1515 """
1516 #include "descrobject.h"
1517 static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
1518 ""","""
1519 static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
1520 /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
1521 /* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */
1522 if (strcmp(Py_TYPE(method)->tp_name, "method_descriptor") == 0) { /* cdef classes */
1523 PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
1524 return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
1525 }
1526 else if (PyMethod_Check(method)) { /* python classes */
1527 return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
1528 }
1529 else if (PyCFunction_Check(method)) {
1530 return PyClassMethod_New(method);
1531 }
1532 PyErr_Format(PyExc_TypeError, "Class-level classmethod() can only be called on a method_descriptor or instance method.");
1533 return NULL;
1534 }
1535 """
1536 ]
