Symtab.py 61 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
William Stein's avatar
William Stein committed
23

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

27
iso_c99_keywords = set(
28 29 30 31
['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 
    'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 
    'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof', 
    'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 
32 33
    'volatile', 'while',
    '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict'])
34 35

def c_safe_identifier(cname):
36 37 38 39 40
    # 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):
41 42 43
        cname = Naming.pyrex_prefix + cname
    return cname

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

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

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

William Stein's avatar
William Stein committed
169 170 171 172 173 174
    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
175
        self.assignments = []
Robert Bradshaw's avatar
Robert Bradshaw committed
176 177 178
    
    def __repr__(self):
        return "Entry(name=%s, type=%s)" % (self.name, self.type)
179
        
180 181 182
    def redeclared(self, pos):
        error(pos, "'%s' does not match previous declaration" % self.name)
        error(self.pos, "Previous declaration is here")
183

184
class Scope(object):
William Stein's avatar
William Stein committed
185 186 187 188
    # 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
189
    # type_entries      [Entry]            Struct/union/enum/typedef/exttype entries
William Stein's avatar
William Stein committed
190 191 192 193 194 195 196
    # 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
197
    # int_to_entry      {int : Entry}      Temp cname to entry mapping
William Stein's avatar
William Stein committed
198 199 200 201 202 203 204 205
    # 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
    # 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
206
    # control_flow     ControlFlow  Used for keeping track of environment state
207
    # nogil             boolean            In a nogil section
208 209
    # directives       dict                Helper variable for the recursive
    #                                      analysis, contains directive values.
William Stein's avatar
William Stein committed
210 211 212

    is_py_class_scope = 0
    is_c_class_scope = 0
213
    is_module_scope = 0
William Stein's avatar
William Stein committed
214 215
    scope_prefix = ""
    in_cinclude = 0
216
    nogil = 0
William Stein's avatar
William Stein committed
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    
    def __init__(self, name, outer_scope, parent_scope):
        # The outer_scope is the next scope in the lookup chain.
        # The parent_scope is used to derive the qualified name of this scope.
        self.name = name
        self.outer_scope = outer_scope
        self.parent_scope = parent_scope
        mangled_name = "%d%s_" % (len(name), name)
        qual_scope = self.qualifying_scope()
        if qual_scope:
            self.qualified_name = qual_scope.qualify_name(name)
            self.scope_prefix = qual_scope.scope_prefix + mangled_name
        else:
            self.qualified_name = name
            self.scope_prefix = mangled_name
        self.entries = {}
        self.const_entries = []
234
        self.type_entries = []
William Stein's avatar
William Stein committed
235 236 237 238 239 240 241 242 243 244
        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 = {}
245
        self.identifier_to_entry = {}
246
        self.num_to_entry = {}
Robert Bradshaw's avatar
Robert Bradshaw committed
247
        self.obj_to_entry = {}
William Stein's avatar
William Stein committed
248
        self.pystring_entries = []
249
        self.buffer_entries = []
250
        self.control_flow = ControlFlow.LinearControlFlow()
251
        self.return_type = None
252 253 254
        
    def start_branching(self, pos):
        self.control_flow = self.control_flow.start_branch(pos)
William Stein's avatar
William Stein committed
255
    
256 257 258 259 260 261
    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
262 263
    def __str__(self):
        return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
264

William Stein's avatar
William Stein committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    def qualifying_scope(self):
        return self.parent_scope
    
    def mangle(self, prefix, name = None):
        if name:
            return "%s%s%s" % (prefix, self.scope_prefix, name)
        else:
            return self.parent_scope.mangle(prefix, self.name)
    
    def mangle_internal(self, name):
        # Mangle an internal name so as not to clash with any
        # user-defined name in this scope.
        prefix = "%s%s_" % (Naming.pyrex_prefix, name)
        return self.mangle(prefix)
        #return self.parent_scope.mangle(prefix, self.name)
    
    def global_scope(self):
        # Return the module-level scope containing this scope.
        return self.outer_scope.global_scope()
    
285 286 287 288
    def builtin_scope(self):
        # Return the module-level scope containing this scope.
        return self.outer_scope.builtin_scope()

289
    def declare(self, name, cname, type, pos, visibility):
William Stein's avatar
William Stein committed
290
        # Create new entry, and add to dictionary if
291
        # name is not None. Reports a warning if already 
William Stein's avatar
William Stein committed
292
        # declared.
293
        if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
294
            # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names 
295
            warning(pos, "'%s' is a reserved name in C." % cname, -1)
Stefan Behnel's avatar
Stefan Behnel committed
296 297
        entries = self.entries
        if name and name in entries:
298 299
            if visibility == 'extern':
                warning(pos, "'%s' redeclared " % name, 0)
300
            elif visibility != 'ignore':
301
                error(pos, "'%s' redeclared " % name)
William Stein's avatar
William Stein committed
302 303 304 305
        entry = Entry(name, cname, type, pos = pos)
        entry.in_cinclude = self.in_cinclude
        if name:
            entry.qualified_name = self.qualify_name(name)
