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

import re
6
from Cython import Utils
7
from Errors import warning, error, InternalError
8
from StringEncoding import EncodedString
9
import Options, Naming
10
import PyrexTypes
11
from PyrexTypes import py_object_type, unspecified_type
12
import TypeSlots
William Stein's avatar
William Stein committed
13 14 15
from TypeSlots import \
    pyfunction_signature, pymethod_signature, \
    get_special_method_signature, get_property_accessor_signature
16
import ControlFlow
17
import Code
Stefan Behnel's avatar
Stefan Behnel committed
18
import __builtin__ as builtins
Stefan Behnel's avatar
Stefan Behnel committed
19 20 21 22
try:
    set
except NameError:
    from sets import Set as set
23
import copy
William Stein's avatar
William Stein committed
24

25
possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
26
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
William Stein's avatar
William Stein committed
27

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

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

45
class BufferAux(object):
46 47
    writable_needed = False
    
48 49
    def __init__(self, buffer_info_var, stridevars, shapevars,
                 suboffsetvars):
50 51 52
        self.buffer_info_var = buffer_info_var
        self.stridevars = stridevars
        self.shapevars = shapevars
53
        self.suboffsetvars = suboffsetvars
54
        
55 56 57
    def __repr__(self):
        return "<BufferAux %r>" % self.__dict__

58
class Entry(object):
William Stein's avatar
William Stein committed
59 60 61 62 63 64 65 66
    # 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'
67
    # is_builtin       boolean    Is an entry in the Python builtins dict
William Stein's avatar
William Stein committed
68 69 70 71
    # is_cglobal       boolean    Is a C global variable
    # is_pyglobal      boolean    Is a Python module-level variable
    #                               or class attribute during
    #                               class construction
72
    # is_member        boolean    Is an assigned class member
Stefan Behnel's avatar
Stefan Behnel committed
73
    # is_pyclass_attr  boolean    Is a name in a Python class namespace
William Stein's avatar
William Stein committed
74 75 76
    # is_variable      boolean    Is a variable
    # is_cfunction     boolean    Is a C function
    # is_cmethod       boolean    Is a C method of an extension type
77
    # is_unbound_cmethod boolean  Is an unbound C method of an extension type
78
    # is_lambda        boolean    Is a lambda function
William Stein's avatar
William Stein committed
79
    # is_type          boolean    Is a type definition
80
    # is_cclass        boolean    Is an extension class
Danilo Freitas's avatar
Danilo Freitas committed
81
    # is_cpp_class     boolean    Is a C++ class
William Stein's avatar
William Stein committed
82 83 84 85 86 87
    # 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
88
    # is_arg           boolean    Is the arg of a method
89
    # is_local         boolean    Is a local variable
90
    # in_closure       boolean    Is referenced in an inner scope
William Stein's avatar
William Stein committed
91 92
    # is_readonly      boolean    Can't be assigned to
    # func_cname       string     C func implementing Python func
93
    # func_modifiers   [string]   C function modifiers ('inline')
William Stein's avatar
William Stein committed
94 95 96 97 98 99 100
    # 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
    # init_to_none     boolean    True if initial value should be None
    # as_variable      Entry      Alternative interpretation of extension
101
    #                               type name or builtin C function as a variable
William Stein's avatar
William Stein committed
102 103 104 105 106 107 108 109 110 111 112
    # 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
113
    # is_identifier    boolean    For string const entries, value is an identifier
114
    # used             boolean
115 116 117
    # 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
118
    # api              boolean    Generate C API for C class or function
Stefan Behnel's avatar
Stefan Behnel committed
119
    # utility_code     string     Utility code needed when this entry is used
120
    #
121
    # buffer_aux       BufferAux or None  Extra information needed for buffer variables
122 123
    # inline_func_in_pxd boolean  Hacky special case for inline function in pxd file.
    #                             Ideally this should not be necesarry.
124
    # assignments      [ExprNode] List of expressions that get assigned to this entry.
Craig Citro's avatar
Craig Citro committed
125
    # might_overflow   boolean    In an arithmetic expression that could cause
126
    #                             overflow (used for type inference).
William Stein's avatar
William Stein committed
127

128
    inline_func_in_pxd = False
William Stein's avatar
William Stein committed
129 130 131 132 133 134
    borrowed = 0
    init = ""
    visibility = 'private'
    is_builtin = 0
    is_cglobal = 0
    is_pyglobal = 0
135
    is_member = 0
Stefan Behnel's avatar
Stefan Behnel committed
136
    is_pyclass_attr = 0
William Stein's avatar
William Stein committed
137 138 139
    is_variable = 0
    is_cfunction = 0
    is_cmethod = 0
140
    is_unbound_cmethod = 0
141
    is_lambda = 0
William Stein's avatar
William Stein committed
142
    is_type = 0
143
    is_cclass = 0
Danilo Freitas's avatar
Danilo Freitas committed
144
    is_cpp_class = 0
William Stein's avatar
William Stein committed
145 146 147 148 149 150
    is_const = 0
    is_property = 0
    doc_cname = None
    getter_cname = None
    setter_cname = None
    is_self_arg = 0
151
    is_arg = 0
152
    is_local = 0
153
    in_closure = 0
154
    from_closure = 0
William Stein's avatar
William Stein committed
155 156 157
    is_declared_generic = 0
    is_readonly = 0
    func_cname = None
158
    func_modifiers = []
William Stein's avatar
William Stein committed
159 160 161 162 163 164 165 166
    doc = None
    init_to_none = 0
    as_variable = None
    xdecref_cleanup = 0
    in_cinclude = 0
    as_module = None
    is_inherited = 0
    pystring_cname = None
167
    is_identifier = 0
William Stein's avatar
William Stein committed
168
    is_interned = 0
169
    used = 0
170 171
    is_special = 0
    defined_in_pxd = 0
172
    is_implemented = 0
173
    api = 0
Stefan Behnel's avatar
Stefan Behnel committed
174
    utility_code = None
175
    is_overridable = 0
176
    buffer_aux = None
177
    prev_entry = None
178
    might_overflow = 0
179

William Stein's avatar
William Stein committed
180 181 182 183 184 185
    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
186
        self.overloaded_alternatives = []
187
        self.assignments = []
Robert Bradshaw's avatar
Robert Bradshaw committed
188 189 190
    
    def __repr__(self):
        return "Entry(name=%s, type=%s)" % (self.name, self.type)
191
        
192 193 194
    def redeclared(self, pos):
        error(pos, "'%s' does not match previous declaration" % self.name)
        error(self.pos, "Previous declaration is here")
195 196 197
    
    def all_alternatives(self):
        return [self] + self.overloaded_alternatives
198

199
class Scope(object):
William Stein's avatar
William Stein committed
200 201 202 203
    # 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
204
    # type_entries      [Entry]            Struct/union/enum/typedef/exttype entries
William Stein's avatar
William Stein committed
205 206 207 208 209 210 211
    # 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
212
    # int_to_entry      {int : Entry}      Temp cname to entry mapping
William Stein's avatar
William Stein committed
213 214 215
    # return_type       PyrexType or None  Return type of function owning scope
    # 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
216 217
    # is_closure_scope  boolean            Is a closure scope
    # is_passthrough    boolean            Outer scope is passed directly
218 219
    # 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
220 221 222 223 224
    # scope_prefix      string             Disambiguator for C names
    # in_cinclude       boolean            Suppress C declaration code
    # qualified_name    string             "modname" or "modname.classname"
    # pystring_entries  [Entry]            String const entries newly used as
    #                                        Python strings in this scope
225
    # control_flow     ControlFlow  Used for keeping track of environment state
226
    # nogil             boolean            In a nogil section
227 228
    # directives       dict                Helper variable for the recursive
    #                                      analysis, contains directive values.
229
    # is_internal       boolean            Is only used internally (simpler setup)
William Stein's avatar
William Stein committed
230 231 232

    is_py_class_scope = 0
    is_c_class_scope = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
233
    is_closure_scope = 0
Vitja Makarov's avatar
Vitja Makarov committed
234
    is_passthrough = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
235
    is_cpp_class_scope = 0
236
    is_property_scope = 0
237
    is_module_scope = 0
238
    is_internal = 0
William Stein's avatar
William Stein committed
239 240
    scope_prefix = ""
    in_cinclude = 0
241
    nogil = 0
William Stein's avatar
William Stein committed
242 243 244 245 246 247 248 249 250 251 252 253 254
    
    def __init__(self, name, outer_scope, parent_scope):
        # The outer_scope is the next scope in the lookup chain.
        # The parent_scope is used to derive the qualified name of this scope.
        self.name = name
        self.outer_scope = outer_scope
        self.parent_scope = parent_scope
        mangled_name = "%d%s_" % (len(name), name)
        qual_scope = self.qualifying_scope()
        if qual_scope:
            self.qualified_name = qual_scope.qualify_name(name)
            self.scope_prefix = qual_scope.scope_prefix + mangled_name
        else:
255
            self.qualified_name = EncodedString(name)
William Stein's avatar
William Stein committed
256 257 258
            self.scope_prefix = mangled_name
        self.entries = {}
        self.const_entries = []
259
        self.type_entries = []
William Stein's avatar
William Stein committed
260 261 262 263 264 265 266 267 268 269
        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 = {}
270
        self.identifier_to_entry = {}
271
        self.num_to_entry = {}
Robert Bradshaw's avatar
Robert Bradshaw committed
272
        self.obj_to_entry = {}
William Stein's avatar
William Stein committed
273
        self.pystring_entries = []
274
        self.buffer_entries = []
Stefan Behnel's avatar
Stefan Behnel committed
275
        self.lambda_defs = []
276
        self.control_flow = ControlFlow.LinearControlFlow()
277
        self.return_type = None
278 279
        self.id_counters = {}

280 281
    def start_branching(self, pos):
        self.control_flow = self.control_flow.start_branch(pos)
William Stein's avatar
William Stein committed
282
    
283 284 285 286 287 288
    def next_branch(self, pos):
        self.control_flow = self.control_flow.next_branch(pos)
        
    def finish_branching(self, pos):
        self.control_flow = self.control_flow.finish_branch(pos)
        
William Stein's avatar
William Stein committed
289 290
    def __str__(self):
        return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
291

William Stein's avatar
William Stein committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
    def qualifying_scope(self):
        return self.parent_scope
    
    def mangle(self, prefix, name = None):
        if name:
            return "%s%s%s" % (prefix, self.scope_prefix, name)
        else:
            return self.parent_scope.mangle(prefix, self.name)
    
    def mangle_internal(self, name):
        # Mangle an internal name so as not to clash with any
        # user-defined name in this scope.
        prefix = "%s%s_" % (Naming.pyrex_prefix, name)
        return self.mangle(prefix)
        #return self.parent_scope.mangle(prefix, self.name)
307 308 309 310 311 312 313 314 315 316 317 318 319

    def next_id(self, name=None):
        # Return a cname fragment that is unique for this scope.
        try:
            count = self.id_counters[name] + 1
        except KeyError:
            count = 0
        self.id_counters[name] = count
        if name:
            return '%s%d' % (name, count)
        else:
            return '%d' % count

William Stein's avatar
William Stein committed
320 321 322 323
    def global_scope(self):
        # Return the module-level scope containing this scope.
        return self.outer_scope.global_scope()
    
324 325 326 327
    def builtin_scope(self):
        # Return the module-level scope containing this scope.
        return self.outer_scope.builtin_scope()

328
    def declare(self, name, cname, type, pos, visibility):
William Stein's avatar
William Stein committed
329
        # Create new entry, and add to dictionary if
330
        # name is not None. Reports a warning if already 
William Stein's avatar
William Stein committed
331
        # declared.
332 333
        if type.is_buffer and not isinstance(self, LocalScope):
            error(pos, ERR_BUF_LOCALONLY)
334
        if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
335
            # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names 
336
            warning(pos, "'%s' is a reserved name in C." % cname, -1)
Stefan Behnel's avatar
Stefan Behnel committed
337 338
        entries = self.entries
        if name and name in entries:
339 340
            if visibility == 'extern':
                warning(pos, "'%s' redeclared " % name, 0)
341
            elif visibility != 'ignore':
342
                error(pos, "'%s' redeclared " % name)
William Stein's avatar
William Stein committed
343 344 345 346
        entry = Entry(name, cname, type, pos = pos)
        entry.in_cinclude = self.in_cinclude
        if name:
            entry.qualified_name = self.qualify_name(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
347 348 349 350
#            if name in entries and self.is_cpp():
#                entries[name].overloaded_alternatives.append(entry)
#            else:
#                entries[name] = entry
Stefan Behnel's avatar
Stefan Behnel committed
351
            entries[name] = entry
352
        entry.scope = self
353
        entry.visibility = visibility
William Stein's avatar
William Stein committed
354 355 356
        return entry
    
    def qualify_name(self, name):
357
        return EncodedString("%s.%s" % (self.qualified_name, name))
358

Robert Bradshaw's avatar
Robert Bradshaw committed
359
    def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
William Stein's avatar
William Stein committed
360 361
        # Add an entry for a named constant.
        if not cname:
362
            if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
363 364 365
                cname = name
            else:
                cname = self.mangle(Naming.enum_prefix, name)
Robert Bradshaw's avatar
Robert Bradshaw committed
366
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
367
        entry.is_const = 1
368
        entry.value_node = value
William Stein's avatar
William Stein committed
369 370 371
        return entry
    
    def declare_type(self, name, type, pos, 
372
            cname = None, visibility = 'private', defining = 1):
William Stein's avatar
William Stein committed
373 374 375
        # Add an entry for a type definition.
        if not cname:
            cname = name
376
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
377
        entry.is_type = 1
378 379
        if defining:
            self.type_entries.append(entry)
380
        # here we would set as_variable to an object representing this type
William Stein's avatar
William Stein committed
381
        return entry
382 383 384 385 386 387 388 389
    
    def declare_typedef(self, name, base_type, pos, cname = None,
            visibility = 'private'):
        if not cname:
            if self.in_cinclude or visibility == 'public':
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
390
        try:
391 392
            type = PyrexTypes.create_typedef_type(name, base_type, cname, 
                                                  (visibility == 'extern'))
393
        except ValueError, e:
394
            error(pos, e.args[0])
395
            type = PyrexTypes.error_type
396 397
        entry = self.declare_type(name, type, pos, cname, visibility)
        type.qualified_name = entry.qualified_name
Stefan Behnel's avatar
Stefan Behnel committed
398
        return entry
William Stein's avatar
William Stein committed
399 400
        
    def declare_struct_or_union(self, name, kind, scope, 
401 402
            typedef_flag, pos, cname = None, visibility = 'private',
            packed = False):
William Stein's avatar
William Stein committed
403 404
        # Add an entry for a struct or union definition.
        if not cname:
405
            if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
406 407 408 409 410
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
        entry = self.lookup_here(name)
        if not entry:
411
            type = PyrexTypes.CStructOrUnionType(
412
                name, kind, scope, typedef_flag, cname, packed)
413 414
            entry = self.declare_type(name, type, pos, cname,
                visibility = visibility, defining = scope is not None)
William Stein's avatar
William Stein committed
415
            self.sue_entries.append(entry)
416
            type.entry = entry
William Stein's avatar
William Stein committed
417
        else:
418 419
            if not (entry.is_type and entry.type.is_struct_or_union
                    and entry.type.kind == kind):
420
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
421
            elif scope and entry.type.scope:
422
                warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0)
William Stein's avatar
William Stein committed
423 424
            else:
                self.check_previous_typedef_flag(entry, typedef_flag, pos)
425
                self.check_previous_visibility(entry, visibility, pos)
William Stein's avatar
William Stein committed
426 427
                if scope:
                    entry.type.scope = scope
428
                    self.type_entries.append(entry)
William Stein's avatar
William Stein committed
429 430 431 432
        if not scope and not entry.type.scope:
            self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
        return entry
    
Robert Bradshaw's avatar
Robert Bradshaw committed
433 434 435 436 437 438 439
    def declare_cpp_class(self, name, scope,
            pos, cname = None, base_classes = [],
            visibility = 'extern', templates = None):
        if visibility != 'extern':
            error(pos, "C++ classes may only be extern")
        if cname is None:
            cname = name
440
        entry = self.lookup_here(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
        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)
        else:
            if not (entry.is_type and entry.type.is_cpp_class):
                warning(pos, "'%s' redeclared  " % name, 0)
            elif scope and entry.type.scope:
                warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0)
            else:
                if scope:
                    entry.type.scope = scope
                    self.type_entries.append(entry)
        if templates is not None:
            for T in templates:
                template_entry = entry.type.scope.declare(T.name, T.name, T, None, 'extern')
                template_entry.is_type = 1
        
        def declare_inherited_attributes(entry, base_classes):
            for base_class in base_classes:
                declare_inherited_attributes(entry, base_class.base_classes)
                entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)                 
464 465
        if entry.type.scope:
            declare_inherited_attributes(entry, base_classes)
Robert Bradshaw's avatar
Robert Bradshaw committed
466 467 468 469
        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
470
    def check_previous_typedef_flag(self, entry, typedef_flag, pos):
Stefan Behnel's avatar
Stefan Behnel committed
471
        if typedef_flag != entry.type.typedef_flag:
