Symtab.py 103 KB
Newer Older
William Stein's avatar
William Stein committed
1
#
2
#   Symbol Table
William Stein's avatar
William Stein committed
3 4
#

5 6
from __future__ import absolute_import

William Stein's avatar
William Stein committed
7
import re
8 9
import copy
import operator
10 11 12 13 14 15

try:
    import __builtin__ as builtins
except ImportError:  # Py3
    import builtins

16 17 18 19 20
from .Errors import warning, error, InternalError
from .StringEncoding import EncodedString
from . import Options, Naming
from . import PyrexTypes
from .PyrexTypes import py_object_type, unspecified_type
21 22 23
from .TypeSlots import (
    pyfunction_signature, pymethod_signature, richcmp_special_methods,
    get_special_method_signature, get_property_accessor_signature)
24

25
from . import Code
William Stein's avatar
William Stein committed
26

27
iso_c99_keywords = set(
28 29 30 31
['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',
32 33
    'volatile', 'while',
    '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict'])
34

35

36
def c_safe_identifier(cname):
37 38 39
    # There are some C limitations on struct entry names.
    if ((cname[:2] == '__'
         and not (cname.startswith(Naming.pyrex_prefix)
40
                  or cname in ('__weakref__', '__dict__')))
41
        or cname in iso_c99_keywords):
42 43 44
        cname = Naming.pyrex_prefix + cname
    return cname

45
class BufferAux(object):
46
    writable_needed = False
47

48 49 50
    def __init__(self, buflocal_nd_var, rcbuf_var):
        self.buflocal_nd_var = buflocal_nd_var
        self.rcbuf_var = rcbuf_var
51

52 53 54
    def __repr__(self):
        return "<BufferAux %r>" % self.__dict__

Stefan Behnel's avatar
Stefan Behnel committed
55

56
class Entry(object):
William Stein's avatar
William Stein committed
57 58 59 60 61 62 63 64
    # 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'
65
    # is_builtin       boolean    Is an entry in the Python builtins dict
William Stein's avatar
William Stein committed
66 67 68 69
    # is_cglobal       boolean    Is a C global variable
    # is_pyglobal      boolean    Is a Python module-level variable
    #                               or class attribute during
    #                               class construction
70
    # is_member        boolean    Is an assigned class member
Stefan Behnel's avatar
Stefan Behnel committed
71
    # is_pyclass_attr  boolean    Is a name in a Python class namespace
William Stein's avatar
William Stein committed
72 73 74
    # is_variable      boolean    Is a variable
    # is_cfunction     boolean    Is a C function
    # is_cmethod       boolean    Is a C method of an extension type
Stefan Behnel's avatar
Stefan Behnel committed
75
    # is_builtin_cmethod boolean  Is a C method of a builtin type (implies is_cmethod)
76
    # is_unbound_cmethod boolean  Is an unbound C method of an extension type
77 78
    # is_final_cmethod   boolean  Is non-overridable C method
    # is_inline_cmethod  boolean  Is inlined C method
79
    # is_anonymous     boolean    Is a anonymous pyfunction entry
William Stein's avatar
William Stein committed
80
    # is_type          boolean    Is a type definition
81
    # is_cclass        boolean    Is an extension class
Danilo Freitas's avatar
Danilo Freitas committed
82
    # is_cpp_class     boolean    Is a C++ class
William Stein's avatar
William Stein committed
83 84 85 86 87 88
    # 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
89
    # is_arg           boolean    Is the arg of a method
90
    # is_local         boolean    Is a local variable
91
    # in_closure       boolean    Is referenced in an inner scope
92
    # in_subscope      boolean    Belongs to a generator expression scope
William Stein's avatar
William Stein committed
93 94
    # is_readonly      boolean    Can't be assigned to
    # func_cname       string     C func implementing Python func
95
    # func_modifiers   [string]   C function modifiers ('inline')
William Stein's avatar
William Stein committed
96 97 98 99 100 101
    # 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
102
    #                               type name or builtin C function as a variable
William Stein's avatar
William Stein committed
103 104 105 106 107 108 109 110 111 112 113
    # 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
114
    # is_identifier    boolean    For string const entries, value is an identifier
115
    # used             boolean
116 117 118
    # 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)
Stefan Behnel's avatar
Stefan Behnel committed
119
    # api              boolean    Generate C API for C class or function
Stefan Behnel's avatar
Stefan Behnel committed
120
    # utility_code     string     Utility code needed when this entry is used
121
    #
122
    # buffer_aux       BufferAux or None  Extra information needed for buffer variables
123 124
    # inline_func_in_pxd boolean  Hacky special case for inline function in pxd file.
    #                             Ideally this should not be necesarry.
Craig Citro's avatar
Craig Citro committed
125
    # might_overflow   boolean    In an arithmetic expression that could cause
126
    #                             overflow (used for type inference).
127 128 129
    # utility_code_definition     For some Cython builtins, the utility code
    #                             which contains the definition of the entry.
    #                             Currently only supported for CythonScope entries.
130 131
    # error_on_uninitialized      Have Control Flow issue an error when this entry is
    #                             used uninitialized
Vitja Makarov's avatar
Vitja Makarov committed
132
    # cf_used          boolean    Entry is used
133 134
    # is_fused_specialized boolean Whether this entry of a cdef or def function
    #                              is a specialization
William Stein's avatar
William Stein committed
135

136
    # TODO: utility_code and utility_code_definition serves the same purpose...
William Stein's avatar
William Stein committed
137

138
    inline_func_in_pxd = False
William Stein's avatar
William Stein committed
139 140 141 142 143 144
    borrowed = 0
    init = ""
    visibility = 'private'
    is_builtin = 0
    is_cglobal = 0
    is_pyglobal = 0
145
    is_member = 0
Stefan Behnel's avatar
Stefan Behnel committed
146
    is_pyclass_attr = 0
William Stein's avatar
William Stein committed
147 148 149
    is_variable = 0
    is_cfunction = 0
    is_cmethod = 0
Stefan Behnel's avatar
Stefan Behnel committed
150
    is_builtin_cmethod = False
151
    is_unbound_cmethod = 0
152
    is_final_cmethod = 0
153
    is_inline_cmethod = 0
154
    is_anonymous = 0
William Stein's avatar
William Stein committed
155
    is_type = 0
156
    is_cclass = 0
Danilo Freitas's avatar
Danilo Freitas committed
157
    is_cpp_class = 0
William Stein's avatar
William Stein committed
158 159 160 161 162 163
    is_const = 0
    is_property = 0
    doc_cname = None
    getter_cname = None
    setter_cname = None
    is_self_arg = 0
164
    is_arg = 0
165
    is_local = 0
166
    in_closure = 0
167
    from_closure = 0
168
    in_subscope = 0
William Stein's avatar
William Stein committed
169 170
    is_declared_generic = 0
    is_readonly = 0
171
    pyfunc_cname = None
William Stein's avatar
William Stein committed
172
    func_cname = None
173
    func_modifiers = []
174
    final_func_cname = None
William Stein's avatar
William Stein committed
175 176 177 178 179 180 181
    doc = None
    as_variable = None
    xdecref_cleanup = 0
    in_cinclude = 0
    as_module = None
    is_inherited = 0
    pystring_cname = None
182
    is_identifier = 0
William Stein's avatar
William Stein committed
183
    is_interned = 0
184
    used = 0
185 186
    is_special = 0
    defined_in_pxd = 0
187
    is_implemented = 0
188
    api = 0
Stefan Behnel's avatar
Stefan Behnel committed
189
    utility_code = None
190
    is_overridable = 0
191
    buffer_aux = None
192
    prev_entry = None
193
    might_overflow = 0
194
    fused_cfunction = None
195
    is_fused_specialized = False
196
    utility_code_definition = None
197
    needs_property = False
198
    in_with_gil_block = 0
199
    from_cython_utility_code = None
200
    error_on_uninitialized = False
Vitja Makarov's avatar
Vitja Makarov committed
201
    cf_used = True
202
    outer_entry = None
203

William Stein's avatar
William Stein committed
204 205 206 207 208 209
    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
DaniloFreitas's avatar
DaniloFreitas committed
210
        self.overloaded_alternatives = []
211 212
        self.cf_assignments = []
        self.cf_references = []
213
        self.inner_entries = []
214
        self.defining_entry = self
215

Robert Bradshaw's avatar
Robert Bradshaw committed
216
    def __repr__(self):
217
        return "%s(<%x>, name=%s, type=%s)" % (type(self).__name__, id(self), self.name, self.type)
218

219 220 221
    def redeclared(self, pos):
        error(pos, "'%s' does not match previous declaration" % self.name)
        error(self.pos, "Previous declaration is here")
222

223 224
    def all_alternatives(self):
        return [self] + self.overloaded_alternatives
225

226
    def all_entries(self):
227 228
        return [self] + self.inner_entries

229 230 231 232 233 234
    def __lt__(left, right):
        if isinstance(left, Entry) and isinstance(right, Entry):
            return (left.name, left.cname) < (right.name, right.cname)
        else:
            return NotImplemented

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261

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):
Stefan Behnel's avatar
Stefan Behnel committed
262 263 264
        if name.startswith('__'):
            # we wouldn't have been called if it was there
            raise AttributeError(name)
265
        return getattr(self.defining_entry, name)
266

267 268 269
    def all_entries(self):
        return self.defining_entry.all_entries()

270

271
class Scope(object):
William Stein's avatar
William Stein committed
272 273 274 275
    # 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
276
    # type_entries      [Entry]            Struct/union/enum/typedef/exttype entries
William Stein's avatar
William Stein committed
277 278 279 280 281 282 283 284
    # 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
285
    # is_builtin_scope  boolean            Is the builtin scope of Python/Cython
William Stein's avatar
William Stein committed
286 287
    # is_py_class_scope boolean            Is a Python class scope
    # is_c_class_scope  boolean            Is an extension type scope
Vitja Makarov's avatar
Vitja Makarov committed
288 289
    # is_closure_scope  boolean            Is a closure scope
    # is_passthrough    boolean            Outer scope is passed directly
290 291
    # is_cpp_class_scope  boolean          Is a C++ class scope
    # is_property_scope boolean            Is a extension type property scope
William Stein's avatar
William Stein committed
292 293 294 295
    # 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
296
    # nogil             boolean            In a nogil section
297
    # directives        dict               Helper variable for the recursive
298
    #                                      analysis, contains directive values.
299
    # is_internal       boolean            Is only used internally (simpler setup)
William Stein's avatar
William Stein committed
300

301
    is_builtin_scope = 0
William Stein's avatar
William Stein committed
302 303
    is_py_class_scope = 0
    is_c_class_scope = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
304
    is_closure_scope = 0
305
    is_genexpr_scope = 0
Vitja Makarov's avatar
Vitja Makarov committed
306
    is_passthrough = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
307
    is_cpp_class_scope = 0
308
    is_property_scope = 0
309
    is_module_scope = 0
310
    is_internal = 0
William Stein's avatar
William Stein committed
311 312
    scope_prefix = ""
    in_cinclude = 0
313
    nogil = 0
314
    fused_to_specific = None
315
    return_type = None
316

William Stein's avatar
William Stein committed
317 318 319 320 321 322
    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
323
        mangled_name = "%d%s_" % (len(name), name.replace('.', '_dot_'))
William Stein's avatar
William Stein committed
324 325 326 327 328
        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:
329
            self.qualified_name = EncodedString(name)
William Stein's avatar
William Stein committed
330 331
            self.scope_prefix = mangled_name
        self.entries = {}
332
        self.subscopes = set()
William Stein's avatar
William Stein committed
333
        self.const_entries = []