Stefan Behnel's avatar
Stefan Behnel committed
306
            entries[name] = entry
307
        entry.scope = self
308
        entry.visibility = visibility
William Stein's avatar
William Stein committed
309 310 311 312
        return entry
    
    def qualify_name(self, name):
        return "%s.%s" % (self.qualified_name, name)
313

Robert Bradshaw's avatar
Robert Bradshaw committed
314
    def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
William Stein's avatar
William Stein committed
315 316
        # Add an entry for a named constant.
        if not cname:
317
            if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
318 319 320
                cname = name
            else:
                cname = self.mangle(Naming.enum_prefix, name)
Robert Bradshaw's avatar
Robert Bradshaw committed
321
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
322
        entry.is_const = 1
323
        entry.value_node = value
William Stein's avatar
William Stein committed
324 325 326
        return entry
    
    def declare_type(self, name, type, pos, 
327
            cname = None, visibility = 'private', defining = 1):
William Stein's avatar
William Stein committed
328 329 330
        # Add an entry for a type definition.
        if not cname:
            cname = name
331
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
332
        entry.is_type = 1
333 334
        if defining:
            self.type_entries.append(entry)
335
        # here we would set as_variable to an object representing this type
William Stein's avatar
William Stein committed
336
        return entry
337 338 339 340 341 342 343 344
    
    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)
345
        type = PyrexTypes.CTypedefType(cname, base_type, (visibility == 'extern'))
346 347
        entry = self.declare_type(name, type, pos, cname, visibility)
        type.qualified_name = entry.qualified_name
Stefan Behnel's avatar
Stefan Behnel committed
348
        return entry
William Stein's avatar
William Stein committed
349 350
        
    def declare_struct_or_union(self, name, kind, scope, 
351 352
            typedef_flag, pos, cname = None, visibility = 'private',
            packed = False):
William Stein's avatar
William Stein committed
353 354
        # Add an entry for a struct or union definition.
        if not cname:
355
            if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
356 357 358 359 360
                cname = name
            else:
                cname = self.mangle(Naming.type_prefix, name)
        entry = self.lookup_here(name)
        if not entry:
361
            type = PyrexTypes.CStructOrUnionType(
362
                name, kind, scope, typedef_flag, cname, packed)
363 364
            entry = self.declare_type(name, type, pos, cname,
                visibility = visibility, defining = scope is not None)
William Stein's avatar
William Stein committed
365 366
            self.sue_entries.append(entry)
        else:
367 368
            if not (entry.is_type and entry.type.is_struct_or_union
                    and entry.type.kind == kind):
369
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
370
            elif scope and entry.type.scope:
371
                warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0)
William Stein's avatar
William Stein committed
372 373
            else:
                self.check_previous_typedef_flag(entry, typedef_flag, pos)
374
                self.check_previous_visibility(entry, visibility, pos)
William Stein's avatar
William Stein committed
375 376
                if scope:
                    entry.type.scope = scope
377
                    self.type_entries.append(entry)
William Stein's avatar
William Stein committed
378 379 380 381 382
        if not scope and not entry.type.scope:
            self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
        return entry
    
    def check_previous_typedef_flag(self, entry, typedef_flag, pos):
Stefan Behnel's avatar
Stefan Behnel committed
383
        if typedef_flag != entry.type.typedef_flag:
William Stein's avatar
William Stein committed
384 385 386
            error(pos, "'%s' previously declared using '%s'" % (
                entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag]))
    
387
    def check_previous_visibility(self, entry, visibility, pos):
Stefan Behnel's avatar
Stefan Behnel committed
388
        if entry.visibility != visibility:
389 390 391 392 393
            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
394 395
        if name:
            if not cname:
396
                if self.in_cinclude or visibility == 'public':
William Stein's avatar
William Stein committed
397 398 399
                    cname = name
                else:
                    cname = self.mangle(Naming.type_prefix, name)
400
            type = PyrexTypes.CEnumType(name, cname, typedef_flag)
William Stein's avatar
William Stein committed
401
        else:
402 403 404
            type = PyrexTypes.c_anon_enum_type
        entry = self.declare_type(name, type, pos, cname = cname,
            visibility = visibility)
William Stein's avatar
William Stein committed
405 406
        entry.enum_values = []
        self.sue_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
407
        return entry    
William Stein's avatar
William Stein committed
408 409 410 411 412
    
    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
413
            if visibility != 'private':
William Stein's avatar
William Stein committed
414 415 416
                cname = name
            else:
                cname = self.mangle(Naming.var_prefix, name)
417
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
418
        entry.is_variable = 1
419
        self.control_flow.set_state((), (name, 'initalized'), False)
William Stein's avatar
William Stein committed
420 421 422 423 424 425 426
        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.
427
        entry = self.lookup_here(name)
428
        if entry and not entry.type.is_cfunction:
429 430
            # This is legal Python, but for now will produce invalid C.
            error(pos, "'%s' already declared" % name)
431
        entry = self.declare_var(name, py_object_type, pos, visibility='extern')