William Stein's avatar
William Stein committed
472 473 474
            error(pos, "'%s' previously declared using '%s'" % (
                entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
    
475
    def check_previous_visibility(self, entry, visibility, pos):
Stefan Behnel's avatar
Stefan Behnel committed
476
        if entry.visibility != visibility:
477 478 479 480 481
            error(pos, "'%s' previously declared as '%s'" % (
                entry.name, entry.visibility))
    
    def declare_enum(self, name, pos, cname, typedef_flag,
            visibility = 'private'):
William Stein's avatar
William Stein committed
482 483
        if name:
            if not cname:
484
                if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
485 486 487
                    cname = name
                else:
                    cname = self.mangle(Naming.type_prefix, name)
488
            type = PyrexTypes.CEnumType(name, cname, typedef_flag)
William Stein's avatar
William Stein committed
489
        else:
490 491 492
            type = PyrexTypes.c_anon_enum_type
        entry = self.declare_type(name, type, pos, cname = cname,
            visibility = visibility)
William Stein's avatar
William Stein committed
493 494
        entry.enum_values = []
        self.sue_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
495
        return entry    
William Stein's avatar
William Stein committed
496 497 498 499 500
    
    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
        # Add an entry for a variable.
        if not cname:
Stefan Behnel's avatar
Stefan Behnel committed
501
            if visibility != 'private':
William Stein's avatar
William Stein committed
502 503 504
                cname = name
            else:
                cname = self.mangle(Naming.var_prefix, name)
505 506 507
        if type.is_cpp_class and visibility != 'extern':
            constructor = type.scope.lookup(u'<init>')
            if constructor is not None and PyrexTypes.best_match([], constructor.all_alternatives()) is None:
Robert Bradshaw's avatar
Robert Bradshaw committed
508
                error(pos, "C++ class must have a default constructor to be stack allocated")
509
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
510
        entry.is_variable = 1
Craig Citro's avatar
Craig Citro committed
511
        self.control_flow.set_state((), (name, 'initialized'), False)
William Stein's avatar
William Stein committed
512 513 514 515 516 517 518
        return entry
        
    def declare_builtin(self, name, pos):
        return self.outer_scope.declare_builtin(name, pos)
    
    def declare_pyfunction(self, name, pos):
        # Add an entry for a Python function.
519
        entry = self.lookup_here(name)
520
        if entry and not entry.type.is_cfunction:
521 522
            # This is legal Python, but for now will produce invalid C.
            error(pos, "'%s' already declared" % name)
523
        entry = self.declare_var(name, py_object_type, pos, visibility='extern')
William Stein's avatar
William Stein committed
524 525 526
        entry.signature = pyfunction_signature
        self.pyfunc_entries.append(entry)
        return entry
Stefan Behnel's avatar
Stefan Behnel committed
527 528 529 530 531 532 533 534

    def declare_lambda_function(self, func_cname, pos):
        # Add an entry for an anonymous Python function.
        entry = self.declare_var(None, py_object_type, pos,
                                 cname=func_cname, visibility='private')
        entry.name = EncodedString(func_cname)
        entry.func_cname = func_cname
        entry.signature = pyfunction_signature
535
        entry.is_lambda = True
Stefan Behnel's avatar
Stefan Behnel committed
536 537 538 539 540
        return entry

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

William Stein's avatar
William Stein committed
541 542 543 544
    def register_pyfunction(self, entry):
        self.pyfunc_entries.append(entry)
    
    def declare_cfunction(self, name, type, pos, 
545
                          cname = None, visibility = 'private', defining = 0,
546
                          api = 0, in_pxd = 0, modifiers = (), utility_code = None):
William Stein's avatar
William Stein committed
547
        # Add an entry for a C function.
DaniloFreitas's avatar
DaniloFreitas committed
548 549 550 551 552
        if not cname:
            if api or visibility != 'private':
                cname = name
            else:
                cname = self.mangle(Naming.func_prefix, name)
553 554
        entry = self.lookup_here(name)
        if entry:
Stefan Behnel's avatar
Stefan Behnel committed
555
            if visibility != 'private' and visibility != entry.visibility:
556
                warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
557
            if not entry.type.same_as(type):
558
                if visibility == 'extern' and entry.visibility == 'extern':
559 560 561 562 563 564 565 566 567 568 569 570
                    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:
571
                        temp = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
572
                        temp.overloaded_alternatives = entry.all_alternatives()
573 574 575 576
                        entry = temp
                    else:
                        warning(pos, "Function signature does not match previous declaration", 1)
                        entry.type = type
577 578
                else:
                    error(pos, "Function signature does not match previous declaration")
579
        else:
580
            entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
581
            entry.func_cname = cname
Stefan Behnel's avatar
Stefan Behnel committed
582
        if in_pxd and visibility != 'extern':
583 584 585
            entry.defined_in_pxd = 1
        if api:
            entry.api = 1
Stefan Behnel's avatar
Stefan Behnel committed
586
        if not defining and not in_pxd and visibility != 'extern':
Stefan Behnel's avatar
Stefan Behnel committed
587
            error(pos, "Non-extern C function '%s' declared but not defined" % name)
588 589
        if defining:
            entry.is_implemented = True
590 591
        if modifiers:
            entry.func_modifiers = modifiers
592
        entry.utility_code = utility_code
William Stein's avatar
William Stein committed
593 594
        return entry
    
595
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
William Stein's avatar
William Stein committed
596
        # Add a C function entry without giving it a func_cname.
597
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
598
        entry.is_cfunction = 1
599 600
        if modifiers:
            entry.func_modifiers = modifiers
William Stein's avatar
William Stein committed
601 602 603 604 605 606 607 608 609 610 611
        self.cfunc_entries.append(entry)
        return entry
    
    def find(self, name, pos):
        # Look up name, report error if not found.
        entry = self.lookup(name)
        if entry:
            return entry
        else:
            error(pos, "'%s' is not declared" % name)
    
612 613 614 615 616 617 618 619 620 621 622
    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:
623
                error(pos, "'%s' is not a cimported module" % '.'.join(path))
624 625 626
                return None
        return scope
        
William Stein's avatar
William Stein committed
627 628 629 630
    def lookup(self, name):
        # Look up name in this scope or an enclosing one.
        # Return None if not found.
        return (self.lookup_here(name)
631
            or (self.outer_scope and self.outer_scope.lookup(name))
William Stein's avatar
William Stein committed
632 633 634 635 636 637 638 639 640 641 642 643 644
            or None)

    def lookup_here(self, name):
        # Look up in this scope only, return None if not found.
        return self.entries.get(name, None)
        
    def lookup_target(self, name):
        # Look up name in this scope only. Declare as Python
        # variable if not found.
        entry = self.lookup_here(name)
        if not entry:
            entry = self.declare_var(name, py_object_type, None)
        return entry
645 646 647 648 649
        
    def lookup_type(self, name):
        entry = self.lookup(name)
        if entry and entry.is_type:
            return entry.type
650 651 652 653 654 655 656 657 658 659 660 661 662
    
    def lookup_operator(self, operator, operands):
        if operands[0].type.is_cpp_class:
            obj_type = operands[0].type
            method = obj_type.scope.lookup("operator%s" % operator)
            if method is not None:
                res = PyrexTypes.best_match(operands[1:], method.all_alternatives())
                if res is not None:
                    return res
        function = self.lookup("operator%s" % operator)
        if function is None:
            return None
        return PyrexTypes.best_match(operands, function.all_alternatives())
663

664 665
    def use_utility_code(self, new_code):
        self.global_scope().use_utility_code(new_code)
666

William Stein's avatar
William Stein committed
667 668 669 670 671 672 673 674
    def generate_library_function_declarations(self, code):
        # Generate extern decls for C library funcs used.
        pass
        
    def defines_any(self, names):
        # Test whether any of the given names are
        # defined in this scope.
        for name in names:
Robert Bradshaw's avatar
Robert Bradshaw committed
675
            if name in self.entries:    
William Stein's avatar
William Stein committed
676 677
                return 1
        return 0
678 679
    
    def infer_types(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
680 681
        from TypeInference import get_type_inferer
        get_type_inferer().infer_types(self)
Robert Bradshaw's avatar
Robert Bradshaw committed
682
    
Robert Bradshaw's avatar
Robert Bradshaw committed
683
    def is_cpp(self):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
684 685 686 687 688
        outer = self.outer_scope
        if outer is None:
            return False
        else:
            return outer.is_cpp()
William Stein's avatar
William Stein committed
689

690
class PreImportScope(Scope):
691 692 693

    namespace_cname = Naming.preimport_cname

694 695 696 697
    def __init__(self):
        Scope.__init__(self, Options.pre_import, None, None)
        
    def declare_builtin(self, name, pos):
698
        entry = self.declare(name, name, py_object_type, pos, 'private')
699 700 701 702
        entry.is_variable = True
        entry.is_pyglobal = True
        return entry

William Stein's avatar
William Stein committed
703 704 705 706 707

class BuiltinScope(Scope):
    #  The builtin namespace.
    
    def __init__(self):
708 709 710 711
        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
712
        self.type_names = {}
713
        
Robert Bradshaw's avatar
Robert Bradshaw committed
714 715 716
        for name, definition in self.builtin_entries.iteritems():
            cname, type = definition
            self.declare_var(name, type, None, cname)
717
        
William Stein's avatar
William Stein committed
718
    def declare_builtin(self, name, pos):
Stefan Behnel's avatar
Stefan Behnel committed
719
        if not hasattr(builtins, name):
720 721 722 723
            if self.outer_scope is not None:
                return self.outer_scope.declare_builtin(name, pos)
            else:
                error(pos, "undeclared name not builtin: %s"%name)
Stefan Behnel's avatar
Stefan Behnel committed
724 725 726 727 728
    
    def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
            utility_code = None):
        # If python_equiv == "*", the Python equivalent has the same name
        # as the entry, otherwise it has the name specified by python_equiv.
729
        name = EncodedString(name)
730 731
        entry = self.declare_cfunction(name, type, None, cname, visibility='extern',
                                       utility_code = utility_code)
Stefan Behnel's avatar
Stefan Behnel committed
732 733 734
        if python_equiv:
            if python_equiv == "*":
                python_equiv = name
735
            else:
736
                python_equiv = EncodedString(python_equiv)
Stefan Behnel's avatar
Stefan Behnel committed
737
            var_entry = Entry(python_equiv, python_equiv, py_object_type)
738 739
            var_entry.is_variable = 1
            var_entry.is_builtin = 1
740
            var_entry.utility_code = utility_code
741 742
            entry.as_variable = var_entry
        return entry
Robert Bradshaw's avatar
Robert Bradshaw committed
743
        
744
    def declare_builtin_type(self, name, cname, utility_code = None):
745
        name = EncodedString(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
746
        type = PyrexTypes.BuiltinObjectType(name, cname)
747 748 749 750 751
        scope = CClassScope(name, outer_scope=None, visibility='extern')
        scope.directives = {}
        if name == 'bool':
            scope.directives['final'] = True
        type.set_scope(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
752 753
        self.type_names[name] = 1
        entry = self.declare_type(name, type, None, visibility='extern')
754
        entry.utility_code = utility_code
Robert Bradshaw's avatar
Robert Bradshaw committed
755 756

        var_entry = Entry(name = entry.name,
757
            type = self.lookup('type').type, # make sure "type" is the first type declared...
Robert Bradshaw's avatar
Robert Bradshaw committed
758 759 760 761 762
            pos = entry.pos,
            cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
        var_entry.is_variable = 1
        var_entry.is_cglobal = 1
        var_entry.is_readonly = 1
763
        var_entry.is_builtin = 1
764
        var_entry.utility_code = utility_code
Robert Bradshaw's avatar
Robert Bradshaw committed
765 766 767
        entry.as_variable = var_entry

        return type
768

769 770
    def builtin_scope(self):
        return self
771

Robert Bradshaw's avatar
Robert Bradshaw committed
772
    builtin_entries = {
773 774 775 776

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

        "bool":   ["((PyObject*)&PyBool_Type)", py_object_type],
777 778 779
        "int":    ["((PyObject*)&PyInt_Type)", py_object_type],
        "long":   ["((PyObject*)&PyLong_Type)", py_object_type],
        "float":  ["((PyObject*)&PyFloat_Type)", py_object_type],
780 781 782 783
        "complex":["((PyObject*)&PyComplex_Type)", py_object_type],

        "bytes":  ["((PyObject*)&PyBytes_Type)", py_object_type],
        "str":    ["((PyObject*)&PyString_Type)", py_object_type],
784
        "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type],
785

786 787 788 789 790
        "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],
791

792
        "slice":  ["((PyObject*)&PySlice_Type)", py_object_type],
793
#        "file":   ["((PyObject*)&PyFile_Type)", py_object_type],  # not in Py3
794

Robert Bradshaw's avatar
Robert Bradshaw committed
795 796 797 798
        "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
799

800 801
const_counter = 1 # As a temporary solution for compiling code in pxds

William Stein's avatar
William Stein committed
802 803 804 805 806 807 808
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
809
    # utility_code_list    [UtilityCode]      Queuing utility codes for forwarding to Code.py
William Stein's avatar
William Stein committed
810 811 812
    # 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
813
    # identifier_to_entry  {string : Entry}   Map identifier string const to entry
William Stein's avatar
William Stein committed
814 815 816 817
    # 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)
818
    # included_files       [string]           Cython sources included with 'include'
William Stein's avatar
William Stein committed
819 820
    # pxd_file_loaded      boolean            Corresponding .pxd file has been processed
    # cimported_modules    [ModuleScope]      Modules imported with cimport
821
    # types_imported       {PyrexType : 1}    Set of types for which import code generated
822
    # has_import_star      boolean            Module contains import *
Robert Bradshaw's avatar
Robert Bradshaw committed
823
    # cpp                  boolean            Compiling a C++ file
824 825
    
    is_module_scope = 1
826
    has_import_star = 0
William Stein's avatar
William Stein committed
827 828 829 830 831

    def __init__(self, name, parent_module, context):
        self.parent_module = parent_module
        outer_scope = context.find_submodule("__builtin__")
        Scope.__init__(self, name, outer_scope, parent_module)
832 833 834 835 836 837
        if name != "__init__":
            self.module_name = name
        else:
            # Treat Spam/__init__.pyx specially, so that when Python loads
            # Spam/__init__.so, initSpam() is defined.
            self.module_name = parent_module.module_name
838
        self.module_name = EncodedString(self.module_name)
William Stein's avatar
William Stein committed
839 840 841 842 843 844
        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
845
        self.utility_code_list = []
William Stein's avatar
William Stein committed
846
        self.module_entries = {}
847
        self.python_include_files = ["Python.h"]
William Stein's avatar
William Stein committed
848
        self.include_files = []
Robert Bradshaw's avatar
Robert Bradshaw committed
849
        self.type_names = dict(outer_scope.type_names)
William Stein's avatar
William Stein committed
850 851
        self.pxd_file_loaded = 0
        self.cimported_modules = []
852
        self.types_imported = {}
853
        self.included_files = []
854
        self.has_extern_class = 0
855 856
        self.cached_builtins = []
        self.undeclared_cached_builtins = []
857
        self.namespace_cname = self.module_cname
858 859
        for name in ['__builtins__', '__name__', '__file__', '__doc__']:
            self.declare_var(EncodedString(name), py_object_type, None)
William Stein's avatar
William Stein committed
860 861 862 863 864 865 866 867
    
    def qualifying_scope(self):
        return self.parent_module
    
    def global_scope(self):
        return self
    
    def declare_builtin(self, name, pos):
868 869
        if not hasattr(builtins, name) and name != 'xrange':
            # 'xrange' is special cased in Code.py
870 871 872 873
            if self.has_import_star:
                entry = self.declare_var(name, py_object_type, pos)
                return entry
            elif self.outer_scope is not None:
874 875 876
                return self.outer_scope.declare_builtin(name, pos)
            else:
                error(pos, "undeclared name not builtin: %s"%name)
877 878 879 880
        if Options.cache_builtins:
            for entry in self.cached_builtins:
                if entry.name == name:
                    return entry
881
        entry = self.declare(None, None, py_object_type, pos, 'private')
882 883 884
        if Options.cache_builtins:
            entry.is_builtin = 1
            entry.is_const = 1
885
            entry.name = name
886 887 888 889 890
            entry.cname = Naming.builtin_prefix + name
            self.cached_builtins.append(entry)
            self.undeclared_cached_builtins.append(entry)
        else:
            entry.is_builtin = 1
William Stein's avatar
William Stein committed
891
        return entry
892

William Stein's avatar
William Stein committed
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
    def find_module(self, module_name, pos):
        # Find a module in the import namespace, interpreting
        # relative imports relative to this module's parent.
        # Finds and parses the module's .pxd file if the module
        # has not been referenced before.
        return self.global_scope().context.find_module(
            module_name, relative_to = self.parent_module, pos = pos)
    
    def find_submodule(self, name):
        # Find and return scope for a submodule of this module,
        # creating a new empty one if necessary. Doesn't parse .pxd.
        scope = self.lookup_submodule(name)
        if not scope:
            scope = ModuleScope(name, 
                parent_module = self, context = self.context)
            self.module_entries[name] = scope
        return scope
    
    def lookup_submodule(self, name):
        # Return scope for submodule of this module, or None.
        return self.module_entries.get(name, None)
    
    def add_include_file(self, filename):
        if filename not in self.python_include_files \
            and filename not in self.include_files:
                self.include_files.append(filename)
    
    def add_imported_module(self, scope):
        if scope not in self.cimported_modules:
922 923
            for filename in scope.include_files:
                self.add_include_file(filename)
William Stein's avatar
William Stein committed
924
            self.cimported_modules.append(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
925 926
            for m in scope.cimported_modules:
                self.add_imported_module(m)
William Stein's avatar
William Stein committed
927 928 929 930 931
    
    def add_imported_entry(self, name, entry, pos):
        if entry not in self.entries:
            self.entries[name] = entry
        else:
932
            warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
933 934 935 936 937 938 939 940
    
    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:
941 942
            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
943
            if not (entry.is_pyglobal and not entry.as_module):
944 945 946 947 948 949 950 951
                # SAGE -- I put this here so Pyrex
                # cimport's work across directories.
                # Currently it tries to multiply define
                # every module appearing in an import list.
                # It shouldn't be an error for a module
                # name to appear again, and indeed the generated
                # code compiles fine. 
                return entry
952
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
953 954 955 956
                return None
        else:
            entry = self.declare_var(name, py_object_type, pos)
        entry.as_module = scope
Robert Bradshaw's avatar
Robert Bradshaw committed
957
        self.add_imported_module(scope)
William Stein's avatar
William Stein committed
958 959 960 961 962 963 964 965 966 967 968 969 970
        return entry
    
    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
        # Add an entry for a global variable. If it is a Python
        # object type, and not declared with cdef, it will live 
        # in the module dictionary, otherwise it will be a C 
        # global variable.
        entry = Scope.declare_var(self, name, type, pos, 
            cname, visibility, is_cdef)
        if not visibility in ('private', 'public', 'extern'):
            error(pos, "Module-level variable cannot be declared %s" % visibility)
        if not is_cdef:
971 972
            if type is unspecified_type:
                type = py_object_type
William Stein's avatar
William Stein committed
973 974 975 976 977 978
            if not (type.is_pyobject and not type.is_extension_type):
                raise InternalError(
                    "Non-cdef global variable is not a generic Python object")
            entry.is_pyglobal = 1
        else:
            entry.is_cglobal = 1
979 980
            if entry.type.is_pyobject:
                entry.init = 0
William Stein's avatar
William Stein committed
981 982 983 984 985 986 987 988
            self.var_entries.append(entry)
        return entry
    
    def declare_global(self, name, pos):
        entry = self.lookup_here(name)
        if not entry:
            self.declare_var(name, py_object_type, pos)
    
989
    def use_utility_code(self, new_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
990
        if new_code is not None:
991
            self.utility_code_list.append(new_code)
992

993 994
    def declare_c_class(self, name, pos, defining = 0, implementing = 0,
        module_name = None, base_type = None, objstruct_cname = None,
995 996
        typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
        buffer_defaults = None):
997 998 999 1000
        # If this is a non-extern typedef class, expose the typedef, but use
        # the non-typedef struct internally to avoid needing forward
        # declarations for anonymous structs. 
        if typedef_flag and visibility != 'extern':
Robert Bradshaw's avatar
Robert Bradshaw committed
1001 1002
            if visibility != 'public':
                warning(pos, "ctypedef only valid for public and extern classes", 2)
1003 1004 1005 1006
            objtypedef_cname = objstruct_cname
            typedef_flag = 0
        else:
            objtypedef_cname = None
William Stein's avatar
William Stein committed
1007
        #
1008
        #  Look for previous declaration as a type
William Stein's avatar
William Stein committed
1009 1010 1011 1012 1013
        #
        entry = self.lookup_here(name)
        if entry:
            type = entry.type
            if not (entry.is_type and type.is_extension_type):
1014
                entry = None # Will cause redeclaration and produce an error
William Stein's avatar
William Stein committed
1015
            else:
1016
                scope = type.scope
Robert Bradshaw's avatar
Robert Bradshaw committed
1017
                if typedef_flag and (not scope or scope.defined):
1018 1019 1020 1021 1022 1023
                    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
1024
        #
1025
        #  Make a new entry if needed
William Stein's avatar
William Stein committed
1026 1027
        #
        if not entry:
1028
            type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern')
1029
            type.pos = pos
1030
            type.buffer_defaults = buffer_defaults
1031 1032
            if objtypedef_cname is not None:
                type.objtypedef_cname = objtypedef_cname
William Stein's avatar
William Stein committed
1033 1034 1035 1036 1037
            if visibility == 'extern':
                type.module_name = module_name
            else:
                type.module_name = self.qualified_name
            type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
1038 1039
            entry = self.declare_type(name, type, pos, visibility = visibility,
                defining = 0)
1040
            entry.is_cclass = True
William Stein's avatar
William Stein committed
1041 1042 1043
            if objstruct_cname:
                type.objstruct_cname = objstruct_cname
            elif not entry.in_cinclude:
1044
                type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
William Stein's avatar
William Stein committed
1045 1046 1047 1048 1049 1050
            else:
                error(entry.pos, 
                    "Object name required for 'public' or 'extern' C class")
            self.attach_var_entry_to_c_class(entry)
            self.c_class_entries.append(entry)
        #
1051
        #  Check for re-definition and create scope if needed
William Stein's avatar
William Stein committed
1052 1053 1054 1055 1056
        #
        if not type.scope:
            if defining or implementing:
                scope = CClassScope(name = name, outer_scope = self,
                    visibility = visibility)
1057
                if base_type and base_type.scope:
William Stein's avatar
William Stein committed
1058 1059
                    scope.declare_inherited_c_attributes(base_type.scope)
                type.set_scope(scope)
1060
                self.type_entries.append(entry)
William Stein's avatar
William Stein committed
1061 1062 1063 1064 1065 1066 1067 1068
            else:
                self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
        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)
        #
1069
        #  Fill in options, checking for compatibility with any previous declaration
William Stein's avatar
William Stein committed
1070
        #
1071 1072
        if defining:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
1073 1074
        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
1075
        if visibility != 'private' and entry.visibility != visibility:
Stefan Behnel's avatar
Stefan Behnel committed
1076 1077 1078 1079
            error(pos, "Class '%s' previously declared as '%s'"
                % (name, entry.visibility))
        if api:
            entry.api = 1
William Stein's avatar
William Stein committed
1080
        if objstruct_cname:
Stefan Behnel's avatar
Stefan Behnel committed
1081
            if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
William Stein's avatar
William Stein committed
1082
                error(pos, "Object struct name differs from previous declaration")
Robert Bradshaw's avatar
Robert Bradshaw committed
1083
            type.objstruct_cname = objstruct_cname        
William Stein's avatar
William Stein committed
1084
        if typeobj_cname:
Stefan Behnel's avatar
Stefan Behnel committed
1085
            if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
William Stein's avatar
William Stein committed
1086 1087 1088
                    error(pos, "Type object name differs from previous declaration")
            type.typeobj_cname = typeobj_cname
        #
Robert Bradshaw's avatar
Robert Bradshaw committed
1089
        # Return new or existing entry    
William Stein's avatar
William Stein committed
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
        #
        return entry
    
    def check_for_illegal_incomplete_ctypedef(self, typedef_flag, pos):
        if typedef_flag and not self.in_cinclude:
            error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
    
    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:
            #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)

1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
    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
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151

    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
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
    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
1168
            print("Scope.check_c_classes: checking scope " + self.qualified_name)
William Stein's avatar
William Stein committed
1169 1170
        for entry in self.c_class_entries:
            if debug_check_c_classes:
Stefan Behnel's avatar
Stefan Behnel committed
1171
                print("...entry %s %s" % (entry.name, entry))
1172 1173
                print("......type = ",  entry.type)
                print("......visibility = ", entry.visibility)
Vitja Makarov's avatar
Vitja Makarov committed
1174 1175
            self.check_c_class(entry)

1176 1177 1178 1179 1180 1181
    def check_c_functions(self):
        # Performs post-analysis checking making sure all 
        # defined c functions are actually implemented.
        for name, entry in self.entries.items():
            if entry.is_cfunction:
                if (entry.defined_in_pxd 
1182
                        and entry.scope is self
1183 1184 1185 1186
                        and entry.visibility != 'extern'
                        and not entry.in_cinclude 
                        and not entry.is_implemented):
                    error(entry.pos, "Non-extern C function '%s' declared but not defined" % name)
William Stein's avatar
William Stein committed
1187 1188 1189 1190 1191 1192 1193 1194
    
    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.
1195
        import Builtin
William Stein's avatar
William Stein committed
1196
        var_entry = Entry(name = entry.name,
1197
            type = Builtin.type_type,
William Stein's avatar
William Stein committed
1198 1199 1200 1201 1202 1203
            pos = entry.pos,
            cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
        var_entry.is_variable = 1
        var_entry.is_cglobal = 1
        var_entry.is_readonly = 1
        entry.as_variable = var_entry
Robert Bradshaw's avatar
Robert Bradshaw committed
1204
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1205 1206
    def is_cpp(self):
        return self.cpp
William Stein's avatar
William Stein committed
1207
        
Robert Bradshaw's avatar
Robert Bradshaw committed
1208 1209 1210
    def infer_types(self):
        from TypeInference import PyObjectTypeInferer
        PyObjectTypeInferer().infer_types(self)
William Stein's avatar
William Stein committed
1211
        
1212
class LocalScope(Scope):
William Stein's avatar
William Stein committed
1213

1214 1215 1216 1217
    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)
William Stein's avatar
William Stein committed
1218 1219
    
    def mangle(self, prefix, name):
1220
        return prefix + name
William Stein's avatar
William Stein committed
1221 1222 1223 1224

    def declare_arg(self, name, type, pos):
        # Add an entry for an argument of a function.
        cname = self.mangle(Naming.var_prefix, name)
1225
        entry = self.declare(name, cname, type, pos, 'private')
William Stein's avatar
William Stein committed
1226 1227 1228
        entry.is_variable = 1
        if type.is_pyobject:
            entry.init = "0"
1229
        entry.is_arg = 1
William Stein's avatar
William Stein committed
1230 1231
        #entry.borrowed = 1 # Not using borrowed arg refs for now
        self.arg_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
1232
        self.control_flow.set_state((), (name, 'source'), 'arg')
William Stein's avatar
William Stein committed
1233 1234 1235 1236 1237 1238 1239 1240 1241
        return entry
    
    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
        # Add an entry for a local variable.
        if visibility in ('public', 'readonly'):
            error(pos, "Local variable cannot be declared %s" % visibility)
        entry = Scope.declare_var(self, name, type, pos, 
            cname, visibility, is_cdef)
Robert Bradshaw's avatar
Robert Bradshaw committed
1242 1243
        if type.is_pyobject and not Options.init_local_none:
            entry.init = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
1244
        entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
1245
        entry.is_local = 1
William Stein's avatar
William Stein committed
1246 1247 1248 1249 1250 1251
        self.var_entries.append(entry)
        return entry
    
    def declare_global(self, name, pos):
        # Pull entry from global scope into local scope.
        if self.lookup_here(name):
1252
            warning(pos, "'%s' redeclared  ", 0)
William Stein's avatar
William Stein committed
1253 1254 1255 1256
        else:
            entry = self.global_scope().lookup_target(name)
            self.entries[name] = entry
        
1257 1258 1259 1260 1261 1262
    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
1263 1264
                if hasattr(entry.scope, "scope_class"):
                    raise InternalError, "lookup() after scope class created."
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
                # The actual c fragment for the different scopes differs 
                # on the outside and inside, so we make a new entry
                entry.in_closure = True
                # Would it be better to declare_var here?
                inner_entry = Entry(entry.name, entry.cname, entry.type, entry.pos)
                inner_entry.scope = self
                inner_entry.is_variable = True
                inner_entry.outer_entry = entry
                inner_entry.from_closure = True
                self.entries[name] = inner_entry
                return inner_entry
        return entry
1277
            
1278
    def mangle_closure_cnames(self, outer_scope_cname):
1279
        for entry in self.entries.values():
1280 1281
            if entry.from_closure:
                cname = entry.outer_entry.cname
Vitja Makarov's avatar
Vitja Makarov committed
1282 1283 1284 1285 1286 1287
                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)
1288 1289 1290
            elif entry.in_closure:
                entry.original_cname = entry.cname
                entry.cname = "%s->%s" % (Naming.cur_scope_cname, entry.cname)
1291

1292
class GeneratorExpressionScope(Scope):
1293 1294 1295 1296 1297 1298
    """Scope for generator expressions and comprehensions.  As opposed
    to generators, these can be easily inlined in some cases, so all
    we really need is a scope that holds the loop variable(s).
    """
    def __init__(self, outer_scope):
        name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref)
1299
        Scope.__init__(self, name, outer_scope, outer_scope)
1300
        self.directives = outer_scope.directives
1301 1302
        self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name)

1303
    def mangle(self, prefix, name):
1304
        return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(self, prefix, name))
1305 1306

    def declare_var(self, name, type, pos,
1307
                    cname = None, visibility = 'private', is_cdef = True):
1308 1309 1310
        if type is unspecified_type:
            # if the outer scope defines a type for this variable, inherit it
            outer_entry = self.outer_scope.lookup(name)
1311
            if outer_entry and outer_entry.is_variable:
1312
                type = outer_entry.type # may still be 'unspecified_type' !
1313
        # the parent scope needs to generate code for the variable, but
1314
        # this scope must hold its name exclusively
1315
        cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.var_prefix, name))
1316 1317 1318
        entry = self.declare(name, cname, type, pos, visibility)
        entry.is_variable = 1
        self.var_entries.append(entry)
1319 1320 1321 1322
        self.entries[name] = entry
        return entry


Robert Bradshaw's avatar
Robert Bradshaw committed
1323
class ClosureScope(LocalScope):
1324

Robert Bradshaw's avatar
Robert Bradshaw committed
1325 1326 1327 1328 1329 1330 1331
    is_closure_scope = True

    def __init__(self, name, scope_name, outer_scope):
        LocalScope.__init__(self, name, outer_scope)
        self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name)

