Cython has moved to github.

cython-devel

view Cython/Compiler/Symtab.py @ 2118:97069bd04411

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