William Stein's avatar
William Stein committed
432 433 434 435 436 437 438 439
        entry.signature = pyfunction_signature
        self.pyfunc_entries.append(entry)
        return entry
    
    def register_pyfunction(self, entry):
        self.pyfunc_entries.append(entry)
    
    def declare_cfunction(self, name, type, pos, 
440 441
                          cname = None, visibility = 'private', defining = 0,
                          api = 0, in_pxd = 0, modifiers = ()):
William Stein's avatar
William Stein committed
442
        # Add an entry for a C function.
443 444
        entry = self.lookup_here(name)
        if entry:
Stefan Behnel's avatar
Stefan Behnel committed
445
            if visibility != 'private' and visibility != entry.visibility:
446
                warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
447
            if not entry.type.same_as(type):
448 449 450 451 452
                if visibility == 'extern' and entry.visibility == 'extern':
                    warning(pos, "Function signature does not match previous declaration", 1)
                    entry.type = type
                else:
                    error(pos, "Function signature does not match previous declaration")
453 454
        else:
            if not cname:
Stefan Behnel's avatar
Stefan Behnel committed
455
                if api or visibility != 'private':
456 457 458
                    cname = name
                else:
                    cname = self.mangle(Naming.func_prefix, name)
459
            entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
460
            entry.func_cname = cname
Stefan Behnel's avatar
Stefan Behnel committed
461
        if in_pxd and visibility != 'extern':
462 463 464
            entry.defined_in_pxd = 1
        if api:
            entry.api = 1
Stefan Behnel's avatar
Stefan Behnel committed
465
        if not defining and not in_pxd and visibility != 'extern':
Stefan Behnel's avatar
Stefan Behnel committed
466
            error(pos, "Non-extern C function '%s' declared but not defined" % name)
467 468
        if defining:
            entry.is_implemented = True
469 470
        if modifiers:
            entry.func_modifiers = modifiers
William Stein's avatar
William Stein committed
471 472
        return entry
    
473
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
William Stein's avatar
William Stein committed
474
        # Add a C function entry without giving it a func_cname.
475
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
476
        entry.is_cfunction = 1
477 478
        if modifiers:
            entry.func_modifiers = modifiers
William Stein's avatar
William Stein committed
479 480 481 482 483 484 485 486 487 488 489
        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)
    
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    def find_imported_module(self, path, pos):
        # Look up qualified name, must be a module, report error if not found.
        # Path is a list of names.
        scope = self
        for name in path:
            entry = scope.find(name, pos)
            if not entry:
                return None
            if entry.as_module:
                scope = entry.as_module
            else:
                error(pos, "'%s' is not a cimported module" % scope.qualified_name)
                return None
        return scope
        
