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