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