Cython has moved to github.

cython-devel

view Cython/Compiler/Symtab.py @ 3091:1a2e04bc1395

remove dependency on structmember.h
author Lisandro Dalcin <dalcinl@gmail.com>
date Thu Mar 11 17:21:13 2010 -0300 (2 years ago)
parents 3345e2713fcb
children 667c147a8dc2
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, unspecified_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 Code
18 import __builtin__ as builtins
19 try:
20 set
21 except NameError:
22 from sets import Set as set
24 possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
25 nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
27 iso_c99_keywords = set(
28 ['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do',
29 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if',
30 'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof',
31 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void',
32 'volatile', 'while',
33 '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict'])
35 def c_safe_identifier(cname):
36 # There are some C limitations on struct entry names.
37 if ((cname[:2] == '__'
38 and not (cname.startswith(Naming.pyrex_prefix)
39 or cname == '__weakref__'))
40 or cname in iso_c99_keywords):
41 cname = Naming.pyrex_prefix + cname
42 return cname
44 class BufferAux(object):
45 writable_needed = False
47 def __init__(self, buffer_info_var, stridevars, shapevars,
48 suboffsetvars):
49 self.buffer_info_var = buffer_info_var
50 self.stridevars = stridevars
51 self.shapevars = shapevars
52 self.suboffsetvars = suboffsetvars
54 def __repr__(self):
55 return "<BufferAux %r>" % self.__dict__
57 class Entry(object):
58 # A symbol table entry in a Scope or ModuleNamespace.
59 #
60 # name string Python name of entity
61 # cname string C name of entity
62 # type PyrexType Type of entity
63 # doc string Doc string
64 # init string Initial value
65 # visibility 'private' or 'public' or 'extern'
66 # is_builtin boolean Is an entry in the Python builtins dict
67 # is_cglobal boolean Is a C global variable
68 # is_pyglobal boolean Is a Python module-level variable
69 # or class attribute during
70 # class construction
71 # is_member boolean Is an assigned class member
72 # is_variable boolean Is a variable
73 # is_cfunction boolean Is a C function
74 # is_cmethod boolean Is a C method of an extension type
75 # is_unbound_cmethod boolean Is an unbound C method of an extension type
76 # is_type boolean Is a type definition
77 # is_cclass boolean Is an extension class
78 # is_cpp_class boolean Is a C++ class
79 # is_const boolean Is a constant
80 # is_property boolean Is a property of an extension type:
81 # doc_cname string or None C const holding the docstring
82 # getter_cname string C func for getting property
83 # setter_cname string C func for setting or deleting property
84 # is_self_arg boolean Is the "self" arg of an exttype method
85 # is_arg boolean Is the arg of a method
86 # is_local boolean Is a local variable
87 # in_closure boolean Is referenced in an inner scope
88 # is_readonly boolean Can't be assigned to
89 # func_cname string C func implementing Python func
90 # func_modifiers [string] C function modifiers ('inline')
91 # pos position Source position where declared
92 # namespace_cname string If is_pyglobal, the C variable
93 # holding its home namespace
94 # pymethdef_cname string PyMethodDef structure
95 # signature Signature Arg & return types for Python func
96 # init_to_none boolean True if initial value should be None
97 # as_variable Entry Alternative interpretation of extension
98 # type name or builtin C function as a variable
99 # xdecref_cleanup boolean Use Py_XDECREF for error cleanup
100 # in_cinclude boolean Suppress C declaration code
101 # enum_values [Entry] For enum types, list of values
102 # qualified_name string "modname.funcname" or "modname.classname"
103 # or "modname.classname.funcname"
104 # is_declared_generic boolean Is declared as PyObject * even though its
105 # type is an extension type
106 # as_module None Module scope, if a cimported module
107 # is_inherited boolean Is an inherited attribute of an extension type
108 # pystring_cname string C name of Python version of string literal
109 # is_interned boolean For string const entries, value is interned
110 # is_identifier boolean For string const entries, value is an identifier
111 # used boolean
112 # is_special boolean Is a special method or property accessor
113 # of an extension type
114 # defined_in_pxd boolean Is defined in a .pxd file (not just declared)
115 # api boolean Generate C API for C class or function
116 # utility_code string Utility code needed when this entry is used
117 #
118 # buffer_aux BufferAux or None Extra information needed for buffer variables
119 # inline_func_in_pxd boolean Hacky special case for inline function in pxd file.
120 # Ideally this should not be necesarry.
121 # assignments [ExprNode] List of expressions that get assigned to this entry.
122 # might_overflow boolean In an arithmetic expression that could cause
123 # overflow (used for type inference).
125 inline_func_in_pxd = False
126 borrowed = 0
127 init = ""
128 visibility = 'private'
129 is_builtin = 0
130 is_cglobal = 0
131 is_pyglobal = 0
132 is_member = 0
133 is_variable = 0
134 is_cfunction = 0
135 is_cmethod = 0
136 is_unbound_cmethod = 0
137 is_type = 0
138 is_cclass = 0
139 is_cpp_class = 0
140 is_const = 0
141 is_property = 0
142 doc_cname = None
143 getter_cname = None
144 setter_cname = None
145 is_self_arg = 0
146 is_arg = 0
147 is_local = 0
148 in_closure = 0
149 is_declared_generic = 0
150 is_readonly = 0
151 func_cname = None
152 func_modifiers = []
153 doc = None
154 init_to_none = 0
155 as_variable = None
156 xdecref_cleanup = 0
157 in_cinclude = 0
158 as_module = None
159 is_inherited = 0
160 pystring_cname = None
161 is_identifier = 0
162 is_interned = 0
163 used = 0
164 is_special = 0
165 defined_in_pxd = 0
166 is_implemented = 0
167 api = 0
168 utility_code = None
169 is_overridable = 0
170 buffer_aux = None
171 prev_entry = None
172 might_overflow = 0
174 def __init__(self, name, cname, type, pos = None, init = None):
175 self.name = name
176 self.cname = cname
177 self.type = type
178 self.pos = pos
179 self.init = init
180 self.overloaded_alternatives = []
181 self.assignments = []
183 def __repr__(self):
184 return "Entry(name=%s, type=%s)" % (self.name, self.type)
186 def redeclared(self, pos):
187 error(pos, "'%s' does not match previous declaration" % self.name)
188 error(self.pos, "Previous declaration is here")
190 def all_alternatives(self):
191 return [self] + self.overloaded_alternatives
193 class Scope(object):
194 # name string Unqualified name
195 # outer_scope Scope or None Enclosing scope
196 # entries {string : Entry} Python name to entry, non-types
197 # const_entries [Entry] Constant entries
198 # type_entries [Entry] Struct/union/enum/typedef/exttype entries
199 # sue_entries [Entry] Struct/union/enum entries
200 # arg_entries [Entry] Function argument entries
201 # var_entries [Entry] User-defined variable entries
202 # pyfunc_entries [Entry] Python function entries
203 # cfunc_entries [Entry] C function entries
204 # c_class_entries [Entry] All extension type entries
205 # cname_to_entry {string : Entry} Temp cname to entry mapping
206 # int_to_entry {int : Entry} Temp cname to entry mapping
207 # return_type PyrexType or None Return type of function owning scope
208 # is_py_class_scope boolean Is a Python class scope
209 # is_c_class_scope boolean Is an extension type scope
210 # scope_prefix string Disambiguator for C names
211 # in_cinclude boolean Suppress C declaration code
212 # qualified_name string "modname" or "modname.classname"
213 # pystring_entries [Entry] String const entries newly used as
214 # Python strings in this scope
215 # control_flow ControlFlow Used for keeping track of environment state
216 # nogil boolean In a nogil section
217 # directives dict Helper variable for the recursive
218 # analysis, contains directive values.
220 is_py_class_scope = 0
221 is_c_class_scope = 0
222 is_cpp_class_scope = 0
223 is_module_scope = 0
224 scope_prefix = ""
225 in_cinclude = 0
226 nogil = 0
228 def __init__(self, name, outer_scope, parent_scope):
229 # The outer_scope is the next scope in the lookup chain.
230 # The parent_scope is used to derive the qualified name of this scope.
231 self.name = name
232 self.outer_scope = outer_scope
233 self.parent_scope = parent_scope
234 mangled_name = "%d%s_" % (len(name), name)
235 qual_scope = self.qualifying_scope()
236 if qual_scope:
237 self.qualified_name = qual_scope.qualify_name(name)
238 self.scope_prefix = qual_scope.scope_prefix + mangled_name
239 else:
240 self.qualified_name = name
241 self.scope_prefix = mangled_name
242 self.entries = {}
243 self.const_entries = []
244 self.type_entries = []
245 self.sue_entries = []
246 self.arg_entries = []
247 self.var_entries = []
248 self.pyfunc_entries = []
249 self.cfunc_entries = []
250 self.c_class_entries = []
251 self.defined_c_classes = []
252 self.imported_c_classes = {}
253 self.cname_to_entry = {}
254 self.string_to_entry = {}
255 self.identifier_to_entry = {}
256 self.num_to_entry = {}
257 self.obj_to_entry = {}
258 self.pystring_entries = []
259 self.buffer_entries = []
260 self.control_flow = ControlFlow.LinearControlFlow()
261 self.return_type = None
263 def start_branching(self, pos):
264 self.control_flow = self.control_flow.start_branch(pos)
266 def next_branch(self, pos):
267 self.control_flow = self.control_flow.next_branch(pos)
269 def finish_branching(self, pos):
270 self.control_flow = self.control_flow.finish_branch(pos)
272 def __str__(self):
273 return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
275 def qualifying_scope(self):
276 return self.parent_scope
278 def mangle(self, prefix, name = None):
279 if name:
280 return "%s%s%s" % (prefix, self.scope_prefix, name)
281 else:
282 return self.parent_scope.mangle(prefix, self.name)
284 def mangle_internal(self, name):
285 # Mangle an internal name so as not to clash with any
286 # user-defined name in this scope.
287 prefix = "%s%s_" % (Naming.pyrex_prefix, name)
288 return self.mangle(prefix)
289 #return self.parent_scope.mangle(prefix, self.name)
291 def global_scope(self):
292 # Return the module-level scope containing this scope.
293 return self.outer_scope.global_scope()
295 def builtin_scope(self):
296 # Return the module-level scope containing this scope.
297 return self.outer_scope.builtin_scope()
299 def declare(self, name, cname, type, pos, visibility):
300 # Create new entry, and add to dictionary if
301 # name is not None. Reports a warning if already
302 # declared.
303 if type.is_buffer and not isinstance(self, LocalScope):
304 error(pos, ERR_BUF_LOCALONLY)
305 if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
306 # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
307 warning(pos, "'%s' is a reserved name in C." % cname, -1)
308 entries = self.entries
309 if name and name in entries:
310 if visibility == 'extern':
311 warning(pos, "'%s' redeclared " % name, 0)
312 elif visibility != 'ignore':
313 error(pos, "'%s' redeclared " % name)
314 entry = Entry(name, cname, type, pos = pos)
315 entry.in_cinclude = self.in_cinclude
316 if name:
317 entry.qualified_name = self.qualify_name(name)
318 # if name in entries and self.is_cpp():
319 # entries[name].overloaded_alternatives.append(entry)
320 # else:
321 # entries[name] = entry
322 entries[name] = entry
323 entry.scope = self
324 entry.visibility = visibility
325 return entry
327 def qualify_name(self, name):
328 return "%s.%s" % (self.qualified_name, name)
330 def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
331 # Add an entry for a named constant.
332 if not cname:
333 if self.in_cinclude or visibility == 'public':
334 cname = name
335 else:
336 cname = self.mangle(Naming.enum_prefix, name)
337 entry = self.declare(name, cname, type, pos, visibility)
338 entry.is_const = 1
339 entry.value_node = value
340 return entry
342 def declare_type(self, name, type, pos,
343 cname = None, visibility = 'private', defining = 1):
344 # Add an entry for a type definition.
345 if not cname:
346 cname = name
347 entry = self.declare(name, cname, type, pos, visibility)
348 entry.is_type = 1
349 if defining:
350 self.type_entries.append(entry)
351 # here we would set as_variable to an object representing this type
352 return entry
354 def declare_typedef(self, name, base_type, pos, cname = None,
355 visibility = 'private'):
356 if not cname:
357 if self.in_cinclude or visibility == 'public':
358 cname = name
359 else:
360 cname = self.mangle(Naming.type_prefix, name)
361 try:
362 type = PyrexTypes.create_typedef_type(name, base_type, cname,
363 (visibility == 'extern'))
364 except ValueError, e:
365 error(pos, e.message)
366 type = PyrexTypes.error_type
367 entry = self.declare_type(name, type, pos, cname, visibility)
368 type.qualified_name = entry.qualified_name
369 return entry
371 def declare_struct_or_union(self, name, kind, scope,
372 typedef_flag, pos, cname = None, visibility = 'private',
373 packed = False):
374 # Add an entry for a struct or union definition.
375 if not cname:
376 if self.in_cinclude or visibility == 'public':
377 cname = name
378 else:
379 cname = self.mangle(Naming.type_prefix, name)
380 entry = self.lookup_here(name)
381 if not entry:
382 type = PyrexTypes.CStructOrUnionType(
383 name, kind, scope, typedef_flag, cname, packed)
384 entry = self.declare_type(name, type, pos, cname,
385 visibility = visibility, defining = scope is not None)
386 self.sue_entries.append(entry)
387 type.entry = entry
388 else:
389 if not (entry.is_type and entry.type.is_struct_or_union
390 and entry.type.kind == kind):
391 warning(pos, "'%s' redeclared " % name, 0)
392 elif scope and entry.type.scope:
393 warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
394 else:
395 self.check_previous_typedef_flag(entry, typedef_flag, pos)
396 self.check_previous_visibility(entry, visibility, pos)
397 if scope:
398 entry.type.scope = scope
399 self.type_entries.append(entry)
400 if not scope and not entry.type.scope:
401 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
402 return entry
404 def declare_cpp_class(self, name, scope,
405 pos, cname = None, base_classes = [],
406 visibility = 'extern', templates = None):
407 if visibility != 'extern':
408 error(pos, "C++ classes may only be extern")
409 if cname is None:
410 cname = name
411 entry = self.lookup(name)
412 if not entry:
413 type = PyrexTypes.CppClassType(
414 name, scope, cname, base_classes, templates = templates)
415 entry = self.declare_type(name, type, pos, cname,
416 visibility = visibility, defining = scope is not None)
417 else:
418 if not (entry.is_type and entry.type.is_cpp_class):
419 warning(pos, "'%s' redeclared " % name, 0)
420 elif scope and entry.type.scope:
421 warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
422 else:
423 if scope:
424 entry.type.scope = scope
425 self.type_entries.append(entry)
426 if not scope and not entry.type.scope:
427 entry.type.scope = CppClassScope(name, self)
428 if templates is not None:
429 for T in templates:
430 template_entry = entry.type.scope.declare(T.name, T.name, T, None, 'extern')
431 template_entry.is_type = 1
433 def declare_inherited_attributes(entry, base_classes):
434 for base_class in base_classes:
435 declare_inherited_attributes(entry, base_class.base_classes)
436 entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
437 declare_inherited_attributes(entry, base_classes)
438 if self.is_cpp_class_scope:
439 entry.type.namespace = self.outer_scope.lookup(self.name).type
440 return entry
442 def check_previous_typedef_flag(self, entry, typedef_flag, pos):
443 if typedef_flag != entry.type.typedef_flag:
444 error(pos, "'%s' previously declared using '%s'" % (
445 entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
447 def check_previous_visibility(self, entry, visibility, pos):
448 if entry.visibility != visibility:
449 error(pos, "'%s' previously declared as '%s'" % (
450 entry.name, entry.visibility))
452 def declare_enum(self, name, pos, cname, typedef_flag,
453 visibility = 'private'):
454 if name:
455 if not cname:
456 if self.in_cinclude or visibility == 'public':
457 cname = name
458 else:
459 cname = self.mangle(Naming.type_prefix, name)
460 type = PyrexTypes.CEnumType(name, cname, typedef_flag)
461 else:
462 type = PyrexTypes.c_anon_enum_type
463 entry = self.declare_type(name, type, pos, cname = cname,
464 visibility = visibility)
465 entry.enum_values = []
466 self.sue_entries.append(entry)
467 return entry
469 def declare_var(self, name, type, pos,
470 cname = None, visibility = 'private', is_cdef = 0):
471 # Add an entry for a variable.
472 if not cname:
473 if visibility != 'private':
474 cname = name
475 else:
476 cname = self.mangle(Naming.var_prefix, name)
477 if type.is_cpp_class and visibility != 'extern':
478 constructor = type.scope.lookup(u'<init>')
479 if constructor is not None and PyrexTypes.best_match([], constructor.all_alternatives()) is None:
480 error(pos, "C++ class must have a default constructor to be stack allocated")
481 entry = self.declare(name, cname, type, pos, visibility)
482 entry.is_variable = 1
483 self.control_flow.set_state((), (name, 'initalized'), False)
484 return entry
486 def declare_builtin(self, name, pos):
487 return self.outer_scope.declare_builtin(name, pos)
489 def declare_pyfunction(self, name, pos):
490 # Add an entry for a Python function.
491 entry = self.lookup_here(name)
492 if entry and not entry.type.is_cfunction:
493 # This is legal Python, but for now will produce invalid C.
494 error(pos, "'%s' already declared" % name)
495 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
496 entry.signature = pyfunction_signature
497 self.pyfunc_entries.append(entry)
498 return entry
500 def register_pyfunction(self, entry):
501 self.pyfunc_entries.append(entry)
503 def declare_cfunction(self, name, type, pos,
504 cname = None, visibility = 'private', defining = 0,
505 api = 0, in_pxd = 0, modifiers = ()):
506 # Add an entry for a C function.
507 if not cname:
508 if api or visibility != 'private':
509 cname = name
510 else:
511 cname = self.mangle(Naming.func_prefix, name)
512 entry = self.lookup_here(name)
513 if entry:
514 if visibility != 'private' and visibility != entry.visibility:
515 warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
516 if not entry.type.same_as(type):
517 if visibility == 'extern' and entry.visibility == 'extern':
518 if self.is_cpp():
519 temp = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
520 temp.overloaded_alternatives = entry.all_alternatives()
521 entry = temp
522 else:
523 warning(pos, "Function signature does not match previous declaration", 1)
524 entry.type = type
525 else:
526 error(pos, "Function signature does not match previous declaration")
527 else:
528 entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
529 entry.func_cname = cname
530 if in_pxd and visibility != 'extern':
531 entry.defined_in_pxd = 1
532 if api:
533 entry.api = 1
534 if not defining and not in_pxd and visibility != 'extern':
535 error(pos, "Non-extern C function '%s' declared but not defined" % name)
536 if defining:
537 entry.is_implemented = True
538 if modifiers:
539 entry.func_modifiers = modifiers
540 return entry
542 def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
543 # Add a C function entry without giving it a func_cname.
544 entry = self.declare(name, cname, type, pos, visibility)
545 entry.is_cfunction = 1
546 if modifiers:
547 entry.func_modifiers = modifiers
548 self.cfunc_entries.append(entry)
549 return entry
551 def find(self, name, pos):
552 # Look up name, report error if not found.
553 entry = self.lookup(name)
554 if entry:
555 return entry
556 else:
557 error(pos, "'%s' is not declared" % name)
559 def find_imported_module(self, path, pos):
560 # Look up qualified name, must be a module, report error if not found.
561 # Path is a list of names.
562 scope = self
563 for name in path:
564 entry = scope.find(name, pos)
565 if not entry:
566 return None
567 if entry.as_module:
568 scope = entry.as_module
569 else:
570 error(pos, "'%s' is not a cimported module" % '.'.join(path))
571 return None
572 return scope
574 def lookup(self, name):
575 # Look up name in this scope or an enclosing one.
576 # Return None if not found.
577 return (self.lookup_here(name)
578 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
579 or None)
581 def lookup_from_inner(self, name):
582 # Look up name in this scope or an enclosing one.
583 # This is only called from enclosing scopes.
584 return (self.lookup_here(name)
585 or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
586 or None)
588 def lookup_here(self, name):
589 # Look up in this scope only, return None if not found.
590 return self.entries.get(name, None)
592 def lookup_target(self, name):
593 # Look up name in this scope only. Declare as Python
594 # variable if not found.
595 entry = self.lookup_here(name)
596 if not entry:
597 entry = self.declare_var(name, py_object_type, None)
598 return entry
600 def lookup_type(self, name):
601 entry = self.lookup(name)
602 if entry and entry.is_type:
603 return entry.type
605 def lookup_operator(self, operator, operands):
606 if operands[0].type.is_cpp_class:
607 obj_type = operands[0].type
608 method = obj_type.scope.lookup("operator%s" % operator)
609 if method is not None:
610 res = PyrexTypes.best_match(operands[1:], method.all_alternatives())
611 if res is not None:
612 return res
613 function = self.lookup("operator%s" % operator)
614 if function is None:
615 return None
616 return PyrexTypes.best_match(operands, function.all_alternatives())
618 def use_utility_code(self, new_code):
619 self.global_scope().use_utility_code(new_code)
621 def generate_library_function_declarations(self, code):
622 # Generate extern decls for C library funcs used.
623 pass
625 def defines_any(self, names):
626 # Test whether any of the given names are
627 # defined in this scope.
628 for name in names:
629 if name in self.entries:
630 return 1
631 return 0
633 def infer_types(self):
634 from TypeInference import get_type_inferer
635 get_type_inferer().infer_types(self)
637 def is_cpp(self):
638 outer = self.outer_scope
639 if outer is None:
640 return False
641 else:
642 return outer.is_cpp()
644 class PreImportScope(Scope):
646 namespace_cname = Naming.preimport_cname
648 def __init__(self):
649 Scope.__init__(self, Options.pre_import, None, None)
651 def declare_builtin(self, name, pos):
652 entry = self.declare(name, name, py_object_type, pos, 'private')
653 entry.is_variable = True
654 entry.is_pyglobal = True
655 return entry
658 class BuiltinScope(Scope):
659 # The builtin namespace.
661 def __init__(self):
662 if Options.pre_import is None:
663 Scope.__init__(self, "__builtin__", None, None)
664 else:
665 Scope.__init__(self, "__builtin__", PreImportScope(), None)
666 self.type_names = {}
668 for name, definition in self.builtin_entries.iteritems():
669 cname, type = definition
670 self.declare_var(name, type, None, cname)
672 def declare_builtin(self, name, pos):
673 if not hasattr(builtins, name):
674 if self.outer_scope is not None:
675 return self.outer_scope.declare_builtin(name, pos)
676 else:
677 error(pos, "undeclared name not builtin: %s"%name)
679 def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
680 utility_code = None):
681 # If python_equiv == "*", the Python equivalent has the same name
682 # as the entry, otherwise it has the name specified by python_equiv.
683 name = EncodedString(name)
684 entry = self.declare_cfunction(name, type, None, cname, visibility='extern')
685 entry.utility_code = utility_code
686 if python_equiv:
687 if python_equiv == "*":
688 python_equiv = name
689 else:
690 python_equiv = EncodedString(python_equiv)
691 var_entry = Entry(python_equiv, python_equiv, py_object_type)
692 var_entry.is_variable = 1
693 var_entry.is_builtin = 1
694 entry.as_variable = var_entry
695 return entry
697 def declare_builtin_type(self, name, cname, utility_code = None):
698 name = EncodedString(name)
699 type = PyrexTypes.BuiltinObjectType(name, cname)
700 type.set_scope(CClassScope(name, outer_scope=None, visibility='extern'))
701 self.type_names[name] = 1
702 entry = self.declare_type(name, type, None, visibility='extern')
704 var_entry = Entry(name = entry.name,
705 type = self.lookup('type').type, # make sure "type" is the first type declared...
706 pos = entry.pos,
707 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
708 var_entry.is_variable = 1
709 var_entry.is_cglobal = 1
710 var_entry.is_readonly = 1
711 var_entry.is_builtin = 1
712 var_entry.utility_code = utility_code
713 entry.as_variable = var_entry
715 return type
717 def builtin_scope(self):
718 return self
720 builtin_entries = {
722 "type": ["((PyObject*)&PyType_Type)", py_object_type],
724 "bool": ["((PyObject*)&PyBool_Type)", py_object_type],
725 "int": ["((PyObject*)&PyInt_Type)", py_object_type],
726 "long": ["((PyObject*)&PyLong_Type)", py_object_type],
727 "float": ["((PyObject*)&PyFloat_Type)", py_object_type],
728 "complex":["((PyObject*)&PyComplex_Type)", py_object_type],
730 "bytes": ["((PyObject*)&PyBytes_Type)", py_object_type],
731 "str": ["((PyObject*)&PyString_Type)", py_object_type],
732 "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type],
734 "tuple": ["((PyObject*)&PyTuple_Type)", py_object_type],
735 "list": ["((PyObject*)&PyList_Type)", py_object_type],
736 "dict": ["((PyObject*)&PyDict_Type)", py_object_type],
737 "set": ["((PyObject*)&PySet_Type)", py_object_type],
738 "frozenset": ["((PyObject*)&PyFrozenSet_Type)", py_object_type],
740 "slice": ["((PyObject*)&PySlice_Type)", py_object_type],
741 "file": ["((PyObject*)&PyFile_Type)", py_object_type],
743 "None": ["Py_None", py_object_type],
744 "False": ["Py_False", py_object_type],
745 "True": ["Py_True", py_object_type],
746 }
748 const_counter = 1 # As a temporary solution for compiling code in pxds
750 class ModuleScope(Scope):
751 # module_name string Python name of the module
752 # module_cname string C name of Python module object
753 # #module_dict_cname string C name of module dict object
754 # method_table_cname string C name of method table
755 # doc string Module doc string
756 # doc_cname string C name of module doc string
757 # utility_code_list [UtilityCode] Queuing utility codes for forwarding to Code.py
758 # python_include_files [string] Standard Python headers to be included
759 # include_files [string] Other C headers to be included
760 # string_to_entry {string : Entry} Map string const to entry
761 # identifier_to_entry {string : Entry} Map identifier string const to entry
762 # context Context
763 # parent_module Scope Parent in the import namespace
764 # module_entries {string : Entry} For cimport statements
765 # type_names {string : 1} Set of type names (used during parsing)
766 # included_files [string] Cython sources included with 'include'
767 # pxd_file_loaded boolean Corresponding .pxd file has been processed
768 # cimported_modules [ModuleScope] Modules imported with cimport
769 # types_imported {PyrexType : 1} Set of types for which import code generated
770 # has_import_star boolean Module contains import *
771 # cpp boolean Compiling a C++ file
773 is_module_scope = 1
774 has_import_star = 0
776 def __init__(self, name, parent_module, context):
777 self.parent_module = parent_module
778 outer_scope = context.find_submodule("__builtin__")
779 Scope.__init__(self, name, outer_scope, parent_module)
780 if name != "__init__":
781 self.module_name = name
782 else:
783 # Treat Spam/__init__.pyx specially, so that when Python loads
784 # Spam/__init__.so, initSpam() is defined.
785 self.module_name = parent_module.module_name
786 self.context = context
787 self.module_cname = Naming.module_cname
788 self.module_dict_cname = Naming.moddict_cname
789 self.method_table_cname = Naming.methtable_cname
790 self.doc = ""
791 self.doc_cname = Naming.moddoc_cname
792 self.utility_code_list = []
793 self.module_entries = {}
794 self.python_include_files = ["Python.h"]
795 self.include_files = []
796 self.type_names = dict(outer_scope.type_names)
797 self.pxd_file_loaded = 0
798 self.cimported_modules = []
799 self.types_imported = {}
800 self.included_files = []
801 self.has_extern_class = 0
802 self.cached_builtins = []
803 self.undeclared_cached_builtins = []
804 self.namespace_cname = self.module_cname
805 for name in ['__builtins__', '__name__', '__file__', '__doc__']:
806 self.declare_var(EncodedString(name), py_object_type, None)
808 def qualifying_scope(self):
809 return self.parent_module
811 def global_scope(self):
812 return self
814 def declare_builtin(self, name, pos):
815 if not hasattr(builtins, name) and name != 'xrange':
816 # 'xrange' is special cased in Code.py
817 if self.has_import_star:
818 entry = self.declare_var(name, py_object_type, pos)
819 return entry
820 elif self.outer_scope is not None:
821 return self.outer_scope.declare_builtin(name, pos)
822 else:
823 error(pos, "undeclared name not builtin: %s"%name)
824 if Options.cache_builtins:
825 for entry in self.cached_builtins:
826 if entry.name == name:
827 return entry
828 entry = self.declare(None, None, py_object_type, pos, 'private')
829 if Options.cache_builtins:
830 entry.is_builtin = 1
831 entry.is_const = 1
832 entry.name = name
833 entry.cname = Naming.builtin_prefix + name
834 self.cached_builtins.append(entry)
835 self.undeclared_cached_builtins.append(entry)
836 else:
837 entry.is_builtin = 1
838 return entry
840 def find_module(self, module_name, pos):
841 # Find a module in the import namespace, interpreting
842 # relative imports relative to this module's parent.
843 # Finds and parses the module's .pxd file if the module
844 # has not been referenced before.
845 return self.global_scope().context.find_module(
846 module_name, relative_to = self.parent_module, pos = pos)
848 def find_submodule(self, name):
849 # Find and return scope for a submodule of this module,
850 # creating a new empty one if necessary. Doesn't parse .pxd.
851 scope = self.lookup_submodule(name)
852 if not scope:
853 scope = ModuleScope(name,
854 parent_module = self, context = self.context)
855 self.module_entries[name] = scope
856 return scope
858 def lookup_submodule(self, name):
859 # Return scope for submodule of this module, or None.
860 return self.module_entries.get(name, None)
862 def add_include_file(self, filename):
863 if filename not in self.python_include_files \
864 and filename not in self.include_files:
865 self.include_files.append(filename)
867 def add_imported_module(self, scope):
868 if scope not in self.cimported_modules:
869 for filename in scope.include_files:
870 self.add_include_file(filename)
871 self.cimported_modules.append(scope)
872 for m in scope.cimported_modules:
873 self.add_imported_module(m)
875 def add_imported_entry(self, name, entry, pos):
876 if entry not in self.entries:
877 self.entries[name] = entry
878 else:
879 warning(pos, "'%s' redeclared " % name, 0)
881 def declare_module(self, name, scope, pos):
882 # Declare a cimported module. This is represented as a
883 # Python module-level variable entry with a module
884 # scope attached to it. Reports an error and returns
885 # None if previously declared as something else.
886 entry = self.lookup_here(name)
887 if entry:
888 if entry.is_pyglobal and entry.as_module is scope:
889 return entry # Already declared as the same module
890 if not (entry.is_pyglobal and not entry.as_module):
891 # SAGE -- I put this here so Pyrex
892 # cimport's work across directories.
893 # Currently it tries to multiply define
894 # every module appearing in an import list.
895 # It shouldn't be an error for a module
896 # name to appear again, and indeed the generated
897 # code compiles fine.
898 return entry
899 warning(pos, "'%s' redeclared " % name, 0)
900 return None
901 else:
902 entry = self.declare_var(name, py_object_type, pos)
903 entry.as_module = scope
904 self.add_imported_module(scope)
905 return entry
907 def declare_var(self, name, type, pos,
908 cname = None, visibility = 'private', is_cdef = 0):
909 # Add an entry for a global variable. If it is a Python
910 # object type, and not declared with cdef, it will live
911 # in the module dictionary, otherwise it will be a C
912 # global variable.
913 entry = Scope.declare_var(self, name, type, pos,
914 cname, visibility, is_cdef)
915 if not visibility in ('private', 'public', 'extern'):
916 error(pos, "Module-level variable cannot be declared %s" % visibility)
917 if not is_cdef:
918 if type is unspecified_type:
919 type = py_object_type
920 if not (type.is_pyobject and not type.is_extension_type):
921 raise InternalError(
922 "Non-cdef global variable is not a generic Python object")
923 entry.is_pyglobal = 1
924 else:
925 entry.is_cglobal = 1
926 if entry.type.is_pyobject:
927 entry.init = 0
928 self.var_entries.append(entry)
929 return entry
931 def declare_global(self, name, pos):
932 entry = self.lookup_here(name)
933 if not entry:
934 self.declare_var(name, py_object_type, pos)
936 def use_utility_code(self, new_code):
937 if new_code is not None:
938 self.utility_code_list.append(new_code)
940 def declare_c_class(self, name, pos, defining = 0, implementing = 0,
941 module_name = None, base_type = None, objstruct_cname = None,
942 typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
943 buffer_defaults = None):
944 # If this is a non-extern typedef class, expose the typedef, but use
945 # the non-typedef struct internally to avoid needing forward
946 # declarations for anonymous structs.
947 if typedef_flag and visibility != 'extern':
948 if visibility != 'public':
949 warning(pos, "ctypedef only valid for public and extern classes", 2)
950 objtypedef_cname = objstruct_cname
951 objstruct_cname = None
952 typedef_flag = 0
953 else:
954 objtypedef_cname = None
955 #
956 # Look for previous declaration as a type
957 #
958 entry = self.lookup_here(name)
959 if entry:
960 type = entry.type
961 if not (entry.is_type and type.is_extension_type):
962 entry = None # Will cause redeclaration and produce an error
963 else:
964 scope = type.scope
965 if typedef_flag and (not scope or scope.defined):
966 self.check_previous_typedef_flag(entry, typedef_flag, pos)
967 if (scope and scope.defined) or (base_type and type.base_type):
968 if base_type and base_type is not type.base_type:
969 error(pos, "Base type does not match previous declaration")
970 if base_type and not type.base_type:
971 type.base_type = base_type
972 #
973 # Make a new entry if needed
974 #
975 if not entry:
976 type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern')
977 type.pos = pos
978 type.buffer_defaults = buffer_defaults
979 if objtypedef_cname is not None:
980 type.objtypedef_cname = objtypedef_cname
981 if visibility == 'extern':
982 type.module_name = module_name
983 else:
984 type.module_name = self.qualified_name
985 type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
986 entry = self.declare_type(name, type, pos, visibility = visibility,
987 defining = 0)
988 entry.is_cclass = True
989 if objstruct_cname:
990 type.objstruct_cname = objstruct_cname
991 elif not entry.in_cinclude:
992 type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
993 else:
994 error(entry.pos,
995 "Object name required for 'public' or 'extern' C class")
996 self.attach_var_entry_to_c_class(entry)
997 self.c_class_entries.append(entry)
998 #
999 # Check for re-definition and create scope if needed
1001 if not type.scope:
1002 if defining or implementing:
1003 scope = CClassScope(name = name, outer_scope = self,
1004 visibility = visibility)
1005 if base_type and base_type.scope:
1006 scope.declare_inherited_c_attributes(base_type.scope)
1007 type.set_scope(scope)
1008 self.type_entries.append(entry)
1009 else:
1010 self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
1011 else:
1012 if defining and type.scope.defined:
1013 error(pos, "C class '%s' already defined" % name)
1014 elif implementing and type.scope.implemented:
1015 error(pos, "C class '%s' already implemented" % name)
1017 # Fill in options, checking for compatibility with any previous declaration
1019 if defining:
1020 entry.defined_in_pxd = 1
1021 if implementing: # So that filenames in runtime exceptions refer to
1022 entry.pos = pos # the .pyx file and not the .pxd file
1023 if visibility != 'private' and entry.visibility != visibility:
1024 error(pos, "Class '%s' previously declared as '%s'"
1025 % (name, entry.visibility))
1026 if api:
1027 entry.api = 1
1028 if objstruct_cname:
1029 if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
1030 error(pos, "Object struct name differs from previous declaration")
1031 type.objstruct_cname = objstruct_cname
1032 if typeobj_cname:
1033 if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
1034 error(pos, "Type object name differs from previous declaration")
1035 type.typeobj_cname = typeobj_cname
1037 # Return new or existing entry
1039 return entry
1041 def check_for_illegal_incomplete_ctypedef(self, typedef_flag, pos):
1042 if typedef_flag and not self.in_cinclude:
1043 error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
1045 def allocate_vtable_names(self, entry):
1046 # If extension type has a vtable, allocate vtable struct and
1047 # slot names for it.
1048 type = entry.type
1049 if type.base_type and type.base_type.vtabslot_cname:
1050 #print "...allocating vtabslot_cname because base type has one" ###
1051 type.vtabslot_cname = "%s.%s" % (
1052 Naming.obj_base_cname, type.base_type.vtabslot_cname)
1053 elif type.scope and type.scope.cfunc_entries:
1054 #print "...allocating vtabslot_cname because there are C methods" ###
1055 type.vtabslot_cname = Naming.vtabslot_cname
1056 if type.vtabslot_cname:
1057 #print "...allocating other vtable related cnames" ###
1058 type.vtabstruct_cname = self.mangle(Naming.vtabstruct_prefix, entry.name)
1059 type.vtabptr_cname = self.mangle(Naming.vtabptr_prefix, entry.name)
1061 def check_c_classes_pxd(self):
1062 # Performs post-analysis checking and finishing up of extension types
1063 # being implemented in this module. This is called only for the .pxd.
1065 # Checks all extension types declared in this scope to
1066 # make sure that:
1068 # * The extension type is fully declared
1070 # Also allocates a name for the vtable if needed.
1072 for entry in self.c_class_entries:
1073 # Check defined
1074 if not entry.type.scope:
1075 error(entry.pos, "C class '%s' is declared but not defined" % entry.name)
1077 def check_c_classes(self):
1078 # Performs post-analysis checking and finishing up of extension types
1079 # being implemented in this module. This is called only for the main
1080 # .pyx file scope, not for cimported .pxd scopes.
1082 # Checks all extension types declared in this scope to
1083 # make sure that:
1085 # * The extension type is implemented
1086 # * All required object and type names have been specified or generated
1087 # * All non-inherited C methods are implemented
1089 # Also allocates a name for the vtable if needed.
1091 debug_check_c_classes = 0
1092 if debug_check_c_classes:
1093 print("Scope.check_c_classes: checking scope " + self.qualified_name)
1094 for entry in self.c_class_entries:
1095 if debug_check_c_classes:
1096 print("...entry %s %s" % (entry.name, entry))
1097 print("......type = ", entry.type)
1098 print("......visibility = ", entry.visibility)
1099 type = entry.type
1100 name = entry.name
1101 visibility = entry.visibility
1102 # Check defined
1103 if not type.scope:
1104 error(entry.pos, "C class '%s' is declared but not defined" % name)
1105 # Generate typeobj_cname
1106 if visibility != 'extern' and not type.typeobj_cname:
1107 type.typeobj_cname = self.mangle(Naming.typeobj_prefix, name)
1108 ## Generate typeptr_cname
1109 #type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1110 # Check C methods defined
1111 if type.scope:
1112 for method_entry in type.scope.cfunc_entries:
1113 if not method_entry.is_inherited and not method_entry.func_cname:
1114 error(method_entry.pos, "C method '%s' is declared but not defined" %
1115 method_entry.name)
1116 # Allocate vtable name if necessary
1117 if type.vtabslot_cname:
1118 #print "ModuleScope.check_c_classes: allocating vtable cname for", self ###
1119 type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name)
1121 def check_c_functions(self):
1122 # Performs post-analysis checking making sure all
1123 # defined c functions are actually implemented.
1124 for name, entry in self.entries.items():
1125 if entry.is_cfunction:
1126 if (entry.defined_in_pxd
1127 and entry.scope is self
1128 and entry.visibility != 'extern'
1129 and not entry.in_cinclude
1130 and not entry.is_implemented):
1131 error(entry.pos, "Non-extern C function '%s' declared but not defined" % name)
1133 def attach_var_entry_to_c_class(self, entry):
1134 # The name of an extension class has to serve as both a type
1135 # name and a variable name holding the type object. It is
1136 # represented in the symbol table by a type entry with a
1137 # variable entry attached to it. For the variable entry,
1138 # we use a read-only C global variable whose name is an
1139 # expression that refers to the type object.
1140 import Builtin
1141 var_entry = Entry(name = entry.name,
1142 type = Builtin.type_type,
1143 pos = entry.pos,
1144 cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
1145 var_entry.is_variable = 1
1146 var_entry.is_cglobal = 1
1147 var_entry.is_readonly = 1
1148 entry.as_variable = var_entry
1150 def is_cpp(self):
1151 return self.cpp
1153 def infer_types(self):
1154 from TypeInference import PyObjectTypeInferer
1155 PyObjectTypeInferer().infer_types(self)
1157 class LocalScope(Scope):
1159 def __init__(self, name, outer_scope, parent_scope = None):
1160 if parent_scope is None:
1161 parent_scope = outer_scope
1162 Scope.__init__(self, name, outer_scope, parent_scope)
1164 def mangle(self, prefix, name):
1165 return prefix + name
1167 def declare_arg(self, name, type, pos):
1168 # Add an entry for an argument of a function.
1169 cname = self.mangle(Naming.var_prefix, name)
1170 entry = self.declare(name, cname, type, pos, 'private')
1171 entry.is_variable = 1
1172 if type.is_pyobject:
1173 entry.init = "0"
1174 entry.is_arg = 1
1175 #entry.borrowed = 1 # Not using borrowed arg refs for now
1176 self.arg_entries.append(entry)
1177 self.control_flow.set_state((), (name, 'source'), 'arg')
1178 return entry
1180 def declare_var(self, name, type, pos,
1181 cname = None, visibility = 'private', is_cdef = 0):
1182 # Add an entry for a local variable.
1183 if visibility in ('public', 'readonly'):
1184 error(pos, "Local variable cannot be declared %s" % visibility)
1185 entry = Scope.declare_var(self, name, type, pos,
1186 cname, visibility, is_cdef)
1187 if type.is_pyobject and not Options.init_local_none:
1188 entry.init = "0"
1189 entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
1190 entry.is_local = 1
1191 self.var_entries.append(entry)
1192 return entry
1194 def declare_global(self, name, pos):
1195 # Pull entry from global scope into local scope.
1196 if self.lookup_here(name):
1197 warning(pos, "'%s' redeclared ", 0)
1198 else:
1199 entry = self.global_scope().lookup_target(name)
1200 self.entries[name] = entry
1202 def lookup_from_inner(self, name):
1203 entry = self.lookup_here(name)
1204 if entry:
1205 entry.in_closure = 1
1206 return entry
1207 else:
1208 return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
1210 def mangle_closure_cnames(self, scope_var):
1211 for entry in self.entries.values():
1212 if entry.in_closure:
1213 if not hasattr(entry, 'orig_cname'):
1214 entry.orig_cname = entry.cname
1215 entry.cname = scope_var + "->" + entry.cname
1218 class GeneratorLocalScope(LocalScope):
1220 def mangle_closure_cnames(self, scope_var):
1221 # for entry in self.entries.values() + self.temp_entries:
1222 # entry.in_closure = 1
1223 LocalScope.mangle_closure_cnames(self, scope_var)
1225 # def mangle(self, prefix, name):
1226 # return "%s->%s" % (Naming.scope_obj_cname, name)
1228 class StructOrUnionScope(Scope):
1229 # Namespace of a C struct or union.
1231 def __init__(self, name="?"):
1232 Scope.__init__(self, name, None, None)
1234 def declare_var(self, name, type, pos,
1235 cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
1236 # Add an entry for an attribute.
1237 if not cname:
1238 cname = name
1239 if visibility == 'private':
1240 cname = c_safe_identifier(cname)
1241 if type.is_cfunction:
1242 type = PyrexTypes.CPtrType(type)
1243 entry = self.declare(name, cname, type, pos, visibility)
1244 entry.is_variable = 1
1245 self.var_entries.append(entry)
1246 if type.is_pyobject and not allow_pyobject:
1247 error(pos,
1248 "C struct/union member cannot be a Python object")
1249 if visibility != 'private':
1250 error(pos,
1251 "C struct/union member cannot be declared %s" % visibility)
1252 return entry
1254 def declare_cfunction(self, name, type, pos,
1255 cname = None, visibility = 'private', defining = 0,
1256 api = 0, in_pxd = 0, modifiers = ()):
1257 return self.declare_var(name, type, pos, cname, visibility)
1259 class ClassScope(Scope):
1260 # Abstract base class for namespace of
1261 # Python class or extension type.
1263 # class_name string Pyrex name of the class
1264 # scope_prefix string Additional prefix for names
1265 # declared in the class
1266 # doc string or None Doc string
1268 def __init__(self, name, outer_scope):
1269 Scope.__init__(self, name, outer_scope, outer_scope)
1270 self.class_name = name
1271 self.doc = None
1273 def add_string_const(self, value, identifier = False):
1274 return self.outer_scope.add_string_const(value, identifier)
1276 def lookup(self, name):
1277 entry = Scope.lookup(self, name)
1278 if entry:
1279 return entry
1280 if name == "classmethod":
1281 # We don't want to use the builtin classmethod here 'cause it won't do the
1282 # right thing in this scope (as the class memebers aren't still functions).
1283 # Don't want to add a cfunction to this scope 'cause that would mess with
1284 # the type definition, so we just return the right entry.
1285 self.use_utility_code(classmethod_utility_code)
1286 entry = Entry(
1287 "classmethod",
1288 "__Pyx_Method_ClassMethod",
1289 PyrexTypes.CFuncType(
1290 py_object_type,
1291 [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0))
1292 entry.is_cfunction = 1
1293 return entry
1296 class PyClassScope(ClassScope):
1297 # Namespace of a Python class.
1299 # class_obj_cname string C variable holding class object
1301 is_py_class_scope = 1
1303 def declare_var(self, name, type, pos,
1304 cname = None, visibility = 'private', is_cdef = 0):
1305 if type is unspecified_type:
1306 type = py_object_type
1307 # Add an entry for a class attribute.
1308 entry = Scope.declare_var(self, name, type, pos,
1309 cname, visibility, is_cdef)
1310 entry.is_pyglobal = 1
1311 return entry
1313 def add_default_value(self, type):
1314 return self.outer_scope.add_default_value(type)
1317 class CClassScope(ClassScope):
1318 # Namespace of an extension type.
1320 # parent_type CClassType
1321 # #typeobj_cname string or None
1322 # #objstruct_cname string
1323 # method_table_cname string
1324 # getset_table_cname string
1325 # has_pyobject_attrs boolean Any PyObject attributes?
1326 # property_entries [Entry]
1327 # defined boolean Defined in .pxd file
1328 # implemented boolean Defined in .pyx file
1329 # inherited_var_entries [Entry] Adapted var entries from base class
1331 is_c_class_scope = 1
1333 def __init__(self, name, outer_scope, visibility):
1334 ClassScope.__init__(self, name, outer_scope)
1335 if visibility != 'extern':
1336 self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
1337 self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
1338 self.has_pyobject_attrs = 0
1339 self.property_entries = []
1340 self.inherited_var_entries = []
1341 self.defined = 0
1342 self.implemented = 0
1344 def needs_gc(self):
1345 # If the type or any of its base types have Python-valued
1346 # C attributes, then it needs to participate in GC.
1347 return self.has_pyobject_attrs or \
1348 (self.parent_type.base_type and
1349 self.parent_type.base_type.scope is not None and
1350 self.parent_type.base_type.scope.needs_gc())
1352 def declare_var(self, name, type, pos,
1353 cname = None, visibility = 'private', is_cdef = 0):
1354 if is_cdef:
1355 # Add an entry for an attribute.
1356 if self.defined:
1357 error(pos,
1358 "C attributes cannot be added in implementation part of"
1359 " extension type defined in a pxd")
1360 if get_special_method_signature(name):
1361 error(pos,
1362 "The name '%s' is reserved for a special method."
1363 % name)
1364 if not cname:
1365 cname = name
1366 if visibility == 'private':
1367 cname = c_safe_identifier(cname)
1368 if type.is_cpp_class and visibility != 'extern':
1369 error(pos, "C++ classes not allowed as members of an extension type, use a pointer or reference instead")
1370 entry = self.declare(name, cname, type, pos, visibility)
1371 entry.is_variable = 1
1372 self.var_entries.append(entry)
1373 if type.is_pyobject:
1374 self.has_pyobject_attrs = 1
1375 if visibility not in ('private', 'public', 'readonly'):
1376 error(pos,
1377 "Attribute of extension type cannot be declared %s" % visibility)
1378 if visibility in ('public', 'readonly'):
1379 if name == "__weakref__":
1380 error(pos, "Special attribute __weakref__ cannot be exposed to Python")
1381 if not type.is_pyobject:
1382 if (not type.create_to_py_utility_code(self) or
1383 (visibility=='public' and not
1384 type.create_from_py_utility_code(self))):
1385 error(pos,
1386 "C attribute of type '%s' cannot be accessed from Python" % type)
1387 return entry
1388 else:
1389 if type is unspecified_type:
1390 type = py_object_type
1391 # Add an entry for a class attribute.
1392 entry = Scope.declare_var(self, name, type, pos,
1393 cname, visibility, is_cdef)
1394 entry.is_member = 1
1395 entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
1396 # I keep it in for now. is_member should be enough
1397 # later on
1398 self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
1399 return entry
1402 def declare_pyfunction(self, name, pos):
1403 # Add an entry for a method.
1404 if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
1405 error(pos, "Special method %s must be implemented via __richcmp__" % name)
1406 if name == "__new__":
1407 warning(pos, "__new__ method of extension type will change semantics "
1408 "in a future version of Pyrex and Cython. Use __cinit__ instead.")
1409 name = EncodedString("__cinit__")
1410 entry = self.declare_var(name, py_object_type, pos, visibility='extern')
1411 special_sig = get_special_method_signature(name)
1412 if special_sig:
1413 # Special methods get put in the method table with a particular
1414 # signature declared in advance.
1415 entry.signature = special_sig
1416 entry.is_special = 1
1417 else:
1418 entry.signature = pymethod_signature
1419 entry.is_special = 0
1421 self.pyfunc_entries.append(entry)
1422 return entry
1424 def lookup_here(self, name):
1425 if name == "__new__":
1426 name = EncodedString("__cinit__")
1427 return ClassScope.lookup_here(self, name)
1429 def declare_cfunction(self, name, type, pos,
1430 cname = None, visibility = 'private',
1431 defining = 0, api = 0, in_pxd = 0, modifiers = ()):
1432 if get_special_method_signature(name):
1433 error(pos, "Special methods must be declared with 'def', not 'cdef'")
1434 args = type.args
1435 if not args:
1436 error(pos, "C method has no self argument")
1437 elif not args[0].type.same_as(self.parent_type):
1438 error(pos, "Self argument (%s) of C method '%s' does not match parent type (%s)" %
1439 (args[0].type, name, self.parent_type))
1440 entry = self.lookup_here(name)
1441 if entry:
1442 if not entry.is_cfunction:
1443 warning(pos, "'%s' redeclared " % name, 0)
1444 else:
1445 if defining and entry.func_cname:
1446 error(pos, "'%s' already defined" % name)
1447 #print "CClassScope.declare_cfunction: checking signature" ###
1448 if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1449 pass
1450 elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1451 entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore', modifiers=modifiers)
1452 defining = 1
1453 else:
1454 error(pos, "Signature not compatible with previous declaration")
1455 error(entry.pos, "Previous declaration is here")
1456 else:
1457 if self.defined:
1458 error(pos,
1459 "C method '%s' not previously declared in definition part of"
1460 " extension type" % name)
1461 entry = self.add_cfunction(name, type, pos, cname or name,
1462 visibility, modifiers)
1463 if defining:
1464 entry.func_cname = self.mangle(Naming.func_prefix, name)
1465 return entry
1467 def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
1468 # Add a cfunction entry without giving it a func_cname.
1469 prev_entry = self.lookup_here(name)
1470 entry = ClassScope.add_cfunction(self, name, type, pos, cname,
1471 visibility, modifiers)
1472 entry.is_cmethod = 1
1473 entry.prev_entry = prev_entry
1474 return entry
1476 def declare_property(self, name, doc, pos):
1477 entry = self.lookup_here(name)
1478 if entry is None:
1479 entry = self.declare(name, name, py_object_type, pos, 'private')
1480 entry.is_property = 1
1481 entry.doc = doc
1482 entry.scope = PropertyScope(name,
1483 outer_scope = self.global_scope(), parent_scope = self)
1484 entry.scope.parent_type = self.parent_type
1485 self.property_entries.append(entry)
1486 return entry
1488 def declare_inherited_c_attributes(self, base_scope):
1489 # Declare entries for all the C attributes of an
1490 # inherited type, with cnames modified appropriately
1491 # to work with this type.
1492 def adapt(cname):
1493 return "%s.%s" % (Naming.obj_base_cname, base_entry.cname)
1494 for base_entry in \
1495 base_scope.inherited_var_entries + base_scope.var_entries:
1496 entry = self.declare(base_entry.name, adapt(base_entry.cname),
1497 base_entry.type, None, 'private')
1498 entry.is_variable = 1
1499 self.inherited_var_entries.append(entry)
1500 for base_entry in base_scope.cfunc_entries:
1501 entry = self.add_cfunction(base_entry.name, base_entry.type,
1502 base_entry.pos, adapt(base_entry.cname),
1503 base_entry.visibility, base_entry.func_modifiers)
1504 entry.is_inherited = 1
1507 class CppClassScope(Scope):
1508 # Namespace of a C++ class.
1510 is_cpp_class_scope = 1
1512 default_constructor = None
1514 def __init__(self, name, outer_scope):
1515 Scope.__init__(self, name, outer_scope, None)
1516 self.directives = outer_scope.directives
1517 self.inherited_var_entries = []
1519 def declare_var(self, name, type, pos,
1520 cname = None, visibility = 'extern', is_cdef = 0, allow_pyobject = 0):
1521 # Add an entry for an attribute.
1522 if not cname:
1523 cname = name
1524 if type.is_cfunction:
1525 type = PyrexTypes.CPtrType(type)
1526 entry = self.declare(name, cname, type, pos, visibility)
1527 entry.is_variable = 1
1528 self.var_entries.append(entry)
1529 if type.is_pyobject and not allow_pyobject:
1530 error(pos,
1531 "C++ class member cannot be a Python object")
1532 return entry
1534 def check_base_default_constructor(self, pos):
1535 # Look for default constructors in all base classes.
1536 if self.default_constructor is None:
1537 entry = self.lookup(self.name)
1538 if len(entry.type.base_classes) == 0:
1539 self.default_constructor = True
1540 return
1541 for base_class in entry.type.base_classes:
1542 temp_entry = base_class.scope.lookup_here("<init>")
1543 found = False
1544 if temp_entry is None:
1545 continue
1546 for alternative in temp_entry.all_alternatives():
1547 type = alternative.type
1548 if type.is_ptr:
1549 type = type.base_type
1550 if len(type.args) == 0:
1551 found = True
1552 break
1553 if not found:
1554 self.default_constructor = temp_entry.scope.name
1555 error(pos, "no matching function for call to " \
1556 "%s::%s()" % (temp_entry.scope.name, temp_entry.scope.name))
1557 elif not self.default_constructor:
1558 error(pos, "no matching function for call to %s::%s()" %
1559 (self.default_constructor, self.default_constructor))
1561 def declare_cfunction(self, name, type, pos,
1562 cname = None, visibility = 'extern', defining = 0,
1563 api = 0, in_pxd = 0, modifiers = ()):
1564 if name == self.name.split('::')[-1] and cname is None:
1565 self.check_base_default_constructor(pos)
1566 name = '<init>'
1567 type.return_type = self.lookup(self.name).type
1568 prev_entry = self.lookup_here(name)
1569 entry = self.declare_var(name, type, pos, cname, visibility)
1570 if prev_entry:
1571 entry.overloaded_alternatives = prev_entry.all_alternatives()
1573 def declare_inherited_cpp_attributes(self, base_scope):
1574 # Declare entries for all the C++ attributes of an
1575 # inherited type, with cnames modified appropriately
1576 # to work with this type.
1577 for base_entry in \
1578 base_scope.inherited_var_entries + base_scope.var_entries:
1579 #contructor is not inherited
1580 if base_entry.name == "<init>":
1581 continue
1582 #print base_entry.name, self.entries
1583 if base_entry.name in self.entries:
1584 base_entry.name
1585 entry = self.declare(base_entry.name, base_entry.cname,
1586 base_entry.type, None, 'extern')
1587 entry.is_variable = 1
1588 self.inherited_var_entries.append(entry)
1589 for base_entry in base_scope.cfunc_entries:
1590 entry = self.declare_cfunction(base_entry.name, base_entry.type,
1591 base_entry.pos, base_entry.cname,
1592 base_entry.visibility, base_entry.func_modifiers)
1593 entry.is_inherited = 1
1595 def specialize(self, values):
1596 scope = CppClassScope(self.name, self.outer_scope)
1597 for entry in self.entries.values():
1598 if entry.is_type:
1599 scope.declare_type(entry.name,
1600 entry.type.specialize(values),
1601 entry.pos,
1602 entry.cname)
1603 else:
1604 # scope.declare_var(entry.name,
1605 # entry.type.specialize(values),
1606 # entry.pos,
1607 # entry.cname,
1608 # entry.visibility)
1609 for e in entry.all_alternatives():
1610 scope.declare_cfunction(e.name,
1611 e.type.specialize(values),
1612 e.pos,
1613 e.cname)
1614 return scope
1617 class PropertyScope(Scope):
1618 # Scope holding the __get__, __set__ and __del__ methods for
1619 # a property of an extension type.
1621 # parent_type PyExtensionType The type to which the property belongs
1623 def declare_pyfunction(self, name, pos):
1624 # Add an entry for a method.
1625 signature = get_property_accessor_signature(name)
1626 if signature:
1627 entry = self.declare(name, name, py_object_type, pos, 'private')
1628 entry.is_special = 1
1629 entry.signature = signature
1630 return entry
1631 else:
1632 error(pos, "Only __get__, __set__ and __del__ methods allowed "
1633 "in a property declaration")
1634 return None
1637 # Should this go elsewhere (and then get imported)?
1638 #------------------------------------------------------------------------------------
1640 classmethod_utility_code = Code.UtilityCode(
1641 proto = """
1642 #include "descrobject.h"
1643 static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
1644 """,
1645 impl = """
1646 static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
1647 /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
1648 static PyTypeObject *methoddescr_type = NULL;
1649 if (methoddescr_type == NULL) {
1650 PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
1651 if (!meth) return NULL;
1652 methoddescr_type = Py_TYPE(meth);
1653 Py_DECREF(meth);
1655 if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
1656 PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
1657 #if PY_VERSION_HEX < 0x03020000
1658 PyTypeObject *d_type = descr->d_type;
1659 #else
1660 PyTypeObject *d_type = descr->d_common.d_type;
1661 #endif
1662 return PyDescr_NewClassMethod(d_type, descr->d_method);
1664 else if (PyMethod_Check(method)) { /* python classes */
1665 return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
1667 else if (PyCFunction_Check(method)) {
1668 return PyClassMethod_New(method);
1670 PyErr_Format(PyExc_TypeError,
1671 "Class-level classmethod() can only be called on"
1672 "a method_descriptor or instance method.");
1673 return NULL;
1675 """)
1677 #------------------------------------------------------------------------------------
1679 ERR_BUF_LOCALONLY = 'Buffer types only allowed as function local variables'