334
        self.type_entries = []
William Stein's avatar
William Stein committed
335 336 337 338 339 340 341 342 343 344
        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 = {}
345
        self.identifier_to_entry = {}
346
        self.num_to_entry = {}
Robert Bradshaw's avatar
Robert Bradshaw committed
347
        self.obj_to_entry = {}
348
        self.buffer_entries = []
Stefan Behnel's avatar
Stefan Behnel committed
349
        self.lambda_defs = []
350 351
        self.id_counters = {}

352 353 354
    def __deepcopy__(self, memo):
        return self

355
    def merge_in(self, other, merge_unused=True, whitelist=None):
356
        # Use with care...
357
        entries = []
358
        for name, entry in other.entries.items():
359 360 361
            if not whitelist or name in whitelist:
                if entry.used or merge_unused:
                    entries.append((name, entry))
Mark Florisson's avatar
Mark Florisson committed
362

363 364 365
        self.entries.update(entries)

        for attr in ('const_entries',
366 367 368 369 370 371 372
                     'type_entries',
                     'sue_entries',
                     'arg_entries',
                     'var_entries',
                     'pyfunc_entries',
                     'cfunc_entries',
                     'c_class_entries'):
373
            self_entries = getattr(self, attr)
Stefan Behnel's avatar
Stefan Behnel committed
374
            names = set(e.name for e in self_entries)
375
            for entry in getattr(other, attr):
376
                if (entry.used or merge_unused) and entry.name not in names:
377
                    self_entries.append(entry)
378

William Stein's avatar
William Stein committed
379 380
    def __str__(self):
        return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
381

William Stein's avatar
William Stein committed
382 383
    def qualifying_scope(self):
        return self.parent_scope
384

William Stein's avatar
William Stein committed
385 386 387 388 389
    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)
390

William Stein's avatar
William Stein committed
391 392 393 394 395 396
    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)
397

398 399 400 401 402
    def mangle_class_private_name(self, name):
        if self.parent_scope:
            return self.parent_scope.mangle_class_private_name(name)
        return name

403
    def next_id(self, name=None):
404 405
        # Return a cname fragment that is unique for this module
        counters = self.global_scope().id_counters
406
        try:
407
            count = counters[name] + 1
408 409
        except KeyError:
            count = 0
410
        counters[name] = count
411
        if name:
412 413 414
            if not count:
                # unique names don't need a suffix, reoccurrences will get one
                return name
415 416 417 418
            return '%s%d' % (name, count)
        else:
            return '%d' % count

William Stein's avatar
William Stein committed
419
    def global_scope(self):
420
        """ Return the module-level scope containing this scope. """
William Stein's avatar
William Stein committed
421
        return self.outer_scope.global_scope()
422

423
    def builtin_scope(self):
424
        """ Return the module-level scope containing this scope. """
425 426
        return self.outer_scope.builtin_scope()

427 428 429 430 431 432
    def iter_local_scopes(self):
        yield self
        if self.subscopes:
            for scope in sorted(self.subscopes, key=operator.attrgetter('scope_prefix')):
                yield scope

433
    def declare(self, name, cname, type, pos, visibility, shadow = 0, is_type = 0, create_wrapper = 0):
William Stein's avatar
William Stein committed
434
        # Create new entry, and add to dictionary if
435
        # name is not None. Reports a warning if already
William Stein's avatar
William Stein committed
436
        # declared.
437
        if type.is_buffer and not isinstance(self, LocalScope): # and not is_type:
438
            error(pos, 'Buffer types only allowed as function local variables')
439
        if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
440
            # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
441
            warning(pos, "'%s' is a reserved name in C." % cname, -1)
Stefan Behnel's avatar
Stefan Behnel committed
442
        entries = self.entries
443
        if name and name in entries and not shadow:
444 445 446 447
            old_type = entries[name].type
            if self.is_cpp_class_scope and type.is_cfunction and old_type.is_cfunction and type != old_type:
                # C++ method overrides are ok
                pass
448 449 450
            elif self.is_cpp_class_scope and entries[name].is_inherited:
                # Likewise ignore inherited classes.
                pass
451
            elif visibility == 'extern':
452
                warning(pos, "'%s' redeclared " % name, 0)
453
            elif visibility != 'ignore':
454
                error(pos, "'%s' redeclared " % name)
William Stein's avatar
William Stein committed
455 456
        entry = Entry(name, cname, type, pos = pos)
        entry.in_cinclude = self.in_cinclude
457
        entry.create_wrapper = create_wrapper
William Stein's avatar
William Stein committed
458 459
        if name:
            entry.qualified_name = self.qualify_name(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
460 461 462 463
#            if name in entries and self.is_cpp():
#                entries[name].overloaded_alternatives.append(entry)
#            else:
#                entries[name] = entry
464 465
            if not shadow:
                entries[name] = entry
466 467

        if type.is_memoryviewslice:
468
            from . import MemoryView
Mark Florisson's avatar
Mark Florisson committed
469
            entry.init = MemoryView.memslice_entry_init
470

471
        entry.scope = self
472
        entry.visibility = visibility
William Stein's avatar
William Stein committed
473
        return entry
474

William Stein's avatar
William Stein committed
475
    def qualify_name(self, name):
476
        return EncodedString("%s.%s" % (self.qualified_name, name))
477

478
    def declare_const(self, name, type, value, pos, cname = None, visibility = 'private', api = 0, create_wrapper = 0):
William Stein's avatar
William Stein committed
479 480
        # Add an entry for a named constant.
        if not cname:
481
            if self.in_cinclude or (visibility == 'public' or api):
William Stein's avatar
William Stein committed
482 483 484
                cname = name
            else:
                cname = self.mangle(Naming.enum_prefix, name)
485
        entry = self.declare(name, cname, type, pos, visibility, create_wrapper = create_wrapper)
William Stein's avatar
William Stein committed
486
        entry.is_const = 1
487
        entry.value_node = value
William Stein's avatar
William Stein committed
488
        return entry
489 490

    def declare_type(self, name, type, pos,
491 492
            cname = None, visibility = 'private', api = 0, defining = 1,
            shadow = 0, template = 0):
William Stein's avatar
William Stein committed
493 494 495
        # Add an entry for a type definition.
        if not cname:
            cname = name
496 497
        entry = self.declare(name, cname, type, pos, visibility, shadow,
                             is_type=True)
William Stein's avatar
William Stein committed
498
        entry.is_type = 1
499
        entry.api = api
500 501
        if defining:
            self.type_entries.append(entry)
502

503 504
        if not template:
            type.entry = entry
505

506
        # here we would set as_variable to an object representing this type
William Stein's avatar
William Stein committed
507
        return entry
508

509
    def declare_typedef(self, name, base_type, pos, cname = None,
510
                        visibility = 'private', api = 0):
511
        if not cname:
512
            if self.in_cinclude or (visibility != 'private' or api):
513 514 515
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
516
        try:
517 518 519 520
            if self.is_cpp_class_scope:
                namespace = self.outer_scope.lookup(self.name).type
            else:
                namespace = None
521
            type = PyrexTypes.create_typedef_type(name, base_type, cname,
522 523
                                                  (visibility == 'extern'),
                                                  namespace)
524
        except ValueError as e:
525
            error(pos, e.args[0])
526
            type = PyrexTypes.error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
527
        entry = self.declare_type(name, type, pos, cname,
528
                                  visibility = visibility, api = api)
529
        type.qualified_name = entry.qualified_name
Stefan Behnel's avatar
Stefan Behnel committed
530
        return entry
Robert Bradshaw's avatar
Robert Bradshaw committed
531 532 533

    def declare_struct_or_union(self, name, kind, scope,
                                typedef_flag, pos, cname = None,
534 535
                                visibility = 'private', api = 0,
                                packed = False):
William Stein's avatar
William Stein committed
536 537
        # Add an entry for a struct or union definition.
        if not cname:
538
            if self.in_cinclude or (visibility == 'public' or api):
William Stein's avatar
William Stein committed
539 540 541 542 543
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
        entry = self.lookup_here(name)
        if not entry:
544
            type = PyrexTypes.CStructOrUnionType(
545
                name, kind, scope, typedef_flag, cname, packed)
546
            entry = self.declare_type(name, type, pos, cname,
547 548
                visibility = visibility, api = api,
                defining = scope is not None)
William Stein's avatar
William Stein committed
549
            self.sue_entries.append(entry)
550
            type.entry = entry
William Stein's avatar
William Stein committed
551
        else:
552 553
            if not (entry.is_type and entry.type.is_struct_or_union
                    and entry.type.kind == kind):
554
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
555
            elif scope and entry.type.scope:
556
                warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0)
William Stein's avatar
William Stein committed
557 558
            else:
                self.check_previous_typedef_flag(entry, typedef_flag, pos)
559
                self.check_previous_visibility(entry, visibility, pos)
William Stein's avatar
William Stein committed
560 561
                if scope:
                    entry.type.scope = scope
562
                    self.type_entries.append(entry)
563 564
        if self.is_cpp_class_scope:
            entry.type.namespace = self.outer_scope.lookup(self.name).type
William Stein's avatar
William Stein committed
565
        return entry
566

Robert Bradshaw's avatar
Robert Bradshaw committed
567
    def declare_cpp_class(self, name, scope,
568
            pos, cname = None, base_classes = (),
Robert Bradshaw's avatar
Robert Bradshaw committed
569 570
            visibility = 'extern', templates = None):
        if cname is None:
571 572 573 574
            if self.in_cinclude or (visibility != 'private'):
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
575
        base_classes = list(base_classes)
576
        entry = self.lookup_here(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
577 578 579 580 581
        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)
582
            self.sue_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
583 584
        else:
            if not (entry.is_type and entry.type.is_cpp_class):
585 586
                error(pos, "'%s' redeclared " % name)
                return None
Robert Bradshaw's avatar
Robert Bradshaw committed
587 588 589 590 591 592
            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)
593
            if base_classes:
Stefan Behnel's avatar
Stefan Behnel committed
594
                if entry.type.base_classes and entry.type.base_classes != base_classes:
595 596 597 598 599 600
                    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")
601

Robert Bradshaw's avatar
Robert Bradshaw committed
602 603
        def declare_inherited_attributes(entry, base_classes):
            for base_class in base_classes:
Robert Bradshaw's avatar
Robert Bradshaw committed
604 605
                if base_class is PyrexTypes.error_type:
                    continue
606 607 608 609
                if base_class.scope is None:
                    error(pos, "Cannot inherit from incomplete type")
                else:
                    declare_inherited_attributes(entry, base_class.base_classes)
610
                    entry.type.scope.declare_inherited_cpp_attributes(base_class)
611
        if scope:
612
            declare_inherited_attributes(entry, base_classes)
613
            scope.declare_var(name="this", cname="this", type=PyrexTypes.CPtrType(entry.type), pos=entry.pos)
Robert Bradshaw's avatar
Robert Bradshaw committed
614 615 616 617
        if self.is_cpp_class_scope:
            entry.type.namespace = self.outer_scope.lookup(self.name).type
        return entry

William Stein's avatar
William Stein committed
618
    def check_previous_typedef_flag(self, entry, typedef_flag, pos):
Stefan Behnel's avatar
Stefan Behnel committed
619
        if typedef_flag != entry.type.typedef_flag:
