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