|  | # | 
|  | #   Symbol Table | 
|  | # | 
|  |  | 
|  | import copy | 
|  | import re | 
|  | from Errors import warning, error, InternalError | 
|  | from StringEncoding import EncodedString | 
|  | import Options, Naming | 
|  | import PyrexTypes | 
|  | from PyrexTypes import py_object_type, unspecified_type | 
|  | from TypeSlots import \ | 
|  | pyfunction_signature, pymethod_signature, \ | 
|  | get_special_method_signature, get_property_accessor_signature | 
|  | import Code | 
|  | import __builtin__ as builtins | 
|  |  | 
|  | iso_c99_keywords = set( | 
|  | ['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', | 
|  | 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', | 
|  | 'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof', | 
|  | 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', | 
|  | 'volatile', 'while', | 
|  | '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict']) | 
|  |  | 
|  | def c_safe_identifier(cname): | 
|  | # There are some C limitations on struct entry names. | 
|  | if ((cname[:2] == '__' | 
|  | and not (cname.startswith(Naming.pyrex_prefix) | 
|  | or cname == '__weakref__')) | 
|  | or cname in iso_c99_keywords): | 
|  | cname = Naming.pyrex_prefix + cname | 
|  | return cname | 
|  |  | 
|  | class BufferAux(object): | 
|  | writable_needed = False | 
|  |  | 
|  | def __init__(self, buflocal_nd_var, rcbuf_var): | 
|  | self.buflocal_nd_var = buflocal_nd_var | 
|  | self.rcbuf_var = rcbuf_var | 
|  |  | 
|  | def __repr__(self): | 
|  | return "<BufferAux %r>" % self.__dict__ | 
|  |  | 
|  |  | 
|  | class Entry(object): | 
|  | # A symbol table entry in a Scope or ModuleNamespace. | 
|  | # | 
|  | # name             string     Python name of entity | 
|  | # cname            string     C name of entity | 
|  | # type             PyrexType  Type of entity | 
|  | # doc              string     Doc string | 
|  | # init             string     Initial value | 
|  | # visibility       'private' or 'public' or 'extern' | 
|  | # is_builtin       boolean    Is an entry in the Python builtins dict | 
|  | # is_cglobal       boolean    Is a C global variable | 
|  | # is_pyglobal      boolean    Is a Python module-level variable | 
|  | #                               or class attribute during | 
|  | #                               class construction | 
|  | # is_member        boolean    Is an assigned class member | 
|  | # is_pyclass_attr  boolean    Is a name in a Python class namespace | 
|  | # is_variable      boolean    Is a variable | 
|  | # is_cfunction     boolean    Is a C function | 
|  | # is_cmethod       boolean    Is a C method of an extension type | 
|  | # is_builtin_cmethod boolean  Is a C method of a builtin type (implies is_cmethod) | 
|  | # is_unbound_cmethod boolean  Is an unbound C method of an extension type | 
|  | # is_final_cmethod   boolean  Is non-overridable C method | 
|  | # is_inline_cmethod  boolean  Is inlined C method | 
|  | # is_anonymous     boolean    Is a anonymous pyfunction entry | 
|  | # is_type          boolean    Is a type definition | 
|  | # is_cclass        boolean    Is an extension class | 
|  | # is_cpp_class     boolean    Is a C++ class | 
|  | # is_const         boolean    Is a constant | 
|  | # is_property      boolean    Is a property of an extension type: | 
|  | # doc_cname        string or None  C const holding the docstring | 
|  | # getter_cname     string          C func for getting property | 
|  | # setter_cname     string          C func for setting or deleting property | 
|  | # is_self_arg      boolean    Is the "self" arg of an exttype method | 
|  | # is_arg           boolean    Is the arg of a method | 
|  | # is_local         boolean    Is a local variable | 
|  | # in_closure       boolean    Is referenced in an inner scope | 
|  | # is_readonly      boolean    Can't be assigned to | 
|  | # func_cname       string     C func implementing Python func | 
|  | # func_modifiers   [string]   C function modifiers ('inline') | 
|  | # pos              position   Source position where declared | 
|  | # namespace_cname  string     If is_pyglobal, the C variable | 
|  | #                               holding its home namespace | 
|  | # pymethdef_cname  string     PyMethodDef structure | 
|  | # signature        Signature  Arg & return types for Python func | 
|  | # as_variable      Entry      Alternative interpretation of extension | 
|  | #                               type name or builtin C function as a variable | 
|  | # xdecref_cleanup  boolean    Use Py_XDECREF for error cleanup | 
|  | # in_cinclude      boolean    Suppress C declaration code | 
|  | # enum_values      [Entry]    For enum types, list of values | 
|  | # qualified_name   string     "modname.funcname" or "modname.classname" | 
|  | #                               or "modname.classname.funcname" | 
|  | # is_declared_generic  boolean  Is declared as PyObject * even though its | 
|  | #                                 type is an extension type | 
|  | # as_module        None       Module scope, if a cimported module | 
|  | # is_inherited     boolean    Is an inherited attribute of an extension type | 
|  | # pystring_cname   string     C name of Python version of string literal | 
|  | # is_interned      boolean    For string const entries, value is interned | 
|  | # is_identifier    boolean    For string const entries, value is an identifier | 
|  | # used             boolean | 
|  | # is_special       boolean    Is a special method or property accessor | 
|  | #                               of an extension type | 
|  | # defined_in_pxd   boolean    Is defined in a .pxd file (not just declared) | 
|  | # api              boolean    Generate C API for C class or function | 
|  | # utility_code     string     Utility code needed when this entry is used | 
|  | # | 
|  | # buffer_aux       BufferAux or None  Extra information needed for buffer variables | 
|  | # inline_func_in_pxd boolean  Hacky special case for inline function in pxd file. | 
|  | #                             Ideally this should not be necesarry. | 
|  | # might_overflow   boolean    In an arithmetic expression that could cause | 
|  | #                             overflow (used for type inference). | 
|  | # utility_code_definition     For some Cython builtins, the utility code | 
|  | #                             which contains the definition of the entry. | 
|  | #                             Currently only supported for CythonScope entries. | 
|  | # error_on_uninitialized      Have Control Flow issue an error when this entry is | 
|  | #                             used uninitialized | 
|  | # cf_used          boolean    Entry is used | 
|  | # is_fused_specialized boolean Whether this entry of a cdef or def function | 
|  | #                              is a specialization | 
|  |  | 
|  | # TODO: utility_code and utility_code_definition serves the same purpose... | 
|  |  | 
|  | inline_func_in_pxd = False | 
|  | borrowed = 0 | 
|  | init = "" | 
|  | visibility = 'private' | 
|  | is_builtin = 0 | 
|  | is_cglobal = 0 | 
|  | is_pyglobal = 0 | 
|  | is_member = 0 | 
|  | is_pyclass_attr = 0 | 
|  | is_variable = 0 | 
|  | is_cfunction = 0 | 
|  | is_cmethod = 0 | 
|  | is_builtin_cmethod = False | 
|  | is_unbound_cmethod = 0 | 
|  | is_final_cmethod = 0 | 
|  | is_inline_cmethod = 0 | 
|  | is_anonymous = 0 | 
|  | is_type = 0 | 
|  | is_cclass = 0 | 
|  | is_cpp_class = 0 | 
|  | is_const = 0 | 
|  | is_property = 0 | 
|  | doc_cname = None | 
|  | getter_cname = None | 
|  | setter_cname = None | 
|  | is_self_arg = 0 | 
|  | is_arg = 0 | 
|  | is_local = 0 | 
|  | in_closure = 0 | 
|  | from_closure = 0 | 
|  | is_declared_generic = 0 | 
|  | is_readonly = 0 | 
|  | pyfunc_cname = None | 
|  | func_cname = None | 
|  | func_modifiers = [] | 
|  | final_func_cname = None | 
|  | doc = None | 
|  | as_variable = None | 
|  | xdecref_cleanup = 0 | 
|  | in_cinclude = 0 | 
|  | as_module = None | 
|  | is_inherited = 0 | 
|  | pystring_cname = None | 
|  | is_identifier = 0 | 
|  | is_interned = 0 | 
|  | used = 0 | 
|  | is_special = 0 | 
|  | defined_in_pxd = 0 | 
|  | is_implemented = 0 | 
|  | api = 0 | 
|  | utility_code = None | 
|  | is_overridable = 0 | 
|  | buffer_aux = None | 
|  | prev_entry = None | 
|  | might_overflow = 0 | 
|  | fused_cfunction = None | 
|  | is_fused_specialized = False | 
|  | utility_code_definition = None | 
|  | needs_property = False | 
|  | in_with_gil_block = 0 | 
|  | from_cython_utility_code = None | 
|  | error_on_uninitialized = False | 
|  | cf_used = True | 
|  | outer_entry = None | 
|  |  | 
|  | def __init__(self, name, cname, type, pos = None, init = None): | 
|  | self.name = name | 
|  | self.cname = cname | 
|  | self.type = type | 
|  | self.pos = pos | 
|  | self.init = init | 
|  | self.overloaded_alternatives = [] | 
|  | self.cf_assignments = [] | 
|  | self.cf_references = [] | 
|  | self.inner_entries = [] | 
|  | self.defining_entry = self | 
|  |  | 
|  | def __repr__(self): | 
|  | return "%s(<%x>, name=%s, type=%s)" % (type(self).__name__, id(self), self.name, self.type) | 
|  |  | 
|  | def redeclared(self, pos): | 
|  | error(pos, "'%s' does not match previous declaration" % self.name) | 
|  | error(self.pos, "Previous declaration is here") | 
|  |  | 
|  | def all_alternatives(self): | 
|  | return [self] + self.overloaded_alternatives | 
|  |  | 
|  | def all_entries(self): | 
|  | return [self] + self.inner_entries | 
|  |  | 
|  |  | 
|  | class InnerEntry(Entry): | 
|  | """ | 
|  | An entry in a closure scope that represents the real outer Entry. | 
|  | """ | 
|  | from_closure = True | 
|  |  | 
|  | def __init__(self, outer_entry, scope): | 
|  | Entry.__init__(self, outer_entry.name, | 
|  | outer_entry.cname, | 
|  | outer_entry.type, | 
|  | outer_entry.pos) | 
|  | self.outer_entry = outer_entry | 
|  | self.scope = scope | 
|  |  | 
|  | # share state with (outermost) defining entry | 
|  | outermost_entry = outer_entry | 
|  | while outermost_entry.outer_entry: | 
|  | outermost_entry = outermost_entry.outer_entry | 
|  | self.defining_entry = outermost_entry | 
|  | self.inner_entries = outermost_entry.inner_entries | 
|  | self.cf_assignments = outermost_entry.cf_assignments | 
|  | self.cf_references = outermost_entry.cf_references | 
|  | self.overloaded_alternatives = outermost_entry.overloaded_alternatives | 
|  | self.inner_entries.append(self) | 
|  |  | 
|  | def __getattr__(self, name): | 
|  | if name.startswith('__'): | 
|  | # we wouldn't have been called if it was there | 
|  | raise AttributeError(name) | 
|  | return getattr(self.defining_entry, name) | 
|  |  | 
|  | def all_entries(self): | 
|  | return self.defining_entry.all_entries() | 
|  |  | 
|  |  | 
|  | class Scope(object): | 
|  | # name              string             Unqualified name | 
|  | # outer_scope       Scope or None      Enclosing scope | 
|  | # entries           {string : Entry}   Python name to entry, non-types | 
|  | # const_entries     [Entry]            Constant entries | 
|  | # type_entries      [Entry]            Struct/union/enum/typedef/exttype entries | 
|  | # sue_entries       [Entry]            Struct/union/enum entries | 
|  | # arg_entries       [Entry]            Function argument entries | 
|  | # var_entries       [Entry]            User-defined variable entries | 
|  | # pyfunc_entries    [Entry]            Python function entries | 
|  | # cfunc_entries     [Entry]            C function entries | 
|  | # c_class_entries   [Entry]            All extension type entries | 
|  | # cname_to_entry    {string : Entry}   Temp cname to entry mapping | 
|  | # return_type       PyrexType or None  Return type of function owning scope | 
|  | # is_builtin_scope  boolean            Is the builtin scope of Python/Cython | 
|  | # is_py_class_scope boolean            Is a Python class scope | 
|  | # is_c_class_scope  boolean            Is an extension type scope | 
|  | # is_closure_scope  boolean            Is a closure scope | 
|  | # is_passthrough    boolean            Outer scope is passed directly | 
|  | # is_cpp_class_scope  boolean          Is a C++ class scope | 
|  | # is_property_scope boolean            Is a extension type property scope | 
|  | # scope_prefix      string             Disambiguator for C names | 
|  | # in_cinclude       boolean            Suppress C declaration code | 
|  | # qualified_name    string             "modname" or "modname.classname" | 
|  | #                                        Python strings in this scope | 
|  | # nogil             boolean            In a nogil section | 
|  | # directives        dict               Helper variable for the recursive | 
|  | #                                      analysis, contains directive values. | 
|  | # is_internal       boolean            Is only used internally (simpler setup) | 
|  |  | 
|  | is_builtin_scope = 0 | 
|  | is_py_class_scope = 0 | 
|  | is_c_class_scope = 0 | 
|  | is_closure_scope = 0 | 
|  | is_passthrough = 0 | 
|  | is_cpp_class_scope = 0 | 
|  | is_property_scope = 0 | 
|  | is_module_scope = 0 | 
|  | is_internal = 0 | 
|  | scope_prefix = "" | 
|  | in_cinclude = 0 | 
|  | nogil = 0 | 
|  | fused_to_specific = None | 
|  |  | 
|  | def __init__(self, name, outer_scope, parent_scope): | 
|  | # The outer_scope is the next scope in the lookup chain. | 
|  | # The parent_scope is used to derive the qualified name of this scope. | 
|  | self.name = name | 
|  | self.outer_scope = outer_scope | 
|  | self.parent_scope = parent_scope | 
|  | mangled_name = "%d%s_" % (len(name), name) | 
|  | qual_scope = self.qualifying_scope() | 
|  | if qual_scope: | 
|  | self.qualified_name = qual_scope.qualify_name(name) | 
|  | self.scope_prefix = qual_scope.scope_prefix + mangled_name | 
|  | else: | 
|  | self.qualified_name = EncodedString(name) | 
|  | self.scope_prefix = mangled_name | 
|  | self.entries = {} | 
|  | self.const_entries = [] | 
|  | self.type_entries = [] | 
|  | self.sue_entries = [] | 
|  | self.arg_entries = [] | 
|  | self.var_entries = [] | 
|  | self.pyfunc_entries = [] | 
|  | self.cfunc_entries = [] | 
|  | self.c_class_entries = [] | 
|  | self.defined_c_classes = [] | 
|  | self.imported_c_classes = {} | 
|  | self.cname_to_entry = {} | 
|  | self.string_to_entry = {} | 
|  | self.identifier_to_entry = {} | 
|  | self.num_to_entry = {} | 
|  | self.obj_to_entry = {} | 
|  | self.buffer_entries = [] | 
|  | self.lambda_defs = [] | 
|  | self.return_type = None | 
|  | self.id_counters = {} | 
|  |  | 
|  | def __deepcopy__(self, memo): | 
|  | return self | 
|  |  | 
|  | def merge_in(self, other, merge_unused=True, whitelist=None): | 
|  | # Use with care... | 
|  | entries = [] | 
|  | for name, entry in other.entries.iteritems(): | 
|  | if not whitelist or name in whitelist: | 
|  | if entry.used or merge_unused: | 
|  | entries.append((name, entry)) | 
|  |  | 
|  | self.entries.update(entries) | 
|  |  | 
|  | for attr in ('const_entries', | 
|  | 'type_entries', | 
|  | 'sue_entries', | 
|  | 'arg_entries', | 
|  | 'var_entries', | 
|  | 'pyfunc_entries', | 
|  | 'cfunc_entries', | 
|  | 'c_class_entries'): | 
|  | self_entries = getattr(self, attr) | 
|  | names = set([e.name for e in self_entries]) | 
|  | for entry in getattr(other, attr): | 
|  | if (entry.used or merge_unused) and entry.name not in names: | 
|  | self_entries.append(entry) | 
|  |  | 
|  | def __str__(self): | 
|  | return "<%s %s>" % (self.__class__.__name__, self.qualified_name) | 
|  |  | 
|  | def qualifying_scope(self): | 
|  | return self.parent_scope | 
|  |  | 
|  | def mangle(self, prefix, name = None): | 
|  | if name: | 
|  | return "%s%s%s" % (prefix, self.scope_prefix, name) | 
|  | else: | 
|  | return self.parent_scope.mangle(prefix, self.name) | 
|  |  | 
|  | def mangle_internal(self, name): | 
|  | # Mangle an internal name so as not to clash with any | 
|  | # user-defined name in this scope. | 
|  | prefix = "%s%s_" % (Naming.pyrex_prefix, name) | 
|  | return self.mangle(prefix) | 
|  | #return self.parent_scope.mangle(prefix, self.name) | 
|  |  | 
|  | def mangle_class_private_name(self, name): | 
|  | if self.parent_scope: | 
|  | return self.parent_scope.mangle_class_private_name(name) | 
|  | return name | 
|  |  | 
|  | def next_id(self, name=None): | 
|  | # Return a cname fragment that is unique for this module | 
|  | counters = self.global_scope().id_counters | 
|  | try: | 
|  | count = counters[name] + 1 | 
|  | except KeyError: | 
|  | count = 0 | 
|  | counters[name] = count | 
|  | if name: | 
|  | if not count: | 
|  | # unique names don't need a suffix, reoccurrences will get one | 
|  | return name | 
|  | return '%s%d' % (name, count) | 
|  | else: | 
|  | return '%d' % count | 
|  |  | 
|  | def global_scope(self): | 
|  | """ Return the module-level scope containing this scope. """ | 
|  | return self.outer_scope.global_scope() | 
|  |  | 
|  | def builtin_scope(self): | 
|  | """ Return the module-level scope containing this scope. """ | 
|  | return self.outer_scope.builtin_scope() | 
|  |  | 
|  | def declare(self, name, cname, type, pos, visibility, shadow = 0, is_type = 0): | 
|  | # Create new entry, and add to dictionary if | 
|  | # name is not None. Reports a warning if already | 
|  | # declared. | 
|  | if type.is_buffer and not isinstance(self, LocalScope): # and not is_type: | 
|  | error(pos, 'Buffer types only allowed as function local variables') | 
|  | if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname): | 
|  | # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names | 
|  | warning(pos, "'%s' is a reserved name in C." % cname, -1) | 
|  | entries = self.entries | 
|  | if name and name in entries and not shadow: | 
|  | if visibility == 'extern': | 
|  | warning(pos, "'%s' redeclared " % name, 0) | 
|  | elif visibility != 'ignore': | 
|  | error(pos, "'%s' redeclared " % name) | 
|  | entry = Entry(name, cname, type, pos = pos) | 
|  | entry.in_cinclude = self.in_cinclude | 
|  | if name: | 
|  | entry.qualified_name = self.qualify_name(name) | 
|  | #            if name in entries and self.is_cpp(): | 
|  | #                entries[name].overloaded_alternatives.append(entry) | 
|  | #            else: | 
|  | #                entries[name] = entry | 
|  | if not shadow: | 
|  | entries[name] = entry | 
|  |  | 
|  | if type.is_memoryviewslice: | 
|  | import MemoryView | 
|  | entry.init = MemoryView.memslice_entry_init | 
|  |  | 
|  | entry.scope = self | 
|  | entry.visibility = visibility | 
|  | return entry | 
|  |  | 
|  | def qualify_name(self, name): | 
|  | return EncodedString("%s.%s" % (self.qualified_name, name)) | 
|  |  | 
|  | def declare_const(self, name, type, value, pos, cname = None, visibility = 'private', api = 0): | 
|  | # Add an entry for a named constant. | 
|  | if not cname: | 
|  | if self.in_cinclude or (visibility == 'public' or api): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.enum_prefix, name) | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_const = 1 | 
|  | entry.value_node = value | 
|  | return entry | 
|  |  | 
|  | def declare_type(self, name, type, pos, | 
|  | cname = None, visibility = 'private', api = 0, defining = 1, | 
|  | shadow = 0, template = 0): | 
|  | # Add an entry for a type definition. | 
|  | if not cname: | 
|  | cname = name | 
|  | entry = self.declare(name, cname, type, pos, visibility, shadow, | 
|  | is_type=True) | 
|  | entry.is_type = 1 | 
|  | entry.api = api | 
|  | if defining: | 
|  | self.type_entries.append(entry) | 
|  |  | 
|  | if not template: | 
|  | type.entry = entry | 
|  |  | 
|  | # here we would set as_variable to an object representing this type | 
|  | return entry | 
|  |  | 
|  | def declare_typedef(self, name, base_type, pos, cname = None, | 
|  | visibility = 'private', api = 0): | 
|  | if not cname: | 
|  | if self.in_cinclude or (visibility == 'public' or api): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.type_prefix, name) | 
|  | try: | 
|  | type = PyrexTypes.create_typedef_type(name, base_type, cname, | 
|  | (visibility == 'extern')) | 
|  | except ValueError, e: | 
|  | error(pos, e.args[0]) | 
|  | type = PyrexTypes.error_type | 
|  | entry = self.declare_type(name, type, pos, cname, | 
|  | visibility = visibility, api = api) | 
|  | type.qualified_name = entry.qualified_name | 
|  | return entry | 
|  |  | 
|  | def declare_struct_or_union(self, name, kind, scope, | 
|  | typedef_flag, pos, cname = None, | 
|  | visibility = 'private', api = 0, | 
|  | packed = False): | 
|  | # Add an entry for a struct or union definition. | 
|  | if not cname: | 
|  | if self.in_cinclude or (visibility == 'public' or api): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.type_prefix, name) | 
|  | entry = self.lookup_here(name) | 
|  | if not entry: | 
|  | type = PyrexTypes.CStructOrUnionType( | 
|  | name, kind, scope, typedef_flag, cname, packed) | 
|  | entry = self.declare_type(name, type, pos, cname, | 
|  | visibility = visibility, api = api, | 
|  | defining = scope is not None) | 
|  | self.sue_entries.append(entry) | 
|  | type.entry = entry | 
|  | else: | 
|  | if not (entry.is_type and entry.type.is_struct_or_union | 
|  | and entry.type.kind == kind): | 
|  | warning(pos, "'%s' redeclared  " % name, 0) | 
|  | elif scope and entry.type.scope: | 
|  | warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0) | 
|  | else: | 
|  | self.check_previous_typedef_flag(entry, typedef_flag, pos) | 
|  | self.check_previous_visibility(entry, visibility, pos) | 
|  | if scope: | 
|  | entry.type.scope = scope | 
|  | self.type_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_cpp_class(self, name, scope, | 
|  | pos, cname = None, base_classes = (), | 
|  | visibility = 'extern', templates = None): | 
|  | if cname is None: | 
|  | if self.in_cinclude or (visibility != 'private'): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.type_prefix, name) | 
|  | base_classes = list(base_classes) | 
|  | entry = self.lookup_here(name) | 
|  | if not entry: | 
|  | type = PyrexTypes.CppClassType( | 
|  | name, scope, cname, base_classes, templates = templates) | 
|  | entry = self.declare_type(name, type, pos, cname, | 
|  | visibility = visibility, defining = scope is not None) | 
|  | self.sue_entries.append(entry) | 
|  | else: | 
|  | if not (entry.is_type and entry.type.is_cpp_class): | 
|  | error(pos, "'%s' redeclared " % name) | 
|  | return None | 
|  | elif scope and entry.type.scope: | 
|  | warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0) | 
|  | else: | 
|  | if scope: | 
|  | entry.type.scope = scope | 
|  | self.type_entries.append(entry) | 
|  | if base_classes: | 
|  | if entry.type.base_classes and entry.type.base_classes != base_classes: | 
|  | error(pos, "Base type does not match previous declaration") | 
|  | else: | 
|  | entry.type.base_classes = base_classes | 
|  | if templates or entry.type.templates: | 
|  | if templates != entry.type.templates: | 
|  | error(pos, "Template parameters do not match previous declaration") | 
|  |  | 
|  | def declare_inherited_attributes(entry, base_classes): | 
|  | for base_class in base_classes: | 
|  | if base_class is PyrexTypes.error_type: | 
|  | continue | 
|  | if base_class.scope is None: | 
|  | error(pos, "Cannot inherit from incomplete type") | 
|  | else: | 
|  | declare_inherited_attributes(entry, base_class.base_classes) | 
|  | entry.type.scope.declare_inherited_cpp_attributes(base_class.scope) | 
|  | if entry.type.scope: | 
|  | declare_inherited_attributes(entry, base_classes) | 
|  | entry.type.scope.declare_var(name="this", cname="this", type=PyrexTypes.CPtrType(entry.type), pos=entry.pos) | 
|  | if self.is_cpp_class_scope: | 
|  | entry.type.namespace = self.outer_scope.lookup(self.name).type | 
|  | return entry | 
|  |  | 
|  | def check_previous_typedef_flag(self, entry, typedef_flag, pos): | 
|  | if typedef_flag != entry.type.typedef_flag: | 
|  | error(pos, "'%s' previously declared using '%s'" % ( | 
|  | entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag])) | 
|  |  | 
|  | def check_previous_visibility(self, entry, visibility, pos): | 
|  | if entry.visibility != visibility: | 
|  | error(pos, "'%s' previously declared as '%s'" % ( | 
|  | entry.name, entry.visibility)) | 
|  |  | 
|  | def declare_enum(self, name, pos, cname, typedef_flag, | 
|  | visibility = 'private', api = 0): | 
|  | if name: | 
|  | if not cname: | 
|  | if self.in_cinclude or (visibility == 'public' or api): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.type_prefix, name) | 
|  | type = PyrexTypes.CEnumType(name, cname, typedef_flag) | 
|  | else: | 
|  | type = PyrexTypes.c_anon_enum_type | 
|  | entry = self.declare_type(name, type, pos, cname = cname, | 
|  | visibility = visibility, api = api) | 
|  | entry.enum_values = [] | 
|  | self.sue_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0): | 
|  | # Add an entry for a variable. | 
|  | if not cname: | 
|  | if visibility != 'private' or api: | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.var_prefix, name) | 
|  | if type.is_cpp_class and visibility != 'extern': | 
|  | type.check_nullary_constructor(pos) | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_variable = 1 | 
|  | if in_pxd and visibility != 'extern': | 
|  | entry.defined_in_pxd = 1 | 
|  | entry.used = 1 | 
|  | if api: | 
|  | entry.api = 1 | 
|  | entry.used = 1 | 
|  | return entry | 
|  |  | 
|  | def declare_builtin(self, name, pos): | 
|  | return self.outer_scope.declare_builtin(name, pos) | 
|  |  | 
|  | def _declare_pyfunction(self, name, pos, visibility='extern', entry=None): | 
|  | if entry and not entry.type.is_cfunction: | 
|  | error(pos, "'%s' already declared" % name) | 
|  | error(entry.pos, "Previous declaration is here") | 
|  | entry = self.declare_var(name, py_object_type, pos, visibility=visibility) | 
|  | entry.signature = pyfunction_signature | 
|  | self.pyfunc_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_pyfunction(self, name, pos, allow_redefine=False, visibility='extern'): | 
|  | # Add an entry for a Python function. | 
|  | entry = self.lookup_here(name) | 
|  | if not allow_redefine: | 
|  | return self._declare_pyfunction(name, pos, visibility=visibility, entry=entry) | 
|  | if entry: | 
|  | if entry.type.is_unspecified: | 
|  | entry.type = py_object_type | 
|  | elif entry.type is not py_object_type: | 
|  | return self._declare_pyfunction(name, pos, visibility=visibility, entry=entry) | 
|  | else: # declare entry stub | 
|  | self.declare_var(name, py_object_type, pos, visibility=visibility) | 
|  | entry = self.declare_var(None, py_object_type, pos, | 
|  | cname=name, visibility='private') | 
|  | entry.name = EncodedString(name) | 
|  | entry.qualified_name = self.qualify_name(name) | 
|  | entry.signature = pyfunction_signature | 
|  | entry.is_anonymous = True | 
|  | return entry | 
|  |  | 
|  | def declare_lambda_function(self, lambda_name, pos): | 
|  | # Add an entry for an anonymous Python function. | 
|  | func_cname = self.mangle(Naming.lambda_func_prefix + u'funcdef_', lambda_name) | 
|  | pymethdef_cname = self.mangle(Naming.lambda_func_prefix + u'methdef_', lambda_name) | 
|  | qualified_name = self.qualify_name(lambda_name) | 
|  |  | 
|  | entry = self.declare(None, func_cname, py_object_type, pos, 'private') | 
|  | entry.name = lambda_name | 
|  | entry.qualified_name = qualified_name | 
|  | entry.pymethdef_cname = pymethdef_cname | 
|  | entry.func_cname = func_cname | 
|  | entry.signature = pyfunction_signature | 
|  | entry.is_anonymous = True | 
|  | return entry | 
|  |  | 
|  | def add_lambda_def(self, def_node): | 
|  | self.lambda_defs.append(def_node) | 
|  |  | 
|  | def register_pyfunction(self, entry): | 
|  | self.pyfunc_entries.append(entry) | 
|  |  | 
|  | def declare_cfunction(self, name, type, pos, | 
|  | cname = None, visibility = 'private', api = 0, in_pxd = 0, | 
|  | defining = 0, modifiers = (), utility_code = None): | 
|  | # Add an entry for a C function. | 
|  | if not cname: | 
|  | if visibility != 'private' or api: | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.func_prefix, name) | 
|  | entry = self.lookup_here(name) | 
|  | if entry: | 
|  | if visibility != 'private' and visibility != entry.visibility: | 
|  | warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1) | 
|  | if not entry.type.same_as(type): | 
|  | if visibility == 'extern' and entry.visibility == 'extern': | 
|  | can_override = False | 
|  | if self.is_cpp(): | 
|  | can_override = True | 
|  | elif cname: | 
|  | # if all alternatives have different cnames, | 
|  | # it's safe to allow signature overrides | 
|  | for alt_entry in entry.all_alternatives(): | 
|  | if not alt_entry.cname or cname == alt_entry.cname: | 
|  | break # cname not unique! | 
|  | else: | 
|  | can_override = True | 
|  | if can_override: | 
|  | temp = self.add_cfunction(name, type, pos, cname, visibility, modifiers) | 
|  | temp.overloaded_alternatives = entry.all_alternatives() | 
|  | entry = temp | 
|  | else: | 
|  | warning(pos, "Function signature does not match previous declaration", 1) | 
|  | entry.type = type | 
|  | else: | 
|  | error(pos, "Function signature does not match previous declaration") | 
|  | else: | 
|  | entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers) | 
|  | entry.func_cname = cname | 
|  | if in_pxd and visibility != 'extern': | 
|  | entry.defined_in_pxd = 1 | 
|  | if api: | 
|  | entry.api = 1 | 
|  | if not defining and not in_pxd and visibility != 'extern': | 
|  | error(pos, "Non-extern C function '%s' declared but not defined" % name) | 
|  | if defining: | 
|  | entry.is_implemented = True | 
|  | if modifiers: | 
|  | entry.func_modifiers = modifiers | 
|  | if utility_code: | 
|  | assert not entry.utility_code, "duplicate utility code definition in entry %s (%s)" % (name, cname) | 
|  | entry.utility_code = utility_code | 
|  | type.entry = entry | 
|  | return entry | 
|  |  | 
|  | def add_cfunction(self, name, type, pos, cname, visibility, modifiers): | 
|  | # Add a C function entry without giving it a func_cname. | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_cfunction = 1 | 
|  | if modifiers: | 
|  | entry.func_modifiers = modifiers | 
|  | self.cfunc_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def find(self, name, pos): | 
|  | # Look up name, report error if not found. | 
|  | entry = self.lookup(name) | 
|  | if entry: | 
|  | return entry | 
|  | else: | 
|  | error(pos, "'%s' is not declared" % name) | 
|  |  | 
|  | def find_imported_module(self, path, pos): | 
|  | # Look up qualified name, must be a module, report error if not found. | 
|  | # Path is a list of names. | 
|  | scope = self | 
|  | for name in path: | 
|  | entry = scope.find(name, pos) | 
|  | if not entry: | 
|  | return None | 
|  | if entry.as_module: | 
|  | scope = entry.as_module | 
|  | else: | 
|  | error(pos, "'%s' is not a cimported module" % '.'.join(path)) | 
|  | return None | 
|  | return scope | 
|  |  | 
|  | def lookup(self, name): | 
|  | # Look up name in this scope or an enclosing one. | 
|  | # Return None if not found. | 
|  | return (self.lookup_here(name) | 
|  | or (self.outer_scope and self.outer_scope.lookup(name)) | 
|  | or None) | 
|  |  | 
|  | def lookup_here(self, name): | 
|  | # Look up in this scope only, return None if not found. | 
|  | return self.entries.get(name, None) | 
|  |  | 
|  | def lookup_target(self, name): | 
|  | # Look up name in this scope only. Declare as Python | 
|  | # variable if not found. | 
|  | entry = self.lookup_here(name) | 
|  | if not entry: | 
|  | entry = self.declare_var(name, py_object_type, None) | 
|  | return entry | 
|  |  | 
|  | def lookup_type(self, name): | 
|  | entry = self.lookup(name) | 
|  | if entry and entry.is_type: | 
|  | if entry.type.is_fused and self.fused_to_specific: | 
|  | return entry.type.specialize(self.fused_to_specific) | 
|  | return entry.type | 
|  |  | 
|  | def lookup_operator(self, operator, operands): | 
|  | if operands[0].type.is_cpp_class: | 
|  | obj_type = operands[0].type | 
|  | method = obj_type.scope.lookup("operator%s" % operator) | 
|  | if method is not None: | 
|  | res = PyrexTypes.best_match(operands[1:], method.all_alternatives()) | 
|  | if res is not None: | 
|  | return res | 
|  | function = self.lookup("operator%s" % operator) | 
|  | if function is None: | 
|  | return None | 
|  | return PyrexTypes.best_match(operands, function.all_alternatives()) | 
|  |  | 
|  | def lookup_operator_for_types(self, pos, operator, types): | 
|  | from Nodes import Node | 
|  | class FakeOperand(Node): | 
|  | pass | 
|  | operands = [FakeOperand(pos, type=type) for type in types] | 
|  | return self.lookup_operator(operator, operands) | 
|  |  | 
|  | def use_utility_code(self, new_code): | 
|  | self.global_scope().use_utility_code(new_code) | 
|  |  | 
|  | def generate_library_function_declarations(self, code): | 
|  | # Generate extern decls for C library funcs used. | 
|  | pass | 
|  |  | 
|  | def defines_any(self, names): | 
|  | # Test whether any of the given names are | 
|  | # defined in this scope. | 
|  | for name in names: | 
|  | if name in self.entries: | 
|  | return 1 | 
|  | return 0 | 
|  |  | 
|  | def infer_types(self): | 
|  | from TypeInference import get_type_inferer | 
|  | get_type_inferer().infer_types(self) | 
|  |  | 
|  | def is_cpp(self): | 
|  | outer = self.outer_scope | 
|  | if outer is None: | 
|  | return False | 
|  | else: | 
|  | return outer.is_cpp() | 
|  |  | 
|  | def add_include_file(self, filename): | 
|  | self.outer_scope.add_include_file(filename) | 
|  |  | 
|  |  | 
|  | class PreImportScope(Scope): | 
|  |  | 
|  | namespace_cname = Naming.preimport_cname | 
|  |  | 
|  | def __init__(self): | 
|  | Scope.__init__(self, Options.pre_import, None, None) | 
|  |  | 
|  | def declare_builtin(self, name, pos): | 
|  | entry = self.declare(name, name, py_object_type, pos, 'private') | 
|  | entry.is_variable = True | 
|  | entry.is_pyglobal = True | 
|  | return entry | 
|  |  | 
|  |  | 
|  | class BuiltinScope(Scope): | 
|  | #  The builtin namespace. | 
|  |  | 
|  | is_builtin_scope = True | 
|  |  | 
|  | def __init__(self): | 
|  | if Options.pre_import is None: | 
|  | Scope.__init__(self, "__builtin__", None, None) | 
|  | else: | 
|  | Scope.__init__(self, "__builtin__", PreImportScope(), None) | 
|  | self.type_names = {} | 
|  |  | 
|  | for name, definition in self.builtin_entries.iteritems(): | 
|  | cname, type = definition | 
|  | self.declare_var(name, type, None, cname) | 
|  |  | 
|  | def lookup(self, name, language_level=None): | 
|  | # 'language_level' is passed by ModuleScope | 
|  | if language_level == 3: | 
|  | if name == 'str': | 
|  | name = 'unicode' | 
|  | return Scope.lookup(self, name) | 
|  |  | 
|  | def declare_builtin(self, name, pos): | 
|  | if not hasattr(builtins, name): | 
|  | if self.outer_scope is not None: | 
|  | return self.outer_scope.declare_builtin(name, pos) | 
|  | else: | 
|  | if Options.error_on_unknown_names: | 
|  | error(pos, "undeclared name not builtin: %s" % name) | 
|  | else: | 
|  | warning(pos, "undeclared name not builtin: %s" % name, 2) | 
|  |  | 
|  | def declare_builtin_cfunction(self, name, type, cname, python_equiv = None, | 
|  | utility_code = None): | 
|  | # If python_equiv == "*", the Python equivalent has the same name | 
|  | # as the entry, otherwise it has the name specified by python_equiv. | 
|  | name = EncodedString(name) | 
|  | entry = self.declare_cfunction(name, type, None, cname, visibility='extern', | 
|  | utility_code = utility_code) | 
|  | if python_equiv: | 
|  | if python_equiv == "*": | 
|  | python_equiv = name | 
|  | else: | 
|  | python_equiv = EncodedString(python_equiv) | 
|  | var_entry = Entry(python_equiv, python_equiv, py_object_type) | 
|  | var_entry.is_variable = 1 | 
|  | var_entry.is_builtin = 1 | 
|  | var_entry.utility_code = utility_code | 
|  | entry.as_variable = var_entry | 
|  | return entry | 
|  |  | 
|  | def declare_builtin_type(self, name, cname, utility_code = None, objstruct_cname = None): | 
|  | name = EncodedString(name) | 
|  | type = PyrexTypes.BuiltinObjectType(name, cname, objstruct_cname) | 
|  | scope = CClassScope(name, outer_scope=None, visibility='extern') | 
|  | scope.directives = {} | 
|  | if name == 'bool': | 
|  | type.is_final_type = True | 
|  | type.set_scope(scope) | 
|  | self.type_names[name] = 1 | 
|  | entry = self.declare_type(name, type, None, visibility='extern') | 
|  | entry.utility_code = utility_code | 
|  |  | 
|  | var_entry = Entry(name = entry.name, | 
|  | type = self.lookup('type').type, # make sure "type" is the first type declared... | 
|  | pos = entry.pos, | 
|  | cname = "((PyObject*)%s)" % entry.type.typeptr_cname) | 
|  | var_entry.is_variable = 1 | 
|  | var_entry.is_cglobal = 1 | 
|  | var_entry.is_readonly = 1 | 
|  | var_entry.is_builtin = 1 | 
|  | var_entry.utility_code = utility_code | 
|  | if Options.cache_builtins: | 
|  | var_entry.is_const = True | 
|  | entry.as_variable = var_entry | 
|  |  | 
|  | return type | 
|  |  | 
|  | def builtin_scope(self): | 
|  | return self | 
|  |  | 
|  | builtin_entries = { | 
|  |  | 
|  | "type":   ["((PyObject*)&PyType_Type)", py_object_type], | 
|  |  | 
|  | "bool":   ["((PyObject*)&PyBool_Type)", py_object_type], | 
|  | "int":    ["((PyObject*)&PyInt_Type)", py_object_type], | 
|  | "long":   ["((PyObject*)&PyLong_Type)", py_object_type], | 
|  | "float":  ["((PyObject*)&PyFloat_Type)", py_object_type], | 
|  | "complex":["((PyObject*)&PyComplex_Type)", py_object_type], | 
|  |  | 
|  | "bytes":  ["((PyObject*)&PyBytes_Type)", py_object_type], | 
|  | "bytearray":   ["((PyObject*)&PyByteArray_Type)", py_object_type], | 
|  | "str":    ["((PyObject*)&PyString_Type)", py_object_type], | 
|  | "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type], | 
|  |  | 
|  | "tuple":  ["((PyObject*)&PyTuple_Type)", py_object_type], | 
|  | "list":   ["((PyObject*)&PyList_Type)", py_object_type], | 
|  | "dict":   ["((PyObject*)&PyDict_Type)", py_object_type], | 
|  | "set":    ["((PyObject*)&PySet_Type)", py_object_type], | 
|  | "frozenset":   ["((PyObject*)&PyFrozenSet_Type)", py_object_type], | 
|  |  | 
|  | "slice":  ["((PyObject*)&PySlice_Type)", py_object_type], | 
|  | #        "file":   ["((PyObject*)&PyFile_Type)", py_object_type],  # not in Py3 | 
|  |  | 
|  | "None":   ["Py_None", py_object_type], | 
|  | "False":  ["Py_False", py_object_type], | 
|  | "True":   ["Py_True", py_object_type], | 
|  | } | 
|  |  | 
|  | const_counter = 1 # As a temporary solution for compiling code in pxds | 
|  |  | 
|  | class ModuleScope(Scope): | 
|  | # module_name          string             Python name of the module | 
|  | # module_cname         string             C name of Python module object | 
|  | # #module_dict_cname   string             C name of module dict object | 
|  | # method_table_cname   string             C name of method table | 
|  | # doc                  string             Module doc string | 
|  | # doc_cname            string             C name of module doc string | 
|  | # utility_code_list    [UtilityCode]      Queuing utility codes for forwarding to Code.py | 
|  | # python_include_files [string]           Standard  Python headers to be included | 
|  | # include_files        [string]           Other C headers to be included | 
|  | # string_to_entry      {string : Entry}   Map string const to entry | 
|  | # identifier_to_entry  {string : Entry}   Map identifier string const to entry | 
|  | # context              Context | 
|  | # parent_module        Scope              Parent in the import namespace | 
|  | # module_entries       {string : Entry}   For cimport statements | 
|  | # type_names           {string : 1}       Set of type names (used during parsing) | 
|  | # included_files       [string]           Cython sources included with 'include' | 
|  | # pxd_file_loaded      boolean            Corresponding .pxd file has been processed | 
|  | # cimported_modules    [ModuleScope]      Modules imported with cimport | 
|  | # types_imported       {PyrexType}        Set of types for which import code generated | 
|  | # has_import_star      boolean            Module contains import * | 
|  | # cpp                  boolean            Compiling a C++ file | 
|  | # is_cython_builtin    boolean            Is this the Cython builtin scope (or a child scope) | 
|  | # is_package           boolean            Is this a package module? (__init__) | 
|  |  | 
|  | is_module_scope = 1 | 
|  | has_import_star = 0 | 
|  | is_cython_builtin = 0 | 
|  |  | 
|  | def __init__(self, name, parent_module, context): | 
|  | import Builtin | 
|  | self.parent_module = parent_module | 
|  | outer_scope = Builtin.builtin_scope | 
|  | Scope.__init__(self, name, outer_scope, parent_module) | 
|  | if name == "__init__": | 
|  | # Treat Spam/__init__.pyx specially, so that when Python loads | 
|  | # Spam/__init__.so, initSpam() is defined. | 
|  | self.module_name = parent_module.module_name | 
|  | self.is_package = True | 
|  | else: | 
|  | self.module_name = name | 
|  | self.is_package = False | 
|  | self.module_name = EncodedString(self.module_name) | 
|  | self.context = context | 
|  | self.module_cname = Naming.module_cname | 
|  | self.module_dict_cname = Naming.moddict_cname | 
|  | self.method_table_cname = Naming.methtable_cname | 
|  | self.doc = "" | 
|  | self.doc_cname = Naming.moddoc_cname | 
|  | self.utility_code_list = [] | 
|  | self.module_entries = {} | 
|  | self.python_include_files = ["Python.h"] | 
|  | self.include_files = [] | 
|  | self.type_names = dict(outer_scope.type_names) | 
|  | self.pxd_file_loaded = 0 | 
|  | self.cimported_modules = [] | 
|  | self.types_imported = set() | 
|  | self.included_files = [] | 
|  | self.has_extern_class = 0 | 
|  | self.cached_builtins = [] | 
|  | self.undeclared_cached_builtins = [] | 
|  | self.namespace_cname = self.module_cname | 
|  | for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__path__']: | 
|  | self.declare_var(EncodedString(var_name), py_object_type, None) | 
|  |  | 
|  | def qualifying_scope(self): | 
|  | return self.parent_module | 
|  |  | 
|  | def global_scope(self): | 
|  | return self | 
|  |  | 
|  | def lookup(self, name): | 
|  | entry = self.lookup_here(name) | 
|  | if entry is not None: | 
|  | return entry | 
|  |  | 
|  | if self.context is not None: | 
|  | language_level = self.context.language_level | 
|  | else: | 
|  | language_level = 3 | 
|  |  | 
|  | return self.outer_scope.lookup(name, language_level=language_level) | 
|  |  | 
|  | def declare_builtin(self, name, pos): | 
|  | if not hasattr(builtins, name) \ | 
|  | and name not in Code.non_portable_builtins_map \ | 
|  | and name not in Code.uncachable_builtins: | 
|  | if self.has_import_star: | 
|  | entry = self.declare_var(name, py_object_type, pos) | 
|  | return entry | 
|  | else: | 
|  | if Options.error_on_unknown_names: | 
|  | error(pos, "undeclared name not builtin: %s" % name) | 
|  | else: | 
|  | warning(pos, "undeclared name not builtin: %s" % name, 2) | 
|  | # unknown - assume it's builtin and look it up at runtime | 
|  | entry = self.declare(name, None, py_object_type, pos, 'private') | 
|  | entry.is_builtin = 1 | 
|  | return entry | 
|  | if Options.cache_builtins: | 
|  | for entry in self.cached_builtins: | 
|  | if entry.name == name: | 
|  | return entry | 
|  | entry = self.declare(None, None, py_object_type, pos, 'private') | 
|  | if Options.cache_builtins and name not in Code.uncachable_builtins: | 
|  | entry.is_builtin = 1 | 
|  | entry.is_const = 1 # cached | 
|  | entry.name = name | 
|  | entry.cname = Naming.builtin_prefix + name | 
|  | self.cached_builtins.append(entry) | 
|  | self.undeclared_cached_builtins.append(entry) | 
|  | else: | 
|  | entry.is_builtin = 1 | 
|  | entry.name = name | 
|  | return entry | 
|  |  | 
|  | def find_module(self, module_name, pos): | 
|  | # Find a module in the import namespace, interpreting | 
|  | # relative imports relative to this module's parent. | 
|  | # Finds and parses the module's .pxd file if the module | 
|  | # has not been referenced before. | 
|  | return self.global_scope().context.find_module( | 
|  | module_name, relative_to = self.parent_module, pos = pos) | 
|  |  | 
|  | def find_submodule(self, name): | 
|  | # Find and return scope for a submodule of this module, | 
|  | # creating a new empty one if necessary. Doesn't parse .pxd. | 
|  | scope = self.lookup_submodule(name) | 
|  | if not scope: | 
|  | scope = ModuleScope(name, | 
|  | parent_module = self, context = self.context) | 
|  | self.module_entries[name] = scope | 
|  | return scope | 
|  |  | 
|  | def lookup_submodule(self, name): | 
|  | # Return scope for submodule of this module, or None. | 
|  | return self.module_entries.get(name, None) | 
|  |  | 
|  | def add_include_file(self, filename): | 
|  | if filename not in self.python_include_files \ | 
|  | and filename not in self.include_files: | 
|  | self.include_files.append(filename) | 
|  |  | 
|  | def add_imported_module(self, scope): | 
|  | if scope not in self.cimported_modules: | 
|  | for filename in scope.include_files: | 
|  | self.add_include_file(filename) | 
|  | self.cimported_modules.append(scope) | 
|  | for m in scope.cimported_modules: | 
|  | self.add_imported_module(m) | 
|  |  | 
|  | def add_imported_entry(self, name, entry, pos): | 
|  | if entry not in self.entries: | 
|  | self.entries[name] = entry | 
|  | else: | 
|  | warning(pos, "'%s' redeclared  " % name, 0) | 
|  |  | 
|  | def declare_module(self, name, scope, pos): | 
|  | # Declare a cimported module. This is represented as a | 
|  | # Python module-level variable entry with a module | 
|  | # scope attached to it. Reports an error and returns | 
|  | # None if previously declared as something else. | 
|  | entry = self.lookup_here(name) | 
|  | if entry: | 
|  | if entry.is_pyglobal and entry.as_module is scope: | 
|  | return entry # Already declared as the same module | 
|  | if not (entry.is_pyglobal and not entry.as_module): | 
|  | # SAGE -- I put this here so Pyrex | 
|  | # cimport's work across directories. | 
|  | # Currently it tries to multiply define | 
|  | # every module appearing in an import list. | 
|  | # It shouldn't be an error for a module | 
|  | # name to appear again, and indeed the generated | 
|  | # code compiles fine. | 
|  | return entry | 
|  | else: | 
|  | entry = self.declare_var(name, py_object_type, pos) | 
|  | entry.as_module = scope | 
|  | self.add_imported_module(scope) | 
|  | return entry | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0): | 
|  | # Add an entry for a global variable. If it is a Python | 
|  | # object type, and not declared with cdef, it will live | 
|  | # in the module dictionary, otherwise it will be a C | 
|  | # global variable. | 
|  | if not visibility in ('private', 'public', 'extern'): | 
|  | error(pos, "Module-level variable cannot be declared %s" % visibility) | 
|  | if not is_cdef: | 
|  | if type is unspecified_type: | 
|  | type = py_object_type | 
|  | if not (type.is_pyobject and not type.is_extension_type): | 
|  | raise InternalError( | 
|  | "Non-cdef global variable is not a generic Python object") | 
|  |  | 
|  | if not cname: | 
|  | defining = not in_pxd | 
|  | if visibility == 'extern' or (visibility == 'public' and defining): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.var_prefix, name) | 
|  |  | 
|  | entry = self.lookup_here(name) | 
|  | if entry and entry.defined_in_pxd: | 
|  | #if visibility != 'private' and visibility != entry.visibility: | 
|  | #    warning(pos, "Variable '%s' previously declared as '%s'" % (name, entry.visibility), 1) | 
|  | if not entry.type.same_as(type): | 
|  | if visibility == 'extern' and entry.visibility == 'extern': | 
|  | warning(pos, "Variable '%s' type does not match previous declaration" % name, 1) | 
|  | entry.type = type | 
|  | #else: | 
|  | #    error(pos, "Variable '%s' type does not match previous declaration" % name) | 
|  | if entry.visibility != "private": | 
|  | mangled_cname = self.mangle(Naming.var_prefix, name) | 
|  | if entry.cname == mangled_cname: | 
|  | cname = name | 
|  | entry.cname = name | 
|  | if not entry.is_implemented: | 
|  | entry.is_implemented = True | 
|  | return entry | 
|  |  | 
|  | entry = Scope.declare_var(self, name, type, pos, | 
|  | cname=cname, visibility=visibility, | 
|  | api=api, in_pxd=in_pxd, is_cdef=is_cdef) | 
|  | if is_cdef: | 
|  | entry.is_cglobal = 1 | 
|  | if entry.type.is_pyobject: | 
|  | entry.init = 0 | 
|  | self.var_entries.append(entry) | 
|  | else: | 
|  | entry.is_pyglobal = 1 | 
|  | if Options.cimport_from_pyx: | 
|  | entry.used = 1 | 
|  | return entry | 
|  |  | 
|  | def declare_cfunction(self, name, type, pos, | 
|  | cname = None, visibility = 'private', api = 0, in_pxd = 0, | 
|  | defining = 0, modifiers = (), utility_code = None): | 
|  | # Add an entry for a C function. | 
|  | if not cname: | 
|  | if visibility == 'extern' or (visibility == 'public' and defining): | 
|  | cname = name | 
|  | else: | 
|  | cname = self.mangle(Naming.func_prefix, name) | 
|  | entry = self.lookup_here(name) | 
|  | if entry and entry.defined_in_pxd: | 
|  | if entry.visibility != "private": | 
|  | mangled_cname = self.mangle(Naming.var_prefix, name) | 
|  | if entry.cname == mangled_cname: | 
|  | cname = name | 
|  | entry.cname = cname | 
|  | entry.func_cname = cname | 
|  | entry = Scope.declare_cfunction( | 
|  | self, name, type, pos, | 
|  | cname = cname, visibility = visibility, api = api, in_pxd = in_pxd, | 
|  | defining = defining, modifiers = modifiers, utility_code = utility_code) | 
|  | return entry | 
|  |  | 
|  | def declare_global(self, name, pos): | 
|  | entry = self.lookup_here(name) | 
|  | if not entry: | 
|  | self.declare_var(name, py_object_type, pos) | 
|  |  | 
|  | def use_utility_code(self, new_code): | 
|  | if new_code is not None: | 
|  | self.utility_code_list.append(new_code) | 
|  |  | 
|  | def declare_c_class(self, name, pos, defining = 0, implementing = 0, | 
|  | module_name = None, base_type = None, objstruct_cname = None, | 
|  | typeobj_cname = None, typeptr_cname = None, visibility = 'private', typedef_flag = 0, api = 0, | 
|  | buffer_defaults = None, shadow = 0): | 
|  | # If this is a non-extern typedef class, expose the typedef, but use | 
|  | # the non-typedef struct internally to avoid needing forward | 
|  | # declarations for anonymous structs. | 
|  | if typedef_flag and visibility != 'extern': | 
|  | if not (visibility == 'public' or api): | 
|  | warning(pos, "ctypedef only valid for 'extern' , 'public', and 'api'", 2) | 
|  | objtypedef_cname = objstruct_cname | 
|  | typedef_flag = 0 | 
|  | else: | 
|  | objtypedef_cname = None | 
|  | # | 
|  | #  Look for previous declaration as a type | 
|  | # | 
|  | entry = self.lookup_here(name) | 
|  | if entry and not shadow: | 
|  | type = entry.type | 
|  | if not (entry.is_type and type.is_extension_type): | 
|  | entry = None # Will cause redeclaration and produce an error | 
|  | else: | 
|  | scope = type.scope | 
|  | if typedef_flag and (not scope or scope.defined): | 
|  | self.check_previous_typedef_flag(entry, typedef_flag, pos) | 
|  | if (scope and scope.defined) or (base_type and type.base_type): | 
|  | if base_type and base_type is not type.base_type: | 
|  | error(pos, "Base type does not match previous declaration") | 
|  | if base_type and not type.base_type: | 
|  | type.base_type = base_type | 
|  | # | 
|  | #  Make a new entry if needed | 
|  | # | 
|  | if not entry or shadow: | 
|  | type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern') | 
|  | type.pos = pos | 
|  | type.buffer_defaults = buffer_defaults | 
|  | if objtypedef_cname is not None: | 
|  | type.objtypedef_cname = objtypedef_cname | 
|  | if visibility == 'extern': | 
|  | type.module_name = module_name | 
|  | else: | 
|  | type.module_name = self.qualified_name | 
|  | if typeptr_cname: | 
|  | type.typeptr_cname = typeptr_cname | 
|  | else: | 
|  | type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) | 
|  | entry = self.declare_type(name, type, pos, visibility = visibility, | 
|  | defining = 0, shadow = shadow) | 
|  | entry.is_cclass = True | 
|  | if objstruct_cname: | 
|  | type.objstruct_cname = objstruct_cname | 
|  | elif not entry.in_cinclude: | 
|  | type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name) | 
|  | else: | 
|  | error(entry.pos, | 
|  | "Object name required for 'public' or 'extern' C class") | 
|  | self.attach_var_entry_to_c_class(entry) | 
|  | self.c_class_entries.append(entry) | 
|  | # | 
|  | #  Check for re-definition and create scope if needed | 
|  | # | 
|  | if not type.scope: | 
|  | if defining or implementing: | 
|  | scope = CClassScope(name = name, outer_scope = self, | 
|  | visibility = visibility) | 
|  | scope.directives = self.directives.copy() | 
|  | if base_type and base_type.scope: | 
|  | scope.declare_inherited_c_attributes(base_type.scope) | 
|  | type.set_scope(scope) | 
|  | self.type_entries.append(entry) | 
|  | else: | 
|  | if defining and type.scope.defined: | 
|  | error(pos, "C class '%s' already defined" % name) | 
|  | elif implementing and type.scope.implemented: | 
|  | error(pos, "C class '%s' already implemented" % name) | 
|  | # | 
|  | #  Fill in options, checking for compatibility with any previous declaration | 
|  | # | 
|  | if defining: | 
|  | entry.defined_in_pxd = 1 | 
|  | if implementing:   # So that filenames in runtime exceptions refer to | 
|  | entry.pos = pos  # the .pyx file and not the .pxd file | 
|  | if visibility != 'private' and entry.visibility != visibility: | 
|  | error(pos, "Class '%s' previously declared as '%s'" | 
|  | % (name, entry.visibility)) | 
|  | if api: | 
|  | entry.api = 1 | 
|  | if objstruct_cname: | 
|  | if type.objstruct_cname and type.objstruct_cname != objstruct_cname: | 
|  | error(pos, "Object struct name differs from previous declaration") | 
|  | type.objstruct_cname = objstruct_cname | 
|  | if typeobj_cname: | 
|  | if type.typeobj_cname and type.typeobj_cname != typeobj_cname: | 
|  | error(pos, "Type object name differs from previous declaration") | 
|  | type.typeobj_cname = typeobj_cname | 
|  |  | 
|  | if self.directives.get('final'): | 
|  | entry.type.is_final_type = True | 
|  |  | 
|  | # cdef classes are always exported, but we need to set it to | 
|  | # distinguish between unused Cython utility code extension classes | 
|  | entry.used = True | 
|  |  | 
|  | # | 
|  | # Return new or existing entry | 
|  | # | 
|  | return entry | 
|  |  | 
|  | def allocate_vtable_names(self, entry): | 
|  | #  If extension type has a vtable, allocate vtable struct and | 
|  | #  slot names for it. | 
|  | type = entry.type | 
|  | if type.base_type and type.base_type.vtabslot_cname: | 
|  | #print "...allocating vtabslot_cname because base type has one" ### | 
|  | type.vtabslot_cname = "%s.%s" % ( | 
|  | Naming.obj_base_cname, type.base_type.vtabslot_cname) | 
|  | elif type.scope and type.scope.cfunc_entries: | 
|  | # one special case here: when inheriting from builtin | 
|  | # types, the methods may also be built-in, in which | 
|  | # case they won't need a vtable | 
|  | entry_count = len(type.scope.cfunc_entries) | 
|  | base_type = type.base_type | 
|  | while base_type: | 
|  | # FIXME: this will break if we ever get non-inherited C methods | 
|  | if not base_type.scope or entry_count > len(base_type.scope.cfunc_entries): | 
|  | break | 
|  | if base_type.is_builtin_type: | 
|  | # builtin base type defines all methods => no vtable needed | 
|  | return | 
|  | base_type = base_type.base_type | 
|  | #print "...allocating vtabslot_cname because there are C methods" ### | 
|  | type.vtabslot_cname = Naming.vtabslot_cname | 
|  | if type.vtabslot_cname: | 
|  | #print "...allocating other vtable related cnames" ### | 
|  | type.vtabstruct_cname = self.mangle(Naming.vtabstruct_prefix, entry.name) | 
|  | type.vtabptr_cname = self.mangle(Naming.vtabptr_prefix, entry.name) | 
|  |  | 
|  | def check_c_classes_pxd(self): | 
|  | # Performs post-analysis checking and finishing up of extension types | 
|  | # being implemented in this module. This is called only for the .pxd. | 
|  | # | 
|  | # Checks all extension types declared in this scope to | 
|  | # make sure that: | 
|  | # | 
|  | #    * The extension type is fully declared | 
|  | # | 
|  | # Also allocates a name for the vtable if needed. | 
|  | # | 
|  | for entry in self.c_class_entries: | 
|  | # Check defined | 
|  | if not entry.type.scope: | 
|  | error(entry.pos, "C class '%s' is declared but not defined" % entry.name) | 
|  |  | 
|  | def check_c_class(self, entry): | 
|  | type = entry.type | 
|  | name = entry.name | 
|  | visibility = entry.visibility | 
|  | # Check defined | 
|  | if not type.scope: | 
|  | error(entry.pos, "C class '%s' is declared but not defined" % name) | 
|  | # Generate typeobj_cname | 
|  | if visibility != 'extern' and not type.typeobj_cname: | 
|  | type.typeobj_cname = self.mangle(Naming.typeobj_prefix, name) | 
|  | ## Generate typeptr_cname | 
|  | #type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) | 
|  | # Check C methods defined | 
|  | if type.scope: | 
|  | for method_entry in type.scope.cfunc_entries: | 
|  | if not method_entry.is_inherited and not method_entry.func_cname: | 
|  | error(method_entry.pos, "C method '%s' is declared but not defined" % | 
|  | method_entry.name) | 
|  | # Allocate vtable name if necessary | 
|  | if type.vtabslot_cname: | 
|  | #print "ModuleScope.check_c_classes: allocating vtable cname for", self ### | 
|  | type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name) | 
|  |  | 
|  | def check_c_classes(self): | 
|  | # Performs post-analysis checking and finishing up of extension types | 
|  | # being implemented in this module. This is called only for the main | 
|  | # .pyx file scope, not for cimported .pxd scopes. | 
|  | # | 
|  | # Checks all extension types declared in this scope to | 
|  | # make sure that: | 
|  | # | 
|  | #    * The extension type is implemented | 
|  | #    * All required object and type names have been specified or generated | 
|  | #    * All non-inherited C methods are implemented | 
|  | # | 
|  | # Also allocates a name for the vtable if needed. | 
|  | # | 
|  | debug_check_c_classes = 0 | 
|  | if debug_check_c_classes: | 
|  | print("Scope.check_c_classes: checking scope " + self.qualified_name) | 
|  | for entry in self.c_class_entries: | 
|  | if debug_check_c_classes: | 
|  | print("...entry %s %s" % (entry.name, entry)) | 
|  | print("......type = ",  entry.type) | 
|  | print("......visibility = ", entry.visibility) | 
|  | self.check_c_class(entry) | 
|  |  | 
|  | def check_c_functions(self): | 
|  | # Performs post-analysis checking making sure all | 
|  | # defined c functions are actually implemented. | 
|  | for name, entry in self.entries.items(): | 
|  | if entry.is_cfunction: | 
|  | if (entry.defined_in_pxd | 
|  | and entry.scope is self | 
|  | and entry.visibility != 'extern' | 
|  | and not entry.in_cinclude | 
|  | and not entry.is_implemented): | 
|  | error(entry.pos, "Non-extern C function '%s' declared but not defined" % name) | 
|  |  | 
|  | def attach_var_entry_to_c_class(self, entry): | 
|  | # The name of an extension class has to serve as both a type | 
|  | # name and a variable name holding the type object. It is | 
|  | # represented in the symbol table by a type entry with a | 
|  | # variable entry attached to it. For the variable entry, | 
|  | # we use a read-only C global variable whose name is an | 
|  | # expression that refers to the type object. | 
|  | import Builtin | 
|  | var_entry = Entry(name = entry.name, | 
|  | type = Builtin.type_type, | 
|  | pos = entry.pos, | 
|  | cname = "((PyObject*)%s)" % entry.type.typeptr_cname) | 
|  | var_entry.is_variable = 1 | 
|  | var_entry.is_cglobal = 1 | 
|  | var_entry.is_readonly = 1 | 
|  | entry.as_variable = var_entry | 
|  |  | 
|  | def is_cpp(self): | 
|  | return self.cpp | 
|  |  | 
|  | def infer_types(self): | 
|  | from TypeInference import PyObjectTypeInferer | 
|  | PyObjectTypeInferer().infer_types(self) | 
|  |  | 
|  |  | 
|  | class LocalScope(Scope): | 
|  |  | 
|  | # Does the function have a 'with gil:' block? | 
|  | has_with_gil_block = False | 
|  |  | 
|  | # Transient attribute, used for symbol table variable declarations | 
|  | _in_with_gil_block = False | 
|  |  | 
|  | def __init__(self, name, outer_scope, parent_scope = None): | 
|  | if parent_scope is None: | 
|  | parent_scope = outer_scope | 
|  | Scope.__init__(self, name, outer_scope, parent_scope) | 
|  |  | 
|  | def mangle(self, prefix, name): | 
|  | return prefix + name | 
|  |  | 
|  | def declare_arg(self, name, type, pos): | 
|  | # Add an entry for an argument of a function. | 
|  | cname = self.mangle(Naming.var_prefix, name) | 
|  | entry = self.declare(name, cname, type, pos, 'private') | 
|  | entry.is_variable = 1 | 
|  | if type.is_pyobject: | 
|  | entry.init = "0" | 
|  | entry.is_arg = 1 | 
|  | #entry.borrowed = 1 # Not using borrowed arg refs for now | 
|  | self.arg_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0): | 
|  | # Add an entry for a local variable. | 
|  | if visibility in ('public', 'readonly'): | 
|  | error(pos, "Local variable cannot be declared %s" % visibility) | 
|  | entry = Scope.declare_var(self, name, type, pos, | 
|  | cname=cname, visibility=visibility, | 
|  | api=api, in_pxd=in_pxd, is_cdef=is_cdef) | 
|  | if type.is_pyobject: | 
|  | entry.init = "0" | 
|  | entry.is_local = 1 | 
|  |  | 
|  | entry.in_with_gil_block = self._in_with_gil_block | 
|  | self.var_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_global(self, name, pos): | 
|  | # Pull entry from global scope into local scope. | 
|  | if self.lookup_here(name): | 
|  | warning(pos, "'%s' redeclared  ", 0) | 
|  | else: | 
|  | entry = self.global_scope().lookup_target(name) | 
|  | self.entries[name] = entry | 
|  |  | 
|  | def declare_nonlocal(self, name, pos): | 
|  | # Pull entry from outer scope into local scope | 
|  | orig_entry = self.lookup_here(name) | 
|  | if orig_entry and orig_entry.scope is self and not orig_entry.from_closure: | 
|  | error(pos, "'%s' redeclared as nonlocal" % name) | 
|  | else: | 
|  | entry = self.lookup(name) | 
|  | if entry is None or not entry.from_closure: | 
|  | error(pos, "no binding for nonlocal '%s' found" % name) | 
|  |  | 
|  | def lookup(self, name): | 
|  | # Look up name in this scope or an enclosing one. | 
|  | # Return None if not found. | 
|  | entry = Scope.lookup(self, name) | 
|  | if entry is not None: | 
|  | if entry.scope is not self and entry.scope.is_closure_scope: | 
|  | if hasattr(entry.scope, "scope_class"): | 
|  | raise InternalError("lookup() after scope class created.") | 
|  | # The actual c fragment for the different scopes differs | 
|  | # on the outside and inside, so we make a new entry | 
|  | entry.in_closure = True | 
|  | inner_entry = InnerEntry(entry, self) | 
|  | inner_entry.is_variable = True | 
|  | self.entries[name] = inner_entry | 
|  | return inner_entry | 
|  | return entry | 
|  |  | 
|  | def mangle_closure_cnames(self, outer_scope_cname): | 
|  | for entry in self.entries.values(): | 
|  | if entry.from_closure: | 
|  | cname = entry.outer_entry.cname | 
|  | if self.is_passthrough: | 
|  | entry.cname = cname | 
|  | else: | 
|  | if cname.startswith(Naming.cur_scope_cname): | 
|  | cname = cname[len(Naming.cur_scope_cname)+2:] | 
|  | entry.cname = "%s->%s" % (outer_scope_cname, cname) | 
|  | elif entry.in_closure: | 
|  | entry.original_cname = entry.cname | 
|  | entry.cname = "%s->%s" % (Naming.cur_scope_cname, entry.cname) | 
|  |  | 
|  |  | 
|  | class GeneratorExpressionScope(Scope): | 
|  | """Scope for generator expressions and comprehensions.  As opposed | 
|  | to generators, these can be easily inlined in some cases, so all | 
|  | we really need is a scope that holds the loop variable(s). | 
|  | """ | 
|  | def __init__(self, outer_scope): | 
|  | name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref) | 
|  | Scope.__init__(self, name, outer_scope, outer_scope) | 
|  | self.directives = outer_scope.directives | 
|  | self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name) | 
|  |  | 
|  | def mangle(self, prefix, name): | 
|  | return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, name)) | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = True): | 
|  | if type is unspecified_type: | 
|  | # if the outer scope defines a type for this variable, inherit it | 
|  | outer_entry = self.outer_scope.lookup(name) | 
|  | if outer_entry and outer_entry.is_variable: | 
|  | type = outer_entry.type # may still be 'unspecified_type' ! | 
|  | # the parent scope needs to generate code for the variable, but | 
|  | # this scope must hold its name exclusively | 
|  | cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.var_prefix, name or self.next_id())) | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_variable = 1 | 
|  | entry.is_local = 1 | 
|  | self.var_entries.append(entry) | 
|  | self.entries[name] = entry | 
|  | return entry | 
|  |  | 
|  | def declare_pyfunction(self, name, pos, allow_redefine=False): | 
|  | return self.outer_scope.declare_pyfunction( | 
|  | name, pos, allow_redefine) | 
|  |  | 
|  | def declare_lambda_function(self, func_cname, pos): | 
|  | return self.outer_scope.declare_lambda_function(func_cname, pos) | 
|  |  | 
|  | def add_lambda_def(self, def_node): | 
|  | return self.outer_scope.add_lambda_def(def_node) | 
|  |  | 
|  |  | 
|  | class ClosureScope(LocalScope): | 
|  |  | 
|  | is_closure_scope = True | 
|  |  | 
|  | def __init__(self, name, scope_name, outer_scope, parent_scope=None): | 
|  | LocalScope.__init__(self, name, outer_scope, parent_scope) | 
|  | self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name) | 
|  |  | 
|  | #    def mangle_closure_cnames(self, scope_var): | 
|  | #        for entry in self.entries.values() + self.temp_entries: | 
|  | #            entry.in_closure = 1 | 
|  | #        LocalScope.mangle_closure_cnames(self, scope_var) | 
|  |  | 
|  | #    def mangle(self, prefix, name): | 
|  | #        return "%s->%s" % (self.cur_scope_cname, name) | 
|  | #        return "%s->%s" % (self.closure_cname, name) | 
|  |  | 
|  | def declare_pyfunction(self, name, pos, allow_redefine=False): | 
|  | return LocalScope.declare_pyfunction(self, name, pos, allow_redefine, visibility='private') | 
|  |  | 
|  |  | 
|  | class StructOrUnionScope(Scope): | 
|  | #  Namespace of a C struct or union. | 
|  |  | 
|  | def __init__(self, name="?"): | 
|  | Scope.__init__(self, name, None, None) | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0, | 
|  | allow_pyobject = 0): | 
|  | # Add an entry for an attribute. | 
|  | if not cname: | 
|  | cname = name | 
|  | if visibility == 'private': | 
|  | cname = c_safe_identifier(cname) | 
|  | if type.is_cfunction: | 
|  | type = PyrexTypes.CPtrType(type) | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_variable = 1 | 
|  | self.var_entries.append(entry) | 
|  | if type.is_pyobject and not allow_pyobject: | 
|  | error(pos, | 
|  | "C struct/union member cannot be a Python object") | 
|  | if visibility != 'private': | 
|  | error(pos, | 
|  | "C struct/union member cannot be declared %s" % visibility) | 
|  | return entry | 
|  |  | 
|  | def declare_cfunction(self, name, type, pos, | 
|  | cname = None, visibility = 'private', api = 0, in_pxd = 0, | 
|  | defining = 0, modifiers = ()): # currently no utility code ... | 
|  | return self.declare_var(name, type, pos, | 
|  | cname=cname, visibility=visibility) | 
|  |  | 
|  |  | 
|  | class ClassScope(Scope): | 
|  | #  Abstract base class for namespace of | 
|  | #  Python class or extension type. | 
|  | # | 
|  | #  class_name     string   Python name of the class | 
|  | #  scope_prefix   string   Additional prefix for names | 
|  | #                          declared in the class | 
|  | #  doc    string or None   Doc string | 
|  |  | 
|  | def __init__(self, name, outer_scope): | 
|  | Scope.__init__(self, name, outer_scope, outer_scope) | 
|  | self.class_name = name | 
|  | self.doc = None | 
|  |  | 
|  | def lookup(self, name): | 
|  | entry = Scope.lookup(self, name) | 
|  | if entry: | 
|  | return entry | 
|  | if name == "classmethod": | 
|  | # We don't want to use the builtin classmethod here 'cause it won't do the | 
|  | # right thing in this scope (as the class members aren't still functions). | 
|  | # Don't want to add a cfunction to this scope 'cause that would mess with | 
|  | # the type definition, so we just return the right entry. | 
|  | entry = Entry( | 
|  | "classmethod", | 
|  | "__Pyx_Method_ClassMethod", | 
|  | PyrexTypes.CFuncType( | 
|  | py_object_type, | 
|  | [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0)) | 
|  | entry.utility_code_definition = Code.UtilityCode.load_cached("ClassMethod", "CythonFunction.c") | 
|  | entry.is_cfunction = 1 | 
|  | return entry | 
|  |  | 
|  |  | 
|  | class PyClassScope(ClassScope): | 
|  | #  Namespace of a Python class. | 
|  | # | 
|  | #  class_obj_cname     string   C variable holding class object | 
|  |  | 
|  | is_py_class_scope = 1 | 
|  |  | 
|  | def mangle_class_private_name(self, name): | 
|  | return self.mangle_special_name(name) | 
|  |  | 
|  | def mangle_special_name(self, name): | 
|  | if name and name.startswith('__') and not name.endswith('__'): | 
|  | name = EncodedString('_%s%s' % (self.class_name.lstrip('_'), name)) | 
|  | return name | 
|  |  | 
|  | def lookup_here(self, name): | 
|  | name = self.mangle_special_name(name) | 
|  | return ClassScope.lookup_here(self, name) | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0): | 
|  | name = self.mangle_special_name(name) | 
|  | if type is unspecified_type: | 
|  | type = py_object_type | 
|  | # Add an entry for a class attribute. | 
|  | entry = Scope.declare_var(self, name, type, pos, | 
|  | cname=cname, visibility=visibility, | 
|  | api=api, in_pxd=in_pxd, is_cdef=is_cdef) | 
|  | entry.is_pyglobal = 1 | 
|  | entry.is_pyclass_attr = 1 | 
|  | return entry | 
|  |  | 
|  | def declare_nonlocal(self, name, pos): | 
|  | # Pull entry from outer scope into local scope | 
|  | orig_entry = self.lookup_here(name) | 
|  | if orig_entry and orig_entry.scope is self and not orig_entry.from_closure: | 
|  | error(pos, "'%s' redeclared as nonlocal" % name) | 
|  | else: | 
|  | entry = self.lookup(name) | 
|  | if entry is None: | 
|  | error(pos, "no binding for nonlocal '%s' found" % name) | 
|  | else: | 
|  | # FIXME: this works, but it's unclear if it's the | 
|  | # right thing to do | 
|  | self.entries[name] = entry | 
|  |  | 
|  | def declare_global(self, name, pos): | 
|  | # Pull entry from global scope into local scope. | 
|  | if self.lookup_here(name): | 
|  | warning(pos, "'%s' redeclared  ", 0) | 
|  | else: | 
|  | entry = self.global_scope().lookup_target(name) | 
|  | self.entries[name] = entry | 
|  |  | 
|  | def add_default_value(self, type): | 
|  | return self.outer_scope.add_default_value(type) | 
|  |  | 
|  |  | 
|  | class CClassScope(ClassScope): | 
|  | #  Namespace of an extension type. | 
|  | # | 
|  | #  parent_type           CClassType | 
|  | #  #typeobj_cname        string or None | 
|  | #  #objstruct_cname      string | 
|  | #  method_table_cname    string | 
|  | #  getset_table_cname    string | 
|  | #  has_pyobject_attrs    boolean  Any PyObject attributes? | 
|  | #  has_memoryview_attrs  boolean  Any memory view attributes? | 
|  | #  has_cyclic_pyobject_attrs    boolean  Any PyObject attributes that may need GC? | 
|  | #  property_entries      [Entry] | 
|  | #  defined               boolean  Defined in .pxd file | 
|  | #  implemented           boolean  Defined in .pyx file | 
|  | #  inherited_var_entries [Entry]  Adapted var entries from base class | 
|  |  | 
|  | is_c_class_scope = 1 | 
|  |  | 
|  | has_pyobject_attrs = False | 
|  | has_memoryview_attrs = False | 
|  | has_cyclic_pyobject_attrs = False | 
|  | defined = False | 
|  | implemented = False | 
|  |  | 
|  | def __init__(self, name, outer_scope, visibility): | 
|  | ClassScope.__init__(self, name, outer_scope) | 
|  | if visibility != 'extern': | 
|  | self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name) | 
|  | self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name) | 
|  | self.property_entries = [] | 
|  | self.inherited_var_entries = [] | 
|  |  | 
|  | def needs_gc(self): | 
|  | # If the type or any of its base types have Python-valued | 
|  | # C attributes, then it needs to participate in GC. | 
|  | if self.has_cyclic_pyobject_attrs: | 
|  | return True | 
|  | base_type = self.parent_type.base_type | 
|  | if base_type and base_type.scope is not None: | 
|  | return base_type.scope.needs_gc() | 
|  | elif self.parent_type.is_builtin_type: | 
|  | return not self.parent_type.is_gc_simple | 
|  | return False | 
|  |  | 
|  | def needs_tp_clear(self): | 
|  | """ | 
|  | Do we need to generate an implementation for the tp_clear slot? Can | 
|  | be disabled to keep references for the __dealloc__ cleanup function. | 
|  | """ | 
|  | return self.needs_gc() and not self.directives.get('no_gc_clear', False) | 
|  |  | 
|  | def get_refcounted_entries(self, include_weakref=False, | 
|  | include_gc_simple=True): | 
|  | py_attrs = [] | 
|  | py_buffers = [] | 
|  | memoryview_slices = [] | 
|  |  | 
|  | for entry in self.var_entries: | 
|  | if entry.type.is_pyobject: | 
|  | if include_weakref or entry.name != "__weakref__": | 
|  | if include_gc_simple or not entry.type.is_gc_simple: | 
|  | py_attrs.append(entry) | 
|  | elif entry.type == PyrexTypes.c_py_buffer_type: | 
|  | py_buffers.append(entry) | 
|  | elif entry.type.is_memoryviewslice: | 
|  | memoryview_slices.append(entry) | 
|  |  | 
|  | have_entries = py_attrs or py_buffers or memoryview_slices | 
|  | return have_entries, (py_attrs, py_buffers, memoryview_slices) | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'private', | 
|  | api = 0, in_pxd = 0, is_cdef = 0): | 
|  | if is_cdef: | 
|  | # Add an entry for an attribute. | 
|  | if self.defined: | 
|  | error(pos, | 
|  | "C attributes cannot be added in implementation part of" | 
|  | " extension type defined in a pxd") | 
|  | if get_special_method_signature(name): | 
|  | error(pos, | 
|  | "The name '%s' is reserved for a special method." | 
|  | % name) | 
|  | if not cname: | 
|  | cname = name | 
|  | if visibility == 'private': | 
|  | cname = c_safe_identifier(cname) | 
|  | if type.is_cpp_class and visibility != 'extern': | 
|  | type.check_nullary_constructor(pos) | 
|  | self.use_utility_code(Code.UtilityCode("#include <new>")) | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_variable = 1 | 
|  | self.var_entries.append(entry) | 
|  | if type.is_memoryviewslice: | 
|  | self.has_memoryview_attrs = True | 
|  | elif type.is_pyobject and name != '__weakref__': | 
|  | self.has_pyobject_attrs = True | 
|  | if (not type.is_builtin_type | 
|  | or not type.scope or type.scope.needs_gc()): | 
|  | self.has_cyclic_pyobject_attrs = True | 
|  | if visibility not in ('private', 'public', 'readonly'): | 
|  | error(pos, | 
|  | "Attribute of extension type cannot be declared %s" % visibility) | 
|  | if visibility in ('public', 'readonly'): | 
|  | # If the field is an external typedef, we cannot be sure about the type, | 
|  | # so do conversion ourself rather than rely on the CPython mechanism (through | 
|  | # a property; made in AnalyseDeclarationsTransform). | 
|  | entry.needs_property = True | 
|  | if name == "__weakref__": | 
|  | error(pos, "Special attribute __weakref__ cannot be exposed to Python") | 
|  | if not type.is_pyobject: | 
|  | if (not type.create_to_py_utility_code(self) or | 
|  | (visibility=='public' and not | 
|  | type.create_from_py_utility_code(self))): | 
|  | error(pos, | 
|  | "C attribute of type '%s' cannot be accessed from Python" % type) | 
|  | else: | 
|  | entry.needs_property = False | 
|  | return entry | 
|  | else: | 
|  | if type is unspecified_type: | 
|  | type = py_object_type | 
|  | # Add an entry for a class attribute. | 
|  | entry = Scope.declare_var(self, name, type, pos, | 
|  | cname=cname, visibility=visibility, | 
|  | api=api, in_pxd=in_pxd, is_cdef=is_cdef) | 
|  | entry.is_member = 1 | 
|  | entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that | 
|  | # I keep it in for now. is_member should be enough | 
|  | # later on | 
|  | self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname | 
|  | return entry | 
|  |  | 
|  | def declare_pyfunction(self, name, pos, allow_redefine=False): | 
|  | # Add an entry for a method. | 
|  | if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'): | 
|  | error(pos, "Special method %s must be implemented via __richcmp__" % name) | 
|  | if name == "__new__": | 
|  | error(pos, "__new__ method of extension type will change semantics " | 
|  | "in a future version of Pyrex and Cython. Use __cinit__ instead.") | 
|  | entry = self.declare_var(name, py_object_type, pos, | 
|  | visibility='extern') | 
|  | special_sig = get_special_method_signature(name) | 
|  | if special_sig: | 
|  | # Special methods get put in the method table with a particular | 
|  | # signature declared in advance. | 
|  | entry.signature = special_sig | 
|  | entry.is_special = 1 | 
|  | else: | 
|  | entry.signature = pymethod_signature | 
|  | entry.is_special = 0 | 
|  |  | 
|  | self.pyfunc_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def lookup_here(self, name): | 
|  | if name == "__new__": | 
|  | name = EncodedString("__cinit__") | 
|  | entry = ClassScope.lookup_here(self, name) | 
|  | if entry and entry.is_builtin_cmethod: | 
|  | if not self.parent_type.is_builtin_type: | 
|  | # For subtypes of builtin types, we can only return | 
|  | # optimised C methods if the type if final. | 
|  | # Otherwise, subtypes may choose to override the | 
|  | # method, but the optimisation would prevent the | 
|  | # subtype method from being called. | 
|  | if not self.parent_type.is_final_type: | 
|  | return None | 
|  | return entry | 
|  |  | 
|  | def declare_cfunction(self, name, type, pos, | 
|  | cname = None, visibility = 'private', api = 0, in_pxd = 0, | 
|  | defining = 0, modifiers = (), utility_code = None): | 
|  | if get_special_method_signature(name) and not self.parent_type.is_builtin_type: | 
|  | error(pos, "Special methods must be declared with 'def', not 'cdef'") | 
|  | args = type.args | 
|  | if not args: | 
|  | error(pos, "C method has no self argument") | 
|  | elif not self.parent_type.assignable_from(args[0].type): | 
|  | error(pos, "Self argument (%s) of C method '%s' does not match parent type (%s)" % | 
|  | (args[0].type, name, self.parent_type)) | 
|  | entry = self.lookup_here(name) | 
|  | if cname is None: | 
|  | cname = c_safe_identifier(name) | 
|  | if entry: | 
|  | if not entry.is_cfunction: | 
|  | warning(pos, "'%s' redeclared  " % name, 0) | 
|  | else: | 
|  | if defining and entry.func_cname: | 
|  | error(pos, "'%s' already defined" % name) | 
|  | #print "CClassScope.declare_cfunction: checking signature" ### | 
|  | if entry.is_final_cmethod and entry.is_inherited: | 
|  | error(pos, "Overriding final methods is not allowed") | 
|  | elif type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil: | 
|  | pass | 
|  | elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil: | 
|  | entry = self.add_cfunction(name, type, pos, cname, visibility='ignore', modifiers=modifiers) | 
|  | defining = 1 | 
|  | else: | 
|  | error(pos, "Signature not compatible with previous declaration") | 
|  | error(entry.pos, "Previous declaration is here") | 
|  | else: | 
|  | if self.defined: | 
|  | error(pos, | 
|  | "C method '%s' not previously declared in definition part of" | 
|  | " extension type" % name) | 
|  | entry = self.add_cfunction(name, type, pos, cname, | 
|  | visibility, modifiers) | 
|  | if defining: | 
|  | entry.func_cname = self.mangle(Naming.func_prefix, name) | 
|  | entry.utility_code = utility_code | 
|  | type.entry = entry | 
|  |  | 
|  | if u'inline' in modifiers: | 
|  | entry.is_inline_cmethod = True | 
|  |  | 
|  | if (self.parent_type.is_final_type or entry.is_inline_cmethod or | 
|  | self.directives.get('final')): | 
|  | entry.is_final_cmethod = True | 
|  | entry.final_func_cname = entry.func_cname | 
|  |  | 
|  | return entry | 
|  |  | 
|  | def add_cfunction(self, name, type, pos, cname, visibility, modifiers): | 
|  | # Add a cfunction entry without giving it a func_cname. | 
|  | prev_entry = self.lookup_here(name) | 
|  | entry = ClassScope.add_cfunction(self, name, type, pos, cname, | 
|  | visibility, modifiers) | 
|  | entry.is_cmethod = 1 | 
|  | entry.prev_entry = prev_entry | 
|  | return entry | 
|  |  | 
|  | def declare_builtin_cfunction(self, name, type, cname, utility_code = None): | 
|  | # overridden methods of builtin types still have their Python | 
|  | # equivalent that must be accessible to support bound methods | 
|  | name = EncodedString(name) | 
|  | entry = self.declare_cfunction(name, type, None, cname, visibility='extern', | 
|  | utility_code = utility_code) | 
|  | var_entry = Entry(name, name, py_object_type) | 
|  | var_entry.is_variable = 1 | 
|  | var_entry.is_builtin = 1 | 
|  | var_entry.utility_code = utility_code | 
|  | entry.as_variable = var_entry | 
|  | return entry | 
|  |  | 
|  | def declare_property(self, name, doc, pos): | 
|  | entry = self.lookup_here(name) | 
|  | if entry is None: | 
|  | entry = self.declare(name, name, py_object_type, pos, 'private') | 
|  | entry.is_property = 1 | 
|  | entry.doc = doc | 
|  | entry.scope = PropertyScope(name, | 
|  | outer_scope = self.global_scope(), parent_scope = self) | 
|  | entry.scope.parent_type = self.parent_type | 
|  | self.property_entries.append(entry) | 
|  | return entry | 
|  |  | 
|  | def declare_inherited_c_attributes(self, base_scope): | 
|  | # Declare entries for all the C attributes of an | 
|  | # inherited type, with cnames modified appropriately | 
|  | # to work with this type. | 
|  | def adapt(cname): | 
|  | return "%s.%s" % (Naming.obj_base_cname, base_entry.cname) | 
|  |  | 
|  | entries = base_scope.inherited_var_entries + base_scope.var_entries | 
|  | for base_entry in entries: | 
|  | entry = self.declare( | 
|  | base_entry.name, adapt(base_entry.cname), | 
|  | base_entry.type, None, 'private') | 
|  | entry.is_variable = 1 | 
|  | self.inherited_var_entries.append(entry) | 
|  |  | 
|  | # If the class defined in a pxd, specific entries have not been added. | 
|  | # Ensure now that the parent (base) scope has specific entries | 
|  | # Iterate over a copy as get_all_specialized_function_types() will mutate | 
|  | for base_entry in base_scope.cfunc_entries[:]: | 
|  | if base_entry.type.is_fused: | 
|  | base_entry.type.get_all_specialized_function_types() | 
|  |  | 
|  | for base_entry in base_scope.cfunc_entries: | 
|  | cname = base_entry.cname | 
|  | var_entry = base_entry.as_variable | 
|  | is_builtin = var_entry and var_entry.is_builtin | 
|  | if not is_builtin: | 
|  | cname = adapt(cname) | 
|  | entry = self.add_cfunction(base_entry.name, base_entry.type, | 
|  | base_entry.pos, cname, | 
|  | base_entry.visibility, base_entry.func_modifiers) | 
|  | entry.is_inherited = 1 | 
|  | if base_entry.is_final_cmethod: | 
|  | entry.is_final_cmethod = True | 
|  | entry.is_inline_cmethod = base_entry.is_inline_cmethod | 
|  | if (self.parent_scope == base_scope.parent_scope or | 
|  | entry.is_inline_cmethod): | 
|  | entry.final_func_cname = base_entry.final_func_cname | 
|  | if is_builtin: | 
|  | entry.is_builtin_cmethod = True | 
|  | entry.as_variable = var_entry | 
|  | if base_entry.utility_code: | 
|  | entry.utility_code = base_entry.utility_code | 
|  |  | 
|  |  | 
|  | class CppClassScope(Scope): | 
|  | #  Namespace of a C++ class. | 
|  |  | 
|  | is_cpp_class_scope = 1 | 
|  |  | 
|  | default_constructor = None | 
|  | type = None | 
|  |  | 
|  | def __init__(self, name, outer_scope, templates=None): | 
|  | Scope.__init__(self, name, outer_scope, None) | 
|  | self.directives = outer_scope.directives | 
|  | self.inherited_var_entries = [] | 
|  | if templates is not None: | 
|  | for T in templates: | 
|  | template_entry = self.declare( | 
|  | T, T, PyrexTypes.TemplatePlaceholderType(T), None, 'extern') | 
|  | template_entry.is_type = 1 | 
|  |  | 
|  | def declare_var(self, name, type, pos, | 
|  | cname = None, visibility = 'extern', | 
|  | api = 0, in_pxd = 0, is_cdef = 0, | 
|  | allow_pyobject = 0, defining = 0): | 
|  | # Add an entry for an attribute. | 
|  | if not cname: | 
|  | cname = name | 
|  | entry = self.lookup_here(name) | 
|  | if defining and entry is not None: | 
|  | if not entry.type.same_as(type): | 
|  | error(pos, "Function signature does not match previous declaration") | 
|  | else: | 
|  | entry = self.declare(name, cname, type, pos, visibility) | 
|  | entry.is_variable = 1 | 
|  | if type.is_cfunction and self.type: | 
|  | entry.func_cname = "%s::%s" % (self.type.declaration_code(""), cname) | 
|  | if name != "this" and (defining or name != "<init>"): | 
|  | self.var_entries.append(entry) | 
|  | if type.is_pyobject and not allow_pyobject: | 
|  | error(pos, | 
|  | "C++ class member cannot be a Python object") | 
|  | return entry | 
|  |  | 
|  | def check_base_default_constructor(self, pos): | 
|  | # Look for default constructors in all base classes. | 
|  | if self.default_constructor is None: | 
|  | entry = self.lookup(self.name) | 
|  | if not entry.type.base_classes: | 
|  | self.default_constructor = True | 
|  | return | 
|  | for base_class in entry.type.base_classes: | 
|  | if base_class is PyrexTypes.error_type: | 
|  | continue | 
|  | temp_entry = base_class.scope.lookup_here("<init>") | 
|  | found = False | 
|  | if temp_entry is None: | 
|  | continue | 
|  | for alternative in temp_entry.all_alternatives(): | 
|  | type = alternative.type | 
|  | if type.is_ptr: | 
|  | type = type.base_type | 
|  | if not type.args: | 
|  | found = True | 
|  | break | 
|  | if not found: | 
|  | self.default_constructor = temp_entry.scope.name | 
|  | error(pos, "no matching function for call to " \ | 
|  | "%s::%s()" % (temp_entry.scope.name, temp_entry.scope.name)) | 
|  | elif not self.default_constructor: | 
|  | error(pos, "no matching function for call to %s::%s()" % | 
|  | (self.default_constructor, self.default_constructor)) | 
|  |  | 
|  | def declare_cfunction(self, name, type, pos, | 
|  | cname = None, visibility = 'extern', api = 0, in_pxd = 0, | 
|  | defining = 0, modifiers = (), utility_code = None): | 
|  | if name in (self.name.split('::')[-1], '__init__') and cname is None: | 
|  | self.check_base_default_constructor(pos) | 
|  | cname = self.type.cname | 
|  | name = '<init>' | 
|  | type.return_type = PyrexTypes.InvisibleVoidType() | 
|  | elif name == '__dealloc__' and cname is None: | 
|  | cname = "~%s" % self.type.cname | 
|  | name = '<del>' | 
|  | type.return_type = PyrexTypes.InvisibleVoidType() | 
|  | prev_entry = self.lookup_here(name) | 
|  | entry = self.declare_var(name, type, pos, | 
|  | defining=defining, | 
|  | cname=cname, visibility=visibility) | 
|  | if prev_entry and not defining: | 
|  | entry.overloaded_alternatives = prev_entry.all_alternatives() | 
|  | entry.utility_code = utility_code | 
|  | type.entry = entry | 
|  | return entry | 
|  |  | 
|  | def declare_inherited_cpp_attributes(self, base_scope): | 
|  | # Declare entries for all the C++ attributes of an | 
|  | # inherited type, with cnames modified appropriately | 
|  | # to work with this type. | 
|  | for base_entry in \ | 
|  | base_scope.inherited_var_entries + base_scope.var_entries: | 
|  | #contructor is not inherited | 
|  | if base_entry.name == "<init>": | 
|  | continue | 
|  | #print base_entry.name, self.entries | 
|  | if base_entry.name in self.entries: | 
|  | base_entry.name    # FIXME: is there anything to do in this case? | 
|  | entry = self.declare(base_entry.name, base_entry.cname, | 
|  | base_entry.type, None, 'extern') | 
|  | entry.is_variable = 1 | 
|  | self.inherited_var_entries.append(entry) | 
|  | for base_entry in base_scope.cfunc_entries: | 
|  | entry = self.declare_cfunction(base_entry.name, base_entry.type, | 
|  | base_entry.pos, base_entry.cname, | 
|  | base_entry.visibility, 0, | 
|  | modifiers = base_entry.func_modifiers, | 
|  | utility_code = base_entry.utility_code) | 
|  | entry.is_inherited = 1 | 
|  |  | 
|  | def specialize(self, values): | 
|  | scope = CppClassScope(self.name, self.outer_scope) | 
|  | for entry in self.entries.values(): | 
|  | if entry.is_type: | 
|  | scope.declare_type(entry.name, | 
|  | entry.type.specialize(values), | 
|  | entry.pos, | 
|  | entry.cname, | 
|  | template=1) | 
|  | elif entry.type.is_cfunction: | 
|  | for e in entry.all_alternatives(): | 
|  | scope.declare_cfunction(e.name, | 
|  | e.type.specialize(values), | 
|  | e.pos, | 
|  | e.cname, | 
|  | utility_code = e.utility_code) | 
|  | else: | 
|  | scope.declare_var(entry.name, | 
|  | entry.type.specialize(values), | 
|  | entry.pos, | 
|  | entry.cname, | 
|  | entry.visibility) | 
|  |  | 
|  | return scope | 
|  |  | 
|  |  | 
|  | class PropertyScope(Scope): | 
|  | #  Scope holding the __get__, __set__ and __del__ methods for | 
|  | #  a property of an extension type. | 
|  | # | 
|  | #  parent_type   PyExtensionType   The type to which the property belongs | 
|  |  | 
|  | is_property_scope = 1 | 
|  |  | 
|  | def declare_pyfunction(self, name, pos, allow_redefine=False): | 
|  | # Add an entry for a method. | 
|  | signature = get_property_accessor_signature(name) | 
|  | if signature: | 
|  | entry = self.declare(name, name, py_object_type, pos, 'private') | 
|  | entry.is_special = 1 | 
|  | entry.signature = signature | 
|  | return entry | 
|  | else: | 
|  | error(pos, "Only __get__, __set__ and __del__ methods allowed " | 
|  | "in a property declaration") | 
|  | return None | 
|  |  | 
|  |  | 
|  | class CConstScope(Scope): | 
|  |  | 
|  | def __init__(self, const_base_type_scope): | 
|  | Scope.__init__( | 
|  | self, | 
|  | 'const_' + const_base_type_scope.name, | 
|  | const_base_type_scope.outer_scope, | 
|  | const_base_type_scope.parent_scope) | 
|  | self.const_base_type_scope = const_base_type_scope | 
|  |  | 
|  | def lookup_here(self, name): | 
|  | entry = self.const_base_type_scope.lookup_here(name) | 
|  | if entry is not None: | 
|  | entry = copy.copy(entry) | 
|  | entry.type = PyrexTypes.c_const_type(entry.type) | 
|  | return entry | 
|  |  | 
|  | class TemplateScope(Scope): | 
|  | def __init__(self, name, outer_scope): | 
|  | Scope.__init__(self, name, outer_scope, None) | 
|  | self.directives = outer_scope.directives |