William Stein's avatar
William Stein committed
620 621
            error(pos, "'%s' previously declared using '%s'" % (
                entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
622

623
    def check_previous_visibility(self, entry, visibility, pos):
Stefan Behnel's avatar
Stefan Behnel committed
624
        if entry.visibility != visibility:
625 626
            error(pos, "'%s' previously declared as '%s'" % (
                entry.name, entry.visibility))
Robert Bradshaw's avatar
Robert Bradshaw committed
627

628
    def declare_enum(self, name, pos, cname, typedef_flag,
629
            visibility = 'private', api = 0, create_wrapper = 0):
William Stein's avatar
William Stein committed
630 631
        if name:
            if not cname:
632 633
                if (self.in_cinclude or visibility == 'public'
                    or visibility == 'extern' or api):
William Stein's avatar
William Stein committed
634 635 636
                    cname = name
                else:
                    cname = self.mangle(Naming.type_prefix, name)
637 638 639 640 641
            if self.is_cpp_class_scope:
                namespace = self.outer_scope.lookup(self.name).type
            else:
                namespace = None
            type = PyrexTypes.CEnumType(name, cname, typedef_flag, namespace)
William Stein's avatar
William Stein committed
642
        else:
643 644
            type = PyrexTypes.c_anon_enum_type
        entry = self.declare_type(name, type, pos, cname = cname,
645
            visibility = visibility, api = api)
646
        entry.create_wrapper = create_wrapper
William Stein's avatar
William Stein committed
647 648
        entry.enum_values = []
        self.sue_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
649
        return entry
650

651 652
    def declare_tuple_type(self, pos, components):
        return self.outer_scope.declare_tuple_type(pos, components)
653

654
    def declare_var(self, name, type, pos,
655 656
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0):
William Stein's avatar
William Stein committed
657 658
        # Add an entry for a variable.
        if not cname:
659
            if visibility != 'private' or api:
William Stein's avatar
William Stein committed
660 661 662
                cname = name
            else:
                cname = self.mangle(Naming.var_prefix, name)
663
        if type.is_cpp_class and visibility != 'extern':
664
            type.check_nullary_constructor(pos)
665
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
666
        entry.is_variable = 1
667 668 669 670 671 672
        if in_pxd and visibility != 'extern':
            entry.defined_in_pxd = 1
            entry.used = 1
        if api:
            entry.api = 1
            entry.used = 1
William Stein's avatar
William Stein committed
673
        return entry
674

William Stein's avatar
William Stein committed
675 676
    def declare_builtin(self, name, pos):
        return self.outer_scope.declare_builtin(name, pos)
677 678

    def _declare_pyfunction(self, name, pos, visibility='extern', entry=None):
679
        if entry and not entry.type.is_cfunction:
680
            error(pos, "'%s' already declared" % name)
681 682
            error(entry.pos, "Previous declaration is here")
        entry = self.declare_var(name, py_object_type, pos, visibility=visibility)
William Stein's avatar
William Stein committed
683 684 685
        entry.signature = pyfunction_signature
        self.pyfunc_entries.append(entry)
        return entry
Stefan Behnel's avatar
Stefan Behnel committed
686

687 688 689
    def declare_pyfunction(self, name, pos, allow_redefine=False, visibility='extern'):
        # Add an entry for a Python function.
        entry = self.lookup_here(name)
690
        if not allow_redefine:
691 692 693 694
            return self._declare_pyfunction(name, pos, visibility=visibility, entry=entry)
        if entry:
            if entry.type.is_unspecified:
                entry.type = py_object_type
695
            elif entry.type is not py_object_type:
696 697 698 699 700 701 702 703 704 705 706
                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

707
    def declare_lambda_function(self, lambda_name, pos):
Stefan Behnel's avatar
Stefan Behnel committed
708
        # Add an entry for an anonymous Python function.
709 710 711 712
        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)

713
        entry = self.declare(None, func_cname, py_object_type, pos, 'private')
714 715 716
        entry.name = lambda_name
        entry.qualified_name = qualified_name
        entry.pymethdef_cname = pymethdef_cname
Stefan Behnel's avatar
Stefan Behnel committed
717 718
        entry.func_cname = func_cname
        entry.signature = pyfunction_signature
719
        entry.is_anonymous = True
Stefan Behnel's avatar
Stefan Behnel committed
720 721 722 723 724
        return entry

    def add_lambda_def(self, def_node):
        self.lambda_defs.append(def_node)

William Stein's avatar
William Stein committed
725 726
    def register_pyfunction(self, entry):
        self.pyfunc_entries.append(entry)
727 728

    def declare_cfunction(self, name, type, pos,
729 730
                          cname=None, visibility='private', api=0, in_pxd=0,
                          defining=0, modifiers=(), utility_code=None, overridable=False):
William Stein's avatar
William Stein committed
731
        # Add an entry for a C function.
DaniloFreitas's avatar
DaniloFreitas committed
732
        if not cname:
733
            if visibility != 'private' or api:
DaniloFreitas's avatar
DaniloFreitas committed
734 735 736
                cname = name
            else:
                cname = self.mangle(Naming.func_prefix, name)
737 738
        entry = self.lookup_here(name)
        if entry:
739 740 741 742 743 744 745
            if not in_pxd and visibility != entry.visibility and visibility == 'extern':
                # Previously declared, but now extern => treat this
                # as implementing the function, using the new cname
                defining = True
                visibility = entry.visibility
                entry.cname = cname
                entry.func_cname = cname
Stefan Behnel's avatar
Stefan Behnel committed
746
            if visibility != 'private' and visibility != entry.visibility:
747
                warning(pos, "Function '%s' previously declared as '%s', now as '%s'" % (name, entry.visibility, visibility), 1)
748 749 750
            if overridable != entry.is_overridable:
                warning(pos, "Function '%s' previously declared as '%s'" % (
                    name, 'cpdef' if overridable else 'cdef'), 1)
751
            if entry.type.same_as(type):
752 753
                # Fix with_gil vs nogil.
                entry.type = entry.type.with_with_gil(type.with_gil)
754
            else:
755
                if visibility == 'extern' and entry.visibility == 'extern':
756 757 758 759 760 761 762 763 764 765 766 767
                    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:
768
                        temp = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
769
                        temp.overloaded_alternatives = entry.all_alternatives()
770 771 772 773
                        entry = temp
                    else:
                        warning(pos, "Function signature does not match previous declaration", 1)
                        entry.type = type
774 775 776 777
                elif not in_pxd and entry.defined_in_pxd and type.compatible_signature_with(entry.type):
                    # TODO: check that this was done by a signature optimisation and not a user error.
                    #warning(pos, "Function signature does not match previous declaration", 1)
                    entry.type = type
778 779
                else:
                    error(pos, "Function signature does not match previous declaration")
780
        else:
781
            entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
782
            entry.func_cname = cname
783
            entry.is_overridable = overridable
Stefan Behnel's avatar
Stefan Behnel committed
784
        if in_pxd and visibility != 'extern':
785 786 787
            entry.defined_in_pxd = 1
        if api:
            entry.api = 1
Stefan Behnel's avatar
Stefan Behnel committed
788
        if not defining and not in_pxd and visibility != 'extern':
Stefan Behnel's avatar
Stefan Behnel committed
789
            error(pos, "Non-extern C function '%s' declared but not defined" % name)
790 791
        if defining:
            entry.is_implemented = True
792 793
        if modifiers:
            entry.func_modifiers = modifiers
794 795 796
        if utility_code:
            assert not entry.utility_code, "duplicate utility code definition in entry %s (%s)" % (name, cname)
            entry.utility_code = utility_code
797 798 799 800 801 802 803
        if overridable:
            # names of cpdef functions can be used as variables and can be assigned to
            var_entry = Entry(name, cname, py_object_type)   # FIXME: cname?
            var_entry.is_variable = 1
            var_entry.is_pyglobal = 1
            var_entry.scope = entry.scope
            entry.as_variable = var_entry
804
        type.entry = entry
William Stein's avatar
William Stein committed
805
        return entry
806

807
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers, inherited=False):
William Stein's avatar
William Stein committed
808
        # Add a C function entry without giving it a func_cname.
809
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
810
        entry.is_cfunction = 1
811 812
        if modifiers:
            entry.func_modifiers = modifiers
813 814 815 816 817 818 819 820 821 822 823
        if inherited or type.is_fused:
            self.cfunc_entries.append(entry)
        else:
            # For backwards compatibility reasons, we must keep all non-fused methods
            # before all fused methods, but separately for each type.
            i = len(self.cfunc_entries)
            for cfunc_entry in reversed(self.cfunc_entries):
                if cfunc_entry.is_inherited or not cfunc_entry.type.is_fused:
                    break
                i -= 1
            self.cfunc_entries.insert(i, entry)
William Stein's avatar
William Stein committed
824
        return entry
825

William Stein's avatar
William Stein committed
826 827 828 829 830 831 832
    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)
833

834 835 836 837 838 839 840 841 842 843 844
    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:
845
                error(pos, "'%s' is not a cimported module" % '.'.join(path))
846 847
                return None
        return scope
848

William Stein's avatar
William Stein committed
849 850 851 852
    def lookup(self, name):
        # Look up name in this scope or an enclosing one.
        # Return None if not found.
        return (self.lookup_here(name)
853
            or (self.outer_scope and self.outer_scope.lookup(name))
William Stein's avatar
William Stein committed
854 855 856 857 858
            or None)

    def lookup_here(self, name):
        # Look up in this scope only, return None if not found.
        return self.entries.get(name, None)
859

William Stein's avatar
William Stein committed
860 861 862 863 864 865 866
    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
867

868 869 870
    def lookup_type(self, name):
        entry = self.lookup(name)
        if entry and entry.is_type:
871 872
            if entry.type.is_fused and self.fused_to_specific:
                return entry.type.specialize(self.fused_to_specific)
873
            return entry.type
874

875 876 877 878 879
    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:
880 881 882
                arg_types = [arg.type for arg in operands[1:]]
                res = PyrexTypes.best_match([arg.type for arg in operands[1:]],
                                            method.all_alternatives())
883 884 885 886 887
                if res is not None:
                    return res
        function = self.lookup("operator%s" % operator)
        if function is None:
            return None
888 889
        return PyrexTypes.best_match([arg.type for arg in operands],
                                     function.all_alternatives())
890

891
    def lookup_operator_for_types(self, pos, operator, types):
892
        from .Nodes import Node
893 894 895 896 897
        class FakeOperand(Node):
            pass
        operands = [FakeOperand(pos, type=type) for type in types]
        return self.lookup_operator(operator, operands)

898 899
    def use_utility_code(self, new_code):
        self.global_scope().use_utility_code(new_code)
900

901 902 903
    def use_entry_utility_code(self, entry):
        self.global_scope().use_entry_utility_code(entry)

William Stein's avatar
William Stein committed
904 905 906
    def generate_library_function_declarations(self, code):
        # Generate extern decls for C library funcs used.
        pass
907

William Stein's avatar
William Stein committed
908
    def defines_any(self, names):
909
        # Test whether any of the given names are defined in this scope.
William Stein's avatar
William Stein committed
910
        for name in names:
911
            if name in self.entries:
William Stein's avatar
William Stein committed
912 913
                return 1
        return 0
914

915 916 917 918 919 920 921
    def defines_any_special(self, names):
        # Test whether any of the given names are defined as special methods in this scope.
        for name in names:
            if name in self.entries and self.entries[name].is_special:
                return 1
        return 0

922
    def infer_types(self):
923
        from .TypeInference import get_type_inferer
Robert Bradshaw's avatar
Robert Bradshaw committed
924
        get_type_inferer().infer_types(self)
925

Robert Bradshaw's avatar
Robert Bradshaw committed
926
    def is_cpp(self):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
927 928 929 930 931
        outer = self.outer_scope
        if outer is None:
            return False
        else:
            return outer.is_cpp()
William Stein's avatar
William Stein committed
932