William Stein's avatar
William Stein committed
505 506 507 508
    def lookup(self, name):
        # Look up name in this scope or an enclosing one.
        # Return None if not found.
        return (self.lookup_here(name)
509 510 511 512 513 514 515 516
            or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
            or None)

    def lookup_from_inner(self, name):
        # Look up name in this scope or an enclosing one.
        # This is only called from enclosing scopes.
        return (self.lookup_here(name)
            or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
William Stein's avatar
William Stein committed
517 518 519 520 521 522 523 524 525 526 527 528 529
            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
530 531 532 533 534
        
    def lookup_type(self, name):
        entry = self.lookup(name)
        if entry and entry.is_type:
            return entry.type
535

536 537
    def use_utility_code(self, new_code):
        self.global_scope().use_utility_code(new_code)
538

William Stein's avatar
William Stein committed
539 540 541 542 543 544 545 546
    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
547
            if name in self.entries:    
William Stein's avatar
William Stein committed
548 549
                return 1
        return 0
550 551
    
    def infer_types(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
552 553
        from TypeInference import get_type_inferer
        get_type_inferer().infer_types(self)
William Stein's avatar
William Stein committed
554

555
class PreImportScope(Scope):
556 557 558

    namespace_cname = Naming.preimport_cname

559 560 561 562
    def __init__(self):
        Scope.__init__(self, Options.pre_import, None, None)
        
    def declare_builtin(self, name, pos):
563
        entry = self.declare(name, name, py_object_type, pos, 'private')
564 565 566 567
        entry.is_variable = True
        entry.is_pyglobal = True
        return entry

William Stein's avatar
William Stein committed
568 569 570 571 572

class BuiltinScope(Scope):
    #  The builtin namespace.
    
    def __init__(self):
573 574 575 576
        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
577
        self.type_names = {}
578
        
Robert Bradshaw's avatar
Robert Bradshaw committed
579 580 581
        for name, definition in self.builtin_entries.iteritems():
            cname, type = definition
            self.declare_var(name, type, None, cname)
582
        
William Stein's avatar
William Stein committed
583
    def declare_builtin(self, name, pos):
Stefan Behnel's avatar
Stefan Behnel committed
584
        if not hasattr(builtins, name):
585 586 587 588
            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
589 590 591 592 593
    
    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.
594
        name = EncodedString(name)
595
        entry = self.declare_cfunction(name, type, None, cname, visibility='extern')
Stefan Behnel's avatar
Stefan Behnel committed
596 597 598 599
        entry.utility_code = utility_code
        if python_equiv:
            if python_equiv == "*":
                python_equiv = name
600
            else:
601
                python_equiv = EncodedString(python_equiv)
Stefan Behnel's avatar
Stefan Behnel committed
602
            var_entry = Entry(python_equiv, python_equiv, py_object_type)
603 604 605 606
            var_entry.is_variable = 1
            var_entry.is_builtin = 1
            entry.as_variable = var_entry
        return entry
Robert Bradshaw's avatar
Robert Bradshaw committed
607
        
608
    def declare_builtin_type(self, name, cname, utility_code = None):
609
        name = EncodedString(name)
Robert Bradshaw's avatar
Robert Bradshaw committed
610 611 612 613 614 615
        type = PyrexTypes.BuiltinObjectType(name, cname)
        type.set_scope(CClassScope(name, outer_scope=None, visibility='extern'))
        self.type_names[name] = 1
        entry = self.declare_type(name, type, None, visibility='extern')

        var_entry = Entry(name = entry.name,
616
            type = self.lookup('type').type, # make sure "type" is the first type declared...
Robert Bradshaw's avatar
Robert Bradshaw committed
617 618 619 620 621
            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
622
        var_entry.utility_code = utility_code
Robert Bradshaw's avatar
Robert Bradshaw committed
623 624 625
        entry.as_variable = var_entry

        return type
626

627 628
    def builtin_scope(self):
        return self
629

Robert Bradshaw's avatar
Robert Bradshaw committed
630
    builtin_entries = {
631 632 633 634

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

        "bool":   ["((PyObject*)&PyBool_Type)", py_object_type],
635 636 637
        "int":    ["((PyObject*)&PyInt_Type)", py_object_type],
        "long":   ["((PyObject*)&PyLong_Type)", py_object_type],
        "float":  ["((PyObject*)&PyFloat_Type)", py_object_type],
638 639 640 641
        "complex":["((PyObject*)&PyComplex_Type)", py_object_type],

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

644 645 646 647 648
        "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],
649

650 651
        "slice":  ["((PyObject*)&PySlice_Type)", py_object_type],
        "file":   ["((PyObject*)&PyFile_Type)", py_object_type],
652

Robert Bradshaw's avatar
Robert Bradshaw committed
653 654 655 656
        "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
657

658 659
const_counter = 1 # As a temporary solution for compiling code in pxds

William Stein's avatar
William Stein committed
660 661 662 663 664 665 666
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
667
    # utility_code_list    [UtilityCode]      Queuing utility codes for forwarding to Code.py
William Stein's avatar
William Stein committed
668 669 670
    # 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
671
    # identifier_to_entry  {string : Entry}   Map identifier string const to entry
William Stein's avatar
William Stein committed
672 673 674 675
    # 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)
676
    # included_files       [string]           Cython sources included with 'include'
William Stein's avatar
William Stein committed
677 678
    # pxd_file_loaded      boolean            Corresponding .pxd file has been processed
    # cimported_modules    [ModuleScope]      Modules imported with cimport
679
    # types_imported       {PyrexType : 1}    Set of types for which import code generated
680
    # has_import_star      boolean            Module contains import *
681 682
    
    is_module_scope = 1
683
    has_import_star = 0
William Stein's avatar
William Stein committed
684 685 686 687 688

    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)
689 690 691 692 693 694
        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
William Stein's avatar
William Stein committed
695 696 697 698 699 700
        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
701
        self.utility_code_list = []
William Stein's avatar
William Stein committed
702 703 704
        self.module_entries = {}
        self.python_include_files = ["Python.h", "structmember.h"]
        self.include_files = []
Robert Bradshaw's avatar
Robert Bradshaw committed
705
        self.type_names = dict(outer_scope.type_names)
William Stein's avatar
William Stein committed
706 707
        self.pxd_file_loaded = 0
        self.cimported_modules = []
708
        self.types_imported = {}
709
        self.included_files = []
710
        self.has_extern_class = 0
711 712
        self.cached_builtins = []
        self.undeclared_cached_builtins = []
713
        self.namespace_cname = self.module_cname
714 715
        for name in ['__builtins__', '__name__', '__file__', '__doc__']:
            self.declare_var(EncodedString(name), py_object_type, None)
William Stein's avatar
William Stein committed
716 717 718 719 720 721 722 723
    
    def qualifying_scope(self):
        return self.parent_module
    
    def global_scope(self):
        return self
    
    def declare_builtin(self, name, pos):
Stefan Behnel's avatar
Stefan Behnel committed
724
        if not hasattr(builtins, name):
725 726 727 728
            if self.has_import_star:
                entry = self.declare_var(name, py_object_type, pos)
                return entry
            elif self.outer_scope is not None:
729 730 731
                return self.outer_scope.declare_builtin(name, pos)
            else:
                error(pos, "undeclared name not builtin: %s"%name)
732 733 734 735
        if Options.cache_builtins:
            for entry in self.cached_builtins:
                if entry.name == name:
                    return entry
736
        entry = self.declare(None, None, py_object_type, pos, 'private')
737 738 739
        if Options.cache_builtins:
            entry.is_builtin = 1
            entry.is_const = 1
740
            entry.name = name
741 742 743 744 745
            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
746
        return entry
747

William Stein's avatar
William Stein committed
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
    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:
777 778
            for filename in scope.include_files:
                self.add_include_file(filename)
William Stein's avatar
William Stein committed
779
            self.cimported_modules.append(scope)
Robert Bradshaw's avatar
Robert Bradshaw committed
780 781
            for m in scope.cimported_modules:
                self.add_imported_module(m)
William Stein's avatar
William Stein committed
782 783 784 785 786
    
    def add_imported_entry(self, name, entry, pos):
        if entry not in self.entries:
            self.entries[name] = entry
        else:
787
            warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
788 789 790 791 792 793 794 795
    
    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:
796 797
            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
798
            if not (entry.is_pyglobal and not entry.as_module):
799 800 801 802 803 804 805 806
                # 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
807
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
808 809 810 811
                return None
        else:
            entry = self.declare_var(name, py_object_type, pos)
        entry.as_module = scope
Robert Bradshaw's avatar
Robert Bradshaw committed
812
        self.add_imported_module(scope)
William Stein's avatar
William Stein committed
813 814 815 816 817 818 819 820 821 822 823 824 825
        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:
826 827
            if type is unspecified_type:
                type = py_object_type
William Stein's avatar
William Stein committed
828 829 830 831 832 833
            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
834 835
            if entry.type.is_pyobject:
                entry.init = 0
William Stein's avatar
William Stein committed
836 837 838 839 840 841 842 843
            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)
    
844
    def use_utility_code(self, new_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
845
        if new_code is not None:
846
            self.utility_code_list.append(new_code)
847

848 849
    def declare_c_class(self, name, pos, defining = 0, implementing = 0,
        module_name = None, base_type = None, objstruct_cname = None,
850 851
        typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
        buffer_defaults = None):
852 853 854 855
        # 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
856 857
            if visibility != 'public':
                warning(pos, "ctypedef only valid for public and extern classes", 2)
858 859 860 861 862
            objtypedef_cname = objstruct_cname
            objstruct_cname = None
            typedef_flag = 0
        else:
            objtypedef_cname = None
William Stein's avatar
William Stein committed
863
        #
864
        #  Look for previous declaration as a type
William Stein's avatar
William Stein committed
865 866 867 868 869
        #
        entry = self.lookup_here(name)
        if entry:
            type = entry.type
            if not (entry.is_type and type.is_extension_type):
870
                entry = None # Will cause redeclaration and produce an error
William Stein's avatar
William Stein committed
871
            else:
872
                scope = type.scope
Robert Bradshaw's avatar
Robert Bradshaw committed
873
                if typedef_flag and (not scope or scope.defined):
874 875 876 877 878 879
                    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
880
        #
881
        #  Make a new entry if needed
William Stein's avatar
William Stein committed
882 883
        #
        if not entry:
884
            type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type)
885
            type.pos = pos
886
            type.buffer_defaults = buffer_defaults
887 888
            if objtypedef_cname is not None:
                type.objtypedef_cname = objtypedef_cname
William Stein's avatar
William Stein committed
889 890 891 892 893
            if visibility == 'extern':
                type.module_name = module_name
            else:
                type.module_name = self.qualified_name
            type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
894 895
            entry = self.declare_type(name, type, pos, visibility = visibility,
                defining = 0)
896
            entry.is_cclass = True
William Stein's avatar
William Stein committed
897 898 899
            if objstruct_cname:
                type.objstruct_cname = objstruct_cname
            elif not entry.in_cinclude:
900
                type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name)
William Stein's avatar
William Stein committed
901 902 903 904 905 906
            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)
        #