#    def mangle_closure_cnames(self, scope_var):
1332 1333
#        for entry in self.entries.values() + self.temp_entries:
#            entry.in_closure = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1334
#        LocalScope.mangle_closure_cnames(self, scope_var)
1335
    
1336 1337 1338
#    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
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350

    def declare_pyfunction(self, name, pos):
        # Add an entry for a Python function.
        entry = self.lookup_here(name)
        if entry and not entry.type.is_cfunction:
            # This is legal Python, but for now may produce invalid C.
            error(pos, "'%s' already declared" % name)
        entry = self.declare_var(name, py_object_type, pos)
        entry.signature = pyfunction_signature
        self.pyfunc_entries.append(entry)
        return entry

1351

William Stein's avatar
William Stein committed
1352 1353
class StructOrUnionScope(Scope):
    #  Namespace of a C struct or union.
Robert Bradshaw's avatar
Robert Bradshaw committed
1354
    
1355 1356
    def __init__(self, name="?"):
        Scope.__init__(self, name, None, None)
William Stein's avatar
William Stein committed
1357 1358

    def declare_var(self, name, type, pos, 
1359
            cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
William Stein's avatar
William Stein committed
1360 1361 1362
        # Add an entry for an attribute.
        if not cname:
            cname = name
1363 1364
            if visibility == 'private':
                cname = c_safe_identifier(cname)
1365
        if type.is_cfunction:
1366
            type = PyrexTypes.CPtrType(type)
1367
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
1368 1369
        entry.is_variable = 1
        self.var_entries.append(entry)
1370
        if type.is_pyobject and not allow_pyobject:
William Stein's avatar
William Stein committed
1371
            error(pos,
Craig Citro's avatar
Craig Citro committed
1372
                  "C struct/union member cannot be a Python object")
Stefan Behnel's avatar
Stefan Behnel committed
1373
        if visibility != 'private':
William Stein's avatar
William Stein committed
1374
            error(pos,
Craig Citro's avatar
Craig Citro committed
1375
                  "C struct/union member cannot be declared %s" % visibility)
William Stein's avatar
William Stein committed
1376 1377
        return entry

1378
    def declare_cfunction(self, name, type, pos, 
1379
                          cname = None, visibility = 'private', defining = 0,
1380
                          api = 0, in_pxd = 0, modifiers = ()): # currently no utility code ...
1381
        return self.declare_var(name, type, pos, cname, visibility)
William Stein's avatar
William Stein committed
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396

class ClassScope(Scope):
    #  Abstract base class for namespace of
    #  Python class or extension type.
    #
    #  class_name     string   Pyrex name of the class
    #  scope_prefix   string   Additional prefix for names
    #                          declared in the class
    #  doc    string or None   Doc string

    def __init__(self, name, outer_scope):
        Scope.__init__(self, name, outer_scope, outer_scope)
        self.class_name = name
        self.doc = None

1397
    def lookup(self, name):
1398 1399 1400
        entry = Scope.lookup(self, name)
        if entry:
            return entry
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
        if name == "classmethod":
            # We don't want to use the builtin classmethod here 'cause it won't do the 
            # right thing in this scope (as the class memebers aren't still functions). 
            # Don't want to add a cfunction to this scope 'cause that would mess with 
            # the type definition, so we just return the right entry. 
            self.use_utility_code(classmethod_utility_code)
            entry = Entry(
                "classmethod", 
                "__Pyx_Method_ClassMethod", 
                PyrexTypes.CFuncType(
                    py_object_type,
                    [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0))
            entry.is_cfunction = 1
1414
        return entry
1415
    
William Stein's avatar
William Stein committed
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425

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

    is_py_class_scope = 1
    
    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
1426 1427
        if type is unspecified_type:
            type = py_object_type
William Stein's avatar
William Stein committed
1428 1429 1430 1431
        # Add an entry for a class attribute.
        entry = Scope.declare_var(self, name, type, pos, 
            cname, visibility, is_cdef)
        entry.is_pyglobal = 1
Stefan Behnel's avatar
Stefan Behnel committed
1432
        entry.is_pyclass_attr = 1
William Stein's avatar
William Stein committed
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
        return entry

    def add_default_value(self, type):
        return self.outer_scope.add_default_value(type)


class CClassScope(ClassScope):
    #  Namespace of an extension type.
    #
    #  parent_type           CClassType
    #  #typeobj_cname        string or None
    #  #objstruct_cname      string
    #  method_table_cname    string
    #  getset_table_cname    string
    #  has_pyobject_attrs    boolean  Any PyObject attributes?
    #  property_entries      [Entry]
    #  defined               boolean  Defined in .pxd file
    #  implemented           boolean  Defined in .pyx file
    #  inherited_var_entries [Entry]  Adapted var entries from base class
    
    is_c_class_scope = 1
    
    def __init__(self, name, outer_scope, visibility):
        ClassScope.__init__(self, name, outer_scope)
Stefan Behnel's avatar
Stefan Behnel committed
1457
        if visibility != 'extern':
William Stein's avatar
William Stein committed
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
            self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
            self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
        self.has_pyobject_attrs = 0
        self.property_entries = []
        self.inherited_var_entries = []
        self.defined = 0
        self.implemented = 0
    
    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.
        return self.has_pyobject_attrs or \
1470 1471
            (self.parent_type.base_type and
                self.parent_type.base_type.scope is not None and
William Stein's avatar
William Stein committed
1472 1473 1474 1475
                self.parent_type.base_type.scope.needs_gc())

    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
1476 1477 1478
        if is_cdef:
            # Add an entry for an attribute.
            if self.defined:
William Stein's avatar
William Stein committed
1479
                error(pos,
1480
                    "C attributes cannot be added in implementation part of"
1481
                    " extension type defined in a pxd")
1482 1483 1484 1485 1486 1487
            if get_special_method_signature(name):
                error(pos, 
                    "The name '%s' is reserved for a special method."
                        % name)
            if not cname:
                cname = name
1488 1489
                if visibility == 'private':
                    cname = c_safe_identifier(cname)
1490 1491
            if type.is_cpp_class and visibility != 'extern':
                error(pos, "C++ classes not allowed as members of an extension type, use a pointer or reference instead")
1492
            entry = self.declare(name, cname, type, pos, visibility)
1493 1494 1495 1496 1497 1498 1499 1500
            entry.is_variable = 1
            self.var_entries.append(entry)
            if type.is_pyobject:
                self.has_pyobject_attrs = 1
            if visibility not in ('private', 'public', 'readonly'):
                error(pos,
                    "Attribute of extension type cannot be declared %s" % visibility)
            if visibility in ('public', 'readonly'):
1501 1502 1503 1504 1505 1506 1507 1508
                if name == "__weakref__":
                    error(pos, "Special attribute __weakref__ cannot be exposed to Python")
                if not type.is_pyobject:
                    if (not type.create_to_py_utility_code(self) or
                        (visibility=='public' and not
                         type.create_from_py_utility_code(self))):
                        error(pos,
                              "C attribute of type '%s' cannot be accessed from Python" % type)
1509 1510
            return entry
        else:
1511 1512
            if type is unspecified_type:
                type = py_object_type
1513 1514 1515
            # Add an entry for a class attribute.
            entry = Scope.declare_var(self, name, type, pos, 
                cname, visibility, is_cdef)
1516 1517 1518 1519
            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
1520
            self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
1521
            return entry
1522

William Stein's avatar
William Stein committed
1523 1524 1525

    def declare_pyfunction(self, name, pos):
        # Add an entry for a method.
1526
        if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
Robert Bradshaw's avatar
Robert Bradshaw committed
1527
            error(pos, "Special method %s must be implemented via __richcmp__" % name)
1528 1529 1530
        if name == "__new__":
            warning(pos, "__new__ method of extension type will change semantics "
                "in a future version of Pyrex and Cython. Use __cinit__ instead.")
1531
            name = EncodedString("__cinit__")
1532
        entry = self.declare_var(name, py_object_type, pos, visibility='extern')
William Stein's avatar
William Stein committed
1533 1534
        special_sig = get_special_method_signature(name)
        if special_sig:
1535 1536
            # Special methods get put in the method table with a particular
            # signature declared in advance.
William Stein's avatar
William Stein committed
1537
            entry.signature = special_sig
1538
            entry.is_special = 1
William Stein's avatar
William Stein committed
1539 1540
        else:
            entry.signature = pymethod_signature
1541
            entry.is_special = 0
1542 1543

        self.pyfunc_entries.append(entry)
William Stein's avatar
William Stein committed
1544
        return entry
1545 1546 1547
    
    def lookup_here(self, name):
        if name == "__new__":
1548
            name = EncodedString("__cinit__")
1549 1550
        return ClassScope.lookup_here(self, name)
    
William Stein's avatar
William Stein committed
1551
    def declare_cfunction(self, name, type, pos,
1552
                          cname = None, visibility = 'private',
1553 1554
                          defining = 0, api = 0, in_pxd = 0, modifiers = (),
                          utility_code = None):
William Stein's avatar
William Stein committed
1555 1556 1557 1558 1559
        if get_special_method_signature(name):
            error(pos, "Special methods must be declared with 'def', not 'cdef'")
        args = type.args
        if not args:
            error(pos, "C method has no self argument")
1560
        elif not self.parent_type.assignable_from(args[0].type):
Stefan Behnel's avatar
Stefan Behnel committed
1561 1562
            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
1563 1564 1565
        entry = self.lookup_here(name)
        if entry:
            if not entry.is_cfunction:
1566
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
1567 1568 1569
            else:
                if defining and entry.func_cname:
                    error(pos, "'%s' already defined" % name)
1570
                #print "CClassScope.declare_cfunction: checking signature" ###
1571
                if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1572
                    pass
1573
                elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1574
                    entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore', modifiers=modifiers)
1575
                    defining = 1
1576 1577
                else:
                    error(pos, "Signature not compatible with previous declaration")
1578
                    error(entry.pos, "Previous declaration is here")
William Stein's avatar
William Stein committed
1579 1580 1581 1582 1583
        else:
            if self.defined:
                error(pos,
                    "C method '%s' not previously declared in definition part of"
                    " extension type" % name)
1584 1585
            entry = self.add_cfunction(name, type, pos, cname or name,
                                       visibility, modifiers)
William Stein's avatar
William Stein committed
1586 1587
        if defining:
            entry.func_cname = self.mangle(Naming.func_prefix, name)
1588
        entry.utility_code = utility_code
William Stein's avatar
William Stein committed
1589 1590
        return entry
        
1591
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
William Stein's avatar
William Stein committed
1592
        # Add a cfunction entry without giving it a func_cname.
1593
        prev_entry = self.lookup_here(name)
1594 1595
        entry = ClassScope.add_cfunction(self, name, type, pos, cname,
                                         visibility, modifiers)
William Stein's avatar
William Stein committed
1596
        entry.is_cmethod = 1
1597
        entry.prev_entry = prev_entry
William Stein's avatar
William Stein committed
1598
        return entry
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612

    def declare_builtin_cfunction(self, name, type, cname, utility_code = None):
        # overridden methods of builtin types still have their Python
        # equivalent that must be accessible to support bound methods
        name = EncodedString(name)
        entry = self.declare_cfunction(name, type, None, cname, visibility='extern',
                                       utility_code = utility_code)
        var_entry = Entry(name, name, py_object_type)
        var_entry.is_variable = 1
        var_entry.is_builtin = 1
        var_entry.utility_code = utility_code
        entry.as_variable = var_entry
        return entry

William Stein's avatar
William Stein committed
1613
    def declare_property(self, name, doc, pos):
1614 1615
        entry = self.lookup_here(name)
        if entry is None:
1616
            entry = self.declare(name, name, py_object_type, pos, 'private')
William Stein's avatar
William Stein committed
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633
        entry.is_property = 1
        entry.doc = doc
        entry.scope = PropertyScope(name, 
            outer_scope = self.global_scope(), parent_scope = self)
        entry.scope.parent_type = self.parent_type
        self.property_entries.append(entry)
        return entry
    
    def declare_inherited_c_attributes(self, base_scope):
        # Declare entries for all the C attributes of an
        # inherited type, with cnames modified appropriately
        # to work with this type.
        def adapt(cname):
            return "%s.%s" % (Naming.obj_base_cname, base_entry.cname)
        for base_entry in \
            base_scope.inherited_var_entries + base_scope.var_entries:
                entry = self.declare(base_entry.name, adapt(base_entry.cname), 
1634
                    base_entry.type, None, 'private')
William Stein's avatar
William Stein committed
1635 1636 1637
                entry.is_variable = 1
                self.inherited_var_entries.append(entry)
        for base_entry in base_scope.cfunc_entries:
1638
            entry = self.add_cfunction(base_entry.name, base_entry.type,
1639 1640
                                       base_entry.pos, adapt(base_entry.cname),
                                       base_entry.visibility, base_entry.func_modifiers)
William Stein's avatar
William Stein committed
1641
            entry.is_inherited = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1642
            
1643
        
DaniloFreitas's avatar
DaniloFreitas committed
1644 1645
class CppClassScope(Scope):
    #  Namespace of a C++ class.
Robert Bradshaw's avatar
Robert Bradshaw committed
1646 1647
    
    is_cpp_class_scope = 1
DaniloFreitas's avatar
DaniloFreitas committed
1648
    
1649
    default_constructor = None
DaniloFreitas's avatar
DaniloFreitas committed
1650
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1651 1652 1653
    def __init__(self, name, outer_scope):
        Scope.__init__(self, name, outer_scope, None)
        self.directives = outer_scope.directives
Robert Bradshaw's avatar
Robert Bradshaw committed
1654
        self.inherited_var_entries = []
DaniloFreitas's avatar
DaniloFreitas committed
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669

    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'extern', is_cdef = 0, allow_pyobject = 0):
        # Add an entry for an attribute.
        if not cname:
            cname = name
        if type.is_cfunction:
            type = PyrexTypes.CPtrType(type)
        entry = self.declare(name, cname, type, pos, visibility)
        entry.is_variable = 1
        self.var_entries.append(entry)
        if type.is_pyobject and not allow_pyobject:
            error(pos,
                "C++ class member cannot be a Python object")
        return entry
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
    
    def check_base_default_constructor(self, pos):
        # Look for default constructors in all base classes.
        if self.default_constructor is None:
            entry = self.lookup(self.name)
            if len(entry.type.base_classes) == 0:
                self.default_constructor = True
                return
            for base_class in entry.type.base_classes:
                temp_entry = base_class.scope.lookup_here("<init>")
                found = False
                if temp_entry is None:
                    continue
                for alternative in temp_entry.all_alternatives():
                    type = alternative.type
                    if type.is_ptr:
                        type = type.base_type
                    if len(type.args) == 0:
                        found = True
                        break
                if not found:
                    self.default_constructor = temp_entry.scope.name
                    error(pos, "no matching function for call to " \
                            "%s::%s()" % (temp_entry.scope.name, temp_entry.scope.name))
        elif not self.default_constructor:
            error(pos, "no matching function for call to %s::%s()" %
                  (self.default_constructor, self.default_constructor))
DaniloFreitas's avatar
DaniloFreitas committed
1697

1698 1699
    def declare_cfunction(self, name, type, pos,
            cname = None, visibility = 'extern', defining = 0,
1700
            api = 0, in_pxd = 0, modifiers = (), utility_code = None):
1701
        if name == self.name.split('::')[-1] and cname is None:
1702
            self.check_base_default_constructor(pos)
1703
            name = '<init>'
1704
            type.return_type = self.lookup(self.name).type
1705
        prev_entry = self.lookup_here(name)
1706
        entry = self.declare_var(name, type, pos, cname, visibility)
1707 1708
        if prev_entry:
            entry.overloaded_alternatives = prev_entry.all_alternatives()
1709 1710
        entry.utility_code = utility_code
        return entry
1711

DaniloFreitas's avatar
DaniloFreitas committed
1712 1713 1714 1715 1716 1717
    def declare_inherited_cpp_attributes(self, base_scope):
        # Declare entries for all the C++ attributes of an
        # inherited type, with cnames modified appropriately
        # to work with this type.
        for base_entry in \
            base_scope.inherited_var_entries + base_scope.var_entries:
1718 1719 1720 1721 1722 1723
                #contructor is not inherited
                if base_entry.name == "<init>":
                    continue
                #print base_entry.name, self.entries
                if base_entry.name in self.entries:
                    base_entry.name
1724
                entry = self.declare(base_entry.name, base_entry.cname, 
DaniloFreitas's avatar
DaniloFreitas committed
1725 1726 1727 1728 1729
                    base_entry.type, None, 'extern')
                entry.is_variable = 1
                self.inherited_var_entries.append(entry)
        for base_entry in base_scope.cfunc_entries:
            entry = self.declare_cfunction(base_entry.name, base_entry.type,
1730
                                       base_entry.pos, base_entry.cname,
1731 1732
                                       base_entry.visibility, base_entry.func_modifiers,
                                           utility_code = base_entry.utility_code)
DaniloFreitas's avatar
DaniloFreitas committed
1733
            entry.is_inherited = 1
1734 1735
    
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
1736
        scope = CppClassScope(self.name, self.outer_scope)
1737
        for entry in self.entries.values():
Robert Bradshaw's avatar
Robert Bradshaw committed
1738 1739 1740 1741 1742 1743
            if entry.is_type:
                scope.declare_type(entry.name,
                                    entry.type.specialize(values),
                                    entry.pos,
                                    entry.cname)
            else:
1744 1745 1746 1747 1748 1749 1750 1751 1752
#                scope.declare_var(entry.name,
#                                    entry.type.specialize(values),
#                                    entry.pos,
#                                    entry.cname,
#                                    entry.visibility)
                for e in entry.all_alternatives():
                    scope.declare_cfunction(e.name,
                                            e.type.specialize(values),
                                            e.pos,
1753 1754
                                            e.cname,
                                            utility_code = e.utility_code)
1755
        return scope
1756 1757 1758

    def add_include_file(self, filename):
        self.outer_scope.add_include_file(filename)        
1759
        
William Stein's avatar
William Stein committed
1760 1761 1762 1763 1764
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
1765 1766

    is_property_scope = 1
William Stein's avatar
William Stein committed
1767 1768 1769 1770 1771
    
    def declare_pyfunction(self, name, pos):
        # Add an entry for a method.
        signature = get_property_accessor_signature(name)
        if signature:
1772
            entry = self.declare(name, name, py_object_type, pos, 'private')
Stefan Behnel's avatar
Stefan Behnel committed
1773
            entry.is_special = 1
1774
            entry.signature = signature
William Stein's avatar
William Stein committed
1775 1776 1777 1778 1779
            return entry
        else:
            error(pos, "Only __get__, __set__ and __del__ methods allowed "
                "in a property declaration")
            return None
1780 1781 1782 1783 1784


# Should this go elsewhere (and then get imported)?
#------------------------------------------------------------------------------------

1785
classmethod_utility_code = Code.UtilityCode(
Stefan Behnel's avatar
Stefan Behnel committed
1786
proto = """
1787 1788
#include "descrobject.h"
static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
Stefan Behnel's avatar
Stefan Behnel committed
1789 1790
""",
impl = """
1791 1792
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
    /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
1793 1794 1795 1796 1797 1798 1799 1800
    static PyTypeObject *methoddescr_type = NULL;
    if (methoddescr_type == NULL) {
       PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
       if (!meth) return NULL;
       methoddescr_type = Py_TYPE(meth);
       Py_DECREF(meth);
    }
    if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
1801
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
1802 1803 1804 1805 1806 1807
        #if PY_VERSION_HEX < 0x03020000
        PyTypeObject *d_type = descr->d_type;
        #else
        PyTypeObject *d_type = descr->d_common.d_type;
        #endif
        return PyDescr_NewClassMethod(d_type, descr->d_method);
1808
    }
1809
    else if (PyMethod_Check(method)) { /* python classes */
1810 1811
        return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
    }
1812 1813 1814
    else if (PyCFunction_Check(method)) {
        return PyClassMethod_New(method);
    }
Vitja Makarov's avatar
Vitja Makarov committed
1815 1816 1817 1818 1819
#ifdef __pyx_binding_PyCFunctionType_USED
    else if (PyObject_TypeCheck(method, __pyx_binding_PyCFunctionType)) { /* binded CFunction */
        return PyClassMethod_New(method);
    }
#endif
1820
    PyErr_Format(PyExc_TypeError,
Vitja Makarov's avatar
Vitja Makarov committed
1821
                 "Class-level classmethod() can only be called on "
1822
                 "a method_descriptor or instance method.");
1823 1824
    return NULL;
}
Stefan Behnel's avatar
Stefan Behnel committed
1825
""")
1826 1827 1828 1829

#------------------------------------------------------------------------------------

ERR_BUF_LOCALONLY = 'Buffer types only allowed as function local variables'