Cython has moved to github.

cython-devel

view Cython/Compiler/Symtab.py @ 903:6a8548429322

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