OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Symbol Table |
| 3 # |
| 4 |
| 5 import copy |
| 6 import re |
| 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 from TypeSlots import \ |
| 13 pyfunction_signature, pymethod_signature, \ |
| 14 get_special_method_signature, get_property_accessor_signature |
| 15 import Code |
| 16 import __builtin__ as builtins |
| 17 |
| 18 iso_c99_keywords = set( |
| 19 ['auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', |
| 20 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', |
| 21 'int', 'long', 'register', 'return', 'short', 'signed', 'sizeof', |
| 22 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', |
| 23 'volatile', 'while', |
| 24 '_Bool', '_Complex'', _Imaginary', 'inline', 'restrict']) |
| 25 |
| 26 def c_safe_identifier(cname): |
| 27 # There are some C limitations on struct entry names. |
| 28 if ((cname[:2] == '__' |
| 29 and not (cname.startswith(Naming.pyrex_prefix) |
| 30 or cname == '__weakref__')) |
| 31 or cname in iso_c99_keywords): |
| 32 cname = Naming.pyrex_prefix + cname |
| 33 return cname |
| 34 |
| 35 class BufferAux(object): |
| 36 writable_needed = False |
| 37 |
| 38 def __init__(self, buflocal_nd_var, rcbuf_var): |
| 39 self.buflocal_nd_var = buflocal_nd_var |
| 40 self.rcbuf_var = rcbuf_var |
| 41 |
| 42 def __repr__(self): |
| 43 return "<BufferAux %r>" % self.__dict__ |
| 44 |
| 45 |
| 46 class Entry(object): |
| 47 # A symbol table entry in a Scope or ModuleNamespace. |
| 48 # |
| 49 # name string Python name of entity |
| 50 # cname string C name of entity |
| 51 # type PyrexType Type of entity |
| 52 # doc string Doc string |
| 53 # init string Initial value |
| 54 # visibility 'private' or 'public' or 'extern' |
| 55 # is_builtin boolean Is an entry in the Python builtins dict |
| 56 # is_cglobal boolean Is a C global variable |
| 57 # is_pyglobal boolean Is a Python module-level variable |
| 58 # or class attribute during |
| 59 # class construction |
| 60 # is_member boolean Is an assigned class member |
| 61 # is_pyclass_attr boolean Is a name in a Python class namespace |
| 62 # is_variable boolean Is a variable |
| 63 # is_cfunction boolean Is a C function |
| 64 # is_cmethod boolean Is a C method of an extension type |
| 65 # is_builtin_cmethod boolean Is a C method of a builtin type (implies is_cm
ethod) |
| 66 # is_unbound_cmethod boolean Is an unbound C method of an extension type |
| 67 # is_final_cmethod boolean Is non-overridable C method |
| 68 # is_inline_cmethod boolean Is inlined C method |
| 69 # is_anonymous boolean Is a anonymous pyfunction entry |
| 70 # is_type boolean Is a type definition |
| 71 # is_cclass boolean Is an extension class |
| 72 # is_cpp_class boolean Is a C++ class |
| 73 # is_const boolean Is a constant |
| 74 # is_property boolean Is a property of an extension type: |
| 75 # doc_cname string or None C const holding the docstring |
| 76 # getter_cname string C func for getting property |
| 77 # setter_cname string C func for setting or deleting property |
| 78 # is_self_arg boolean Is the "self" arg of an exttype method |
| 79 # is_arg boolean Is the arg of a method |
| 80 # is_local boolean Is a local variable |
| 81 # in_closure boolean Is referenced in an inner scope |
| 82 # is_readonly boolean Can't be assigned to |
| 83 # func_cname string C func implementing Python func |
| 84 # func_modifiers [string] C function modifiers ('inline') |
| 85 # pos position Source position where declared |
| 86 # namespace_cname string If is_pyglobal, the C variable |
| 87 # holding its home namespace |
| 88 # pymethdef_cname string PyMethodDef structure |
| 89 # signature Signature Arg & return types for Python func |
| 90 # as_variable Entry Alternative interpretation of extension |
| 91 # type name or builtin C function as a variabl
e |
| 92 # xdecref_cleanup boolean Use Py_XDECREF for error cleanup |
| 93 # in_cinclude boolean Suppress C declaration code |
| 94 # enum_values [Entry] For enum types, list of values |
| 95 # qualified_name string "modname.funcname" or "modname.classname" |
| 96 # or "modname.classname.funcname" |
| 97 # is_declared_generic boolean Is declared as PyObject * even though its |
| 98 # type is an extension type |
| 99 # as_module None Module scope, if a cimported module |
| 100 # is_inherited boolean Is an inherited attribute of an extension type |
| 101 # pystring_cname string C name of Python version of string literal |
| 102 # is_interned boolean For string const entries, value is interned |
| 103 # is_identifier boolean For string const entries, value is an identifi
er |
| 104 # used boolean |
| 105 # is_special boolean Is a special method or property accessor |
| 106 # of an extension type |
| 107 # defined_in_pxd boolean Is defined in a .pxd file (not just declared) |
| 108 # api boolean Generate C API for C class or function |
| 109 # utility_code string Utility code needed when this entry is used |
| 110 # |
| 111 # buffer_aux BufferAux or None Extra information needed for buffer va
riables |
| 112 # inline_func_in_pxd boolean Hacky special case for inline function in pxd
file. |
| 113 # Ideally this should not be necesarry. |
| 114 # might_overflow boolean In an arithmetic expression that could cause |
| 115 # overflow (used for type inference). |
| 116 # utility_code_definition For some Cython builtins, the utility code |
| 117 # which contains the definition of the entry. |
| 118 # Currently only supported for CythonScope entri
es. |
| 119 # error_on_uninitialized Have Control Flow issue an error when this ent
ry is |
| 120 # used uninitialized |
| 121 # cf_used boolean Entry is used |
| 122 # is_fused_specialized boolean Whether this entry of a cdef or def function |
| 123 # is a specialization |
| 124 |
| 125 # TODO: utility_code and utility_code_definition serves the same purpose... |
| 126 |
| 127 inline_func_in_pxd = False |
| 128 borrowed = 0 |
| 129 init = "" |
| 130 visibility = 'private' |
| 131 is_builtin = 0 |
| 132 is_cglobal = 0 |
| 133 is_pyglobal = 0 |
| 134 is_member = 0 |
| 135 is_pyclass_attr = 0 |
| 136 is_variable = 0 |
| 137 is_cfunction = 0 |
| 138 is_cmethod = 0 |
| 139 is_builtin_cmethod = False |
| 140 is_unbound_cmethod = 0 |
| 141 is_final_cmethod = 0 |
| 142 is_inline_cmethod = 0 |
| 143 is_anonymous = 0 |
| 144 is_type = 0 |
| 145 is_cclass = 0 |
| 146 is_cpp_class = 0 |
| 147 is_const = 0 |
| 148 is_property = 0 |
| 149 doc_cname = None |
| 150 getter_cname = None |
| 151 setter_cname = None |
| 152 is_self_arg = 0 |
| 153 is_arg = 0 |
| 154 is_local = 0 |
| 155 in_closure = 0 |
| 156 from_closure = 0 |
| 157 is_declared_generic = 0 |
| 158 is_readonly = 0 |
| 159 pyfunc_cname = None |
| 160 func_cname = None |
| 161 func_modifiers = [] |
| 162 final_func_cname = None |
| 163 doc = None |
| 164 as_variable = None |
| 165 xdecref_cleanup = 0 |
| 166 in_cinclude = 0 |
| 167 as_module = None |
| 168 is_inherited = 0 |
| 169 pystring_cname = None |
| 170 is_identifier = 0 |
| 171 is_interned = 0 |
| 172 used = 0 |
| 173 is_special = 0 |
| 174 defined_in_pxd = 0 |
| 175 is_implemented = 0 |
| 176 api = 0 |
| 177 utility_code = None |
| 178 is_overridable = 0 |
| 179 buffer_aux = None |
| 180 prev_entry = None |
| 181 might_overflow = 0 |
| 182 fused_cfunction = None |
| 183 is_fused_specialized = False |
| 184 utility_code_definition = None |
| 185 needs_property = False |
| 186 in_with_gil_block = 0 |
| 187 from_cython_utility_code = None |
| 188 error_on_uninitialized = False |
| 189 cf_used = True |
| 190 outer_entry = None |
| 191 |
| 192 def __init__(self, name, cname, type, pos = None, init = None): |
| 193 self.name = name |
| 194 self.cname = cname |
| 195 self.type = type |
| 196 self.pos = pos |
| 197 self.init = init |
| 198 self.overloaded_alternatives = [] |
| 199 self.cf_assignments = [] |
| 200 self.cf_references = [] |
| 201 self.inner_entries = [] |
| 202 self.defining_entry = self |
| 203 |
| 204 def __repr__(self): |
| 205 return "%s(<%x>, name=%s, type=%s)" % (type(self).__name__, id(self), se
lf.name, self.type) |
| 206 |
| 207 def redeclared(self, pos): |
| 208 error(pos, "'%s' does not match previous declaration" % self.name) |
| 209 error(self.pos, "Previous declaration is here") |
| 210 |
| 211 def all_alternatives(self): |
| 212 return [self] + self.overloaded_alternatives |
| 213 |
| 214 def all_entries(self): |
| 215 return [self] + self.inner_entries |
| 216 |
| 217 |
| 218 class InnerEntry(Entry): |
| 219 """ |
| 220 An entry in a closure scope that represents the real outer Entry. |
| 221 """ |
| 222 from_closure = True |
| 223 |
| 224 def __init__(self, outer_entry, scope): |
| 225 Entry.__init__(self, outer_entry.name, |
| 226 outer_entry.cname, |
| 227 outer_entry.type, |
| 228 outer_entry.pos) |
| 229 self.outer_entry = outer_entry |
| 230 self.scope = scope |
| 231 |
| 232 # share state with (outermost) defining entry |
| 233 outermost_entry = outer_entry |
| 234 while outermost_entry.outer_entry: |
| 235 outermost_entry = outermost_entry.outer_entry |
| 236 self.defining_entry = outermost_entry |
| 237 self.inner_entries = outermost_entry.inner_entries |
| 238 self.cf_assignments = outermost_entry.cf_assignments |
| 239 self.cf_references = outermost_entry.cf_references |
| 240 self.overloaded_alternatives = outermost_entry.overloaded_alternatives |
| 241 self.inner_entries.append(self) |
| 242 |
| 243 def __getattr__(self, name): |
| 244 if name.startswith('__'): |
| 245 # we wouldn't have been called if it was there |
| 246 raise AttributeError(name) |
| 247 return getattr(self.defining_entry, name) |
| 248 |
| 249 def all_entries(self): |
| 250 return self.defining_entry.all_entries() |
| 251 |
| 252 |
| 253 class Scope(object): |
| 254 # name string Unqualified name |
| 255 # outer_scope Scope or None Enclosing scope |
| 256 # entries {string : Entry} Python name to entry, non-types |
| 257 # const_entries [Entry] Constant entries |
| 258 # type_entries [Entry] Struct/union/enum/typedef/exttype ent
ries |
| 259 # sue_entries [Entry] Struct/union/enum entries |
| 260 # arg_entries [Entry] Function argument entries |
| 261 # var_entries [Entry] User-defined variable entries |
| 262 # pyfunc_entries [Entry] Python function entries |
| 263 # cfunc_entries [Entry] C function entries |
| 264 # c_class_entries [Entry] All extension type entries |
| 265 # cname_to_entry {string : Entry} Temp cname to entry mapping |
| 266 # return_type PyrexType or None Return type of function owning scope |
| 267 # is_builtin_scope boolean Is the builtin scope of Python/Cython |
| 268 # is_py_class_scope boolean Is a Python class scope |
| 269 # is_c_class_scope boolean Is an extension type scope |
| 270 # is_closure_scope boolean Is a closure scope |
| 271 # is_passthrough boolean Outer scope is passed directly |
| 272 # is_cpp_class_scope boolean Is a C++ class scope |
| 273 # is_property_scope boolean Is a extension type property scope |
| 274 # scope_prefix string Disambiguator for C names |
| 275 # in_cinclude boolean Suppress C declaration code |
| 276 # qualified_name string "modname" or "modname.classname" |
| 277 # Python strings in this scope |
| 278 # nogil boolean In a nogil section |
| 279 # directives dict Helper variable for the recursive |
| 280 # analysis, contains directive values. |
| 281 # is_internal boolean Is only used internally (simpler setu
p) |
| 282 |
| 283 is_builtin_scope = 0 |
| 284 is_py_class_scope = 0 |
| 285 is_c_class_scope = 0 |
| 286 is_closure_scope = 0 |
| 287 is_passthrough = 0 |
| 288 is_cpp_class_scope = 0 |
| 289 is_property_scope = 0 |
| 290 is_module_scope = 0 |
| 291 is_internal = 0 |
| 292 scope_prefix = "" |
| 293 in_cinclude = 0 |
| 294 nogil = 0 |
| 295 fused_to_specific = None |
| 296 |
| 297 def __init__(self, name, outer_scope, parent_scope): |
| 298 # The outer_scope is the next scope in the lookup chain. |
| 299 # The parent_scope is used to derive the qualified name of this scope. |
| 300 self.name = name |
| 301 self.outer_scope = outer_scope |
| 302 self.parent_scope = parent_scope |
| 303 mangled_name = "%d%s_" % (len(name), name) |
| 304 qual_scope = self.qualifying_scope() |
| 305 if qual_scope: |
| 306 self.qualified_name = qual_scope.qualify_name(name) |
| 307 self.scope_prefix = qual_scope.scope_prefix + mangled_name |
| 308 else: |
| 309 self.qualified_name = EncodedString(name) |
| 310 self.scope_prefix = mangled_name |
| 311 self.entries = {} |
| 312 self.const_entries = [] |
| 313 self.type_entries = [] |
| 314 self.sue_entries = [] |
| 315 self.arg_entries = [] |
| 316 self.var_entries = [] |
| 317 self.pyfunc_entries = [] |
| 318 self.cfunc_entries = [] |
| 319 self.c_class_entries = [] |
| 320 self.defined_c_classes = [] |
| 321 self.imported_c_classes = {} |
| 322 self.cname_to_entry = {} |
| 323 self.string_to_entry = {} |
| 324 self.identifier_to_entry = {} |
| 325 self.num_to_entry = {} |
| 326 self.obj_to_entry = {} |
| 327 self.buffer_entries = [] |
| 328 self.lambda_defs = [] |
| 329 self.return_type = None |
| 330 self.id_counters = {} |
| 331 |
| 332 def __deepcopy__(self, memo): |
| 333 return self |
| 334 |
| 335 def merge_in(self, other, merge_unused=True, whitelist=None): |
| 336 # Use with care... |
| 337 entries = [] |
| 338 for name, entry in other.entries.iteritems(): |
| 339 if not whitelist or name in whitelist: |
| 340 if entry.used or merge_unused: |
| 341 entries.append((name, entry)) |
| 342 |
| 343 self.entries.update(entries) |
| 344 |
| 345 for attr in ('const_entries', |
| 346 'type_entries', |
| 347 'sue_entries', |
| 348 'arg_entries', |
| 349 'var_entries', |
| 350 'pyfunc_entries', |
| 351 'cfunc_entries', |
| 352 'c_class_entries'): |
| 353 self_entries = getattr(self, attr) |
| 354 names = set([e.name for e in self_entries]) |
| 355 for entry in getattr(other, attr): |
| 356 if (entry.used or merge_unused) and entry.name not in names: |
| 357 self_entries.append(entry) |
| 358 |
| 359 def __str__(self): |
| 360 return "<%s %s>" % (self.__class__.__name__, self.qualified_name) |
| 361 |
| 362 def qualifying_scope(self): |
| 363 return self.parent_scope |
| 364 |
| 365 def mangle(self, prefix, name = None): |
| 366 if name: |
| 367 return "%s%s%s" % (prefix, self.scope_prefix, name) |
| 368 else: |
| 369 return self.parent_scope.mangle(prefix, self.name) |
| 370 |
| 371 def mangle_internal(self, name): |
| 372 # Mangle an internal name so as not to clash with any |
| 373 # user-defined name in this scope. |
| 374 prefix = "%s%s_" % (Naming.pyrex_prefix, name) |
| 375 return self.mangle(prefix) |
| 376 #return self.parent_scope.mangle(prefix, self.name) |
| 377 |
| 378 def mangle_class_private_name(self, name): |
| 379 if self.parent_scope: |
| 380 return self.parent_scope.mangle_class_private_name(name) |
| 381 return name |
| 382 |
| 383 def next_id(self, name=None): |
| 384 # Return a cname fragment that is unique for this module |
| 385 counters = self.global_scope().id_counters |
| 386 try: |
| 387 count = counters[name] + 1 |
| 388 except KeyError: |
| 389 count = 0 |
| 390 counters[name] = count |
| 391 if name: |
| 392 if not count: |
| 393 # unique names don't need a suffix, reoccurrences will get one |
| 394 return name |
| 395 return '%s%d' % (name, count) |
| 396 else: |
| 397 return '%d' % count |
| 398 |
| 399 def global_scope(self): |
| 400 """ Return the module-level scope containing this scope. """ |
| 401 return self.outer_scope.global_scope() |
| 402 |
| 403 def builtin_scope(self): |
| 404 """ Return the module-level scope containing this scope. """ |
| 405 return self.outer_scope.builtin_scope() |
| 406 |
| 407 def declare(self, name, cname, type, pos, visibility, shadow = 0, is_type =
0): |
| 408 # Create new entry, and add to dictionary if |
| 409 # name is not None. Reports a warning if already |
| 410 # declared. |
| 411 if type.is_buffer and not isinstance(self, LocalScope): # and not is_typ
e: |
| 412 error(pos, 'Buffer types only allowed as function local variables') |
| 413 if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname): |
| 414 # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Nam
es.html#Reserved-Names |
| 415 warning(pos, "'%s' is a reserved name in C." % cname, -1) |
| 416 entries = self.entries |
| 417 if name and name in entries and not shadow: |
| 418 if visibility == 'extern': |
| 419 warning(pos, "'%s' redeclared " % name, 0) |
| 420 elif visibility != 'ignore': |
| 421 error(pos, "'%s' redeclared " % name) |
| 422 entry = Entry(name, cname, type, pos = pos) |
| 423 entry.in_cinclude = self.in_cinclude |
| 424 if name: |
| 425 entry.qualified_name = self.qualify_name(name) |
| 426 # if name in entries and self.is_cpp(): |
| 427 # entries[name].overloaded_alternatives.append(entry) |
| 428 # else: |
| 429 # entries[name] = entry |
| 430 if not shadow: |
| 431 entries[name] = entry |
| 432 |
| 433 if type.is_memoryviewslice: |
| 434 import MemoryView |
| 435 entry.init = MemoryView.memslice_entry_init |
| 436 |
| 437 entry.scope = self |
| 438 entry.visibility = visibility |
| 439 return entry |
| 440 |
| 441 def qualify_name(self, name): |
| 442 return EncodedString("%s.%s" % (self.qualified_name, name)) |
| 443 |
| 444 def declare_const(self, name, type, value, pos, cname = None, visibility = '
private', api = 0): |
| 445 # Add an entry for a named constant. |
| 446 if not cname: |
| 447 if self.in_cinclude or (visibility == 'public' or api): |
| 448 cname = name |
| 449 else: |
| 450 cname = self.mangle(Naming.enum_prefix, name) |
| 451 entry = self.declare(name, cname, type, pos, visibility) |
| 452 entry.is_const = 1 |
| 453 entry.value_node = value |
| 454 return entry |
| 455 |
| 456 def declare_type(self, name, type, pos, |
| 457 cname = None, visibility = 'private', api = 0, defining = 1, |
| 458 shadow = 0, template = 0): |
| 459 # Add an entry for a type definition. |
| 460 if not cname: |
| 461 cname = name |
| 462 entry = self.declare(name, cname, type, pos, visibility, shadow, |
| 463 is_type=True) |
| 464 entry.is_type = 1 |
| 465 entry.api = api |
| 466 if defining: |
| 467 self.type_entries.append(entry) |
| 468 |
| 469 if not template: |
| 470 type.entry = entry |
| 471 |
| 472 # here we would set as_variable to an object representing this type |
| 473 return entry |
| 474 |
| 475 def declare_typedef(self, name, base_type, pos, cname = None, |
| 476 visibility = 'private', api = 0): |
| 477 if not cname: |
| 478 if self.in_cinclude or (visibility == 'public' or api): |
| 479 cname = name |
| 480 else: |
| 481 cname = self.mangle(Naming.type_prefix, name) |
| 482 try: |
| 483 type = PyrexTypes.create_typedef_type(name, base_type, cname, |
| 484 (visibility == 'extern')) |
| 485 except ValueError, e: |
| 486 error(pos, e.args[0]) |
| 487 type = PyrexTypes.error_type |
| 488 entry = self.declare_type(name, type, pos, cname, |
| 489 visibility = visibility, api = api) |
| 490 type.qualified_name = entry.qualified_name |
| 491 return entry |
| 492 |
| 493 def declare_struct_or_union(self, name, kind, scope, |
| 494 typedef_flag, pos, cname = None, |
| 495 visibility = 'private', api = 0, |
| 496 packed = False): |
| 497 # Add an entry for a struct or union definition. |
| 498 if not cname: |
| 499 if self.in_cinclude or (visibility == 'public' or api): |
| 500 cname = name |
| 501 else: |
| 502 cname = self.mangle(Naming.type_prefix, name) |
| 503 entry = self.lookup_here(name) |
| 504 if not entry: |
| 505 type = PyrexTypes.CStructOrUnionType( |
| 506 name, kind, scope, typedef_flag, cname, packed) |
| 507 entry = self.declare_type(name, type, pos, cname, |
| 508 visibility = visibility, api = api, |
| 509 defining = scope is not None) |
| 510 self.sue_entries.append(entry) |
| 511 type.entry = entry |
| 512 else: |
| 513 if not (entry.is_type and entry.type.is_struct_or_union |
| 514 and entry.type.kind == kind): |
| 515 warning(pos, "'%s' redeclared " % name, 0) |
| 516 elif scope and entry.type.scope: |
| 517 warning(pos, "'%s' already defined (ignoring second definition)
" % name, 0) |
| 518 else: |
| 519 self.check_previous_typedef_flag(entry, typedef_flag, pos) |
| 520 self.check_previous_visibility(entry, visibility, pos) |
| 521 if scope: |
| 522 entry.type.scope = scope |
| 523 self.type_entries.append(entry) |
| 524 return entry |
| 525 |
| 526 def declare_cpp_class(self, name, scope, |
| 527 pos, cname = None, base_classes = (), |
| 528 visibility = 'extern', templates = None): |
| 529 if cname is None: |
| 530 if self.in_cinclude or (visibility != 'private'): |
| 531 cname = name |
| 532 else: |
| 533 cname = self.mangle(Naming.type_prefix, name) |
| 534 base_classes = list(base_classes) |
| 535 entry = self.lookup_here(name) |
| 536 if not entry: |
| 537 type = PyrexTypes.CppClassType( |
| 538 name, scope, cname, base_classes, templates = templates) |
| 539 entry = self.declare_type(name, type, pos, cname, |
| 540 visibility = visibility, defining = scope is not None) |
| 541 self.sue_entries.append(entry) |
| 542 else: |
| 543 if not (entry.is_type and entry.type.is_cpp_class): |
| 544 error(pos, "'%s' redeclared " % name) |
| 545 return None |
| 546 elif scope and entry.type.scope: |
| 547 warning(pos, "'%s' already defined (ignoring second definition)
" % name, 0) |
| 548 else: |
| 549 if scope: |
| 550 entry.type.scope = scope |
| 551 self.type_entries.append(entry) |
| 552 if base_classes: |
| 553 if entry.type.base_classes and entry.type.base_classes != base_c
lasses: |
| 554 error(pos, "Base type does not match previous declaration") |
| 555 else: |
| 556 entry.type.base_classes = base_classes |
| 557 if templates or entry.type.templates: |
| 558 if templates != entry.type.templates: |
| 559 error(pos, "Template parameters do not match previous declar
ation") |
| 560 |
| 561 def declare_inherited_attributes(entry, base_classes): |
| 562 for base_class in base_classes: |
| 563 if base_class is PyrexTypes.error_type: |
| 564 continue |
| 565 if base_class.scope is None: |
| 566 error(pos, "Cannot inherit from incomplete type") |
| 567 else: |
| 568 declare_inherited_attributes(entry, base_class.base_classes) |
| 569 entry.type.scope.declare_inherited_cpp_attributes(base_class
.scope) |
| 570 if entry.type.scope: |
| 571 declare_inherited_attributes(entry, base_classes) |
| 572 entry.type.scope.declare_var(name="this", cname="this", type=PyrexTy
pes.CPtrType(entry.type), pos=entry.pos) |
| 573 if self.is_cpp_class_scope: |
| 574 entry.type.namespace = self.outer_scope.lookup(self.name).type |
| 575 return entry |
| 576 |
| 577 def check_previous_typedef_flag(self, entry, typedef_flag, pos): |
| 578 if typedef_flag != entry.type.typedef_flag: |
| 579 error(pos, "'%s' previously declared using '%s'" % ( |
| 580 entry.name, ("cdef", "ctypedef")[entry.type.typedef_flag])) |
| 581 |
| 582 def check_previous_visibility(self, entry, visibility, pos): |
| 583 if entry.visibility != visibility: |
| 584 error(pos, "'%s' previously declared as '%s'" % ( |
| 585 entry.name, entry.visibility)) |
| 586 |
| 587 def declare_enum(self, name, pos, cname, typedef_flag, |
| 588 visibility = 'private', api = 0): |
| 589 if name: |
| 590 if not cname: |
| 591 if self.in_cinclude or (visibility == 'public' or api): |
| 592 cname = name |
| 593 else: |
| 594 cname = self.mangle(Naming.type_prefix, name) |
| 595 type = PyrexTypes.CEnumType(name, cname, typedef_flag) |
| 596 else: |
| 597 type = PyrexTypes.c_anon_enum_type |
| 598 entry = self.declare_type(name, type, pos, cname = cname, |
| 599 visibility = visibility, api = api) |
| 600 entry.enum_values = [] |
| 601 self.sue_entries.append(entry) |
| 602 return entry |
| 603 |
| 604 def declare_var(self, name, type, pos, |
| 605 cname = None, visibility = 'private', |
| 606 api = 0, in_pxd = 0, is_cdef = 0): |
| 607 # Add an entry for a variable. |
| 608 if not cname: |
| 609 if visibility != 'private' or api: |
| 610 cname = name |
| 611 else: |
| 612 cname = self.mangle(Naming.var_prefix, name) |
| 613 if type.is_cpp_class and visibility != 'extern': |
| 614 type.check_nullary_constructor(pos) |
| 615 entry = self.declare(name, cname, type, pos, visibility) |
| 616 entry.is_variable = 1 |
| 617 if in_pxd and visibility != 'extern': |
| 618 entry.defined_in_pxd = 1 |
| 619 entry.used = 1 |
| 620 if api: |
| 621 entry.api = 1 |
| 622 entry.used = 1 |
| 623 return entry |
| 624 |
| 625 def declare_builtin(self, name, pos): |
| 626 return self.outer_scope.declare_builtin(name, pos) |
| 627 |
| 628 def _declare_pyfunction(self, name, pos, visibility='extern', entry=None): |
| 629 if entry and not entry.type.is_cfunction: |
| 630 error(pos, "'%s' already declared" % name) |
| 631 error(entry.pos, "Previous declaration is here") |
| 632 entry = self.declare_var(name, py_object_type, pos, visibility=visibilit
y) |
| 633 entry.signature = pyfunction_signature |
| 634 self.pyfunc_entries.append(entry) |
| 635 return entry |
| 636 |
| 637 def declare_pyfunction(self, name, pos, allow_redefine=False, visibility='ex
tern'): |
| 638 # Add an entry for a Python function. |
| 639 entry = self.lookup_here(name) |
| 640 if not allow_redefine: |
| 641 return self._declare_pyfunction(name, pos, visibility=visibility, en
try=entry) |
| 642 if entry: |
| 643 if entry.type.is_unspecified: |
| 644 entry.type = py_object_type |
| 645 elif entry.type is not py_object_type: |
| 646 return self._declare_pyfunction(name, pos, visibility=visibility
, entry=entry) |
| 647 else: # declare entry stub |
| 648 self.declare_var(name, py_object_type, pos, visibility=visibility) |
| 649 entry = self.declare_var(None, py_object_type, pos, |
| 650 cname=name, visibility='private') |
| 651 entry.name = EncodedString(name) |
| 652 entry.qualified_name = self.qualify_name(name) |
| 653 entry.signature = pyfunction_signature |
| 654 entry.is_anonymous = True |
| 655 return entry |
| 656 |
| 657 def declare_lambda_function(self, lambda_name, pos): |
| 658 # Add an entry for an anonymous Python function. |
| 659 func_cname = self.mangle(Naming.lambda_func_prefix + u'funcdef_', lambda
_name) |
| 660 pymethdef_cname = self.mangle(Naming.lambda_func_prefix + u'methdef_', l
ambda_name) |
| 661 qualified_name = self.qualify_name(lambda_name) |
| 662 |
| 663 entry = self.declare(None, func_cname, py_object_type, pos, 'private') |
| 664 entry.name = lambda_name |
| 665 entry.qualified_name = qualified_name |
| 666 entry.pymethdef_cname = pymethdef_cname |
| 667 entry.func_cname = func_cname |
| 668 entry.signature = pyfunction_signature |
| 669 entry.is_anonymous = True |
| 670 return entry |
| 671 |
| 672 def add_lambda_def(self, def_node): |
| 673 self.lambda_defs.append(def_node) |
| 674 |
| 675 def register_pyfunction(self, entry): |
| 676 self.pyfunc_entries.append(entry) |
| 677 |
| 678 def declare_cfunction(self, name, type, pos, |
| 679 cname = None, visibility = 'private', api = 0, in_pxd
= 0, |
| 680 defining = 0, modifiers = (), utility_code = None): |
| 681 # Add an entry for a C function. |
| 682 if not cname: |
| 683 if visibility != 'private' or api: |
| 684 cname = name |
| 685 else: |
| 686 cname = self.mangle(Naming.func_prefix, name) |
| 687 entry = self.lookup_here(name) |
| 688 if entry: |
| 689 if visibility != 'private' and visibility != entry.visibility: |
| 690 warning(pos, "Function '%s' previously declared as '%s'" % (name
, entry.visibility), 1) |
| 691 if not entry.type.same_as(type): |
| 692 if visibility == 'extern' and entry.visibility == 'extern': |
| 693 can_override = False |
| 694 if self.is_cpp(): |
| 695 can_override = True |
| 696 elif cname: |
| 697 # if all alternatives have different cnames, |
| 698 # it's safe to allow signature overrides |
| 699 for alt_entry in entry.all_alternatives(): |
| 700 if not alt_entry.cname or cname == alt_entry.cname: |
| 701 break # cname not unique! |
| 702 else: |
| 703 can_override = True |
| 704 if can_override: |
| 705 temp = self.add_cfunction(name, type, pos, cname, visibi
lity, modifiers) |
| 706 temp.overloaded_alternatives = entry.all_alternatives() |
| 707 entry = temp |
| 708 else: |
| 709 warning(pos, "Function signature does not match previous
declaration", 1) |
| 710 entry.type = type |
| 711 else: |
| 712 error(pos, "Function signature does not match previous decla
ration") |
| 713 else: |
| 714 entry = self.add_cfunction(name, type, pos, cname, visibility, modif
iers) |
| 715 entry.func_cname = cname |
| 716 if in_pxd and visibility != 'extern': |
| 717 entry.defined_in_pxd = 1 |
| 718 if api: |
| 719 entry.api = 1 |
| 720 if not defining and not in_pxd and visibility != 'extern': |
| 721 error(pos, "Non-extern C function '%s' declared but not defined" % n
ame) |
| 722 if defining: |
| 723 entry.is_implemented = True |
| 724 if modifiers: |
| 725 entry.func_modifiers = modifiers |
| 726 if utility_code: |
| 727 assert not entry.utility_code, "duplicate utility code definition in
entry %s (%s)" % (name, cname) |
| 728 entry.utility_code = utility_code |
| 729 type.entry = entry |
| 730 return entry |
| 731 |
| 732 def add_cfunction(self, name, type, pos, cname, visibility, modifiers): |
| 733 # Add a C function entry without giving it a func_cname. |
| 734 entry = self.declare(name, cname, type, pos, visibility) |
| 735 entry.is_cfunction = 1 |
| 736 if modifiers: |
| 737 entry.func_modifiers = modifiers |
| 738 self.cfunc_entries.append(entry) |
| 739 return entry |
| 740 |
| 741 def find(self, name, pos): |
| 742 # Look up name, report error if not found. |
| 743 entry = self.lookup(name) |
| 744 if entry: |
| 745 return entry |
| 746 else: |
| 747 error(pos, "'%s' is not declared" % name) |
| 748 |
| 749 def find_imported_module(self, path, pos): |
| 750 # Look up qualified name, must be a module, report error if not found. |
| 751 # Path is a list of names. |
| 752 scope = self |
| 753 for name in path: |
| 754 entry = scope.find(name, pos) |
| 755 if not entry: |
| 756 return None |
| 757 if entry.as_module: |
| 758 scope = entry.as_module |
| 759 else: |
| 760 error(pos, "'%s' is not a cimported module" % '.'.join(path)) |
| 761 return None |
| 762 return scope |
| 763 |
| 764 def lookup(self, name): |
| 765 # Look up name in this scope or an enclosing one. |
| 766 # Return None if not found. |
| 767 return (self.lookup_here(name) |
| 768 or (self.outer_scope and self.outer_scope.lookup(name)) |
| 769 or None) |
| 770 |
| 771 def lookup_here(self, name): |
| 772 # Look up in this scope only, return None if not found. |
| 773 return self.entries.get(name, None) |
| 774 |
| 775 def lookup_target(self, name): |
| 776 # Look up name in this scope only. Declare as Python |
| 777 # variable if not found. |
| 778 entry = self.lookup_here(name) |
| 779 if not entry: |
| 780 entry = self.declare_var(name, py_object_type, None) |
| 781 return entry |
| 782 |
| 783 def lookup_type(self, name): |
| 784 entry = self.lookup(name) |
| 785 if entry and entry.is_type: |
| 786 if entry.type.is_fused and self.fused_to_specific: |
| 787 return entry.type.specialize(self.fused_to_specific) |
| 788 return entry.type |
| 789 |
| 790 def lookup_operator(self, operator, operands): |
| 791 if operands[0].type.is_cpp_class: |
| 792 obj_type = operands[0].type |
| 793 method = obj_type.scope.lookup("operator%s" % operator) |
| 794 if method is not None: |
| 795 res = PyrexTypes.best_match(operands[1:], method.all_alternative
s()) |
| 796 if res is not None: |
| 797 return res |
| 798 function = self.lookup("operator%s" % operator) |
| 799 if function is None: |
| 800 return None |
| 801 return PyrexTypes.best_match(operands, function.all_alternatives()) |
| 802 |
| 803 def lookup_operator_for_types(self, pos, operator, types): |
| 804 from Nodes import Node |
| 805 class FakeOperand(Node): |
| 806 pass |
| 807 operands = [FakeOperand(pos, type=type) for type in types] |
| 808 return self.lookup_operator(operator, operands) |
| 809 |
| 810 def use_utility_code(self, new_code): |
| 811 self.global_scope().use_utility_code(new_code) |
| 812 |
| 813 def generate_library_function_declarations(self, code): |
| 814 # Generate extern decls for C library funcs used. |
| 815 pass |
| 816 |
| 817 def defines_any(self, names): |
| 818 # Test whether any of the given names are |
| 819 # defined in this scope. |
| 820 for name in names: |
| 821 if name in self.entries: |
| 822 return 1 |
| 823 return 0 |
| 824 |
| 825 def infer_types(self): |
| 826 from TypeInference import get_type_inferer |
| 827 get_type_inferer().infer_types(self) |
| 828 |
| 829 def is_cpp(self): |
| 830 outer = self.outer_scope |
| 831 if outer is None: |
| 832 return False |
| 833 else: |
| 834 return outer.is_cpp() |
| 835 |
| 836 def add_include_file(self, filename): |
| 837 self.outer_scope.add_include_file(filename) |
| 838 |
| 839 |
| 840 class PreImportScope(Scope): |
| 841 |
| 842 namespace_cname = Naming.preimport_cname |
| 843 |
| 844 def __init__(self): |
| 845 Scope.__init__(self, Options.pre_import, None, None) |
| 846 |
| 847 def declare_builtin(self, name, pos): |
| 848 entry = self.declare(name, name, py_object_type, pos, 'private') |
| 849 entry.is_variable = True |
| 850 entry.is_pyglobal = True |
| 851 return entry |
| 852 |
| 853 |
| 854 class BuiltinScope(Scope): |
| 855 # The builtin namespace. |
| 856 |
| 857 is_builtin_scope = True |
| 858 |
| 859 def __init__(self): |
| 860 if Options.pre_import is None: |
| 861 Scope.__init__(self, "__builtin__", None, None) |
| 862 else: |
| 863 Scope.__init__(self, "__builtin__", PreImportScope(), None) |
| 864 self.type_names = {} |
| 865 |
| 866 for name, definition in self.builtin_entries.iteritems(): |
| 867 cname, type = definition |
| 868 self.declare_var(name, type, None, cname) |
| 869 |
| 870 def lookup(self, name, language_level=None): |
| 871 # 'language_level' is passed by ModuleScope |
| 872 if language_level == 3: |
| 873 if name == 'str': |
| 874 name = 'unicode' |
| 875 return Scope.lookup(self, name) |
| 876 |
| 877 def declare_builtin(self, name, pos): |
| 878 if not hasattr(builtins, name): |
| 879 if self.outer_scope is not None: |
| 880 return self.outer_scope.declare_builtin(name, pos) |
| 881 else: |
| 882 if Options.error_on_unknown_names: |
| 883 error(pos, "undeclared name not builtin: %s" % name) |
| 884 else: |
| 885 warning(pos, "undeclared name not builtin: %s" % name, 2) |
| 886 |
| 887 def declare_builtin_cfunction(self, name, type, cname, python_equiv = None, |
| 888 utility_code = None): |
| 889 # If python_equiv == "*", the Python equivalent has the same name |
| 890 # as the entry, otherwise it has the name specified by python_equiv. |
| 891 name = EncodedString(name) |
| 892 entry = self.declare_cfunction(name, type, None, cname, visibility='exte
rn', |
| 893 utility_code = utility_code) |
| 894 if python_equiv: |
| 895 if python_equiv == "*": |
| 896 python_equiv = name |
| 897 else: |
| 898 python_equiv = EncodedString(python_equiv) |
| 899 var_entry = Entry(python_equiv, python_equiv, py_object_type) |
| 900 var_entry.is_variable = 1 |
| 901 var_entry.is_builtin = 1 |
| 902 var_entry.utility_code = utility_code |
| 903 entry.as_variable = var_entry |
| 904 return entry |
| 905 |
| 906 def declare_builtin_type(self, name, cname, utility_code = None, objstruct_c
name = None): |
| 907 name = EncodedString(name) |
| 908 type = PyrexTypes.BuiltinObjectType(name, cname, objstruct_cname) |
| 909 scope = CClassScope(name, outer_scope=None, visibility='extern') |
| 910 scope.directives = {} |
| 911 if name == 'bool': |
| 912 type.is_final_type = True |
| 913 type.set_scope(scope) |
| 914 self.type_names[name] = 1 |
| 915 entry = self.declare_type(name, type, None, visibility='extern') |
| 916 entry.utility_code = utility_code |
| 917 |
| 918 var_entry = Entry(name = entry.name, |
| 919 type = self.lookup('type').type, # make sure "type" is the first typ
e declared... |
| 920 pos = entry.pos, |
| 921 cname = "((PyObject*)%s)" % entry.type.typeptr_cname) |
| 922 var_entry.is_variable = 1 |
| 923 var_entry.is_cglobal = 1 |
| 924 var_entry.is_readonly = 1 |
| 925 var_entry.is_builtin = 1 |
| 926 var_entry.utility_code = utility_code |
| 927 if Options.cache_builtins: |
| 928 var_entry.is_const = True |
| 929 entry.as_variable = var_entry |
| 930 |
| 931 return type |
| 932 |
| 933 def builtin_scope(self): |
| 934 return self |
| 935 |
| 936 builtin_entries = { |
| 937 |
| 938 "type": ["((PyObject*)&PyType_Type)", py_object_type], |
| 939 |
| 940 "bool": ["((PyObject*)&PyBool_Type)", py_object_type], |
| 941 "int": ["((PyObject*)&PyInt_Type)", py_object_type], |
| 942 "long": ["((PyObject*)&PyLong_Type)", py_object_type], |
| 943 "float": ["((PyObject*)&PyFloat_Type)", py_object_type], |
| 944 "complex":["((PyObject*)&PyComplex_Type)", py_object_type], |
| 945 |
| 946 "bytes": ["((PyObject*)&PyBytes_Type)", py_object_type], |
| 947 "bytearray": ["((PyObject*)&PyByteArray_Type)", py_object_type], |
| 948 "str": ["((PyObject*)&PyString_Type)", py_object_type], |
| 949 "unicode":["((PyObject*)&PyUnicode_Type)", py_object_type], |
| 950 |
| 951 "tuple": ["((PyObject*)&PyTuple_Type)", py_object_type], |
| 952 "list": ["((PyObject*)&PyList_Type)", py_object_type], |
| 953 "dict": ["((PyObject*)&PyDict_Type)", py_object_type], |
| 954 "set": ["((PyObject*)&PySet_Type)", py_object_type], |
| 955 "frozenset": ["((PyObject*)&PyFrozenSet_Type)", py_object_type], |
| 956 |
| 957 "slice": ["((PyObject*)&PySlice_Type)", py_object_type], |
| 958 # "file": ["((PyObject*)&PyFile_Type)", py_object_type], # not in Py3 |
| 959 |
| 960 "None": ["Py_None", py_object_type], |
| 961 "False": ["Py_False", py_object_type], |
| 962 "True": ["Py_True", py_object_type], |
| 963 } |
| 964 |
| 965 const_counter = 1 # As a temporary solution for compiling code in pxds |
| 966 |
| 967 class ModuleScope(Scope): |
| 968 # module_name string Python name of the module |
| 969 # module_cname string C name of Python module object |
| 970 # #module_dict_cname string C name of module dict object |
| 971 # method_table_cname string C name of method table |
| 972 # doc string Module doc string |
| 973 # doc_cname string C name of module doc string |
| 974 # utility_code_list [UtilityCode] Queuing utility codes for forwardi
ng to Code.py |
| 975 # python_include_files [string] Standard Python headers to be inc
luded |
| 976 # include_files [string] Other C headers to be included |
| 977 # string_to_entry {string : Entry} Map string const to entry |
| 978 # identifier_to_entry {string : Entry} Map identifier string const to ent
ry |
| 979 # context Context |
| 980 # parent_module Scope Parent in the import namespace |
| 981 # module_entries {string : Entry} For cimport statements |
| 982 # type_names {string : 1} Set of type names (used during par
sing) |
| 983 # included_files [string] Cython sources included with 'incl
ude' |
| 984 # pxd_file_loaded boolean Corresponding .pxd file has been p
rocessed |
| 985 # cimported_modules [ModuleScope] Modules imported with cimport |
| 986 # types_imported {PyrexType} Set of types for which import code
generated |
| 987 # has_import_star boolean Module contains import * |
| 988 # cpp boolean Compiling a C++ file |
| 989 # is_cython_builtin boolean Is this the Cython builtin scope (
or a child scope) |
| 990 # is_package boolean Is this a package module? (__init_
_) |
| 991 |
| 992 is_module_scope = 1 |
| 993 has_import_star = 0 |
| 994 is_cython_builtin = 0 |
| 995 |
| 996 def __init__(self, name, parent_module, context): |
| 997 import Builtin |
| 998 self.parent_module = parent_module |
| 999 outer_scope = Builtin.builtin_scope |
| 1000 Scope.__init__(self, name, outer_scope, parent_module) |
| 1001 if name == "__init__": |
| 1002 # Treat Spam/__init__.pyx specially, so that when Python loads |
| 1003 # Spam/__init__.so, initSpam() is defined. |
| 1004 self.module_name = parent_module.module_name |
| 1005 self.is_package = True |
| 1006 else: |
| 1007 self.module_name = name |
| 1008 self.is_package = False |
| 1009 self.module_name = EncodedString(self.module_name) |
| 1010 self.context = context |
| 1011 self.module_cname = Naming.module_cname |
| 1012 self.module_dict_cname = Naming.moddict_cname |
| 1013 self.method_table_cname = Naming.methtable_cname |
| 1014 self.doc = "" |
| 1015 self.doc_cname = Naming.moddoc_cname |
| 1016 self.utility_code_list = [] |
| 1017 self.module_entries = {} |
| 1018 self.python_include_files = ["Python.h"] |
| 1019 self.include_files = [] |
| 1020 self.type_names = dict(outer_scope.type_names) |
| 1021 self.pxd_file_loaded = 0 |
| 1022 self.cimported_modules = [] |
| 1023 self.types_imported = set() |
| 1024 self.included_files = [] |
| 1025 self.has_extern_class = 0 |
| 1026 self.cached_builtins = [] |
| 1027 self.undeclared_cached_builtins = [] |
| 1028 self.namespace_cname = self.module_cname |
| 1029 for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__p
ath__']: |
| 1030 self.declare_var(EncodedString(var_name), py_object_type, None) |
| 1031 |
| 1032 def qualifying_scope(self): |
| 1033 return self.parent_module |
| 1034 |
| 1035 def global_scope(self): |
| 1036 return self |
| 1037 |
| 1038 def lookup(self, name): |
| 1039 entry = self.lookup_here(name) |
| 1040 if entry is not None: |
| 1041 return entry |
| 1042 |
| 1043 if self.context is not None: |
| 1044 language_level = self.context.language_level |
| 1045 else: |
| 1046 language_level = 3 |
| 1047 |
| 1048 return self.outer_scope.lookup(name, language_level=language_level) |
| 1049 |
| 1050 def declare_builtin(self, name, pos): |
| 1051 if not hasattr(builtins, name) \ |
| 1052 and name not in Code.non_portable_builtins_map \ |
| 1053 and name not in Code.uncachable_builtins: |
| 1054 if self.has_import_star: |
| 1055 entry = self.declare_var(name, py_object_type, pos) |
| 1056 return entry |
| 1057 else: |
| 1058 if Options.error_on_unknown_names: |
| 1059 error(pos, "undeclared name not builtin: %s" % name) |
| 1060 else: |
| 1061 warning(pos, "undeclared name not builtin: %s" % name, 2) |
| 1062 # unknown - assume it's builtin and look it up at runtime |
| 1063 entry = self.declare(name, None, py_object_type, pos, 'private') |
| 1064 entry.is_builtin = 1 |
| 1065 return entry |
| 1066 if Options.cache_builtins: |
| 1067 for entry in self.cached_builtins: |
| 1068 if entry.name == name: |
| 1069 return entry |
| 1070 entry = self.declare(None, None, py_object_type, pos, 'private') |
| 1071 if Options.cache_builtins and name not in Code.uncachable_builtins: |
| 1072 entry.is_builtin = 1 |
| 1073 entry.is_const = 1 # cached |
| 1074 entry.name = name |
| 1075 entry.cname = Naming.builtin_prefix + name |
| 1076 self.cached_builtins.append(entry) |
| 1077 self.undeclared_cached_builtins.append(entry) |
| 1078 else: |
| 1079 entry.is_builtin = 1 |
| 1080 entry.name = name |
| 1081 return entry |
| 1082 |
| 1083 def find_module(self, module_name, pos): |
| 1084 # Find a module in the import namespace, interpreting |
| 1085 # relative imports relative to this module's parent. |
| 1086 # Finds and parses the module's .pxd file if the module |
| 1087 # has not been referenced before. |
| 1088 return self.global_scope().context.find_module( |
| 1089 module_name, relative_to = self.parent_module, pos = pos) |
| 1090 |
| 1091 def find_submodule(self, name): |
| 1092 # Find and return scope for a submodule of this module, |
| 1093 # creating a new empty one if necessary. Doesn't parse .pxd. |
| 1094 scope = self.lookup_submodule(name) |
| 1095 if not scope: |
| 1096 scope = ModuleScope(name, |
| 1097 parent_module = self, context = self.context) |
| 1098 self.module_entries[name] = scope |
| 1099 return scope |
| 1100 |
| 1101 def lookup_submodule(self, name): |
| 1102 # Return scope for submodule of this module, or None. |
| 1103 return self.module_entries.get(name, None) |
| 1104 |
| 1105 def add_include_file(self, filename): |
| 1106 if filename not in self.python_include_files \ |
| 1107 and filename not in self.include_files: |
| 1108 self.include_files.append(filename) |
| 1109 |
| 1110 def add_imported_module(self, scope): |
| 1111 if scope not in self.cimported_modules: |
| 1112 for filename in scope.include_files: |
| 1113 self.add_include_file(filename) |
| 1114 self.cimported_modules.append(scope) |
| 1115 for m in scope.cimported_modules: |
| 1116 self.add_imported_module(m) |
| 1117 |
| 1118 def add_imported_entry(self, name, entry, pos): |
| 1119 if entry not in self.entries: |
| 1120 self.entries[name] = entry |
| 1121 else: |
| 1122 warning(pos, "'%s' redeclared " % name, 0) |
| 1123 |
| 1124 def declare_module(self, name, scope, pos): |
| 1125 # Declare a cimported module. This is represented as a |
| 1126 # Python module-level variable entry with a module |
| 1127 # scope attached to it. Reports an error and returns |
| 1128 # None if previously declared as something else. |
| 1129 entry = self.lookup_here(name) |
| 1130 if entry: |
| 1131 if entry.is_pyglobal and entry.as_module is scope: |
| 1132 return entry # Already declared as the same module |
| 1133 if not (entry.is_pyglobal and not entry.as_module): |
| 1134 # SAGE -- I put this here so Pyrex |
| 1135 # cimport's work across directories. |
| 1136 # Currently it tries to multiply define |
| 1137 # every module appearing in an import list. |
| 1138 # It shouldn't be an error for a module |
| 1139 # name to appear again, and indeed the generated |
| 1140 # code compiles fine. |
| 1141 return entry |
| 1142 else: |
| 1143 entry = self.declare_var(name, py_object_type, pos) |
| 1144 entry.as_module = scope |
| 1145 self.add_imported_module(scope) |
| 1146 return entry |
| 1147 |
| 1148 def declare_var(self, name, type, pos, |
| 1149 cname = None, visibility = 'private', |
| 1150 api = 0, in_pxd = 0, is_cdef = 0): |
| 1151 # Add an entry for a global variable. If it is a Python |
| 1152 # object type, and not declared with cdef, it will live |
| 1153 # in the module dictionary, otherwise it will be a C |
| 1154 # global variable. |
| 1155 if not visibility in ('private', 'public', 'extern'): |
| 1156 error(pos, "Module-level variable cannot be declared %s" % visibilit
y) |
| 1157 if not is_cdef: |
| 1158 if type is unspecified_type: |
| 1159 type = py_object_type |
| 1160 if not (type.is_pyobject and not type.is_extension_type): |
| 1161 raise InternalError( |
| 1162 "Non-cdef global variable is not a generic Python object") |
| 1163 |
| 1164 if not cname: |
| 1165 defining = not in_pxd |
| 1166 if visibility == 'extern' or (visibility == 'public' and defining): |
| 1167 cname = name |
| 1168 else: |
| 1169 cname = self.mangle(Naming.var_prefix, name) |
| 1170 |
| 1171 entry = self.lookup_here(name) |
| 1172 if entry and entry.defined_in_pxd: |
| 1173 #if visibility != 'private' and visibility != entry.visibility: |
| 1174 # warning(pos, "Variable '%s' previously declared as '%s'" % (nam
e, entry.visibility), 1) |
| 1175 if not entry.type.same_as(type): |
| 1176 if visibility == 'extern' and entry.visibility == 'extern': |
| 1177 warning(pos, "Variable '%s' type does not match previous dec
laration" % name, 1) |
| 1178 entry.type = type |
| 1179 #else: |
| 1180 # error(pos, "Variable '%s' type does not match previous decl
aration" % name) |
| 1181 if entry.visibility != "private": |
| 1182 mangled_cname = self.mangle(Naming.var_prefix, name) |
| 1183 if entry.cname == mangled_cname: |
| 1184 cname = name |
| 1185 entry.cname = name |
| 1186 if not entry.is_implemented: |
| 1187 entry.is_implemented = True |
| 1188 return entry |
| 1189 |
| 1190 entry = Scope.declare_var(self, name, type, pos, |
| 1191 cname=cname, visibility=visibility, |
| 1192 api=api, in_pxd=in_pxd, is_cdef=is_cdef) |
| 1193 if is_cdef: |
| 1194 entry.is_cglobal = 1 |
| 1195 if entry.type.is_pyobject: |
| 1196 entry.init = 0 |
| 1197 self.var_entries.append(entry) |
| 1198 else: |
| 1199 entry.is_pyglobal = 1 |
| 1200 if Options.cimport_from_pyx: |
| 1201 entry.used = 1 |
| 1202 return entry |
| 1203 |
| 1204 def declare_cfunction(self, name, type, pos, |
| 1205 cname = None, visibility = 'private', api = 0, in_pxd
= 0, |
| 1206 defining = 0, modifiers = (), utility_code = None): |
| 1207 # Add an entry for a C function. |
| 1208 if not cname: |
| 1209 if visibility == 'extern' or (visibility == 'public' and defining): |
| 1210 cname = name |
| 1211 else: |
| 1212 cname = self.mangle(Naming.func_prefix, name) |
| 1213 entry = self.lookup_here(name) |
| 1214 if entry and entry.defined_in_pxd: |
| 1215 if entry.visibility != "private": |
| 1216 mangled_cname = self.mangle(Naming.var_prefix, name) |
| 1217 if entry.cname == mangled_cname: |
| 1218 cname = name |
| 1219 entry.cname = cname |
| 1220 entry.func_cname = cname |
| 1221 entry = Scope.declare_cfunction( |
| 1222 self, name, type, pos, |
| 1223 cname = cname, visibility = visibility, api = api, in_pxd = in_pxd, |
| 1224 defining = defining, modifiers = modifiers, utility_code = utility_c
ode) |
| 1225 return entry |
| 1226 |
| 1227 def declare_global(self, name, pos): |
| 1228 entry = self.lookup_here(name) |
| 1229 if not entry: |
| 1230 self.declare_var(name, py_object_type, pos) |
| 1231 |
| 1232 def use_utility_code(self, new_code): |
| 1233 if new_code is not None: |
| 1234 self.utility_code_list.append(new_code) |
| 1235 |
| 1236 def declare_c_class(self, name, pos, defining = 0, implementing = 0, |
| 1237 module_name = None, base_type = None, objstruct_cname = None, |
| 1238 typeobj_cname = None, typeptr_cname = None, visibility = 'private', type
def_flag = 0, api = 0, |
| 1239 buffer_defaults = None, shadow = 0): |
| 1240 # If this is a non-extern typedef class, expose the typedef, but use |
| 1241 # the non-typedef struct internally to avoid needing forward |
| 1242 # declarations for anonymous structs. |
| 1243 if typedef_flag and visibility != 'extern': |
| 1244 if not (visibility == 'public' or api): |
| 1245 warning(pos, "ctypedef only valid for 'extern' , 'public', and '
api'", 2) |
| 1246 objtypedef_cname = objstruct_cname |
| 1247 typedef_flag = 0 |
| 1248 else: |
| 1249 objtypedef_cname = None |
| 1250 # |
| 1251 # Look for previous declaration as a type |
| 1252 # |
| 1253 entry = self.lookup_here(name) |
| 1254 if entry and not shadow: |
| 1255 type = entry.type |
| 1256 if not (entry.is_type and type.is_extension_type): |
| 1257 entry = None # Will cause redeclaration and produce an error |
| 1258 else: |
| 1259 scope = type.scope |
| 1260 if typedef_flag and (not scope or scope.defined): |
| 1261 self.check_previous_typedef_flag(entry, typedef_flag, pos) |
| 1262 if (scope and scope.defined) or (base_type and type.base_type): |
| 1263 if base_type and base_type is not type.base_type: |
| 1264 error(pos, "Base type does not match previous declaratio
n") |
| 1265 if base_type and not type.base_type: |
| 1266 type.base_type = base_type |
| 1267 # |
| 1268 # Make a new entry if needed |
| 1269 # |
| 1270 if not entry or shadow: |
| 1271 type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, vis
ibility == 'extern') |
| 1272 type.pos = pos |
| 1273 type.buffer_defaults = buffer_defaults |
| 1274 if objtypedef_cname is not None: |
| 1275 type.objtypedef_cname = objtypedef_cname |
| 1276 if visibility == 'extern': |
| 1277 type.module_name = module_name |
| 1278 else: |
| 1279 type.module_name = self.qualified_name |
| 1280 if typeptr_cname: |
| 1281 type.typeptr_cname = typeptr_cname |
| 1282 else: |
| 1283 type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) |
| 1284 entry = self.declare_type(name, type, pos, visibility = visibility, |
| 1285 defining = 0, shadow = shadow) |
| 1286 entry.is_cclass = True |
| 1287 if objstruct_cname: |
| 1288 type.objstruct_cname = objstruct_cname |
| 1289 elif not entry.in_cinclude: |
| 1290 type.objstruct_cname = self.mangle(Naming.objstruct_prefix, name
) |
| 1291 else: |
| 1292 error(entry.pos, |
| 1293 "Object name required for 'public' or 'extern' C class") |
| 1294 self.attach_var_entry_to_c_class(entry) |
| 1295 self.c_class_entries.append(entry) |
| 1296 # |
| 1297 # Check for re-definition and create scope if needed |
| 1298 # |
| 1299 if not type.scope: |
| 1300 if defining or implementing: |
| 1301 scope = CClassScope(name = name, outer_scope = self, |
| 1302 visibility = visibility) |
| 1303 scope.directives = self.directives.copy() |
| 1304 if base_type and base_type.scope: |
| 1305 scope.declare_inherited_c_attributes(base_type.scope) |
| 1306 type.set_scope(scope) |
| 1307 self.type_entries.append(entry) |
| 1308 else: |
| 1309 if defining and type.scope.defined: |
| 1310 error(pos, "C class '%s' already defined" % name) |
| 1311 elif implementing and type.scope.implemented: |
| 1312 error(pos, "C class '%s' already implemented" % name) |
| 1313 # |
| 1314 # Fill in options, checking for compatibility with any previous declara
tion |
| 1315 # |
| 1316 if defining: |
| 1317 entry.defined_in_pxd = 1 |
| 1318 if implementing: # So that filenames in runtime exceptions refer to |
| 1319 entry.pos = pos # the .pyx file and not the .pxd file |
| 1320 if visibility != 'private' and entry.visibility != visibility: |
| 1321 error(pos, "Class '%s' previously declared as '%s'" |
| 1322 % (name, entry.visibility)) |
| 1323 if api: |
| 1324 entry.api = 1 |
| 1325 if objstruct_cname: |
| 1326 if type.objstruct_cname and type.objstruct_cname != objstruct_cname: |
| 1327 error(pos, "Object struct name differs from previous declaration
") |
| 1328 type.objstruct_cname = objstruct_cname |
| 1329 if typeobj_cname: |
| 1330 if type.typeobj_cname and type.typeobj_cname != typeobj_cname: |
| 1331 error(pos, "Type object name differs from previous declarati
on") |
| 1332 type.typeobj_cname = typeobj_cname |
| 1333 |
| 1334 if self.directives.get('final'): |
| 1335 entry.type.is_final_type = True |
| 1336 |
| 1337 # cdef classes are always exported, but we need to set it to |
| 1338 # distinguish between unused Cython utility code extension classes |
| 1339 entry.used = True |
| 1340 |
| 1341 # |
| 1342 # Return new or existing entry |
| 1343 # |
| 1344 return entry |
| 1345 |
| 1346 def allocate_vtable_names(self, entry): |
| 1347 # If extension type has a vtable, allocate vtable struct and |
| 1348 # slot names for it. |
| 1349 type = entry.type |
| 1350 if type.base_type and type.base_type.vtabslot_cname: |
| 1351 #print "...allocating vtabslot_cname because base type has one" ### |
| 1352 type.vtabslot_cname = "%s.%s" % ( |
| 1353 Naming.obj_base_cname, type.base_type.vtabslot_cname) |
| 1354 elif type.scope and type.scope.cfunc_entries: |
| 1355 # one special case here: when inheriting from builtin |
| 1356 # types, the methods may also be built-in, in which |
| 1357 # case they won't need a vtable |
| 1358 entry_count = len(type.scope.cfunc_entries) |
| 1359 base_type = type.base_type |
| 1360 while base_type: |
| 1361 # FIXME: this will break if we ever get non-inherited C methods |
| 1362 if not base_type.scope or entry_count > len(base_type.scope.cfun
c_entries): |
| 1363 break |
| 1364 if base_type.is_builtin_type: |
| 1365 # builtin base type defines all methods => no vtable needed |
| 1366 return |
| 1367 base_type = base_type.base_type |
| 1368 #print "...allocating vtabslot_cname because there are C methods" ##
# |
| 1369 type.vtabslot_cname = Naming.vtabslot_cname |
| 1370 if type.vtabslot_cname: |
| 1371 #print "...allocating other vtable related cnames" ### |
| 1372 type.vtabstruct_cname = self.mangle(Naming.vtabstruct_prefix, entry.
name) |
| 1373 type.vtabptr_cname = self.mangle(Naming.vtabptr_prefix, entry.name) |
| 1374 |
| 1375 def check_c_classes_pxd(self): |
| 1376 # Performs post-analysis checking and finishing up of extension types |
| 1377 # being implemented in this module. This is called only for the .pxd. |
| 1378 # |
| 1379 # Checks all extension types declared in this scope to |
| 1380 # make sure that: |
| 1381 # |
| 1382 # * The extension type is fully declared |
| 1383 # |
| 1384 # Also allocates a name for the vtable if needed. |
| 1385 # |
| 1386 for entry in self.c_class_entries: |
| 1387 # Check defined |
| 1388 if not entry.type.scope: |
| 1389 error(entry.pos, "C class '%s' is declared but not defined" % en
try.name) |
| 1390 |
| 1391 def check_c_class(self, entry): |
| 1392 type = entry.type |
| 1393 name = entry.name |
| 1394 visibility = entry.visibility |
| 1395 # Check defined |
| 1396 if not type.scope: |
| 1397 error(entry.pos, "C class '%s' is declared but not defined" % name) |
| 1398 # Generate typeobj_cname |
| 1399 if visibility != 'extern' and not type.typeobj_cname: |
| 1400 type.typeobj_cname = self.mangle(Naming.typeobj_prefix, name) |
| 1401 ## Generate typeptr_cname |
| 1402 #type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) |
| 1403 # Check C methods defined |
| 1404 if type.scope: |
| 1405 for method_entry in type.scope.cfunc_entries: |
| 1406 if not method_entry.is_inherited and not method_entry.func_cname
: |
| 1407 error(method_entry.pos, "C method '%s' is declared but not d
efined" % |
| 1408 method_entry.name) |
| 1409 # Allocate vtable name if necessary |
| 1410 if type.vtabslot_cname: |
| 1411 #print "ModuleScope.check_c_classes: allocating vtable cname for", s
elf ### |
| 1412 type.vtable_cname = self.mangle(Naming.vtable_prefix, entry.name) |
| 1413 |
| 1414 def check_c_classes(self): |
| 1415 # Performs post-analysis checking and finishing up of extension types |
| 1416 # being implemented in this module. This is called only for the main |
| 1417 # .pyx file scope, not for cimported .pxd scopes. |
| 1418 # |
| 1419 # Checks all extension types declared in this scope to |
| 1420 # make sure that: |
| 1421 # |
| 1422 # * The extension type is implemented |
| 1423 # * All required object and type names have been specified or generat
ed |
| 1424 # * All non-inherited C methods are implemented |
| 1425 # |
| 1426 # Also allocates a name for the vtable if needed. |
| 1427 # |
| 1428 debug_check_c_classes = 0 |
| 1429 if debug_check_c_classes: |
| 1430 print("Scope.check_c_classes: checking scope " + self.qualified_name
) |
| 1431 for entry in self.c_class_entries: |
| 1432 if debug_check_c_classes: |
| 1433 print("...entry %s %s" % (entry.name, entry)) |
| 1434 print("......type = ", entry.type) |
| 1435 print("......visibility = ", entry.visibility) |
| 1436 self.check_c_class(entry) |
| 1437 |
| 1438 def check_c_functions(self): |
| 1439 # Performs post-analysis checking making sure all |
| 1440 # defined c functions are actually implemented. |
| 1441 for name, entry in self.entries.items(): |
| 1442 if entry.is_cfunction: |
| 1443 if (entry.defined_in_pxd |
| 1444 and entry.scope is self |
| 1445 and entry.visibility != 'extern' |
| 1446 and not entry.in_cinclude |
| 1447 and not entry.is_implemented): |
| 1448 error(entry.pos, "Non-extern C function '%s' declared but no
t defined" % name) |
| 1449 |
| 1450 def attach_var_entry_to_c_class(self, entry): |
| 1451 # The name of an extension class has to serve as both a type |
| 1452 # name and a variable name holding the type object. It is |
| 1453 # represented in the symbol table by a type entry with a |
| 1454 # variable entry attached to it. For the variable entry, |
| 1455 # we use a read-only C global variable whose name is an |
| 1456 # expression that refers to the type object. |
| 1457 import Builtin |
| 1458 var_entry = Entry(name = entry.name, |
| 1459 type = Builtin.type_type, |
| 1460 pos = entry.pos, |
| 1461 cname = "((PyObject*)%s)" % entry.type.typeptr_cname) |
| 1462 var_entry.is_variable = 1 |
| 1463 var_entry.is_cglobal = 1 |
| 1464 var_entry.is_readonly = 1 |
| 1465 entry.as_variable = var_entry |
| 1466 |
| 1467 def is_cpp(self): |
| 1468 return self.cpp |
| 1469 |
| 1470 def infer_types(self): |
| 1471 from TypeInference import PyObjectTypeInferer |
| 1472 PyObjectTypeInferer().infer_types(self) |
| 1473 |
| 1474 |
| 1475 class LocalScope(Scope): |
| 1476 |
| 1477 # Does the function have a 'with gil:' block? |
| 1478 has_with_gil_block = False |
| 1479 |
| 1480 # Transient attribute, used for symbol table variable declarations |
| 1481 _in_with_gil_block = False |
| 1482 |
| 1483 def __init__(self, name, outer_scope, parent_scope = None): |
| 1484 if parent_scope is None: |
| 1485 parent_scope = outer_scope |
| 1486 Scope.__init__(self, name, outer_scope, parent_scope) |
| 1487 |
| 1488 def mangle(self, prefix, name): |
| 1489 return prefix + name |
| 1490 |
| 1491 def declare_arg(self, name, type, pos): |
| 1492 # Add an entry for an argument of a function. |
| 1493 cname = self.mangle(Naming.var_prefix, name) |
| 1494 entry = self.declare(name, cname, type, pos, 'private') |
| 1495 entry.is_variable = 1 |
| 1496 if type.is_pyobject: |
| 1497 entry.init = "0" |
| 1498 entry.is_arg = 1 |
| 1499 #entry.borrowed = 1 # Not using borrowed arg refs for now |
| 1500 self.arg_entries.append(entry) |
| 1501 return entry |
| 1502 |
| 1503 def declare_var(self, name, type, pos, |
| 1504 cname = None, visibility = 'private', |
| 1505 api = 0, in_pxd = 0, is_cdef = 0): |
| 1506 # Add an entry for a local variable. |
| 1507 if visibility in ('public', 'readonly'): |
| 1508 error(pos, "Local variable cannot be declared %s" % visibility) |
| 1509 entry = Scope.declare_var(self, name, type, pos, |
| 1510 cname=cname, visibility=visibility, |
| 1511 api=api, in_pxd=in_pxd, is_cdef=is_cdef) |
| 1512 if type.is_pyobject: |
| 1513 entry.init = "0" |
| 1514 entry.is_local = 1 |
| 1515 |
| 1516 entry.in_with_gil_block = self._in_with_gil_block |
| 1517 self.var_entries.append(entry) |
| 1518 return entry |
| 1519 |
| 1520 def declare_global(self, name, pos): |
| 1521 # Pull entry from global scope into local scope. |
| 1522 if self.lookup_here(name): |
| 1523 warning(pos, "'%s' redeclared ", 0) |
| 1524 else: |
| 1525 entry = self.global_scope().lookup_target(name) |
| 1526 self.entries[name] = entry |
| 1527 |
| 1528 def declare_nonlocal(self, name, pos): |
| 1529 # Pull entry from outer scope into local scope |
| 1530 orig_entry = self.lookup_here(name) |
| 1531 if orig_entry and orig_entry.scope is self and not orig_entry.from_closu
re: |
| 1532 error(pos, "'%s' redeclared as nonlocal" % name) |
| 1533 else: |
| 1534 entry = self.lookup(name) |
| 1535 if entry is None or not entry.from_closure: |
| 1536 error(pos, "no binding for nonlocal '%s' found" % name) |
| 1537 |
| 1538 def lookup(self, name): |
| 1539 # Look up name in this scope or an enclosing one. |
| 1540 # Return None if not found. |
| 1541 entry = Scope.lookup(self, name) |
| 1542 if entry is not None: |
| 1543 if entry.scope is not self and entry.scope.is_closure_scope: |
| 1544 if hasattr(entry.scope, "scope_class"): |
| 1545 raise InternalError("lookup() after scope class created.") |
| 1546 # The actual c fragment for the different scopes differs |
| 1547 # on the outside and inside, so we make a new entry |
| 1548 entry.in_closure = True |
| 1549 inner_entry = InnerEntry(entry, self) |
| 1550 inner_entry.is_variable = True |
| 1551 self.entries[name] = inner_entry |
| 1552 return inner_entry |
| 1553 return entry |
| 1554 |
| 1555 def mangle_closure_cnames(self, outer_scope_cname): |
| 1556 for entry in self.entries.values(): |
| 1557 if entry.from_closure: |
| 1558 cname = entry.outer_entry.cname |
| 1559 if self.is_passthrough: |
| 1560 entry.cname = cname |
| 1561 else: |
| 1562 if cname.startswith(Naming.cur_scope_cname): |
| 1563 cname = cname[len(Naming.cur_scope_cname)+2:] |
| 1564 entry.cname = "%s->%s" % (outer_scope_cname, cname) |
| 1565 elif entry.in_closure: |
| 1566 entry.original_cname = entry.cname |
| 1567 entry.cname = "%s->%s" % (Naming.cur_scope_cname, entry.cname) |
| 1568 |
| 1569 |
| 1570 class GeneratorExpressionScope(Scope): |
| 1571 """Scope for generator expressions and comprehensions. As opposed |
| 1572 to generators, these can be easily inlined in some cases, so all |
| 1573 we really need is a scope that holds the loop variable(s). |
| 1574 """ |
| 1575 def __init__(self, outer_scope): |
| 1576 name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref) |
| 1577 Scope.__init__(self, name, outer_scope, outer_scope) |
| 1578 self.directives = outer_scope.directives |
| 1579 self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name) |
| 1580 |
| 1581 def mangle(self, prefix, name): |
| 1582 return '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(prefix, na
me)) |
| 1583 |
| 1584 def declare_var(self, name, type, pos, |
| 1585 cname = None, visibility = 'private', |
| 1586 api = 0, in_pxd = 0, is_cdef = True): |
| 1587 if type is unspecified_type: |
| 1588 # if the outer scope defines a type for this variable, inherit it |
| 1589 outer_entry = self.outer_scope.lookup(name) |
| 1590 if outer_entry and outer_entry.is_variable: |
| 1591 type = outer_entry.type # may still be 'unspecified_type' ! |
| 1592 # the parent scope needs to generate code for the variable, but |
| 1593 # this scope must hold its name exclusively |
| 1594 cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.va
r_prefix, name or self.next_id())) |
| 1595 entry = self.declare(name, cname, type, pos, visibility) |
| 1596 entry.is_variable = 1 |
| 1597 entry.is_local = 1 |
| 1598 self.var_entries.append(entry) |
| 1599 self.entries[name] = entry |
| 1600 return entry |
| 1601 |
| 1602 def declare_pyfunction(self, name, pos, allow_redefine=False): |
| 1603 return self.outer_scope.declare_pyfunction( |
| 1604 name, pos, allow_redefine) |
| 1605 |
| 1606 def declare_lambda_function(self, func_cname, pos): |
| 1607 return self.outer_scope.declare_lambda_function(func_cname, pos) |
| 1608 |
| 1609 def add_lambda_def(self, def_node): |
| 1610 return self.outer_scope.add_lambda_def(def_node) |
| 1611 |
| 1612 |
| 1613 class ClosureScope(LocalScope): |
| 1614 |
| 1615 is_closure_scope = True |
| 1616 |
| 1617 def __init__(self, name, scope_name, outer_scope, parent_scope=None): |
| 1618 LocalScope.__init__(self, name, outer_scope, parent_scope) |
| 1619 self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name) |
| 1620 |
| 1621 # def mangle_closure_cnames(self, scope_var): |
| 1622 # for entry in self.entries.values() + self.temp_entries: |
| 1623 # entry.in_closure = 1 |
| 1624 # LocalScope.mangle_closure_cnames(self, scope_var) |
| 1625 |
| 1626 # def mangle(self, prefix, name): |
| 1627 # return "%s->%s" % (self.cur_scope_cname, name) |
| 1628 # return "%s->%s" % (self.closure_cname, name) |
| 1629 |
| 1630 def declare_pyfunction(self, name, pos, allow_redefine=False): |
| 1631 return LocalScope.declare_pyfunction(self, name, pos, allow_redefine, vi
sibility='private') |
| 1632 |
| 1633 |
| 1634 class StructOrUnionScope(Scope): |
| 1635 # Namespace of a C struct or union. |
| 1636 |
| 1637 def __init__(self, name="?"): |
| 1638 Scope.__init__(self, name, None, None) |
| 1639 |
| 1640 def declare_var(self, name, type, pos, |
| 1641 cname = None, visibility = 'private', |
| 1642 api = 0, in_pxd = 0, is_cdef = 0, |
| 1643 allow_pyobject = 0): |
| 1644 # Add an entry for an attribute. |
| 1645 if not cname: |
| 1646 cname = name |
| 1647 if visibility == 'private': |
| 1648 cname = c_safe_identifier(cname) |
| 1649 if type.is_cfunction: |
| 1650 type = PyrexTypes.CPtrType(type) |
| 1651 entry = self.declare(name, cname, type, pos, visibility) |
| 1652 entry.is_variable = 1 |
| 1653 self.var_entries.append(entry) |
| 1654 if type.is_pyobject and not allow_pyobject: |
| 1655 error(pos, |
| 1656 "C struct/union member cannot be a Python object") |
| 1657 if visibility != 'private': |
| 1658 error(pos, |
| 1659 "C struct/union member cannot be declared %s" % visibility) |
| 1660 return entry |
| 1661 |
| 1662 def declare_cfunction(self, name, type, pos, |
| 1663 cname = None, visibility = 'private', api = 0, in_pxd
= 0, |
| 1664 defining = 0, modifiers = ()): # currently no utility
code ... |
| 1665 return self.declare_var(name, type, pos, |
| 1666 cname=cname, visibility=visibility) |
| 1667 |
| 1668 |
| 1669 class ClassScope(Scope): |
| 1670 # Abstract base class for namespace of |
| 1671 # Python class or extension type. |
| 1672 # |
| 1673 # class_name string Python name of the class |
| 1674 # scope_prefix string Additional prefix for names |
| 1675 # declared in the class |
| 1676 # doc string or None Doc string |
| 1677 |
| 1678 def __init__(self, name, outer_scope): |
| 1679 Scope.__init__(self, name, outer_scope, outer_scope) |
| 1680 self.class_name = name |
| 1681 self.doc = None |
| 1682 |
| 1683 def lookup(self, name): |
| 1684 entry = Scope.lookup(self, name) |
| 1685 if entry: |
| 1686 return entry |
| 1687 if name == "classmethod": |
| 1688 # We don't want to use the builtin classmethod here 'cause it won't
do the |
| 1689 # right thing in this scope (as the class members aren't still funct
ions). |
| 1690 # Don't want to add a cfunction to this scope 'cause that would mess
with |
| 1691 # the type definition, so we just return the right entry. |
| 1692 entry = Entry( |
| 1693 "classmethod", |
| 1694 "__Pyx_Method_ClassMethod", |
| 1695 PyrexTypes.CFuncType( |
| 1696 py_object_type, |
| 1697 [PyrexTypes.CFuncTypeArg("", py_object_type, None)], 0, 0)) |
| 1698 entry.utility_code_definition = Code.UtilityCode.load_cached("ClassM
ethod", "CythonFunction.c") |
| 1699 entry.is_cfunction = 1 |
| 1700 return entry |
| 1701 |
| 1702 |
| 1703 class PyClassScope(ClassScope): |
| 1704 # Namespace of a Python class. |
| 1705 # |
| 1706 # class_obj_cname string C variable holding class object |
| 1707 |
| 1708 is_py_class_scope = 1 |
| 1709 |
| 1710 def mangle_class_private_name(self, name): |
| 1711 return self.mangle_special_name(name) |
| 1712 |
| 1713 def mangle_special_name(self, name): |
| 1714 if name and name.startswith('__') and not name.endswith('__'): |
| 1715 name = EncodedString('_%s%s' % (self.class_name.lstrip('_'), name)) |
| 1716 return name |
| 1717 |
| 1718 def lookup_here(self, name): |
| 1719 name = self.mangle_special_name(name) |
| 1720 return ClassScope.lookup_here(self, name) |
| 1721 |
| 1722 def declare_var(self, name, type, pos, |
| 1723 cname = None, visibility = 'private', |
| 1724 api = 0, in_pxd = 0, is_cdef = 0): |
| 1725 name = self.mangle_special_name(name) |
| 1726 if type is unspecified_type: |
| 1727 type = py_object_type |
| 1728 # Add an entry for a class attribute. |
| 1729 entry = Scope.declare_var(self, name, type, pos, |
| 1730 cname=cname, visibility=visibility, |
| 1731 api=api, in_pxd=in_pxd, is_cdef=is_cdef) |
| 1732 entry.is_pyglobal = 1 |
| 1733 entry.is_pyclass_attr = 1 |
| 1734 return entry |
| 1735 |
| 1736 def declare_nonlocal(self, name, pos): |
| 1737 # Pull entry from outer scope into local scope |
| 1738 orig_entry = self.lookup_here(name) |
| 1739 if orig_entry and orig_entry.scope is self and not orig_entry.from_closu
re: |
| 1740 error(pos, "'%s' redeclared as nonlocal" % name) |
| 1741 else: |
| 1742 entry = self.lookup(name) |
| 1743 if entry is None: |
| 1744 error(pos, "no binding for nonlocal '%s' found" % name) |
| 1745 else: |
| 1746 # FIXME: this works, but it's unclear if it's the |
| 1747 # right thing to do |
| 1748 self.entries[name] = entry |
| 1749 |
| 1750 def declare_global(self, name, pos): |
| 1751 # Pull entry from global scope into local scope. |
| 1752 if self.lookup_here(name): |
| 1753 warning(pos, "'%s' redeclared ", 0) |
| 1754 else: |
| 1755 entry = self.global_scope().lookup_target(name) |
| 1756 self.entries[name] = entry |
| 1757 |
| 1758 def add_default_value(self, type): |
| 1759 return self.outer_scope.add_default_value(type) |
| 1760 |
| 1761 |
| 1762 class CClassScope(ClassScope): |
| 1763 # Namespace of an extension type. |
| 1764 # |
| 1765 # parent_type CClassType |
| 1766 # #typeobj_cname string or None |
| 1767 # #objstruct_cname string |
| 1768 # method_table_cname string |
| 1769 # getset_table_cname string |
| 1770 # has_pyobject_attrs boolean Any PyObject attributes? |
| 1771 # has_memoryview_attrs boolean Any memory view attributes? |
| 1772 # has_cyclic_pyobject_attrs boolean Any PyObject attributes that may ne
ed GC? |
| 1773 # property_entries [Entry] |
| 1774 # defined boolean Defined in .pxd file |
| 1775 # implemented boolean Defined in .pyx file |
| 1776 # inherited_var_entries [Entry] Adapted var entries from base class |
| 1777 |
| 1778 is_c_class_scope = 1 |
| 1779 |
| 1780 has_pyobject_attrs = False |
| 1781 has_memoryview_attrs = False |
| 1782 has_cyclic_pyobject_attrs = False |
| 1783 defined = False |
| 1784 implemented = False |
| 1785 |
| 1786 def __init__(self, name, outer_scope, visibility): |
| 1787 ClassScope.__init__(self, name, outer_scope) |
| 1788 if visibility != 'extern': |
| 1789 self.method_table_cname = outer_scope.mangle(Naming.methtab_prefix,
name) |
| 1790 self.getset_table_cname = outer_scope.mangle(Naming.gstab_prefix, na
me) |
| 1791 self.property_entries = [] |
| 1792 self.inherited_var_entries = [] |
| 1793 |
| 1794 def needs_gc(self): |
| 1795 # If the type or any of its base types have Python-valued |
| 1796 # C attributes, then it needs to participate in GC. |
| 1797 if self.has_cyclic_pyobject_attrs: |
| 1798 return True |
| 1799 base_type = self.parent_type.base_type |
| 1800 if base_type and base_type.scope is not None: |
| 1801 return base_type.scope.needs_gc() |
| 1802 elif self.parent_type.is_builtin_type: |
| 1803 return not self.parent_type.is_gc_simple |
| 1804 return False |
| 1805 |
| 1806 def needs_tp_clear(self): |
| 1807 """ |
| 1808 Do we need to generate an implementation for the tp_clear slot? Can |
| 1809 be disabled to keep references for the __dealloc__ cleanup function. |
| 1810 """ |
| 1811 return self.needs_gc() and not self.directives.get('no_gc_clear', False) |
| 1812 |
| 1813 def get_refcounted_entries(self, include_weakref=False, |
| 1814 include_gc_simple=True): |
| 1815 py_attrs = [] |
| 1816 py_buffers = [] |
| 1817 memoryview_slices = [] |
| 1818 |
| 1819 for entry in self.var_entries: |
| 1820 if entry.type.is_pyobject: |
| 1821 if include_weakref or entry.name != "__weakref__": |
| 1822 if include_gc_simple or not entry.type.is_gc_simple: |
| 1823 py_attrs.append(entry) |
| 1824 elif entry.type == PyrexTypes.c_py_buffer_type: |
| 1825 py_buffers.append(entry) |
| 1826 elif entry.type.is_memoryviewslice: |
| 1827 memoryview_slices.append(entry) |
| 1828 |
| 1829 have_entries = py_attrs or py_buffers or memoryview_slices |
| 1830 return have_entries, (py_attrs, py_buffers, memoryview_slices) |
| 1831 |
| 1832 def declare_var(self, name, type, pos, |
| 1833 cname = None, visibility = 'private', |
| 1834 api = 0, in_pxd = 0, is_cdef = 0): |
| 1835 if is_cdef: |
| 1836 # Add an entry for an attribute. |
| 1837 if self.defined: |
| 1838 error(pos, |
| 1839 "C attributes cannot be added in implementation part of" |
| 1840 " extension type defined in a pxd") |
| 1841 if get_special_method_signature(name): |
| 1842 error(pos, |
| 1843 "The name '%s' is reserved for a special method." |
| 1844 % name) |
| 1845 if not cname: |
| 1846 cname = name |
| 1847 if visibility == 'private': |
| 1848 cname = c_safe_identifier(cname) |
| 1849 if type.is_cpp_class and visibility != 'extern': |
| 1850 type.check_nullary_constructor(pos) |
| 1851 self.use_utility_code(Code.UtilityCode("#include <new>")) |
| 1852 entry = self.declare(name, cname, type, pos, visibility) |
| 1853 entry.is_variable = 1 |
| 1854 self.var_entries.append(entry) |
| 1855 if type.is_memoryviewslice: |
| 1856 self.has_memoryview_attrs = True |
| 1857 elif type.is_pyobject and name != '__weakref__': |
| 1858 self.has_pyobject_attrs = True |
| 1859 if (not type.is_builtin_type |
| 1860 or not type.scope or type.scope.needs_gc()): |
| 1861 self.has_cyclic_pyobject_attrs = True |
| 1862 if visibility not in ('private', 'public', 'readonly'): |
| 1863 error(pos, |
| 1864 "Attribute of extension type cannot be declared %s" % visibi
lity) |
| 1865 if visibility in ('public', 'readonly'): |
| 1866 # If the field is an external typedef, we cannot be sure about t
he type, |
| 1867 # so do conversion ourself rather than rely on the CPython mecha
nism (through |
| 1868 # a property; made in AnalyseDeclarationsTransform). |
| 1869 entry.needs_property = True |
| 1870 if name == "__weakref__": |
| 1871 error(pos, "Special attribute __weakref__ cannot be exposed
to Python") |
| 1872 if not type.is_pyobject: |
| 1873 if (not type.create_to_py_utility_code(self) or |
| 1874 (visibility=='public' and not |
| 1875 type.create_from_py_utility_code(self))): |
| 1876 error(pos, |
| 1877 "C attribute of type '%s' cannot be accessed from
Python" % type) |
| 1878 else: |
| 1879 entry.needs_property = False |
| 1880 return entry |
| 1881 else: |
| 1882 if type is unspecified_type: |
| 1883 type = py_object_type |
| 1884 # Add an entry for a class attribute. |
| 1885 entry = Scope.declare_var(self, name, type, pos, |
| 1886 cname=cname, visibility=visibility, |
| 1887 api=api, in_pxd=in_pxd, is_cdef=is_cdef) |
| 1888 entry.is_member = 1 |
| 1889 entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so man
y places that |
| 1890 # I keep it in for now. is_member should be en
ough |
| 1891 # later on |
| 1892 self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_c
name |
| 1893 return entry |
| 1894 |
| 1895 def declare_pyfunction(self, name, pos, allow_redefine=False): |
| 1896 # Add an entry for a method. |
| 1897 if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'): |
| 1898 error(pos, "Special method %s must be implemented via __richcmp__" %
name) |
| 1899 if name == "__new__": |
| 1900 error(pos, "__new__ method of extension type will change semantics " |
| 1901 "in a future version of Pyrex and Cython. Use __cinit__ instead.
") |
| 1902 entry = self.declare_var(name, py_object_type, pos, |
| 1903 visibility='extern') |
| 1904 special_sig = get_special_method_signature(name) |
| 1905 if special_sig: |
| 1906 # Special methods get put in the method table with a particular |
| 1907 # signature declared in advance. |
| 1908 entry.signature = special_sig |
| 1909 entry.is_special = 1 |
| 1910 else: |
| 1911 entry.signature = pymethod_signature |
| 1912 entry.is_special = 0 |
| 1913 |
| 1914 self.pyfunc_entries.append(entry) |
| 1915 return entry |
| 1916 |
| 1917 def lookup_here(self, name): |
| 1918 if name == "__new__": |
| 1919 name = EncodedString("__cinit__") |
| 1920 entry = ClassScope.lookup_here(self, name) |
| 1921 if entry and entry.is_builtin_cmethod: |
| 1922 if not self.parent_type.is_builtin_type: |
| 1923 # For subtypes of builtin types, we can only return |
| 1924 # optimised C methods if the type if final. |
| 1925 # Otherwise, subtypes may choose to override the |
| 1926 # method, but the optimisation would prevent the |
| 1927 # subtype method from being called. |
| 1928 if not self.parent_type.is_final_type: |
| 1929 return None |
| 1930 return entry |
| 1931 |
| 1932 def declare_cfunction(self, name, type, pos, |
| 1933 cname = None, visibility = 'private', api = 0, in_pxd
= 0, |
| 1934 defining = 0, modifiers = (), utility_code = None): |
| 1935 if get_special_method_signature(name) and not self.parent_type.is_builti
n_type: |
| 1936 error(pos, "Special methods must be declared with 'def', not 'cdef'"
) |
| 1937 args = type.args |
| 1938 if not args: |
| 1939 error(pos, "C method has no self argument") |
| 1940 elif not self.parent_type.assignable_from(args[0].type): |
| 1941 error(pos, "Self argument (%s) of C method '%s' does not match paren
t type (%s)" % |
| 1942 (args[0].type, name, self.parent_type)) |
| 1943 entry = self.lookup_here(name) |
| 1944 if cname is None: |
| 1945 cname = c_safe_identifier(name) |
| 1946 if entry: |
| 1947 if not entry.is_cfunction: |
| 1948 warning(pos, "'%s' redeclared " % name, 0) |
| 1949 else: |
| 1950 if defining and entry.func_cname: |
| 1951 error(pos, "'%s' already defined" % name) |
| 1952 #print "CClassScope.declare_cfunction: checking signature" ### |
| 1953 if entry.is_final_cmethod and entry.is_inherited: |
| 1954 error(pos, "Overriding final methods is not allowed") |
| 1955 elif type.same_c_signature_as(entry.type, as_cmethod = 1) and ty
pe.nogil == entry.type.nogil: |
| 1956 pass |
| 1957 elif type.compatible_signature_with(entry.type, as_cmethod = 1)
and type.nogil == entry.type.nogil: |
| 1958 entry = self.add_cfunction(name, type, pos, cname, visibilit
y='ignore', modifiers=modifiers) |
| 1959 defining = 1 |
| 1960 else: |
| 1961 error(pos, "Signature not compatible with previous declarati
on") |
| 1962 error(entry.pos, "Previous declaration is here") |
| 1963 else: |
| 1964 if self.defined: |
| 1965 error(pos, |
| 1966 "C method '%s' not previously declared in definition part of
" |
| 1967 " extension type" % name) |
| 1968 entry = self.add_cfunction(name, type, pos, cname, |
| 1969 visibility, modifiers) |
| 1970 if defining: |
| 1971 entry.func_cname = self.mangle(Naming.func_prefix, name) |
| 1972 entry.utility_code = utility_code |
| 1973 type.entry = entry |
| 1974 |
| 1975 if u'inline' in modifiers: |
| 1976 entry.is_inline_cmethod = True |
| 1977 |
| 1978 if (self.parent_type.is_final_type or entry.is_inline_cmethod or |
| 1979 self.directives.get('final')): |
| 1980 entry.is_final_cmethod = True |
| 1981 entry.final_func_cname = entry.func_cname |
| 1982 |
| 1983 return entry |
| 1984 |
| 1985 def add_cfunction(self, name, type, pos, cname, visibility, modifiers): |
| 1986 # Add a cfunction entry without giving it a func_cname. |
| 1987 prev_entry = self.lookup_here(name) |
| 1988 entry = ClassScope.add_cfunction(self, name, type, pos, cname, |
| 1989 visibility, modifiers) |
| 1990 entry.is_cmethod = 1 |
| 1991 entry.prev_entry = prev_entry |
| 1992 return entry |
| 1993 |
| 1994 def declare_builtin_cfunction(self, name, type, cname, utility_code = None): |
| 1995 # overridden methods of builtin types still have their Python |
| 1996 # equivalent that must be accessible to support bound methods |
| 1997 name = EncodedString(name) |
| 1998 entry = self.declare_cfunction(name, type, None, cname, visibility='exte
rn', |
| 1999 utility_code = utility_code) |
| 2000 var_entry = Entry(name, name, py_object_type) |
| 2001 var_entry.is_variable = 1 |
| 2002 var_entry.is_builtin = 1 |
| 2003 var_entry.utility_code = utility_code |
| 2004 entry.as_variable = var_entry |
| 2005 return entry |
| 2006 |
| 2007 def declare_property(self, name, doc, pos): |
| 2008 entry = self.lookup_here(name) |
| 2009 if entry is None: |
| 2010 entry = self.declare(name, name, py_object_type, pos, 'private') |
| 2011 entry.is_property = 1 |
| 2012 entry.doc = doc |
| 2013 entry.scope = PropertyScope(name, |
| 2014 outer_scope = self.global_scope(), parent_scope = self) |
| 2015 entry.scope.parent_type = self.parent_type |
| 2016 self.property_entries.append(entry) |
| 2017 return entry |
| 2018 |
| 2019 def declare_inherited_c_attributes(self, base_scope): |
| 2020 # Declare entries for all the C attributes of an |
| 2021 # inherited type, with cnames modified appropriately |
| 2022 # to work with this type. |
| 2023 def adapt(cname): |
| 2024 return "%s.%s" % (Naming.obj_base_cname, base_entry.cname) |
| 2025 |
| 2026 entries = base_scope.inherited_var_entries + base_scope.var_entries |
| 2027 for base_entry in entries: |
| 2028 entry = self.declare( |
| 2029 base_entry.name, adapt(base_entry.cname), |
| 2030 base_entry.type, None, 'private') |
| 2031 entry.is_variable = 1 |
| 2032 self.inherited_var_entries.append(entry) |
| 2033 |
| 2034 # If the class defined in a pxd, specific entries have not been added. |
| 2035 # Ensure now that the parent (base) scope has specific entries |
| 2036 # Iterate over a copy as get_all_specialized_function_types() will mutat
e |
| 2037 for base_entry in base_scope.cfunc_entries[:]: |
| 2038 if base_entry.type.is_fused: |
| 2039 base_entry.type.get_all_specialized_function_types() |
| 2040 |
| 2041 for base_entry in base_scope.cfunc_entries: |
| 2042 cname = base_entry.cname |
| 2043 var_entry = base_entry.as_variable |
| 2044 is_builtin = var_entry and var_entry.is_builtin |
| 2045 if not is_builtin: |
| 2046 cname = adapt(cname) |
| 2047 entry = self.add_cfunction(base_entry.name, base_entry.type, |
| 2048 base_entry.pos, cname, |
| 2049 base_entry.visibility, base_entry.func_mo
difiers) |
| 2050 entry.is_inherited = 1 |
| 2051 if base_entry.is_final_cmethod: |
| 2052 entry.is_final_cmethod = True |
| 2053 entry.is_inline_cmethod = base_entry.is_inline_cmethod |
| 2054 if (self.parent_scope == base_scope.parent_scope or |
| 2055 entry.is_inline_cmethod): |
| 2056 entry.final_func_cname = base_entry.final_func_cname |
| 2057 if is_builtin: |
| 2058 entry.is_builtin_cmethod = True |
| 2059 entry.as_variable = var_entry |
| 2060 if base_entry.utility_code: |
| 2061 entry.utility_code = base_entry.utility_code |
| 2062 |
| 2063 |
| 2064 class CppClassScope(Scope): |
| 2065 # Namespace of a C++ class. |
| 2066 |
| 2067 is_cpp_class_scope = 1 |
| 2068 |
| 2069 default_constructor = None |
| 2070 type = None |
| 2071 |
| 2072 def __init__(self, name, outer_scope, templates=None): |
| 2073 Scope.__init__(self, name, outer_scope, None) |
| 2074 self.directives = outer_scope.directives |
| 2075 self.inherited_var_entries = [] |
| 2076 if templates is not None: |
| 2077 for T in templates: |
| 2078 template_entry = self.declare( |
| 2079 T, T, PyrexTypes.TemplatePlaceholderType(T), None, 'extern') |
| 2080 template_entry.is_type = 1 |
| 2081 |
| 2082 def declare_var(self, name, type, pos, |
| 2083 cname = None, visibility = 'extern', |
| 2084 api = 0, in_pxd = 0, is_cdef = 0, |
| 2085 allow_pyobject = 0, defining = 0): |
| 2086 # Add an entry for an attribute. |
| 2087 if not cname: |
| 2088 cname = name |
| 2089 entry = self.lookup_here(name) |
| 2090 if defining and entry is not None: |
| 2091 if not entry.type.same_as(type): |
| 2092 error(pos, "Function signature does not match previous declarati
on") |
| 2093 else: |
| 2094 entry = self.declare(name, cname, type, pos, visibility) |
| 2095 entry.is_variable = 1 |
| 2096 if type.is_cfunction and self.type: |
| 2097 entry.func_cname = "%s::%s" % (self.type.declaration_code(""), cname
) |
| 2098 if name != "this" and (defining or name != "<init>"): |
| 2099 self.var_entries.append(entry) |
| 2100 if type.is_pyobject and not allow_pyobject: |
| 2101 error(pos, |
| 2102 "C++ class member cannot be a Python object") |
| 2103 return entry |
| 2104 |
| 2105 def check_base_default_constructor(self, pos): |
| 2106 # Look for default constructors in all base classes. |
| 2107 if self.default_constructor is None: |
| 2108 entry = self.lookup(self.name) |
| 2109 if not entry.type.base_classes: |
| 2110 self.default_constructor = True |
| 2111 return |
| 2112 for base_class in entry.type.base_classes: |
| 2113 if base_class is PyrexTypes.error_type: |
| 2114 continue |
| 2115 temp_entry = base_class.scope.lookup_here("<init>") |
| 2116 found = False |
| 2117 if temp_entry is None: |
| 2118 continue |
| 2119 for alternative in temp_entry.all_alternatives(): |
| 2120 type = alternative.type |
| 2121 if type.is_ptr: |
| 2122 type = type.base_type |
| 2123 if not type.args: |
| 2124 found = True |
| 2125 break |
| 2126 if not found: |
| 2127 self.default_constructor = temp_entry.scope.name |
| 2128 error(pos, "no matching function for call to " \ |
| 2129 "%s::%s()" % (temp_entry.scope.name, temp_entry.scop
e.name)) |
| 2130 elif not self.default_constructor: |
| 2131 error(pos, "no matching function for call to %s::%s()" % |
| 2132 (self.default_constructor, self.default_constructor)) |
| 2133 |
| 2134 def declare_cfunction(self, name, type, pos, |
| 2135 cname = None, visibility = 'extern', api = 0, in_pxd =
0, |
| 2136 defining = 0, modifiers = (), utility_code = None): |
| 2137 if name in (self.name.split('::')[-1], '__init__') and cname is None: |
| 2138 self.check_base_default_constructor(pos) |
| 2139 cname = self.type.cname |
| 2140 name = '<init>' |
| 2141 type.return_type = PyrexTypes.InvisibleVoidType() |
| 2142 elif name == '__dealloc__' and cname is None: |
| 2143 cname = "~%s" % self.type.cname |
| 2144 name = '<del>' |
| 2145 type.return_type = PyrexTypes.InvisibleVoidType() |
| 2146 prev_entry = self.lookup_here(name) |
| 2147 entry = self.declare_var(name, type, pos, |
| 2148 defining=defining, |
| 2149 cname=cname, visibility=visibility) |
| 2150 if prev_entry and not defining: |
| 2151 entry.overloaded_alternatives = prev_entry.all_alternatives() |
| 2152 entry.utility_code = utility_code |
| 2153 type.entry = entry |
| 2154 return entry |
| 2155 |
| 2156 def declare_inherited_cpp_attributes(self, base_scope): |
| 2157 # Declare entries for all the C++ attributes of an |
| 2158 # inherited type, with cnames modified appropriately |
| 2159 # to work with this type. |
| 2160 for base_entry in \ |
| 2161 base_scope.inherited_var_entries + base_scope.var_entries: |
| 2162 #contructor is not inherited |
| 2163 if base_entry.name == "<init>": |
| 2164 continue |
| 2165 #print base_entry.name, self.entries |
| 2166 if base_entry.name in self.entries: |
| 2167 base_entry.name # FIXME: is there anything to do in this
case? |
| 2168 entry = self.declare(base_entry.name, base_entry.cname, |
| 2169 base_entry.type, None, 'extern') |
| 2170 entry.is_variable = 1 |
| 2171 self.inherited_var_entries.append(entry) |
| 2172 for base_entry in base_scope.cfunc_entries: |
| 2173 entry = self.declare_cfunction(base_entry.name, base_entry.type, |
| 2174 base_entry.pos, base_entry.cname, |
| 2175 base_entry.visibility, 0, |
| 2176 modifiers = base_entry.func_modifiers
, |
| 2177 utility_code = base_entry.utility_cod
e) |
| 2178 entry.is_inherited = 1 |
| 2179 |
| 2180 def specialize(self, values): |
| 2181 scope = CppClassScope(self.name, self.outer_scope) |
| 2182 for entry in self.entries.values(): |
| 2183 if entry.is_type: |
| 2184 scope.declare_type(entry.name, |
| 2185 entry.type.specialize(values), |
| 2186 entry.pos, |
| 2187 entry.cname, |
| 2188 template=1) |
| 2189 elif entry.type.is_cfunction: |
| 2190 for e in entry.all_alternatives(): |
| 2191 scope.declare_cfunction(e.name, |
| 2192 e.type.specialize(values), |
| 2193 e.pos, |
| 2194 e.cname, |
| 2195 utility_code = e.utility_code) |
| 2196 else: |
| 2197 scope.declare_var(entry.name, |
| 2198 entry.type.specialize(values), |
| 2199 entry.pos, |
| 2200 entry.cname, |
| 2201 entry.visibility) |
| 2202 |
| 2203 return scope |
| 2204 |
| 2205 |
| 2206 class PropertyScope(Scope): |
| 2207 # Scope holding the __get__, __set__ and __del__ methods for |
| 2208 # a property of an extension type. |
| 2209 # |
| 2210 # parent_type PyExtensionType The type to which the property belongs |
| 2211 |
| 2212 is_property_scope = 1 |
| 2213 |
| 2214 def declare_pyfunction(self, name, pos, allow_redefine=False): |
| 2215 # Add an entry for a method. |
| 2216 signature = get_property_accessor_signature(name) |
| 2217 if signature: |
| 2218 entry = self.declare(name, name, py_object_type, pos, 'private') |
| 2219 entry.is_special = 1 |
| 2220 entry.signature = signature |
| 2221 return entry |
| 2222 else: |
| 2223 error(pos, "Only __get__, __set__ and __del__ methods allowed " |
| 2224 "in a property declaration") |
| 2225 return None |
| 2226 |
| 2227 |
| 2228 class CConstScope(Scope): |
| 2229 |
| 2230 def __init__(self, const_base_type_scope): |
| 2231 Scope.__init__( |
| 2232 self, |
| 2233 'const_' + const_base_type_scope.name, |
| 2234 const_base_type_scope.outer_scope, |
| 2235 const_base_type_scope.parent_scope) |
| 2236 self.const_base_type_scope = const_base_type_scope |
| 2237 |
| 2238 def lookup_here(self, name): |
| 2239 entry = self.const_base_type_scope.lookup_here(name) |
| 2240 if entry is not None: |
| 2241 entry = copy.copy(entry) |
| 2242 entry.type = PyrexTypes.c_const_type(entry.type) |
| 2243 return entry |
| 2244 |
| 2245 class TemplateScope(Scope): |
| 2246 def __init__(self, name, outer_scope): |
| 2247 Scope.__init__(self, name, outer_scope, None) |
| 2248 self.directives = outer_scope.directives |
OLD | NEW |