Mark Florisson's avatar
Mark Florisson committed
933 934 935
    def add_include_file(self, filename):
        self.outer_scope.add_include_file(filename)

Mark Florisson's avatar
Mark Florisson committed
936

937
class PreImportScope(Scope):
938 939 940

    namespace_cname = Naming.preimport_cname

941 942
    def __init__(self):
        Scope.__init__(self, Options.pre_import, None, None)
943

944
    def declare_builtin(self, name, pos):
945
        entry = self.declare(name, name, py_object_type, pos, 'private')
946 947 948 949
        entry.is_variable = True
        entry.is_pyglobal = True
        return entry

William Stein's avatar
William Stein committed
950 951 952

class BuiltinScope(Scope):
    #  The builtin namespace.
953

954 955
    is_builtin_scope = True

William Stein's avatar
William Stein committed
956
    def __init__(self):
957 958 959 960
        if Options.pre_import is None:
            Scope.__init__(self, "__builtin__", None, None)
        else:
            Scope.__init__(self, "__builtin__", PreImportScope(), None)
Robert Bradshaw's avatar
Robert Bradshaw committed
961
        self.type_names = {}
962

963
        for name, definition in sorted(self.builtin_entries.items()):
Robert Bradshaw's avatar
Robert Bradshaw committed
964 965
            cname, type = definition
            self.declare_var(name, type, None, cname)
966

967 968 969 970 971 972 973
    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)

William Stein's avatar
William Stein committed
974
    def declare_builtin(self, name, pos):
Stefan Behnel's avatar
Stefan Behnel committed
975
        if not hasattr(builtins, name):
976 977 978
            if self.outer_scope is not None:
                return self.outer_scope.declare_builtin(name, pos)
            else:
979 980 981 982
                if Options.error_on_unknown_names:
                    error(pos, "undeclared name not builtin: %s" % name)
                else:
                    warning(pos, "undeclared name not builtin: %s" % name, 2)
983

984
    def declare_builtin_cfunction(self, name, type, cname, python_equiv=None, utility_code=None):
Stefan Behnel's avatar
Stefan Behnel committed
985 986
        # If python_equiv == "*", the Python equivalent has the same name
        # as the entry, otherwise it has the name specified by python_equiv.
987
        name = EncodedString(name)
988
        entry = self.declare_cfunction(name, type, None, cname, visibility='extern',
989
                                       utility_code=utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
990 991 992
        if python_equiv:
            if python_equiv == "*":
                python_equiv = name
993
            else:
994
                python_equiv = EncodedString(python_equiv)
Stefan Behnel's avatar
Stefan Behnel committed
995
            var_entry = Entry(python_equiv, python_equiv, py_object_type)
996 997
            var_entry.is_variable = 1
            var_entry.is_builtin = 1
998
            var_entry.utility_code = utility_code
999
            var_entry.scope = entry.scope
1000 1001
            entry.as_variable = var_entry
        return entry
1002

1003
    def declare_builtin_type(self, name, cname, utility_code = None, objstruct_cname = None):
1004
        name = EncodedString(name)
1005
        type = PyrexTypes.BuiltinObjectType(name, cname, objstruct_cname)
1006 1007 1008
        scope = CClassScope(name, outer_scope=None, visibility='extern')
        scope.directives = {}
        if name == 'bool':
1009
            type.is_final_type = True
1010
        type.set_scope(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
1011 1012
        self.type_names[name] = 1
        entry = self.declare_type(name, type, None, visibility='extern')
1013
        entry.utility_code = utility_code
Robert Bradshaw's avatar
Robert Bradshaw committed
1014 1015

        var_entry = Entry(name = entry.name,
1016
            type = self.lookup('type').type, # make sure "type" is the first type declared...
Robert Bradshaw's avatar
Robert Bradshaw committed
1017
            pos = entry.pos,
1018
            cname = entry.type.typeptr_cname)
Robert Bradshaw's avatar
Robert Bradshaw committed
1019 1020 1021
        var_entry.is_variable = 1
        var_entry.is_cglobal = 1
        var_entry.is_readonly = 1
1022
        var_entry.is_builtin = 1
1023
        var_entry.utility_code = utility_code
1024
        var_entry.scope = self
1025 1026
        if Options.cache_builtins:
            var_entry.is_const = True
Robert Bradshaw's avatar
Robert Bradshaw committed
1027 1028 1029
        entry.as_variable = var_entry

        return type
1030

1031 1032
    def builtin_scope(self):
        return self
1033

Robert Bradshaw's avatar
Robert Bradshaw committed
1034
    builtin_entries = {
1035 1036 1037 1038

        "type":   ["((PyObject*)&PyType_Type)", py_object_type],

        "bool":   ["((PyObject*)&PyBool_Type)", py_object_type],
1039 1040 1041
        "int":    ["((PyObject*)&PyInt_Type)", py_object_type],
        "long":   ["((PyObject*)&PyLong_Type)", py_object_type],
        "float":  ["((PyObject*)&PyFloat_Type)", py_object_type],
1042 1043 1044
        "complex":["((PyObject*)&PyComplex_Type)", py_object_type],

        "bytes":  ["((PyObject*)&PyBytes_Type)", py_object_type],
1045
        "bytearray":   ["((PyObject*)&PyByteArray_Type)", py_object_type],
1046
        "str":    ["((PyObject*)&PyString_Type)", py_object_type],
1047
        "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type],
1048

1049 1050 1051 1052 1053
        "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],
1054

1055
        "slice":  ["((PyObject*)&PySlice_Type)", py_object_type],
1056
#        "file":   ["((PyObject*)&PyFile_Type)", py_object_type],  # not in Py3
1057

Robert Bradshaw's avatar
Robert Bradshaw committed
1058 1059 1060 1061
        "None":   ["Py_None", py_object_type],
        "False":  ["Py_False", py_object_type],
        "True":   ["Py_True", py_object_type],
    }
William Stein's avatar
William Stein committed
1062

1063 1064
const_counter = 1 # As a temporary solution for compiling code in pxds

William Stein's avatar
William Stein committed
1065 1066 1067 1068 1069 1070 1071
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
1072
    # utility_code_list    [UtilityCode]      Queuing utility codes for forwarding to Code.py
William Stein's avatar
William Stein committed
1073 1074 1075
    # 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
1076
    # identifier_to_entry  {string : Entry}   Map identifier string const to entry
William Stein's avatar
William Stein committed
1077 1078 1079 1080
    # 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)
1081
    # included_files       [string]           Cython sources included with 'include'
William Stein's avatar
William Stein committed
1082 1083
    # pxd_file_loaded      boolean            Corresponding .pxd file has been processed
    # cimported_modules    [ModuleScope]      Modules imported with cimport
1084
    # types_imported       {PyrexType}        Set of types for which import code generated
1085
    # has_import_star      boolean            Module contains import *
Robert Bradshaw's avatar
Robert Bradshaw committed
1086
    # cpp                  boolean            Compiling a C++ file
1087
    # is_cython_builtin    boolean            Is this the Cython builtin scope (or a child scope)
1088
    # is_package           boolean            Is this a package module? (__init__)
1089

1090
    is_module_scope = 1
1091
    has_import_star = 0
1092
    is_cython_builtin = 0
1093
    old_style_globals = 0
William Stein's avatar
William Stein committed
1094 1095

    def __init__(self, name, parent_module, context):
1096
        from . import Builtin
William Stein's avatar
William Stein committed
1097
        self.parent_module = parent_module
1098
        outer_scope = Builtin.builtin_scope
William Stein's avatar
William Stein committed
1099
        Scope.__init__(self, name, outer_scope, parent_module)
1100
        if name == "__init__":
1101 1102 1103
            # Treat Spam/__init__.pyx specially, so that when Python loads
            # Spam/__init__.so, initSpam() is defined.
            self.module_name = parent_module.module_name
1104
            self.is_package = True
1105 1106 1107
        else:
            self.module_name = name
            self.is_package = False
1108
        self.module_name = EncodedString(self.module_name)
William Stein's avatar
William Stein committed
1109 1110 1111 1112 1113 1114
        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
1115
        self.utility_code_list = []
William Stein's avatar
William Stein committed
1116
        self.module_entries = {}
1117
        self.python_include_files = ["Python.h"]
William Stein's avatar
William Stein committed
1118
        self.include_files = []
Robert Bradshaw's avatar
Robert Bradshaw committed
1119
        self.type_names = dict(outer_scope.type_names)
William Stein's avatar
William Stein committed
1120 1121
        self.pxd_file_loaded = 0
        self.cimported_modules = []
1122
        self.types_imported = set()
1123
        self.included_files = []
1124
        self.has_extern_class = 0
1125 1126
        self.cached_builtins = []
        self.undeclared_cached_builtins = []
1127
        self.namespace_cname = self.module_cname
1128
        self._cached_tuple_types = {}
1129 1130
        for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__path__',
                         '__spec__', '__loader__', '__package__', '__cached__']:
1131
            self.declare_var(EncodedString(var_name), py_object_type, None)
1132

William Stein's avatar
William Stein committed
1133 1134
    def qualifying_scope(self):
        return self.parent_module
1135

William Stein's avatar
William Stein committed
1136 1137
    def global_scope(self):
        return self
1138

1139
    def lookup(self, name, language_level=None):
1140 1141 1142
        entry = self.lookup_here(name)
        if entry is not None:
            return entry
Mark Florisson's avatar
Mark Florisson committed
1143

1144 1145
        if language_level is None:
            language_level = self.context.language_level if self.context is not None else 3
Mark Florisson's avatar
Mark Florisson committed
1146

1147
        return self.outer_scope.lookup(name, language_level=language_level)
1148

1149 1150 1151 1152 1153 1154 1155
    def declare_tuple_type(self, pos, components):
        components = tuple(components)
        try:
            ttype = self._cached_tuple_types[components]
        except KeyError:
            ttype = self._cached_tuple_types[components] = PyrexTypes.c_tuple_type(components)
        cname = ttype.cname
Robert Bradshaw's avatar
Robert Bradshaw committed
1156 1157
        entry = self.lookup_here(cname)
        if not entry:
1158
            scope = StructOrUnionScope(cname)
1159
            for ix, component in enumerate(components):
1160
                scope.declare_var(name="f%s" % ix, type=component, pos=pos)
1161 1162
            struct_entry = self.declare_struct_or_union(
                cname + '_struct', 'struct', scope, typedef_flag=True, pos=pos, cname=cname)
Robert Bradshaw's avatar
Robert Bradshaw committed
1163
            self.type_entries.remove(struct_entry)
1164 1165 1166
            ttype.struct_entry = struct_entry
            entry = self.declare_type(cname, ttype, pos, cname)
        ttype.entry = entry
Robert Bradshaw's avatar
Robert Bradshaw committed
1167
        return entry
1168

William Stein's avatar
William Stein committed
1169
    def declare_builtin(self, name, pos):
1170 1171 1172
        if not hasattr(builtins, name) \
               and name not in Code.non_portable_builtins_map \
               and name not in Code.uncachable_builtins:
1173 1174 1175
            if self.has_import_star:
                entry = self.declare_var(name, py_object_type, pos)
                return entry
1176
            else:
1177 1178 1179 1180
                if Options.error_on_unknown_names:
                    error(pos, "undeclared name not builtin: %s" % name)
                else:
                    warning(pos, "undeclared name not builtin: %s" % name, 2)
1181
                # unknown - assume it's builtin and look it up at runtime
1182 1183 1184
                entry = self.declare(name, None, py_object_type, pos, 'private')
                entry.is_builtin = 1
                return entry
1185 1186 1187 1188
        if Options.cache_builtins:
            for entry in self.cached_builtins:
                if entry.name == name:
                    return entry
1189
        if name == 'globals' and not self.old_style_globals:
Robert Bradshaw's avatar
Robert Bradshaw committed
1190
            return self.outer_scope.lookup('__Pyx_Globals')
1191 1192
        else:
            entry = self.declare(None, None, py_object_type, pos, 'private')
1193
        if Options.cache_builtins and name not in Code.uncachable_builtins:
1194
            entry.is_builtin = 1
1195
            entry.is_const = 1 # cached
1196
            entry.name = name
1197 1198 1199 1200 1201
            entry.cname = Naming.builtin_prefix + name
            self.cached_builtins.append(entry)
            self.undeclared_cached_builtins.append(entry)
        else:
            entry.is_builtin = 1
1202
            entry.name = name
William Stein's avatar
William Stein committed
1203
        return entry
1204

1205
    def find_module(self, module_name, pos, relative_level=-1):
William Stein's avatar
William Stein committed
1206 1207 1208 1209
        # 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.
1210
        relative_to = None
1211
        absolute_fallback = False
1212
        if relative_level is not None and relative_level > 0:
1213
            # explicit relative cimport
1214 1215 1216 1217 1218
            # error of going beyond top-level is handled in cimport node
            relative_to = self
            while relative_level > 0 and relative_to:
                relative_to = relative_to.parent_module
                relative_level -= 1
1219 1220 1221 1222
        elif relative_level != 0:
            # -1 or None: try relative cimport first, then absolute
            relative_to = self.parent_module
            absolute_fallback = True
1223 1224

        module_scope = self.global_scope()
1225
        return module_scope.context.find_module(
1226
            module_name, relative_to=relative_to, pos=pos, absolute_fallback=absolute_fallback)
1227

William Stein's avatar
William Stein committed
1228 1229 1230
    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.
1231 1232 1233 1234
        if '.' in name:
            name, submodule = name.split('.', 1)
        else:
            submodule = None
William Stein's avatar
William Stein committed
1235 1236
        scope = self.lookup_submodule(name)
        if not scope:
1237
            scope = ModuleScope(name, parent_module=self, context=self.context)
William Stein's avatar
William Stein committed
1238
            self.module_entries[name] = scope
1239 1240
        if submodule:
            scope = scope.find_submodule(submodule)
William Stein's avatar
William Stein committed
1241
        return scope
1242

1243 1244 1245 1246
    def generate_library_function_declarations(self, code):
        if self.directives['np_pythran']:
            code.putln("import_array();")

William Stein's avatar
William Stein committed
1247 1248
    def lookup_submodule(self, name):
        # Return scope for submodule of this module, or None.
1249 1250 1251 1252 1253 1254 1255 1256
        if '.' in name:
            name, submodule = name.split('.', 1)
        else:
            submodule = None
        module = self.module_entries.get(name, None)
        if submodule and module is not None:
            module = module.lookup_submodule(submodule)
        return module
1257

William Stein's avatar
William Stein committed
1258 1259 1260 1261
    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)