907
        #  Check for re-definition and create scope if needed
William Stein's avatar
William Stein committed
908 909 910 911 912
        #
        if not type.scope:
            if defining or implementing:
                scope = CClassScope(name = name, outer_scope = self,
                    visibility = visibility)
913
                if base_type and base_type.scope:
William Stein's avatar
William Stein committed
914 915
                    scope.declare_inherited_c_attributes(base_type.scope)
                type.set_scope(scope)
916
                self.type_entries.append(entry)
William Stein's avatar
William Stein committed
917 918 919 920 921 922 923 924
            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)
        #
925
        #  Fill in options, checking for compatibility with any previous declaration
William Stein's avatar
William Stein committed
926
        #
927 928
        if defining:
            entry.defined_in_pxd = 1
William Stein's avatar
William Stein committed
929 930
        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
931
        if visibility != 'private' and entry.visibility != visibility:
Stefan Behnel's avatar
Stefan Behnel committed
932 933 934 935
            error(pos, "Class '%s' previously declared as '%s'"
                % (name, entry.visibility))
        if api:
            entry.api = 1
William Stein's avatar
William Stein committed
936
        if objstruct_cname:
Stefan Behnel's avatar
Stefan Behnel committed
937
            if type.objstruct_cname and type.objstruct_cname != objstruct_cname:
William Stein's avatar
William Stein committed
938
                error(pos, "Object struct name differs from previous declaration")
Robert Bradshaw's avatar
Robert Bradshaw committed
939
            type.objstruct_cname = objstruct_cname        
William Stein's avatar
William Stein committed
940
        if typeobj_cname:
Stefan Behnel's avatar
Stefan Behnel committed
941
            if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
William Stein's avatar
William Stein committed
942 943 944
                    error(pos, "Type object name differs from previous declaration")
            type.typeobj_cname = typeobj_cname
        #
Robert Bradshaw's avatar
Robert Bradshaw committed
945
        # Return new or existing entry    
William Stein's avatar
William Stein committed
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
        #
        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)

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
    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)
                
William Stein's avatar
William Stein committed
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
    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
1001
            print("Scope.check_c_classes: checking scope " + self.qualified_name)
William Stein's avatar
William Stein committed
1002 1003
        for entry in self.c_class_entries:
            if debug_check_c_classes:
Stefan Behnel's avatar
Stefan Behnel committed
1004
                print("...entry %s %s" % (entry.name, entry))
1005 1006
                print("......type = ",  entry.type)
                print("......visibility = ", entry.visibility)
William Stein's avatar
William Stein committed
1007 1008 1009 1010 1011 1012 1013
            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
Stefan Behnel's avatar
Stefan Behnel committed
1014
            if visibility != 'extern' and not type.typeobj_cname:
William Stein's avatar
William Stein committed
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
                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)
1028 1029 1030 1031 1032 1033 1034
                
    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 
1035
                        and entry.scope is self
1036 1037 1038 1039
                        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
1040 1041 1042 1043 1044 1045 1046 1047
    
    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.
1048
        import Builtin
William Stein's avatar
William Stein committed
1049
        var_entry = Entry(name = entry.name,
1050
            type = Builtin.type_type,
William Stein's avatar
William Stein committed
1051 1052 1053 1054 1055 1056
            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
1057 1058 1059 1060
    
    def infer_types(self):
        from TypeInference import PyObjectTypeInferer
        PyObjectTypeInferer().infer_types(self)
William Stein's avatar
William Stein committed
1061
        
1062
class LocalScope(Scope):    
William Stein's avatar
William Stein committed
1063 1064 1065 1066 1067

    def __init__(self, name, outer_scope):
        Scope.__init__(self, name, outer_scope, outer_scope)
    
    def mangle(self, prefix, name):
1068
        return prefix + name
William Stein's avatar
William Stein committed
1069 1070 1071 1072

    def declare_arg(self, name, type, pos):
        # Add an entry for an argument of a function.
        cname = self.mangle(Naming.var_prefix, name)
1073
        entry = self.declare(name, cname, type, pos, 'private')
William Stein's avatar
William Stein committed
1074 1075 1076
        entry.is_variable = 1
        if type.is_pyobject:
            entry.init = "0"
1077
        entry.is_arg = 1
William Stein's avatar
William Stein committed
1078 1079
        #entry.borrowed = 1 # Not using borrowed arg refs for now
        self.arg_entries.append(entry)
Robert Bradshaw's avatar
Robert Bradshaw committed
1080
        self.control_flow.set_state((), (name, 'source'), 'arg')
William Stein's avatar
William Stein committed
1081 1082 1083 1084 1085 1086 1087 1088 1089
        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
1090 1091
        if type.is_pyobject and not Options.init_local_none:
            entry.init = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
1092
        entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
1093
        entry.is_local = 1
William Stein's avatar
William Stein committed
1094 1095 1096 1097 1098 1099
        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):
1100
            warning(pos, "'%s' redeclared  ", 0)
William Stein's avatar
William Stein committed
1101 1102 1103 1104
        else:
            entry = self.global_scope().lookup_target(name)
            self.entries[name] = entry
        
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
    def lookup_from_inner(self, name):
        entry = self.lookup_here(name)
        if entry:
            entry.in_closure = 1
            return entry
        else:
            return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
            
    def mangle_closure_cnames(self, scope_var):
        for entry in self.entries.values():
            if entry.in_closure:
                if not hasattr(entry, 'orig_cname'):
                    entry.orig_cname = entry.cname
                entry.cname = scope_var + "->" + entry.cname
                
William Stein's avatar
William Stein committed
1120

1121 1122 1123
class GeneratorLocalScope(LocalScope):

    def mangle_closure_cnames(self, scope_var):
1124 1125
#        for entry in self.entries.values() + self.temp_entries:
#            entry.in_closure = 1
1126 1127 1128 1129
        LocalScope.mangle_closure_cnames(self, scope_var)
    
#    def mangle(self, prefix, name):
#        return "%s->%s" % (Naming.scope_obj_cname, name)
1130

William Stein's avatar
William Stein committed
1131 1132
class StructOrUnionScope(Scope):
    #  Namespace of a C struct or union.
Robert Bradshaw's avatar
Robert Bradshaw committed
1133
    
1134 1135
    def __init__(self, name="?"):
        Scope.__init__(self, name, None, None)
