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