1262

William Stein's avatar
William Stein committed
1263 1264
    def add_imported_module(self, scope):
        if scope not in self.cimported_modules:
1265 1266
            for filename in scope.include_files:
                self.add_include_file(filename)
William Stein's avatar
William Stein committed
1267
            self.cimported_modules.append(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
1268 1269
            for m in scope.cimported_modules:
                self.add_imported_module(m)
1270

William Stein's avatar
William Stein committed
1271
    def add_imported_entry(self, name, entry, pos):
1272 1273 1274
        if entry.is_pyglobal:
            # Allow cimports to follow imports.
            entry.is_variable = True
William Stein's avatar
William Stein committed
1275 1276 1277
        if entry not in self.entries:
            self.entries[name] = entry
        else:
1278
            warning(pos, "'%s' redeclared  " % name, 0)
1279

William Stein's avatar
William Stein committed
1280 1281 1282 1283 1284 1285 1286
    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:
1287 1288
            if entry.is_pyglobal and entry.as_module is scope:
                return entry # Already declared as the same module
William Stein's avatar
William Stein committed
1289
            if not (entry.is_pyglobal and not entry.as_module):
1290 1291 1292 1293 1294 1295
                # 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
1296
                # code compiles fine.
1297
                return entry
William Stein's avatar
William Stein committed
1298 1299
        else:
            entry = self.declare_var(name, py_object_type, pos)
1300
            entry.is_variable = 0
William Stein's avatar
William Stein committed
1301
        entry.as_module = scope
Robert Bradshaw's avatar
Robert Bradshaw committed
1302
        self.add_imported_module(scope)
William Stein's avatar
William Stein committed
1303
        return entry
1304 1305

    def declare_var(self, name, type, pos,
1306 1307
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0):
William Stein's avatar
William Stein committed
1308
        # Add an entry for a global variable. If it is a Python
1309 1310
        # object type, and not declared with cdef, it will live
        # in the module dictionary, otherwise it will be a C
William Stein's avatar
William Stein committed
1311 1312 1313 1314
        # global variable.
        if not visibility in ('private', 'public', 'extern'):
            error(pos, "Module-level variable cannot be declared %s" % visibility)
        if not is_cdef:
1315 1316
            if type is unspecified_type:
                type = py_object_type
William Stein's avatar
William Stein committed
1317 1318 1319
            if not (type.is_pyobject and not type.is_extension_type):
                raise InternalError(
                    "Non-cdef global variable is not a generic Python object")
1320 1321 1322

        if not cname:
            defining = not in_pxd
Stefan Behnel's avatar
Stefan Behnel committed
1323
            if visibility == 'extern' or (visibility == 'public' and defining):
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
                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:
William Stein's avatar
William Stein committed
1351
            entry.is_cglobal = 1
1352 1353
            if entry.type.is_pyobject:
                entry.init = 0
William Stein's avatar
William Stein committed
1354
            self.var_entries.append(entry)
1355 1356
        else:
            entry.is_pyglobal = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1357 1358
        if Options.cimport_from_pyx:
            entry.used = 1
1359 1360 1361
        return entry

    def declare_cfunction(self, name, type, pos,
1362 1363
                          cname=None, visibility='private', api=0, in_pxd=0,
                          defining=0, modifiers=(), utility_code=None, overridable=False):
1364 1365 1366
        if not defining and 'inline' in modifiers:
            # TODO(github/1736): Make this an error.
            warning(pos, "Declarations should not be declared inline.", 1)
1367 1368
        # Add an entry for a C function.
        if not cname:
Stefan Behnel's avatar
Stefan Behnel committed
1369
            if visibility == 'extern' or (visibility == 'public' and defining):
1370 1371 1372
                cname = name
            else:
                cname = self.mangle(Naming.func_prefix, name)
1373
        if visibility == 'extern' and type.optional_arg_count:
Stefan Behnel's avatar
Stefan Behnel committed
1374
            error(pos, "Extern functions cannot have default arguments values.")
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
        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,
1385 1386 1387
            cname=cname, visibility=visibility, api=api, in_pxd=in_pxd,
            defining=defining, modifiers=modifiers, utility_code=utility_code,
            overridable=overridable)
William Stein's avatar
William Stein committed
1388
        return entry
1389

William Stein's avatar
William Stein committed
1390 1391 1392 1393
    def declare_global(self, name, pos):
        entry = self.lookup_here(name)
        if not entry:
            self.declare_var(name, py_object_type, pos)
1394

1395
    def use_utility_code(self, new_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
1396
        if new_code is not None:
1397
            self.utility_code_list.append(new_code)
1398

1399 1400 1401 1402 1403 1404 1405 1406
    def use_entry_utility_code(self, entry):
        if entry is None:
            return
        if entry.utility_code:
            self.utility_code_list.append(entry.utility_code)
        if entry.utility_code_definition:
            self.utility_code_list.append(entry.utility_code_definition)

1407 1408
    def declare_c_class(self, name, pos, defining = 0, implementing = 0,
        module_name = None, base_type = None, objstruct_cname = None,
1409
        typeobj_cname = None, typeptr_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
1410
        buffer_defaults = None, shadow = 0):
1411 1412
        # If this is a non-extern typedef class, expose the typedef, but use
        # the non-typedef struct internally to avoid needing forward
Robert Bradshaw's avatar
Robert Bradshaw committed
1413
        # declarations for anonymous structs.
1414
        if typedef_flag and visibility != 'extern':
1415 1416
            if not (visibility == 'public' or api):
                warning(pos, "ctypedef only valid for 'extern' , 'public', and 'api'", 2)
1417 1418 1419 1420
            objtypedef_cname = objstruct_cname
            typedef_flag = 0
        else:
            objtypedef_cname = None
William Stein's avatar
William Stein committed
1421
        #
1422
        #  Look for previous declaration as a type
William Stein's avatar
William Stein committed
1423 1424
        #
        entry = self.lookup_here(name)
1425
        if entry and not shadow:
William Stein's avatar
William Stein committed
1426 1427
            type = entry.type
            if not (entry.is_type and type.is_extension_type):
1428
                entry = None # Will cause redeclaration and produce an error
William Stein's avatar
William Stein committed
1429
            else:
1430
                scope = type.scope
Robert Bradshaw's avatar
Robert Bradshaw committed
1431
                if typedef_flag and (not scope or scope.defined):
1432 1433 1434 1435 1436 1437
                    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
William Stein's avatar
William Stein committed
1438
        #
1439
        #  Make a new entry if needed
William Stein's avatar
William Stein committed
1440
        #
1441
        if not entry or shadow:
1442
            type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern')
1443
            type.pos = pos
1444
            type.buffer_defaults = buffer_defaults
1445 1446
            if objtypedef_cname is not None:
                type.objtypedef_cname = objtypedef_cname
William Stein's avatar
William Stein committed
1447 1448 1449 1450
            if visibility == 'extern':
                type.module_name = module_name
            else:
                type.module_name = self.qualified_name
1451 1452 1453 1454
            if typeptr_cname:
                type.typeptr_cname = typeptr_cname
            else:
                type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1455
            entry = self.declare_type(name, type, pos, visibility = visibility,
1456
                defining = 0, shadow = shadow)
1457
            entry.is_cclass = True
William Stein's avatar
William Stein committed
1458 1459 1460
            if objstruct_cname:
                type.objstruct_cname = objstruct_cname
            elif not entry.in_cinclude:
1461
                type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
William Stein's avatar
William Stein committed
1462
            else:
1463
                error(entry.pos,
William Stein's avatar
William Stein committed
1464 1465 1466 1467
                    "Object name required for 'public' or 'extern' C class")
            self.attach_var_entry_to_c_class(entry)
            self.c_class_entries.append(entry)
        #
1468
        #  Check for re-definition and create scope if needed
William Stein's avatar
William Stein committed
1469 1470 1471 1472 1473
        #
        if not type.scope:
            if defining or implementing:
                scope = CClassScope(name = name, outer_scope = self,
                    visibility = visibility)
1474
                scope.directives = self.directives.copy()
1475
                if base_type and base_type.scope:
William Stein's avatar
William Stein committed
1476 1477
                    scope.declare_inherited_c_attributes(base_type.scope)
                type.set_scope(scope)
1478
                self.type_entries.append(entry)
William Stein's avatar
William Stein committed
1479 1480 1481 1482 1483 1484
        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)
        #
1485
        #  Fill in options, checking for compatibility with any previous declaration
William Stein's avatar
William Stein committed
1486
        #
1487 1488
        if defining:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
1489 1490
        if implementing:   # So that filenames in runtime exceptions refer to
            entry.pos = pos  # the .pyx file and not the .pxd file
Stefan Behnel's avatar
Stefan Behnel committed
1491
        if visibility != 'private' and entry.visibility != visibility:
Stefan Behnel's avatar
Stefan Behnel committed
1492 1493 1494 1495
            error(pos, "Class '%s' previously declared as '%s'"
                % (name, entry.visibility))
        if api:
            entry.api = 1
William Stein's avatar
William Stein committed
1496
        if objstruct_cname:
Stefan Behnel's avatar
Stefan Behnel committed
1497
            if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
William Stein's avatar
William Stein committed
1498
                error(pos, "Object struct name differs from previous declaration")
1499
            type.objstruct_cname = objstruct_cname
William Stein's avatar
William Stein committed
1500
        if typeobj_cname:
Stefan Behnel's avatar
Stefan Behnel committed
1501
            if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
William Stein's avatar
William Stein committed
1502 1503
                    error(pos, "Type object name differs from previous declaration")
            type.typeobj_cname = typeobj_cname
1504

1505 1506 1507
        if self.directives.get('final'):
            entry.type.is_final_type = True

1508 1509 1510 1511
        # cdef classes are always exported, but we need to set it to
        # distinguish between unused Cython utility code extension classes
        entry.used = True

William Stein's avatar
William Stein committed
1512
        #
1513
        # Return new or existing entry
William Stein's avatar
William Stein committed
1514 1515
        #
        return entry
1516

William Stein's avatar
William Stein committed
1517 1518 1519 1520 1521 1522 1523 1524 1525
    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:
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
            # 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
William Stein's avatar
William Stein committed
1539 1540 1541 1542 1543 1544 1545
            #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)

1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
    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)
Vitja Makarov's avatar
Vitja Makarov committed
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584

    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)

William Stein's avatar
William Stein committed
1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600
    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:
Stefan Behnel's avatar
Stefan Behnel committed
1601
            print("Scope.check_c_classes: checking scope " + self.qualified_name)
William Stein's avatar
William Stein committed
1602 1603
        for entry in self.c_class_entries:
            if debug_check_c_classes:
Stefan Behnel's avatar
Stefan Behnel committed
1604
                print("...entry %s %s" % (entry.name, entry))
1605 1606
                print("......type = ",  entry.type)
                print("......visibility = ", entry.visibility)
Vitja Makarov's avatar
Vitja Makarov committed
1607 1608
            self.check_c_class(entry)

1609
    def check_c_functions(self):
1610
        # Performs post-analysis checking making sure all
1611 1612 1613
        # defined c functions are actually implemented.
        for name, entry in self.entries.items():
            if entry.is_cfunction:
1614
                if (entry.defined_in_pxd
1615
                        and entry.scope is self
1616
                        and entry.visibility != 'extern'
1617
                        and not entry.in_cinclude
1618 1619
                        and not entry.is_implemented):
                    error(entry.pos, "Non-extern C function '%s' declared but not defined" % name)
1620

William Stein's avatar
William Stein committed
1621 1622 1623 1624 1625 1626 1627
    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.
1628
        from . import Builtin
William Stein's avatar
William Stein committed
1629
        var_entry = Entry(name = entry.name,
1630
            type = Builtin.type_type,
William Stein's avatar
William Stein committed
1631
            pos = entry.pos,
1632
            cname = entry.type.typeptr_cname)
William Stein's avatar
William Stein committed
1633 1634 1635
        var_entry.is_variable = 1
        var_entry.is_cglobal = 1
        var_entry.is_readonly = 1
1636
        var_entry.scope = entry.scope
William Stein's avatar
William Stein committed
1637
        entry.as_variable = var_entry
1638

Robert Bradshaw's avatar
Robert Bradshaw committed
1639 1640
    def is_cpp(self):
        return self.cpp
1641

Robert Bradshaw's avatar
Robert Bradshaw committed
1642
    def infer_types(self):
1643
        from .TypeInference import PyObjectTypeInferer
Robert Bradshaw's avatar
Robert Bradshaw committed
1644
        PyObjectTypeInferer().infer_types(self)
1645

1646

1647
class LocalScope(Scope):
William Stein's avatar
William Stein committed
1648

1649 1650 1651 1652 1653 1654
    # 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

1655 1656 1657 1658
    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)
1659

William Stein's avatar
William Stein committed
1660
    def mangle(self, prefix, name):
1661
        return prefix + name
William Stein's avatar
William Stein committed
1662 1663 1664 1665

    def declare_arg(self, name, type, pos):
        # Add an entry for an argument of a function.
        cname = self.mangle(Naming.var_prefix, name)
1666
        entry = self.declare(name, cname, type, pos, 'private')
William Stein's avatar
William Stein committed
1667 1668 1669
        entry.is_variable = 1
        if type.is_pyobject:
            entry.init = "0"
1670
        entry.is_arg = 1
William Stein's avatar
William Stein committed
1671 1672 1673
        #entry.borrowed = 1 # Not using borrowed arg refs for now
        self.arg_entries.append(entry)
        return entry
1674 1675

    def declare_var(self, name, type, pos,
1676 1677
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0):
William Stein's avatar
William Stein committed
1678 1679 1680
        # Add an entry for a local variable.
        if visibility in ('public', 'readonly'):
            error(pos, "Local variable cannot be declared %s" % visibility)
1681
        entry = Scope.declare_var(self, name, type, pos,
1682 1683
                                  cname=cname, visibility=visibility,
                                  api=api, in_pxd=in_pxd, is_cdef=is_cdef)
1684
        if type.is_pyobject:
Robert Bradshaw's avatar
Robert Bradshaw committed
1685
            entry.init = "0"
1686
        entry.is_local = 1
1687 1688

        entry.in_with_gil_block = self._in_with_gil_block
William Stein's avatar
William Stein committed
1689 1690
        self.var_entries.append(entry)
        return entry
1691

William Stein's avatar
William Stein committed
1692 1693 1694
    def declare_global(self, name, pos):
        # Pull entry from global scope into local scope.
        if self.lookup_here(name):
1695
            warning(pos, "'%s' redeclared  ", 0)
William Stein's avatar
William Stein committed
1696 1697 1698
        else:
            entry = self.global_scope().lookup_target(name)
            self.entries[name] = entry
1699 1700 1701

    def declare_nonlocal(self, name, pos):
        # Pull entry from outer scope into local scope
1702 1703 1704
        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)
1705 1706 1707 1708
        else:
            entry = self.lookup(name)
            if entry is None or not entry.from_closure:
                error(pos, "no binding for nonlocal '%s' found" % name)
1709

1710 1711 1712 1713 1714 1715
    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:
Vitja Makarov's avatar
Vitja Makarov committed
1716
                if hasattr(entry.scope, "scope_class"):
1717
                    raise InternalError("lookup() after scope class created.")
1718
                # The actual c fragment for the different scopes differs
1719 1720
                # on the outside and inside, so we make a new entry
                entry.in_closure = True
1721
                inner_entry = InnerEntry(entry, self)
1722 1723 1724 1725
                inner_entry.is_variable = True
                self.entries[name] = inner_entry
                return inner_entry
        return entry
1726

1727
    def mangle_closure_cnames(self, outer_scope_cname):
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
        for scope in self.iter_local_scopes():
            for entry in scope.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)
1741

1742

1743
class GeneratorExpressionScope(Scope):
1744 1745 1746 1747
    """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).
    """
1748 1749
    is_genexpr_scope = True

1750 1751
    def __init__(self, outer_scope):
        name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref)
1752
        Scope.__init__(self, name, outer_scope, outer_scope)
1753
        self.var_entries = outer_scope.var_entries  # keep declarations outside
1754
        self.directives = outer_scope.directives
1755 1756
        self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name)

1757 1758 1759 1760
        while outer_scope.is_genexpr_scope:
            outer_scope = outer_scope.outer_scope
        outer_scope.subscopes.add(self)

1761
    def mangle(self, prefix, name):
1762
        return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, name))
1763 1764

    def declare_var(self, name, type, pos,
1765 1766
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = True):
1767 1768 1769
        if type is unspecified_type:
            # if the outer scope defines a type for this variable, inherit it
            outer_entry = self.outer_scope.lookup(name)
1770
            if outer_entry and outer_entry.is_variable:
1771
                type = outer_entry.type # may still be 'unspecified_type' !
1772
        # the parent scope needs to generate code for the variable, but
1773
        # this scope must hold its name exclusively
1774
        cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.var_prefix, name or self.next_id()))
1775
        entry = self.declare(name, cname, type, pos, visibility)
1776 1777 1778
        entry.is_variable = True
        entry.is_local = True
        entry.in_subscope = True
1779
        self.var_entries.append(entry)
1780 1781 1782
        self.entries[name] = entry
        return entry

1783 1784 1785 1786
    def declare_pyfunction(self, name, pos, allow_redefine=False):
        return self.outer_scope.declare_pyfunction(
            name, pos, allow_redefine)

1787 1788 1789 1790 1791 1792
    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)

1793

Robert Bradshaw's avatar
Robert Bradshaw committed
1794
class ClosureScope(LocalScope):
1795

Robert Bradshaw's avatar
Robert Bradshaw committed
1796 1797
    is_closure_scope = True

1798 1799
    def __init__(self, name, scope_name, outer_scope, parent_scope=None):
        LocalScope.__init__(self, name, outer_scope, parent_scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
1800 1801 1802
        self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name)

#    def mangle_closure_cnames(self, scope_var):
1803 1804
#        for entry in self.entries.values() + self.temp_entries:
#            entry.in_closure = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1805
#        LocalScope.mangle_closure_cnames(self, scope_var)
1806

1807 1808 1809
#    def mangle(self, prefix, name):
#        return "%s->%s" % (self.cur_scope_cname, name)
#        return "%s->%s" % (self.closure_cname, name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1810

1811 1812
    def declare_pyfunction(self, name, pos, allow_redefine=False):
        return LocalScope.declare_pyfunction(self, name, pos, allow_redefine, visibility='private')
1813

1814

William Stein's avatar
William Stein committed
1815 1816
class StructOrUnionScope(Scope):
    #  Namespace of a C struct or union.
1817

1818 1819
    def __init__(self, name="?"):
        Scope.__init__(self, name, None, None)
William Stein's avatar
William Stein committed
1820

1821
    def declare_var(self, name, type, pos,
1822 1823 1824
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0,
                    allow_pyobject = 0):
William Stein's avatar
William Stein committed
1825 1826 1827
        # Add an entry for an attribute.
        if not cname:
            cname = name
1828 1829
            if visibility == 'private':
                cname = c_safe_identifier(cname)
1830
        if type.is_cfunction:
1831
            type = PyrexTypes.CPtrType(type)
1832
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
1833 1834
        entry.is_variable = 1
        self.var_entries.append(entry)
1835
        if type.is_pyobject and not allow_pyobject:
William Stein's avatar
William Stein committed
1836
            error(pos,
Craig Citro's avatar
Craig Citro committed
1837
                  "C struct/union member cannot be a Python object")
Stefan Behnel's avatar
Stefan Behnel committed
1838
        if visibility != 'private':
William Stein's avatar
William Stein committed
1839
            error(pos,
Craig Citro's avatar
Craig Citro committed
1840
                  "C struct/union member cannot be declared %s" % visibility)
William Stein's avatar
William Stein committed
1841 1842
        return entry

1843
    def declare_cfunction(self, name, type, pos,
1844
                          cname=None, visibility='private', api=0, in_pxd=0,
1845 1846 1847
                          defining=0, modifiers=(), overridable=False):  # currently no utility code ...
        if overridable:
            error(pos, "C struct/union member cannot be declared 'cpdef'")
Robert Bradshaw's avatar
Robert Bradshaw committed
1848
        return self.declare_var(name, type, pos,
1849
                                cname=cname, visibility=visibility)
