Cython has moved to github.

cython-devel

view Cython/Compiler/Symtab.py @ 1169:30b7a6c2c7c1

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