William Stein's avatar
William Stein committed
1136 1137

    def declare_var(self, name, type, pos, 
1138
            cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
William Stein's avatar
William Stein committed
1139 1140 1141
        # Add an entry for an attribute.
        if not cname:
            cname = name
1142 1143
            if visibility == 'private':
                cname = c_safe_identifier(cname)
1144
        if type.is_cfunction:
1145
            type = PyrexTypes.CPtrType(type)
1146
        entry = self.declare(name, cname, type, pos, visibility)
William Stein's avatar
William Stein committed
1147 1148
        entry.is_variable = 1
        self.var_entries.append(entry)
1149
        if type.is_pyobject and not allow_pyobject:
William Stein's avatar
William Stein committed
1150 1151
            error(pos,
                "C struct/union member cannot be a Python object")
Stefan Behnel's avatar
Stefan Behnel committed
1152
        if visibility != 'private':
William Stein's avatar
William Stein committed
1153 1154 1155 1156
            error(pos,
                "C struct/union member cannot be declared %s" % visibility)
        return entry

1157
    def declare_cfunction(self, name, type, pos, 
1158 1159
                          cname = None, visibility = 'private', defining = 0,
                          api = 0, in_pxd = 0, modifiers = ()):
1160
        self.declare_var(name, type, pos, cname, visibility)
William Stein's avatar
William Stein committed
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175

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

1176 1177
    def add_string_const(self, value, identifier = False):
        return self.outer_scope.add_string_const(value, identifier)
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195

    def lookup(self, name):
        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
            return entry
        else:
            return Scope.lookup(self, name)
1196
    
William Stein's avatar
William Stein committed
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206

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):
1207 1208
        if type is unspecified_type:
            type = py_object_type
William Stein's avatar
William Stein committed
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
        # Add an entry for a class attribute.
        entry = Scope.declare_var(self, name, type, pos, 
            cname, visibility, is_cdef)
        entry.is_pyglobal = 1
        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
    #  member_table_cname    string
    #  getset_table_cname    string
    #  has_pyobject_attrs    boolean  Any PyObject attributes?
    #  public_attr_entries   boolean  public/readonly attrs
    #  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
1239
        if visibility != 'extern':
William Stein's avatar
William Stein committed
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
            self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix, name)
            self.member_table_cname = outer_scope.mangle(Naming.memtab_prefix, name)
            self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, name)
        self.has_pyobject_attrs = 0
        self.public_attr_entries = []
        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 \
1254 1255
            (self.parent_type.base_type and
                self.parent_type.base_type.scope is not None and
William Stein's avatar
William Stein committed
1256 1257 1258 1259
                self.parent_type.base_type.scope.needs_gc())

    def declare_var(self, name, type, pos, 
            cname = None, visibility = 'private', is_cdef = 0):
1260 1261 1262
        if is_cdef:
            # Add an entry for an attribute.
            if self.defined:
William Stein's avatar
William Stein committed
1263
                error(pos,
1264
                    "C attributes cannot be added in implementation part of"
1265
                    " extension type defined in a pxd")
1266 1267 1268 1269 1270 1271
            if get_special_method_signature(name):
                error(pos, 
                    "The name '%s' is reserved for a special method."
                        % name)
            if not cname:
                cname = name
1272 1273
                if visibility == 'private':
                    cname = c_safe_identifier(cname)
1274
            entry = self.declare(name, cname, type, pos, visibility)
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
            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'):
                if type.pymemberdef_typecode:
                    self.public_attr_entries.append(entry)
                    if name == "__weakref__":
                        error(pos, "Special attribute __weakref__ cannot be exposed to Python")
                else:
                    error(pos,
                        "C attribute of type '%s' cannot be accessed from Python" % type)
            if visibility == 'public' and type.is_extension_type:
                error(pos,
                    "Non-generic Python attribute cannot be exposed for writing from Python")
            return entry
        else:
1295 1296
            if type is unspecified_type:
                type = py_object_type
1297 1298 1299
            # Add an entry for a class attribute.
            entry = Scope.declare_var(self, name, type, pos, 
                cname, visibility, is_cdef)
1300 1301 1302 1303
            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
1304
            self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
1305
            return entry
1306

William Stein's avatar
William Stein committed
1307 1308 1309

    def declare_pyfunction(self, name, pos):
        # Add an entry for a method.
1310
        if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
Robert Bradshaw's avatar
Robert Bradshaw committed
1311
            error(pos, "Special method %s must be implemented via __richcmp__" % name)
1312 1313 1314
        if name == "__new__":
            warning(pos, "__new__ method of extension type will change semantics "
                "in a future version of Pyrex and Cython. Use __cinit__ instead.")
1315
            name = EncodedString("__cinit__")
1316
        entry = self.declare_var(name, py_object_type, pos, visibility='extern')
William Stein's avatar
William Stein committed
1317 1318
        special_sig = get_special_method_signature(name)
        if special_sig:
1319 1320
            # Special methods get put in the method table with a particular
            # signature declared in advance.
William Stein's avatar
William Stein committed
1321
            entry.signature = special_sig