William Stein's avatar
William Stein committed
1850

1851

William Stein's avatar
William Stein committed
1852 1853 1854 1855
class ClassScope(Scope):
    #  Abstract base class for namespace of
    #  Python class or extension type.
    #
1856
    #  class_name     string   Python name of the class
William Stein's avatar
William Stein committed
1857 1858 1859 1860 1861 1862 1863 1864 1865
    #  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

1866
    def lookup(self, name):
1867 1868 1869
        entry = Scope.lookup(self, name)
        if entry:
            return entry
1870
        if name == "classmethod":
1871
            # We don't want to use the builtin classmethod here 'cause it won't do the
1872
            # right thing in this scope (as the class members aren't still functions).
1873 1874
            # 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.
1875
            entry = Entry(
1876 1877
                "classmethod",
                "__Pyx_Method_ClassMethod",
1878 1879 1880
                PyrexTypes.CFuncType(
                    py_object_type,
                    [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0))
1881
            entry.utility_code_definition = Code.UtilityCode.load_cached("ClassMethod", "CythonFunction.c")
1882
            self.use_entry_utility_code(entry)
1883
            entry.is_cfunction = 1
1884
        return entry
1885

William Stein's avatar
William Stein committed
1886 1887 1888 1889 1890 1891 1892

class PyClassScope(ClassScope):
    #  Namespace of a Python class.
    #
    #  class_obj_cname     string   C variable holding class object

    is_py_class_scope = 1
1893

1894 1895 1896 1897 1898
    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('__'):
1899
            name = EncodedString('_%s%s' % (self.class_name.lstrip('_'), name))
1900 1901 1902 1903 1904 1905
        return name

    def lookup_here(self, name):
        name = self.mangle_special_name(name)
        return ClassScope.lookup_here(self, name)

1906
    def declare_var(self, name, type, pos,
1907 1908
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0):
1909
        name = self.mangle_special_name(name)
1910 1911
        if type is unspecified_type:
            type = py_object_type
William Stein's avatar
William Stein committed
1912
        # Add an entry for a class attribute.
1913
        entry = Scope.declare_var(self, name, type, pos,
1914 1915
                                  cname=cname, visibility=visibility,
                                  api=api, in_pxd=in_pxd, is_cdef=is_cdef)
Stefan Behnel's avatar
Stefan Behnel committed
1916
        entry.is_pyglobal = 1
Stefan Behnel's avatar
Stefan Behnel committed
1917
        entry.is_pyclass_attr = 1
William Stein's avatar
William Stein committed
1918 1919
        return entry

1920 1921
    def declare_nonlocal(self, name, pos):
        # Pull entry from outer scope into local scope
1922 1923 1924
        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)
1925 1926 1927 1928 1929
        else:
            entry = self.lookup(name)
            if entry is None:
                error(pos, "no binding for nonlocal '%s' found" % name)
            else:
Stefan Behnel's avatar
Stefan Behnel committed
1930 1931
                # FIXME: this works, but it's unclear if it's the
                # right thing to do
1932 1933
                self.entries[name] = entry

1934 1935 1936 1937 1938 1939 1940 1941
    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

William Stein's avatar
William Stein committed
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954
    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?
1955
    #  has_memoryview_attrs  boolean  Any memory view attributes?
1956
    #  has_cpp_class_attrs   boolean  Any (non-pointer) C++ attributes?
1957
    #  has_cyclic_pyobject_attrs    boolean  Any PyObject attributes that may need GC?
William Stein's avatar
William Stein committed
1958 1959 1960 1961
    #  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
1962

William Stein's avatar
William Stein committed
1963
    is_c_class_scope = 1
1964
    is_closure_class_scope = False
1965

1966
    has_pyobject_attrs = False
1967
    has_memoryview_attrs = False
1968
    has_cpp_class_attrs = False
1969 1970 1971 1972
    has_cyclic_pyobject_attrs = False
    defined = False
    implemented = False

William Stein's avatar
William Stein committed
1973 1974
    def __init__(self, name, outer_scope, visibility):
        ClassScope.__init__(self, name, outer_scope)
Stefan Behnel's avatar
Stefan Behnel committed
1975
        if visibility != 'extern':
William Stein's avatar
William Stein committed
1976 1977 1978 1979
            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 = []
1980

William Stein's avatar
William Stein committed
1981 1982 1983
    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.
1984
        if self.has_cyclic_pyobject_attrs and not self.directives.get('no_gc', False):
1985 1986 1987 1988 1989 1990 1991
            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
William Stein's avatar
William Stein committed
1992

1993 1994 1995 1996 1997 1998 1999
    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)

2000 2001 2002 2003 2004 2005 2006 2007
    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:
2008
                if include_weakref or (self.is_closure_class_scope or entry.name != "__weakref__"):
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
                    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)

2019
    def declare_var(self, name, type, pos,
2020 2021
                    cname = None, visibility = 'private',
                    api = 0, in_pxd = 0, is_cdef = 0):
2022 2023 2024
        if is_cdef:
            # Add an entry for an attribute.
            if self.defined:
William Stein's avatar
William Stein committed
2025
                error(pos,
2026
                    "C attributes cannot be added in implementation part of"
2027
                    " extension type defined in a pxd")
2028
            if not self.is_closure_class_scope and get_special_method_signature(name):
2029
                error(pos,
2030 2031 2032 2033
                    "The name '%s' is reserved for a special method."
                        % name)
            if not cname:
                cname = name
2034 2035
                if visibility == 'private':
                    cname = c_safe_identifier(cname)
2036
            if type.is_cpp_class and visibility != 'extern':
2037
                type.check_nullary_constructor(pos)
Robert Bradshaw's avatar
Robert Bradshaw committed
2038
                self.use_utility_code(Code.UtilityCode("#include <new>"))
2039
            entry = self.declare(name, cname, type, pos, visibility)
2040 2041
            entry.is_variable = 1
            self.var_entries.append(entry)
2042 2043
            if type.is_memoryviewslice:
                self.has_memoryview_attrs = True
2044 2045
            elif type.is_cpp_class:
                self.has_cpp_class_attrs = True
2046
            elif type.is_pyobject and (self.is_closure_class_scope or name != '__weakref__'):
2047 2048 2049 2050
                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
2051 2052 2053 2054
            if visibility not in ('private', 'public', 'readonly'):
                error(pos,
                    "Attribute of extension type cannot be declared %s" % visibility)
            if visibility in ('public', 'readonly'):
2055 2056 2057 2058
                # 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
2059
                if not self.is_closure_class_scope and name == "__weakref__":
2060
                    error(pos, "Special attribute __weakref__ cannot be exposed to Python")
2061 2062 2063
                if not (type.is_pyobject or type.can_coerce_to_pyobject(self)):
                    # we're not testing for coercion *from* Python here - that would fail later
                    error(pos, "C attribute of type '%s' cannot be accessed from Python" % type)
2064 2065
            else:
                entry.needs_property = False
2066 2067
            return entry
        else:
2068 2069
            if type is unspecified_type:
                type = py_object_type
2070
            # Add an entry for a class attribute.
2071
            entry = Scope.declare_var(self, name, type, pos,
2072 2073
                                      cname=cname, visibility=visibility,
                                      api=api, in_pxd=in_pxd, is_cdef=is_cdef)
2074 2075 2076 2077
            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
2078
            self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
2079
            return entry
2080

2081
    def declare_pyfunction(self, name, pos, allow_redefine=False):
William Stein's avatar
William Stein committed
2082
        # Add an entry for a method.
2083 2084 2085 2086 2087 2088 2089
        if name in richcmp_special_methods:
            if self.lookup_here('__richcmp__'):
                error(pos, "Cannot define both % and __richcmp__" % name)
        elif name == '__richcmp__':
            for n in richcmp_special_methods:
                if self.lookup_here(n):
                    error(pos, "Cannot define both % and __richcmp__" % n)
2090
        if name == "__new__":
2091
            error(pos, "__new__ method of extension type will change semantics "
2092
                "in a future version of Pyrex and Cython. Use __cinit__ instead.")
Robert Bradshaw's avatar
Robert Bradshaw committed
2093
        entry = self.declare_var(name, py_object_type, pos,
2094
                                 visibility='extern')
William Stein's avatar
William Stein committed
2095 2096
        special_sig = get_special_method_signature(name)
        if special_sig:
2097 2098
            # Special methods get put in the method table with a particular
            # signature declared in advance.
William Stein's avatar
William Stein committed
2099
            entry.signature = special_sig
2100
            entry.is_special = 1
William Stein's avatar
William Stein committed
2101 2102
        else:
            entry.signature = pymethod_signature
2103
            entry.is_special = 0
2104 2105

        self.pyfunc_entries.append(entry)
William Stein's avatar
William Stein committed
2106
        return entry
2107

2108
    def lookup_here(self, name):
2109
        if not self.is_closure_class_scope and name == "__new__":
2110
            name = EncodedString("__cinit__")
Stefan Behnel's avatar
Stefan Behnel committed
2111 2112 2113 2114 2115 2116 2117 2118
        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.
2119
                if not self.parent_type.is_final_type:
Stefan Behnel's avatar
Stefan Behnel committed
2120 2121
                    return None
        return entry
2122

William Stein's avatar
William Stein committed
2123
    def declare_cfunction(self, name, type, pos,
2124 2125
                          cname=None, visibility='private', api=0, in_pxd=0,
                          defining=0, modifiers=(), utility_code=None, overridable=False):
2126
        if get_special_method_signature(name) and not self.parent_type.is_builtin_type:
William Stein's avatar
William Stein committed
2127 2128
            error(pos, "Special methods must be declared with 'def', not 'cdef'")
        args = type.args
Robert Bradshaw's avatar
Robert Bradshaw committed
2129 2130 2131 2132 2133 2134
        if not type.is_static_method:
            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))
William Stein's avatar
William Stein committed
2135
        entry = self.lookup_here(name)
2136 2137
        if cname is None:
            cname = c_safe_identifier(name)
William Stein's avatar
William Stein committed
2138 2139
        if entry:
            if not entry.is_cfunction:
2140
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
2141 2142 2143
            else:
                if defining and entry.func_cname:
                    error(pos, "'%s' already defined" % name)
2144
                #print "CClassScope.declare_cfunction: checking signature" ###
2145
                if entry.is_final_cmethod and entry.is_inherited:
2146 2147
                    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:
2148 2149
                    # Fix with_gil vs nogil.
                    entry.type = entry.type.with_with_gil(type.with_gil)
2150
                elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
2151 2152
                    if (self.defined and not in_pxd
                        and not type.same_c_signature_as_resolved_type(entry.type, as_cmethod = 1, as_pxd_definition = 1)):
2153 2154
                        # TODO(robertwb): Make this an error.
                        warning(pos,
2155
                            "Compatible but non-identical C method '%s' not redeclared "
2156 2157
                            "in definition part of extension type '%s'.  This may cause incorrect vtables to be generated." % (name, self.class_name), 2)
                        warning(entry.pos, "Previous declaration is here", 2)
2158
                    entry = self.add_cfunction(name, type, pos, cname, visibility='ignore', modifiers=modifiers)
2159 2160
                else:
                    error(pos, "Signature not compatible with previous declaration")
2161
                    error(entry.pos, "Previous declaration is here")
William Stein's avatar
William Stein committed
2162 2163 2164 2165
        else:
            if self.defined:
                error(pos,
                    "C method '%s' not previously declared in definition part of"
2166
                    " extension type '%s'" % (name, self.class_name))
2167
            entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
William Stein's avatar
William Stein committed
2168 2169
        if defining:
            entry.func_cname = self.mangle(Naming.func_prefix, name)
2170
        entry.utility_code = utility_code
Mark Florisson's avatar
Mark Florisson committed
2171
        type.entry = entry
2172

2173 2174
        if u'inline' in modifiers:
            entry.is_inline_cmethod = True
2175

2176 2177
        if (self.parent_type.is_final_type or entry.is_inline_cmethod or
            self.directives.get('final')):
2178 2179
            entry.is_final_cmethod = True
            entry.final_func_cname = entry.func_cname
2180

William Stein's avatar
William Stein committed
2181
        return entry
2182

2183
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers, inherited=False):
William Stein's avatar
William Stein committed
2184
        # Add a cfunction entry without giving it a func_cname.
2185
        prev_entry = self.lookup_here(name)
2186
        entry = ClassScope.add_cfunction(self, name, type, pos, cname,
2187
                                         visibility, modifiers, inherited=inherited)
William Stein's avatar
William Stein committed
2188
        entry.is_cmethod = 1
2189
        entry.prev_entry = prev_entry
William Stein's avatar
William Stein committed
2190
        return entry
2191 2192 2193 2194 2195 2196

    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',
2197
                                       utility_code=utility_code)
2198 2199 2200 2201
        var_entry = Entry(name, name, py_object_type)
        var_entry.is_variable = 1
        var_entry.is_builtin = 1
        var_entry.utility_code = utility_code
2202
        var_entry.scope = entry.scope
2203 2204 2205
        entry.as_variable = var_entry
        return entry

William Stein's avatar
William Stein committed
2206
    def declare_property(self, name, doc, pos):
2207 2208
        entry = self.lookup_here(name)
        if entry is None:
2209
            entry = self.declare(name, name, py_object_type, pos, 'private')
William Stein's avatar
William Stein committed
2210 2211
        entry.is_property = 1
        entry.doc = doc
2212
        entry.scope = PropertyScope(name,
William Stein's avatar
William Stein committed
2213 2214 2215 2216
            outer_scope = self.global_scope(), parent_scope = self)
        entry.scope.parent_type = self.parent_type
        self.property_entries.append(entry)
        return entry
2217

William Stein's avatar
William Stein committed
2218 2219 2220 2221 2222 2223
    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)
2224 2225 2226

        entries = base_scope.inherited_var_entries + base_scope.var_entries
        for base_entry in entries:
Stefan Behnel's avatar
Stefan Behnel committed
2227 2228 2229 2230 2231
            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)
Mark Florisson's avatar
Mark Florisson committed
2232 2233 2234

        # If the class defined in a pxd, specific entries have not been added.
        # Ensure now that the parent (base) scope has specific entries
2235
        # Iterate over a copy as get_all_specialized_function_types() will mutate
Mark Florisson's avatar
Mark Florisson committed
2236 2237
        for base_entry in base_scope.cfunc_entries[:]:
            if base_entry.type.is_fused:
2238
                base_entry.type.get_all_specialized_function_types()
Mark Florisson's avatar
Mark Florisson committed
2239

William Stein's avatar
William Stein committed
2240
        for base_entry in base_scope.cfunc_entries:
Stefan Behnel's avatar
Stefan Behnel committed
2241 2242 2243 2244 2245
            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)
2246
            entry = self.add_cfunction(base_entry.name, base_entry.type,
Stefan Behnel's avatar
Stefan Behnel committed
2247
                                       base_entry.pos, cname,
2248
                                       base_entry.visibility, base_entry.func_modifiers, inherited=True)
William Stein's avatar
William Stein committed
2249
            entry.is_inherited = 1
2250 2251
            if base_entry.is_final_cmethod:
                entry.is_final_cmethod = True
2252 2253
                entry.is_inline_cmethod = base_entry.is_inline_cmethod
                if (self.parent_scope == base_scope.parent_scope or
Stefan Behnel's avatar
Stefan Behnel committed
2254
                        entry.is_inline_cmethod):
2255
                    entry.final_func_cname = base_entry.final_func_cname
Stefan Behnel's avatar
Stefan Behnel committed
2256 2257 2258
            if is_builtin:
                entry.is_builtin_cmethod = True
                entry.as_variable = var_entry
2259 2260
            if base_entry.utility_code:
                entry.utility_code = base_entry.utility_code
2261

2262

DaniloFreitas's avatar
DaniloFreitas committed
2263 2264
class CppClassScope(Scope):
    #  Namespace of a C++ class.
2265

Robert Bradshaw's avatar
Robert Bradshaw committed
2266
    is_cpp_class_scope = 1
2267

2268
    default_constructor = None
2269
    type = None
2270

2271
    def __init__(self, name, outer_scope, templates=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
2272 2273
        Scope.__init__(self, name, outer_scope, None)
        self.directives = outer_scope.directives
Robert Bradshaw's avatar
Robert Bradshaw committed
2274
        self.inherited_var_entries = []
2275 2276 2277 2278 2279
        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
DaniloFreitas's avatar
DaniloFreitas committed
2280

2281
    def declare_var(self, name, type, pos,
2282
                    cname = None, visibility = 'extern',
Robert Bradshaw's avatar
Robert Bradshaw committed
2283
                    api = 0, in_pxd = 0, is_cdef = 0, defining = 0):
DaniloFreitas's avatar
DaniloFreitas committed
2284 2285 2286
        # Add an entry for an attribute.
        if not cname:
            cname = name
2287 2288
        entry = self.lookup_here(name)
        if defining and entry is not None:
2289
            if entry.type.same_as(type):
2290 2291
                # Fix with_gil vs nogil.
                entry.type = entry.type.with_with_gil(type.with_gil)
2292
            else:
2293 2294 2295
                error(pos, "Function signature does not match previous declaration")
        else:
            entry = self.declare(name, cname, type, pos, visibility)
DaniloFreitas's avatar
DaniloFreitas committed
2296
        entry.is_variable = 1
2297
        if type.is_cfunction and self.type:
Robert Bradshaw's avatar
Robert Bradshaw committed
2298
            if not self.type.get_fused_types():
2299
                entry.func_cname = "%s::%s" % (self.type.empty_declaration_code(), cname)
2300 2301
        if name != "this" and (defining or name != "<init>"):
            self.var_entries.append(entry)
DaniloFreitas's avatar
DaniloFreitas committed
2302
        return entry
2303

2304
    def declare_cfunction(self, name, type, pos,
2305 2306
                          cname=None, visibility='extern', api=0, in_pxd=0,
                          defining=0, modifiers=(), utility_code=None, overridable=False):
2307 2308 2309
        class_name = self.name.split('::')[-1]
        if name in (class_name, '__init__') and cname is None:
            cname = "%s__init__%s" % (Naming.func_prefix, class_name)
2310
            name = '<init>'
2311
            type.return_type = PyrexTypes.CVoidType()
2312
        elif name == '__dealloc__' and cname is None:
2313
            cname = "%s__dealloc__%s" % (Naming.func_prefix, class_name)
2314
            name = '<del>'
2315
            type.return_type = PyrexTypes.CVoidType()
2316
        prev_entry = self.lookup_here(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
2317
        entry = self.declare_var(name, type, pos,
2318
                                 defining=defining,
2319
                                 cname=cname, visibility=visibility)
2320
        if prev_entry and not defining:
2321
            entry.overloaded_alternatives = prev_entry.all_alternatives()
2322
        entry.utility_code = utility_code
Mark Florisson's avatar
Mark Florisson committed
2323
        type.entry = entry
2324
        return entry
2325

2326 2327 2328 2329 2330 2331 2332 2333 2334
    def declare_inherited_cpp_attributes(self, base_class):
        base_scope = base_class.scope
        template_type = base_class
        while getattr(template_type, 'template_type', None):
            template_type = template_type.template_type
        if getattr(template_type, 'templates', None):
            base_templates = [T.name for T in template_type.templates]
        else:
            base_templates = ()
DaniloFreitas's avatar
DaniloFreitas committed
2335 2336 2337 2338 2339
        # 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:
2340 2341
                #contructor/destructor is not inherited
                if base_entry.name in ("<init>", "<del>"):
2342 2343 2344
                    continue
                #print base_entry.name, self.entries
                if base_entry.name in self.entries:
Stefan Behnel's avatar
Stefan Behnel committed
2345
                    base_entry.name    # FIXME: is there anything to do in this case?
2346
                entry = self.declare(base_entry.name, base_entry.cname,
DaniloFreitas's avatar
DaniloFreitas committed
2347 2348
                    base_entry.type, None, 'extern')
                entry.is_variable = 1
2349
                entry.is_inherited = 1
DaniloFreitas's avatar
DaniloFreitas committed
2350 2351 2352
                self.inherited_var_entries.append(entry)
        for base_entry in base_scope.cfunc_entries:
            entry = self.declare_cfunction(base_entry.name, base_entry.type,
2353
                                           base_entry.pos, base_entry.cname,
2354 2355 2356
                                           base_entry.visibility, api=0,
                                           modifiers=base_entry.func_modifiers,
                                           utility_code=base_entry.utility_code)
DaniloFreitas's avatar
DaniloFreitas committed
2357
            entry.is_inherited = 1
2358
        for base_entry in base_scope.type_entries:
2359 2360 2361 2362 2363
            if base_entry.name not in base_templates:
                entry = self.declare_type(base_entry.name, base_entry.type,
                                          base_entry.pos, base_entry.cname,
                                          base_entry.visibility)
                entry.is_inherited = 1
2364

2365
    def specialize(self, values, type_entry):
Robert Bradshaw's avatar
Robert Bradshaw committed
2366
        scope = CppClassScope(self.name, self.outer_scope)
2367
        scope.type = type_entry
2368
        for entry in self.entries.values():
Robert Bradshaw's avatar
Robert Bradshaw committed
2369 2370
            if entry.is_type:
                scope.declare_type(entry.name,
2371 2372 2373 2374
                                   entry.type.specialize(values),
                                   entry.pos,
                                   entry.cname,
                                   template=1)
Robert Bradshaw's avatar
Robert Bradshaw committed
2375
            elif entry.type.is_cfunction:
2376 2377 2378 2379
                for e in entry.all_alternatives():
                    scope.declare_cfunction(e.name,
                                            e.type.specialize(values),
                                            e.pos,
2380
                                            e.cname,
2381
                                            utility_code=e.utility_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2382 2383 2384 2385 2386 2387
            else:
                scope.declare_var(entry.name,
                                  entry.type.specialize(values),
                                  entry.pos,
                                  entry.cname,
                                  entry.visibility)
2388

2389
        return scope
2390

2391

William Stein's avatar
William Stein committed
2392 2393 2394 2395 2396
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
2397 2398

    is_property_scope = 1
2399

2400
    def declare_pyfunction(self, name, pos, allow_redefine=False):
William Stein's avatar
William Stein committed
2401 2402 2403
        # Add an entry for a method.
        signature = get_property_accessor_signature(name)
        if signature:
2404
            entry = self.declare(name, name, py_object_type, pos, 'private')
Stefan Behnel's avatar
Stefan Behnel committed
2405
            entry.is_special = 1
2406
            entry.signature = signature
William Stein's avatar
William Stein committed
2407 2408 2409 2410 2411
            return entry
        else:
            error(pos, "Only __get__, __set__ and __del__ methods allowed "
                "in a property declaration")
            return None
Robert Bradshaw's avatar
Robert Bradshaw committed
2412

2413

Robert Bradshaw's avatar
Robert Bradshaw committed
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429
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
2430 2431 2432 2433 2434

class TemplateScope(Scope):
    def __init__(self, name, outer_scope):
        Scope.__init__(self, name, outer_scope, None)
        self.directives = outer_scope.directives