1322
            entry.is_special = 1
William Stein's avatar
William Stein committed
1323 1324
        else:
            entry.signature = pymethod_signature
1325
            entry.is_special = 0
1326 1327

        self.pyfunc_entries.append(entry)
William Stein's avatar
William Stein committed
1328
        return entry
1329 1330 1331
    
    def lookup_here(self, name):
        if name == "__new__":
1332
            name = EncodedString("__cinit__")
1333 1334
        return ClassScope.lookup_here(self, name)
    
William Stein's avatar
William Stein committed
1335
    def declare_cfunction(self, name, type, pos,
1336 1337
                          cname = None, visibility = 'private',
                          defining = 0, api = 0, in_pxd = 0, modifiers = ()):
William Stein's avatar
William Stein committed
1338 1339 1340 1341 1342 1343
        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")
        elif not args[0].type.same_as(self.parent_type):
Stefan Behnel's avatar
Stefan Behnel committed
1344 1345
            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
1346 1347 1348
        entry = self.lookup_here(name)
        if entry:
            if not entry.is_cfunction:
1349
                warning(pos, "'%s' redeclared  " % name, 0)
William Stein's avatar
William Stein committed
1350 1351 1352
            else:
                if defining and entry.func_cname:
                    error(pos, "'%s' already defined" % name)
1353
                #print "CClassScope.declare_cfunction: checking signature" ###
1354
                if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1355
                    pass
1356
                elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
1357
                    entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore', modifiers=modifiers)
1358
                    defining = 1
1359 1360
                else:
                    error(pos, "Signature not compatible with previous declaration")
1361
                    error(entry.pos, "Previous declaration is here")
William Stein's avatar
William Stein committed
1362 1363 1364 1365 1366
        else:
            if self.defined:
                error(pos,
                    "C method '%s' not previously declared in definition part of"
                    " extension type" % name)
1367 1368
            entry = self.add_cfunction(name, type, pos, cname or name,
                                       visibility, modifiers)
William Stein's avatar
William Stein committed
1369 1370 1371 1372
        if defining:
            entry.func_cname = self.mangle(Naming.func_prefix, name)
        return entry
        
1373
    def add_cfunction(self, name, type, pos, cname, visibility, modifiers):
William Stein's avatar
William Stein committed
1374
        # Add a cfunction entry without giving it a func_cname.
1375
        prev_entry = self.lookup_here(name)
1376 1377
        entry = ClassScope.add_cfunction(self, name, type, pos, cname,
                                         visibility, modifiers)
William Stein's avatar
William Stein committed
1378
        entry.is_cmethod = 1
1379
        entry.prev_entry = prev_entry
William Stein's avatar
William Stein committed
1380 1381 1382
        return entry
    
    def declare_property(self, name, doc, pos):
1383 1384
        entry = self.lookup_here(name)
        if entry is None:
1385
            entry = self.declare(name, name, py_object_type, pos, 'private')
William Stein's avatar
William Stein committed
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
        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), 
1403
                    base_entry.type, None, 'private')
William Stein's avatar
William Stein committed
1404 1405 1406
                entry.is_variable = 1
                self.inherited_var_entries.append(entry)
        for base_entry in base_scope.cfunc_entries:
1407
            entry = self.add_cfunction(base_entry.name, base_entry.type,
1408 1409
                                       base_entry.pos, adapt(base_entry.cname),
                                       base_entry.visibility, base_entry.func_modifiers)
William Stein's avatar
William Stein committed
1410
            entry.is_inherited = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1411
            
1412
        
William Stein's avatar
William Stein committed
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422
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
    
    def declare_pyfunction(self, name, pos):
        # Add an entry for a method.
        signature = get_property_accessor_signature(name)
        if signature:
1423
            entry = self.declare(name, name, py_object_type, pos, 'private')
Stefan Behnel's avatar
Stefan Behnel committed
1424
            entry.is_special = 1
1425
            entry.signature = signature
William Stein's avatar
William Stein committed
1426 1427 1428 1429 1430
            return entry
        else:
            error(pos, "Only __get__, __set__ and __del__ methods allowed "
                "in a property declaration")
            return None
1431 1432 1433 1434 1435


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

1436
classmethod_utility_code = Code.UtilityCode(
Stefan Behnel's avatar
Stefan Behnel committed
1437
proto = """
1438 1439
#include "descrobject.h"
static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
Stefan Behnel's avatar
Stefan Behnel committed
1440 1441
""",
impl = """
1442 1443
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
    /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
1444 1445 1446 1447 1448 1449 1450 1451
    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 */
1452 1453 1454 1455 1456 1457
        PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
        return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
    }
    else if (PyMethod_Check(method)) {                                /* python classes */
        return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
    }
1458 1459 1460
    else if (PyCFunction_Check(method)) {
        return PyClassMethod_New(method);
    }
1461 1462 1463
    PyErr_Format(PyExc_TypeError, "Class-level classmethod() can only be called on a method_descriptor or instance method.");
    return NULL;
}
Stefan Behnel's avatar
Stefan Behnel committed
1464
""")