Code.py 55.6 KB
Newer Older
1
# cython: language_level = 3, py2_import=True
William Stein's avatar
William Stein committed
2 3 4 5
#
#   Pyrex - Code output module
#

Stefan Behnel's avatar
Stefan Behnel committed
6 7 8
import cython
cython.declare(re=object, Naming=object, Options=object, StringEncoding=object,
               Utils=object, SourceDescriptor=object, StringIOTree=object,
Stefan Behnel's avatar
Stefan Behnel committed
9
               DebugFlags=object, none_or_sub=object, basestring=object)
Stefan Behnel's avatar
Stefan Behnel committed
10

11
import re
William Stein's avatar
William Stein committed
12
import Naming
Robert Bradshaw's avatar
Robert Bradshaw committed
13
import Options
14 15
import StringEncoding
from Cython import Utils
16
from Scanning import SourceDescriptor
17
from Cython.StringIOTree import StringIOTree
18
import DebugFlags
19

20
from Cython.Utils import none_or_sub
Stefan Behnel's avatar
Stefan Behnel committed
21
try:
Stefan Behnel's avatar
Stefan Behnel committed
22 23 24
    from __builtin__ import basestring
except ImportError:
    from builtins import str as basestring
25

26 27

non_portable_builtins_map = {
28
    # builtins that have different names in different Python versions
29 30 31 32 33 34
    'bytes'         : ('PY_MAJOR_VERSION < 3',  'str'),
    'unicode'       : ('PY_MAJOR_VERSION >= 3', 'str'),
    'xrange'        : ('PY_MAJOR_VERSION >= 3', 'range'),
    'BaseException' : ('PY_VERSION_HEX < 0x02050000', 'Exception'),
    }

35 36 37 38 39 40
uncachable_builtins = [
    # builtin names that cannot be cached because they may or may not
    # be available at import time
    'WindowsError',
    ]

41
class UtilityCode(object):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
42 43 44 45 46
    # Stores utility code to add during code generation.
    #
    # See GlobalState.put_utility_code.
    #
    # hashes/equals by instance
47

48 49
    is_cython_utility = False

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
50 51 52
    def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None,
                 proto_block='utility_code_proto'):
        # proto_block: Which code block to dump prototype in. See GlobalState.
53 54 55 56 57 58 59
        self.proto = proto
        self.impl = impl
        self.init = init
        self.cleanup = cleanup
        self.requires = requires
        self._cache = {}
        self.specialize_list = []
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
60
        self.proto_block = proto_block
61

62 63 64
    def get_tree(self):
        pass
    
65 66 67 68
    def specialize(self, pyrex_type=None, **data):
        # Dicts aren't hashable...
        if pyrex_type is not None:
            data['type'] = pyrex_type.declaration_code('')
Craig Citro's avatar
Craig Citro committed
69
            data['type_name'] = pyrex_type.specialization_name()
70 71 72 73 74 75 76 77 78 79 80 81 82
        key = data.items(); key.sort(); key = tuple(key)
        try:
            return self._cache[key]
        except KeyError:
            if self.requires is None:
                requires = None
            else:
                requires = [r.specialize(data) for r in self.requires]
            s = self._cache[key] = UtilityCode(
                                        none_or_sub(self.proto, data),
                                        none_or_sub(self.impl, data),
                                        none_or_sub(self.init, data),
                                        none_or_sub(self.cleanup, data),
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
83
                                        requires, self.proto_block)
84 85 86
            self.specialize_list.append(s)
            return s

87 88 89 90 91
    def put_code(self, output):
        if self.requires:
            for dependency in self.requires:
                output.use_utility_code(dependency)
        if self.proto:
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
92
            output[self.proto_block].put(self.proto)
93 94
        if self.impl:
            output['utility_code_def'].put(self.impl)
95 96 97 98 99 100 101 102 103 104 105 106
        if self.init:
            writer = output['init_globals']
            if isinstance(self.init, basestring):
                writer.put(self.init)
            else:
                self.init(writer, output.module_pos)
        if self.cleanup and Options.generate_cleanup_code:
            writer = output['cleanup_globals']
            if isinstance(self.cleanup, basestring):
                writer.put(self.cleanup)
            else:
                self.cleanup(writer, output.module_pos)
107 108


109

110 111 112 113 114 115 116 117 118 119
class FunctionState(object):
    # return_label     string          function return point label
    # error_label      string          error catch point label
    # continue_label   string          loop continue point label
    # break_label      string          loop break point label
    # return_from_error_cleanup_label string
    # label_counter    integer         counter for naming labels
    # in_try_finally   boolean         inside try of try...finally
    # exc_vars         (string * 3)    exception variables for reraise, or None

120
    # Not used for now, perhaps later
Stefan Behnel's avatar
Stefan Behnel committed
121
    def __init__(self, owner, names_taken=cython.set()):
122
        self.names_taken = names_taken
123
        self.owner = owner
124

125 126
        self.error_label = None
        self.label_counter = 0
Stefan Behnel's avatar
Stefan Behnel committed
127
        self.labels_used = cython.set()
128 129 130 131 132
        self.return_label = self.new_label()
        self.new_error_label()
        self.continue_label = None
        self.break_label = None

133 134 135
        self.in_try_finally = 0
        self.exc_vars = None

136
        self.temps_allocated = [] # of (name, type, manage_ref)
137 138
        self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
        self.temps_used_type = {} # name -> (type, manage_ref)
139
        self.temp_counter = 0
140
        self.closure_temps = None
141

142 143 144 145
        # This is used to collect temporaries, useful to find out which temps
        # need to be privatized in parallel sections
        self.collect_temps_stack = []

146 147 148 149 150 151
        # This is used for the error indicator, which needs to be local to the
        # function. It used to be global, which relies on the GIL being held.
        # However, exceptions may need to be propagated through 'nogil'
        # sections, in which case we introduce a race condition.
        self.should_declare_error_indicator = False

152 153
    # labels

154
    def new_label(self, name=None):
155 156
        n = self.label_counter
        self.label_counter = n + 1
157 158 159 160
        label = "%s%d" % (Naming.label_prefix, n)
        if name is not None:
            label += '_' + name
        return label
161

162 163
    def new_error_label(self):
        old_err_lbl = self.error_label
164
        self.error_label = self.new_label('error')
165
        return old_err_lbl
166

167 168 169 170
    def get_loop_labels(self):
        return (
            self.continue_label,
            self.break_label)
171

172 173 174
    def set_loop_labels(self, labels):
        (self.continue_label,
         self.break_label) = labels
175

176 177 178
    def new_loop_labels(self):
        old_labels = self.get_loop_labels()
        self.set_loop_labels(
179
            (self.new_label("continue"),
Robert Bradshaw's avatar
Robert Bradshaw committed
180
             self.new_label("break")))
181
        return old_labels
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
    def get_all_labels(self):
        return (
            self.continue_label,
            self.break_label,
            self.return_label,
            self.error_label)

    def set_all_labels(self, labels):
        (self.continue_label,
         self.break_label,
         self.return_label,
         self.error_label) = labels

    def all_new_labels(self):
        old_labels = self.get_all_labels()
        new_labels = []
        for old_label in old_labels:
            if old_label:
                new_labels.append(self.new_label())
            else:
                new_labels.append(old_label)
        self.set_all_labels(new_labels)
        return old_labels
206

207
    def use_label(self, lbl):
Stefan Behnel's avatar
Stefan Behnel committed
208
        self.labels_used.add(lbl)
209

210 211 212
    def label_used(self, lbl):
        return lbl in self.labels_used

213 214
    # temp handling

215
    def allocate_temp(self, type, manage_ref):
216 217 218 219 220
        """
        Allocates a temporary (which may create a new one or get a previously
        allocated and released one of the same type). Type is simply registered
        and handed back, but will usually be a PyrexType.

221 222 223 224 225
        If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
        True, the temp will be decref-ed on return statements and in exception
        handling clauses. Otherwise the caller has to deal with any reference
        counting of the variable.

226 227 228 229
        If not type.is_pyobject, then manage_ref will be ignored, but it
        still has to be passed. It is recommended to pass False by convention
        if it is known that type will never be a Python object.

230 231
        A C string referring to the variable is returned.
        """
232 233 234 235
        if not type.is_pyobject:
            # Make manage_ref canonical, so that manage_ref will always mean
            # a decref is needed.
            manage_ref = False
236
        freelist = self.temps_free.get((type, manage_ref))
237
        if freelist is not None and len(freelist) > 0:
238
            result = freelist.pop()
239
        else:
240 241 242 243
            while True:
                self.temp_counter += 1
                result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
                if not result in self.names_taken: break
244
            self.temps_allocated.append((result, type, manage_ref))
245
        self.temps_used_type[result] = (type, manage_ref)
246 247
        if DebugFlags.debug_temp_code_comments:
            self.owner.putln("/* %s allocated */" % result)
248 249 250 251

        if self.collect_temps_stack:
            self.collect_temps_stack[-1].add((result, type))

252 253 254 255 256 257 258
        return result

    def release_temp(self, name):
        """
        Releases a temporary so that it can be reused by other code needing
        a temp of the same type.
        """
259 260
        type, manage_ref = self.temps_used_type[name]
        freelist = self.temps_free.get((type, manage_ref))
261 262
        if freelist is None:
            freelist = []
263
            self.temps_free[(type, manage_ref)] = freelist
264 265
        if name in freelist:
            raise RuntimeError("Temp %s freed twice!" % name)
266
        freelist.append(name)
267 268
        if DebugFlags.debug_temp_code_comments:
            self.owner.putln("/* %s released */" % name)
269

270
    def temps_in_use(self):
271
        """Return a list of (cname,type,manage_ref) tuples of temp names and their type
272 273 274
        that are currently in use.
        """
        used = []
275
        for name, type, manage_ref in self.temps_allocated:
276
            freelist = self.temps_free.get((type, manage_ref))
277
            if freelist is None or name not in freelist:
278
                used.append((name, type, manage_ref))
279 280
        return used

281
    def temps_holding_reference(self):
282
        """Return a list of (cname,type) tuples of temp names and their type
283 284
        that are currently in use. This includes only temps of a
        Python object type which owns its reference.
285 286
        """
        return [(name, type)
287
                for name, type, manage_ref in self.temps_in_use()
288 289 290 291 292 293 294 295
                if manage_ref]

    def all_managed_temps(self):
        """Return a list of (cname, type) tuples of refcount-managed Python objects.
        """
        return [(cname, type)
                for cname, type, manage_ref in self.temps_allocated
                if manage_ref]
296

297 298 299 300 301 302 303
    def all_free_managed_temps(self):
        """Return a list of (cname, type) tuples of refcount-managed Python
        objects that are not currently in use.  This is used by
        try-except and try-finally blocks to clean up temps in the
        error case.
        """
        return [(cname, type)
Stefan Behnel's avatar
Stefan Behnel committed
304
                for (type, manage_ref), freelist in self.temps_free.items()
305 306 307
                if manage_ref
                for cname in freelist]

308 309 310 311 312 313 314 315 316
    def start_collecting_temps(self):
        """
        Useful to find out which temps were used in a code block
        """
        self.collect_temps_stack.append(cython.set())

    def stop_collecting_temps(self):
        return self.collect_temps_stack.pop()

317 318 319
    def init_closure_temps(self, scope):
        self.closure_temps = ClosureTempAllocator(scope)

320 321 322 323 324 325 326 327 328 329 330 331 332

class IntConst(object):
    """Global info about a Python integer constant held by GlobalState.
    """
    # cname     string
    # value     int
    # is_long   boolean

    def __init__(self, cname, value, is_long):
        self.cname = cname
        self.value = value
        self.is_long = is_long

333 334 335 336 337 338 339 340 341 342
class PyObjectConst(object):
    """Global info about a generic constant held by GlobalState.
    """
    # cname       string
    # type        PyrexType

    def __init__(self, cname, type):
        self.cname = cname
        self.type = type

343 344
cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
               nice_identifier=object, find_alphanums=object)
Stefan Behnel's avatar
Stefan Behnel committed
345 346
possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
347
nice_identifier = re.compile(r'\A[a-zA-Z0-9_]+\Z').match
348
find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
349 350 351 352 353 354 355 356 357 358 359 360 361

class StringConst(object):
    """Global info about a C string constant held by GlobalState.
    """
    # cname            string
    # text             EncodedString or BytesLiteral
    # py_strings       {(identifier, encoding) : PyStringConst}

    def __init__(self, cname, text, byte_string):
        self.cname = cname
        self.text = text
        self.escaped_value = StringEncoding.escape_byte_string(byte_string)
        self.py_strings = None
362 363 364
        self.py_versions = []

    def add_py_version(self, version):
365 366 367
        if not version:
            self.py_versions = [2,3]
        elif version not in self.py_versions:
368
            self.py_versions.append(version)
369

370 371
    def get_py_string_const(self, encoding, identifier=None,
                            is_str=False, py3str_cstring=None):
372 373 374
        py_strings = self.py_strings
        text = self.text

Stefan Behnel's avatar
Stefan Behnel committed
375
        is_str = bool(identifier or is_str)
376
        is_unicode = encoding is None and not is_str
377

378 379 380 381 382 383 384 385 386 387 388 389
        if encoding is None:
            # unicode string
            encoding_key = None
        else:
            # bytes or str
            encoding = encoding.lower()
            if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
                encoding = None
                encoding_key = None
            else:
                encoding_key = ''.join(find_alphanums(encoding))

390 391 392 393 394 395
        key = (is_str, is_unicode, encoding_key, py3str_cstring)
        if py_strings is not None:
            try:
                return py_strings[key]
            except KeyError:
                pass
396
        else:
397
            self.py_strings = {}
398

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
        if identifier:
            intern = True
        elif identifier is None:
            if isinstance(text, unicode):
                intern = bool(possible_unicode_identifier(text))
            else:
                intern = bool(possible_bytes_identifier(text))
        else:
            intern = False
        if intern:
            prefix = Naming.interned_str_prefix
        else:
            prefix = Naming.py_const_prefix
        pystring_cname = "%s%s_%s" % (
            prefix,
            (is_str and 's') or (is_unicode and 'u') or 'b',
            self.cname[len(Naming.const_prefix):])

        py_string = PyStringConst(
            pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
        self.py_strings[key] = py_string
420 421 422 423 424 425
        return py_string

class PyStringConst(object):
    """Global info about a Python string constant held by GlobalState.
    """
    # cname       string
426
    # py3str_cstring string
427
    # encoding    string
428
    # intern      boolean
429 430
    # is_unicode  boolean
    # is_str      boolean
431

432 433
    def __init__(self, cname, encoding, is_unicode, is_str=False,
                 py3str_cstring=None, intern=False):
434
        self.cname = cname
435
        self.py3str_cstring = py3str_cstring
436 437 438
        self.encoding = encoding
        self.is_str = is_str
        self.is_unicode = is_unicode
439 440
        self.intern = intern

Stefan Behnel's avatar
Stefan Behnel committed
441 442 443
    def __lt__(self, other):
        return self.cname < other.cname

444

445 446 447 448 449 450
class GlobalState(object):
    # filename_table   {string : int}  for finding filename table indexes
    # filename_list    [string]        filenames in filename table order
    # input_file_contents dict         contents (=list of lines) of any file that was used as input
    #                                  to create this output C code.  This is
    #                                  used to annotate the comments.
451
    #
452
    # utility_codes   set                IDs of used utility code (to avoid reinsertion)
453 454 455 456 457 458
    #
    # declared_cnames  {string:Entry}  used in a transition phase to merge pxd-declared
    #                                  constants etc. into the pyx-declared ones (i.e,
    #                                  check if constants are already added).
    #                                  In time, hopefully the literals etc. will be
    #                                  supplied directly instead.
459 460 461
    #
    # const_cname_counter int          global counter for constant identifiers
    #
462

463 464
    # parts            {string:CCodeWriter}

465

466 467 468 469
    # interned_strings
    # consts
    # interned_nums

470 471 472 473 474 475
    # directives       set             Temporary variable used to track
    #                                  the current set of directives in the code generation
    #                                  process.

    directives = {}

476 477
    code_layout = [
        'h_code',
Robert Bradshaw's avatar
Robert Bradshaw committed
478
        'filename_table',
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
479
        'utility_code_proto_before_types',
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
480 481 482 483
        'numeric_typedefs',          # Let these detailed individual parts stay!,
        'complex_type_declarations', # as the proper solution is to make a full DAG...
        'type_declarations',         # More coarse-grained blocks would simply hide
        'utility_code_proto',        # the ugliness, not fix it
484 485
        'module_declarations',
        'typeinfo',
486 487
        'before_global_var',
        'global_var',
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
488
        'decls',
489
        'all_the_rest',
490 491
        'pystring_table',
        'cached_builtins',
492
        'cached_constants',
493 494 495 496 497
        'init_globals',
        'init_module',
        'cleanup_globals',
        'cleanup_module',
        'main_method',
498 499
        'utility_code_def',
        'end'
500
    ]
501

502 503

    def __init__(self, writer, emit_linenums=False):
504 505 506
        self.filename_table = {}
        self.filename_list = []
        self.input_file_contents = {}
Stefan Behnel's avatar
Stefan Behnel committed
507
        self.utility_codes = cython.set()
508
        self.declared_cnames = {}
509
        self.in_utility_code_generation = False
510
        self.emit_linenums = emit_linenums
511
        self.parts = {}
512

513 514 515
        self.const_cname_counter = 1
        self.string_const_index = {}
        self.int_const_index = {}
516
        self.py_constants = []
517

518 519
        assert writer.globalstate is None
        writer.globalstate = self
520
        self.rootwriter = writer
521

522 523 524 525
    def initialize_main_c_code(self):
        rootwriter = self.rootwriter
        for part in self.code_layout:
            self.parts[part] = rootwriter.insertion_point()
526

527 528 529 530 531 532
        if not Options.cache_builtins:
            del self.parts['cached_builtins']
        else:
            w = self.parts['cached_builtins']
            w.enter_cfunc_scope()
            w.putln("static int __Pyx_InitCachedBuiltins(void) {")
533

534 535 536 537
        w = self.parts['cached_constants']
        w.enter_cfunc_scope()
        w.putln("")
        w.putln("static int __Pyx_InitCachedConstants(void) {")
538
        w.put_declare_refcount_context()
539 540
        w.put_setup_refcount_context("__Pyx_InitCachedConstants")

541 542 543 544
        w = self.parts['init_globals']
        w.enter_cfunc_scope()
        w.putln("")
        w.putln("static int __Pyx_InitGlobals(void) {")
545

546 547 548 549 550 551 552
        if not Options.generate_cleanup_code:
            del self.parts['cleanup_globals']
        else:
            w = self.parts['cleanup_globals']
            w.enter_cfunc_scope()
            w.putln("")
            w.putln("static void __Pyx_CleanupGlobals(void) {")
553

554 555 556 557 558 559 560 561 562
        #
        # utility_code_def
        #
        code = self.parts['utility_code_def']
        if self.emit_linenums:
            code.write('\n#line 1 "cython_utility"\n')
        code.putln("")
        code.putln("/* Runtime support code */")

563
    def finalize_main_c_code(self):
564 565 566 567 568 569
        self.close_global_decls()

        #
        # utility_code_def
        #
        code = self.parts['utility_code_def']
570
        import PyrexTypes
571 572 573
        code.put(PyrexTypes.type_conversion_functions)
        code.putln("")

574 575 576
    def __getitem__(self, key):
        return self.parts[key]

577 578 579
    #
    # Global constants, interned objects, etc.
    #
580 581
    def close_global_decls(self):
        # This is called when it is known that no more global declarations will
582
        # declared.
583
        self.generate_const_declarations()
584
        if Options.cache_builtins:
585
            w = self.parts['cached_builtins']
586
            w.putln("return 0;")
587 588 589
            if w.label_used(w.error_label):
                w.put_label(w.error_label)
                w.putln("return -1;")
590 591 592
            w.putln("}")
            w.exit_cfunc_scope()

593 594 595 596 597 598 599 600 601 602
        w = self.parts['cached_constants']
        w.put_finish_refcount_context()
        w.putln("return 0;")
        if w.label_used(w.error_label):
            w.put_label(w.error_label)
            w.put_finish_refcount_context()
            w.putln("return -1;")
        w.putln("}")
        w.exit_cfunc_scope()

603
        w = self.parts['init_globals']
604
        w.putln("return 0;")
605 606 607
        if w.label_used(w.error_label):
            w.put_label(w.error_label)
            w.putln("return -1;")
608 609
        w.putln("}")
        w.exit_cfunc_scope()
610

611 612 613 614 615
        if Options.generate_cleanup_code:
            w = self.parts['cleanup_globals']
            w.putln("}")
            w.exit_cfunc_scope()

616 617 618 619
        if Options.generate_cleanup_code:
            w = self.parts['cleanup_module']
            w.putln("}")
            w.exit_cfunc_scope()
620

621
    def put_pyobject_decl(self, entry):
622
        self['global_var'].putln("static PyObject *%s;" % entry.cname)
623

624 625
    # constant handling at code generation time

626 627 628
    def get_cached_constants_writer(self):
        return self.parts['cached_constants']

629
    def get_int_const(self, str_value, longness=False):
630
        longness = bool(longness)
631 632 633 634 635 636
        try:
            c = self.int_const_index[(str_value, longness)]
        except KeyError:
            c = self.new_int_const(str_value, longness)
        return c

637
    def get_py_const(self, type, prefix='', cleanup_level=None):
638
        # create a new Python object constant
639 640
        const = self.new_py_const(type, prefix)
        if cleanup_level is not None \
641
               and cleanup_level <= Options.generate_cleanup_code:
642 643 644
            cleanup_writer = self.parts['cleanup_globals']
            cleanup_writer.put_xdecref_clear(const.cname, type, nanny=False)
        return const
645

646
    def get_string_const(self, text, py_version=None):
647 648 649 650 651 652 653 654 655
        # return a C string constant, creating a new one if necessary
        if text.is_unicode:
            byte_string = text.utf8encode()
        else:
            byte_string = text.byteencode()
        try:
            c = self.string_const_index[byte_string]
        except KeyError:
            c = self.new_string_const(text, byte_string)
656
        c.add_py_version(py_version)
657 658
        return c

659 660
    def get_py_string_const(self, text, identifier=None,
                            is_str=False, unicode_value=None):
661
        # return a Python string constant, creating a new one if necessary
662 663 664
        py3str_cstring = None
        if is_str and unicode_value is not None \
               and unicode_value.utf8encode() != text.byteencode():
665 666 667 668
            py3str_cstring = self.get_string_const(unicode_value, py_version=3)
            c_string = self.get_string_const(text, py_version=2)
        else:
            c_string = self.get_string_const(text)
669 670
        py_string = c_string.get_py_string_const(
            text.encoding, identifier, is_str, py3str_cstring)
671 672
        return py_string

673 674 675
    def get_interned_identifier(self, text):
        return self.get_py_string_const(text, identifier=True)

676
    def new_string_const(self, text, byte_string):
Stefan Behnel's avatar
Stefan Behnel committed
677
        cname = self.new_string_const_cname(byte_string)
678 679 680 681 682 683 684 685 686 687
        c = StringConst(cname, text, byte_string)
        self.string_const_index[byte_string] = c
        return c

    def new_int_const(self, value, longness):
        cname = self.new_int_const_cname(value, longness)
        c = IntConst(cname, value, longness)
        self.int_const_index[(value, longness)] = c
        return c

688 689
    def new_py_const(self, type, prefix=''):
        cname = self.new_const_cname(prefix)
690 691 692 693
        c = PyObjectConst(cname, type)
        self.py_constants.append(c)
        return c

Stefan Behnel's avatar
Stefan Behnel committed
694
    def new_string_const_cname(self, bytes_value, intern=None):
695
        # Create a new globally-unique nice name for a C string constant.
Stefan Behnel's avatar
Stefan Behnel committed
696 697 698 699 700
        try:
            value = bytes_value.decode('ASCII')
        except UnicodeError:
            return self.new_const_cname()

701
        if len(value) < 20 and nice_identifier(value):
702
            return "%s_%s" % (Naming.const_prefix, value)
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
        else:
            return self.new_const_cname()

    def new_int_const_cname(self, value, longness):
        if longness:
            value += 'L'
        cname = "%s%s" % (Naming.interned_num_prefix, value)
        cname = cname.replace('-', 'neg_').replace('.','_')
        return cname

    def new_const_cname(self, prefix=''):
        n = self.const_cname_counter
        self.const_cname_counter += 1
        return "%s%s%d" % (Naming.const_prefix, prefix, n)

    def add_cached_builtin_decl(self, entry):
719
        if entry.is_builtin and entry.is_const:
720 721
            if self.should_declare(entry.cname, entry):
                self.put_pyobject_decl(entry)
722
                w = self.parts['cached_builtins']
723 724 725 726
                condition = None
                if entry.name in non_portable_builtins_map:
                    condition, replacement = non_portable_builtins_map[entry.name]
                    w.putln('#if %s' % condition)
727
                    self.put_cached_builtin_init(
728
                        entry.pos, StringEncoding.EncodedString(replacement),
729
                        entry.cname)
730 731 732 733
                    w.putln('#else')
                self.put_cached_builtin_init(
                    entry.pos, StringEncoding.EncodedString(entry.name),
                    entry.cname)
734
                if condition:
735 736 737 738 739
                    w.putln('#endif')

    def put_cached_builtin_init(self, pos, name, cname):
        w = self.parts['cached_builtins']
        interned_cname = self.get_interned_identifier(name).cname
740 741
        from ExprNodes import get_name_interned_utility_code
        self.use_utility_code(get_name_interned_utility_code)
742 743 744 745 746 747
        w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
            cname,
            Naming.builtins_cname,
            interned_cname,
            cname,
            w.error_goto(pos)))
748 749 750 751

    def generate_const_declarations(self):
        self.generate_string_constants()
        self.generate_int_constants()
752 753 754 755 756 757
        self.generate_object_constant_decls()

    def generate_object_constant_decls(self):
        consts = [ (len(c.cname), c.cname, c)
                   for c in self.py_constants ]
        consts.sort()
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
758
        decls_writer = self.parts['decls']
759
        for _, cname, c in consts:
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
760
            decls_writer.putln(
761
                "static %s;" % c.type.declaration_code(cname))
762 763 764

    def generate_string_constants(self):
        c_consts = [ (len(c.cname), c.cname, c)
Stefan Behnel's avatar
Stefan Behnel committed
765
                     for c in self.string_const_index.values() ]
766 767
        c_consts.sort()
        py_strings = []
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
768 769

        decls_writer = self.parts['decls']
770
        for _, cname, c in c_consts:
771 772 773 774 775
            conditional = False
            if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
                conditional = True
                decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % (
                    (2 in c.py_versions) and '<' or '>='))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
776
            decls_writer.putln('static char %s[] = "%s";' % (
777
                cname, StringEncoding.split_string_literal(c.escaped_value)))
778 779
            if conditional:
                decls_writer.putln("#endif")
780
            if c.py_strings is not None:
Stefan Behnel's avatar
Stefan Behnel committed
781
                for py_string in c.py_strings.values():
782 783 784 785 786 787 788
                    py_strings.append((c.cname, len(py_string.cname), py_string))

        if py_strings:
            import Nodes
            self.use_utility_code(Nodes.init_string_tab_utility_code)

            py_strings.sort()
789 790 791
            w = self.parts['pystring_table']
            w.putln("")
            w.putln("static __Pyx_StringTabEntry %s[] = {" %
792 793
                                      Naming.stringtab_cname)
            for c_cname, _, py_string in py_strings:
794 795 796 797 798 799 800
                if not py_string.is_str or not py_string.encoding or \
                       py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
                                              'UTF8', 'UTF-8'):
                    encoding = '0'
                else:
                    encoding = '"%s"' % py_string.encoding.lower()

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
801
                decls_writer.putln(
802
                    "static PyObject *%s;" % py_string.cname)
803 804 805 806 807 808 809
                if py_string.py3str_cstring:
                    w.putln("#if PY_MAJOR_VERSION >= 3")
                    w.putln(
                        "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
                        py_string.cname,
                        py_string.py3str_cstring.cname,
                        py_string.py3str_cstring.cname,
810 811
                        '0', 1, 0,
                        py_string.intern
812 813
                        ))
                    w.putln("#else")
814
                w.putln(
815
                    "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
816 817 818
                    py_string.cname,
                    c_cname,
                    c_cname,
819 820 821 822
                    encoding,
                    py_string.is_unicode,
                    py_string.is_str,
                    py_string.intern
823
                    ))
824 825
                if py_string.py3str_cstring:
                    w.putln("#endif")
826
            w.putln("{0, 0, 0, 0, 0, 0, 0}")
827
            w.putln("};")
828

829 830
            init_globals = self.parts['init_globals']
            init_globals.putln(
831 832
                "if (__Pyx_InitStrings(%s) < 0) %s;" % (
                    Naming.stringtab_cname,
833
                    init_globals.error_goto(self.module_pos)))
834 835 836

    def generate_int_constants(self):
        consts = [ (len(c.value), c.value, c.is_long, c)
Stefan Behnel's avatar
Stefan Behnel committed
837
                   for c in self.int_const_index.values() ]
838
        consts.sort()
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
839
        decls_writer = self.parts['decls']
840 841
        for _, value, longness, c in consts:
            cname = c.cname
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
842
            decls_writer.putln("static PyObject *%s;" % cname)
843 844
            if longness:
                function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
845 846
            elif Utils.long_literal(value):
                function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;'
847 848
            else:
                function = "%s = PyInt_FromLong(%s); %s;"
849 850
            init_globals = self.parts['init_globals']
            init_globals.putln(function % (
851 852
                cname,
                value,
853
                init_globals.error_goto_if_null(cname, self.module_pos)))
854

855 856 857
    # The functions below are there in a transition phase only
    # and will be deprecated. They are called from Nodes.BlockNode.
    # The copy&paste duplication is intentional in order to be able
858
    # to see quickly how BlockNode worked, until this is replaced.
859

860 861 862
    def should_declare(self, cname, entry):
        if cname in self.declared_cnames:
            other = self.declared_cnames[cname]
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
863
            assert str(entry.type) == str(other.type)
864 865 866 867 868 869 870 871 872
            assert entry.init == other.init
            return False
        else:
            self.declared_cnames[cname] = entry
            return True

    #
    # File name state
    #
873 874 875 876 877 878 879 880 881 882 883 884 885 886

    def lookup_filename(self, filename):
        try:
            index = self.filename_table[filename]
        except KeyError:
            index = len(self.filename_list)
            self.filename_list.append(filename)
            self.filename_table[filename] = index
        return index

    def commented_file_contents(self, source_desc):
        try:
            return self.input_file_contents[source_desc]
        except KeyError:
887 888 889 890
            pass
        source_file = source_desc.get_lines(encoding='ASCII',
                                            error_handling='ignore')
        try:
891 892
            F = [u' * ' + line.rstrip().replace(
                    u'*/', u'*[inserted by cython to avoid comment closer]/'
893 894
                    ).replace(
                    u'/*', u'/[inserted by cython to avoid comment start]*'
895
                    )
896 897 898 899 900 901 902
                 for line in source_file]
        finally:
            if hasattr(source_file, 'close'):
                source_file.close()
        if not F: F.append(u'')
        self.input_file_contents[source_desc] = F
        return F
903

904 905 906
    #
    # Utility code state
    #
907

908
    def use_utility_code(self, utility_code):
909
        """
910 911 912 913
        Adds code to the C file. utility_code should
        a) implement __eq__/__hash__ for the purpose of knowing whether the same
           code has already been included
        b) implement put_code, which takes a globalstate instance
914

915
        See UtilityCode.
916
        """
917 918 919
        if utility_code not in self.utility_codes:
            self.utility_codes.add(utility_code)
            utility_code.put_code(self)
920

921

922
def funccontext_property(name):
923 924 925 926 927 928 929
    try:
        import operator
        attribute_of = operator.attrgetter(name)
    except:
        def attribute_of(o):
            return getattr(o, name)

930
    def get(self):
931
        return attribute_of(self.funcstate)
932
    def set(self, value):
933
        setattr(self.funcstate, name, value)
934 935
    return property(get, set)

936

937
class CCodeWriter(object):
938
    """
939
    Utility class to output C code.
940

941
    When creating an insertion point one must care about the state that is
942
    kept:
943 944
    - formatting state (level, bol) is cloned and used in insertion points
      as well
945 946
    - labels, temps, exc_vars: One must construct a scope in which these can
      exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
947 948 949 950 951
      sanity checking and forward compatabilty). Created insertion points
      looses this scope and cannot access it.
    - marker: Not copied to insertion point
    - filename_table, filename_list, input_file_contents: All codewriters
      coming from the same root share the same instances simultaneously.
952
    """
953

954 955 956 957 958 959 960 961 962 963 964
    # f                   file            output file
    # buffer              StringIOTree

    # level               int             indentation level
    # bol                 bool            beginning of line?
    # marker              string          comment to emit before next line
    # funcstate           FunctionState   contains state local to a C function used for code
    #                                     generation (labels and temps state etc.)
    # globalstate         GlobalState     contains state global for a C file (input file info,
    #                                     utility code, declared constants etc.)
    # emit_linenums       boolean         whether or not to write #line pragmas
965
    #
966 967 968 969
    # c_line_in_traceback boolean         append the c file and line number to the traceback for exceptions
    #
    # pyclass_stack       list            used during recursive code generation to pass information
    #                                     about the current class one is in
970

971
    globalstate = None
972

973
    def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None, c_line_in_traceback=True):
974 975
        if buffer is None: buffer = StringIOTree()
        self.buffer = buffer
976 977
        self.marker = None
        self.last_marker_line = 0
978
        self.source_desc = ""
979
        self.pyclass_stack = []
980

981 982
        self.funcstate = None
        self.level = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
983
        self.call_level = 0
984
        self.bol = 1
985 986

        if create_from is not None:
987 988
            # Use same global state
            self.globalstate = create_from.globalstate
989
            # Clone formatting state
990 991 992
            if copy_formatting:
                self.level = create_from.level
                self.bol = create_from.bol
Robert Bradshaw's avatar
Robert Bradshaw committed
993
                self.call_level = create_from.call_level
994
        if emit_linenums is None and self.globalstate:
995 996 997
            self.emit_linenums = self.globalstate.emit_linenums
        else:
            self.emit_linenums = emit_linenums
998
        self.c_line_in_traceback = c_line_in_traceback
999

1000
    def create_new(self, create_from, buffer, copy_formatting):
1001 1002
        # polymorphic constructor -- very slightly more versatile
        # than using __class__
1003
        result = CCodeWriter(create_from, buffer, copy_formatting, c_line_in_traceback=self.c_line_in_traceback)
1004
        return result
1005 1006 1007 1008

    def copyto(self, f):
        self.buffer.copyto(f)

1009 1010 1011 1012
    def getvalue(self):
        return self.buffer.getvalue()

    def write(self, s):
1013
        # also put invalid markers (lineno 0), to indicate that those lines
Mark Florisson's avatar
Mark Florisson committed
1014 1015 1016 1017 1018
        # have no Cython source code correspondence
        if self.marker is None:
            cython_lineno = self.last_marker_line
        else:
            cython_lineno = self.marker[0]
1019

Mark Florisson's avatar
Mark Florisson committed
1020
        self.buffer.markers.extend([cython_lineno] * s.count('\n'))
1021
        self.buffer.write(s)
1022 1023

    def insertion_point(self):
1024
        other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
1025 1026
        return other

1027 1028 1029 1030 1031
    def new_writer(self):
        """
        Creates a new CCodeWriter connected to the same global state, which
        can later be inserted using insert.
        """
1032
        return CCodeWriter(create_from=self, c_line_in_traceback=self.c_line_in_traceback)
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042

    def insert(self, writer):
        """
        Inserts the contents of another code writer (created with
        the same global state) in the current location.

        It is ok to write to the inserted writer also after insertion.
        """
        assert writer.globalstate is self.globalstate
        self.buffer.insert(writer.buffer)
1043 1044 1045 1046 1047 1048 1049 1050

    # Properties delegated to function scope
    label_counter = funccontext_property("label_counter")
    return_label = funccontext_property("return_label")
    error_label = funccontext_property("error_label")
    labels_used = funccontext_property("labels_used")
    continue_label = funccontext_property("continue_label")
    break_label = funccontext_property("break_label")
1051
    return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
1052 1053

    # Functions delegated to function scope
Dag Sverre Seljebotn's avatar
merge  
Dag Sverre Seljebotn committed
1054
    def new_label(self, name=None):    return self.funcstate.new_label(name)
1055 1056 1057 1058 1059 1060 1061 1062 1063
    def new_error_label(self):         return self.funcstate.new_error_label()
    def get_loop_labels(self):         return self.funcstate.get_loop_labels()
    def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
    def new_loop_labels(self):         return self.funcstate.new_loop_labels()
    def get_all_labels(self):          return self.funcstate.get_all_labels()
    def set_all_labels(self, labels):  return self.funcstate.set_all_labels(labels)
    def all_new_labels(self):          return self.funcstate.all_new_labels()
    def use_label(self, lbl):          return self.funcstate.use_label(lbl)
    def label_used(self, lbl):         return self.funcstate.label_used(lbl)
1064 1065


1066
    def enter_cfunc_scope(self):
1067
        self.funcstate = FunctionState(self)
1068

1069
    def exit_cfunc_scope(self):
1070
        self.funcstate = None
1071

1072 1073 1074 1075 1076
    # constant handling

    def get_py_num(self, str_value, longness):
        return self.globalstate.get_int_const(str_value, longness).cname

1077 1078
    def get_py_const(self, type, prefix='', cleanup_level=None):
        return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
1079

1080 1081 1082
    def get_string_const(self, text):
        return self.globalstate.get_string_const(text).cname

1083 1084 1085 1086
    def get_py_string_const(self, text, identifier=None,
                            is_str=False, unicode_value=None):
        return self.globalstate.get_py_string_const(
            text, identifier, is_str, unicode_value).cname
1087

1088 1089 1090
    def get_argument_default_const(self, type):
        return self.globalstate.get_py_const(type).cname

1091 1092 1093 1094
    def intern(self, text):
        return self.get_py_string_const(text)

    def intern_identifier(self, text):
1095
        return self.get_py_string_const(text, identifier=True)
1096

1097 1098 1099
    def get_cached_constants_writer(self):
        return self.globalstate.get_cached_constants_writer()

1100 1101
    # code generation

1102
    def putln(self, code = "", safe=False):
William Stein's avatar
William Stein committed
1103 1104
        if self.marker and self.bol:
            self.emit_marker()
1105 1106
        if self.emit_linenums and self.last_marker_line != 0:
            self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
1107

William Stein's avatar
William Stein committed
1108
        if code:
1109 1110 1111 1112
            if safe:
                self.put_safe(code)
            else:
                self.put(code)
1113
        self.write("\n");
William Stein's avatar
William Stein committed
1114
        self.bol = 1
1115

William Stein's avatar
William Stein committed
1116
    def emit_marker(self):
1117
        self.write("\n");
William Stein's avatar
William Stein committed
1118
        self.indent()
1119
        self.write("/* %s */\n" % self.marker[1])
1120
        self.last_marker_line = self.marker[0]
William Stein's avatar
William Stein committed
1121 1122
        self.marker = None

1123 1124 1125 1126 1127
    def put_safe(self, code):
        # put code, but ignore {}
        self.write(code)
        self.bol = 0

William Stein's avatar
William Stein committed
1128
    def put(self, code):
1129
        fix_indent = False
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
        if "{" in code:
            dl = code.count("{")
        else:
            dl = 0
        if "}" in code:
            dl -= code.count("}")
            if dl < 0:
                self.level += dl
            elif dl == 0 and code[0] == "}":
                # special cases like "} else {" need a temporary dedent
                fix_indent = True
                self.level -= 1
William Stein's avatar
William Stein committed
1142 1143
        if self.bol:
            self.indent()
1144
        self.write(code)
William Stein's avatar
William Stein committed
1145 1146 1147
        self.bol = 0
        if dl > 0:
            self.level += dl
1148
        elif fix_indent:
1149 1150
            self.level += 1

William Stein's avatar
William Stein committed
1151 1152
    def increase_indent(self):
        self.level = self.level + 1
1153

William Stein's avatar
William Stein committed
1154 1155
    def decrease_indent(self):
        self.level = self.level - 1
1156

William Stein's avatar
William Stein committed
1157 1158 1159
    def begin_block(self):
        self.putln("{")
        self.increase_indent()
1160

William Stein's avatar
William Stein committed
1161 1162 1163
    def end_block(self):
        self.decrease_indent()
        self.putln("}")
1164

William Stein's avatar
William Stein committed
1165
    def indent(self):
1166
        self.write("  " * self.level)
1167

1168 1169 1170
    def get_py_version_hex(self, pyversion):
        return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]

William Stein's avatar
William Stein committed
1171
    def mark_pos(self, pos):
Robert Bradshaw's avatar
Robert Bradshaw committed
1172 1173
        if pos is None:
            return
1174
        source_desc, line, col = pos
1175 1176
        if self.last_marker_line == line:
            return
1177
        assert isinstance(source_desc, SourceDescriptor)
1178
        contents = self.globalstate.commented_file_contents(source_desc)
1179 1180 1181
        lines = contents[max(0,line-3):line] # line numbers start at 1
        lines[-1] += u'             # <<<<<<<<<<<<<<'
        lines += contents[line:line+2]
1182

1183 1184
        marker = u'"%s":%d\n%s\n' % (
            source_desc.get_escaped_description(), line, u'\n'.join(lines))
1185
        self.marker = (line, marker)
1186 1187
        if self.emit_linenums:
            self.source_desc = source_desc.get_escaped_description()
1188

William Stein's avatar
William Stein committed
1189
    def put_label(self, lbl):
1190
        if lbl in self.funcstate.labels_used:
1191
            self.putln("%s:;" % lbl)
1192

1193
    def put_goto(self, lbl):
1194
        self.funcstate.use_label(lbl)
1195
        self.putln("goto %s;" % lbl)
1196

1197 1198
    def put_var_declaration(self, entry, storage_class="",
                            dll_linkage = None, definition = True):
1199
        #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
1200 1201
        if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
            #print "...private and not definition, skipping", entry.cname ###
1202
            return
1203 1204
        if entry.visibility == "private" and not entry.used:
            #print "...private and not used, skipping", entry.cname ###
William Stein's avatar
William Stein committed
1205 1206 1207
            return
        if storage_class:
            self.put("%s " % storage_class)
1208 1209
        self.put(entry.type.declaration_code(
                entry.cname, dll_linkage = dll_linkage))
William Stein's avatar
William Stein committed
1210
        if entry.init is not None:
1211
            self.put_safe(" = %s" % entry.type.literal_code(entry.init))
1212 1213
        elif entry.type.is_pyobject:
            self.put(" = NULL");
William Stein's avatar
William Stein committed
1214
        self.putln(";")
1215 1216

    def put_temp_declarations(self, func_context):
1217
        for name, type, manage_ref in func_context.temps_allocated:
1218 1219 1220 1221 1222 1223
            decl = type.declaration_code(name)
            if type.is_pyobject:
                self.putln("%s = NULL;" % decl)
            else:
                self.putln("%s;" % decl)

1224 1225 1226
    def put_h_guard(self, guard):
        self.putln("#ifndef %s" % guard)
        self.putln("#define %s" % guard)
1227

1228 1229 1230 1231 1232 1233 1234 1235
    def unlikely(self, cond):
        if Options.gcc_branch_hints:
            return 'unlikely(%s)' % cond
        else:
            return cond

    # Python objects and reference counting

William Stein's avatar
William Stein committed
1236 1237
    def entry_as_pyobject(self, entry):
        type = entry.type
1238 1239
        if (not entry.is_self_arg and not entry.type.is_complete()
            or entry.type.is_extension_type):
William Stein's avatar
William Stein committed
1240 1241 1242
            return "(PyObject *)" + entry.cname
        else:
            return entry.cname
1243

William Stein's avatar
William Stein committed
1244
    def as_pyobject(self, cname, type):
1245
        from PyrexTypes import py_object_type, typecast
William Stein's avatar
William Stein committed
1246
        return typecast(py_object_type, type, cname)
1247

1248
    def put_gotref(self, cname):
1249
        self.putln("__Pyx_GOTREF(%s);" % cname)
1250

1251 1252
    def put_giveref(self, cname):
        self.putln("__Pyx_GIVEREF(%s);" % cname)
1253

1254 1255 1256
    def put_xgiveref(self, cname):
        self.putln("__Pyx_XGIVEREF(%s);" % cname)

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1257 1258 1259
    def put_xgotref(self, cname):
        self.putln("__Pyx_XGOTREF(%s);" % cname)

1260 1261 1262 1263 1264
    def put_incref(self, cname, type, nanny=True):
        if nanny:
            self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
        else:
            self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
1265

1266 1267 1268 1269 1270
    def put_decref(self, cname, type, nanny=True):
        if nanny:
            self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
        else:
            self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type))
1271 1272 1273 1274

    def put_var_gotref(self, entry):
        if entry.type.is_pyobject:
            self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
1275

1276 1277 1278 1279
    def put_var_giveref(self, entry):
        if entry.type.is_pyobject:
            self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))

1280 1281 1282 1283
    def put_var_xgotref(self, entry):
        if entry.type.is_pyobject:
            self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))

1284 1285 1286 1287
    def put_var_xgiveref(self, entry):
        if entry.type.is_pyobject:
            self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))

William Stein's avatar
William Stein committed
1288 1289
    def put_var_incref(self, entry):
        if entry.type.is_pyobject:
1290
            self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
1291

1292
    def put_decref_clear(self, cname, type, nanny=True):
1293
        from PyrexTypes import py_object_type, typecast
1294 1295 1296 1297 1298 1299
        if nanny:
            self.putln("__Pyx_DECREF(%s); %s = 0;" % (
                typecast(py_object_type, type, cname), cname))
        else:
            self.putln("Py_DECREF(%s); %s = 0;" % (
                typecast(py_object_type, type, cname), cname))
1300

1301 1302 1303 1304 1305
    def put_xdecref(self, cname, type, nanny=True):
        if nanny:
            self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
        else:
            self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type))
1306

1307 1308 1309 1310 1311 1312 1313
    def put_xdecref_clear(self, cname, type, nanny=True):
        if nanny:
            self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
                self.as_pyobject(cname, type), cname))
        else:
            self.putln("Py_XDECREF(%s); %s = 0;" % (
                self.as_pyobject(cname, type), cname))
William Stein's avatar
William Stein committed
1314 1315 1316

    def put_var_decref(self, entry):
        if entry.type.is_pyobject:
1317
            self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1318

William Stein's avatar
William Stein committed
1319 1320
    def put_var_decref_clear(self, entry):
        if entry.type.is_pyobject:
1321
            self.putln("__Pyx_DECREF(%s); %s = 0;" % (
William Stein's avatar
William Stein committed
1322
                self.entry_as_pyobject(entry), entry.cname))
1323

William Stein's avatar
William Stein committed
1324 1325
    def put_var_xdecref(self, entry):
        if entry.type.is_pyobject:
1326
            self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1327

William Stein's avatar
William Stein committed
1328 1329
    def put_var_xdecref_clear(self, entry):
        if entry.type.is_pyobject:
1330
            self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
William Stein's avatar
William Stein committed
1331
                self.entry_as_pyobject(entry), entry.cname))
1332

1333
    def put_var_decrefs(self, entries, used_only = 0):
William Stein's avatar
William Stein committed
1334
        for entry in entries:
1335 1336 1337 1338 1339
            if not used_only or entry.used:
                if entry.xdecref_cleanup:
                    self.put_var_xdecref(entry)
                else:
                    self.put_var_decref(entry)
1340

William Stein's avatar
William Stein committed
1341 1342 1343
    def put_var_xdecrefs(self, entries):
        for entry in entries:
            self.put_var_xdecref(entry)
1344

William Stein's avatar
William Stein committed
1345 1346 1347
    def put_var_xdecrefs_clear(self, entries):
        for entry in entries:
            self.put_var_xdecref_clear(entry)
1348

1349
    def put_init_to_py_none(self, cname, type, nanny=True):
1350
        from PyrexTypes import py_object_type, typecast
William Stein's avatar
William Stein committed
1351
        py_none = typecast(type, py_object_type, "Py_None")
1352 1353 1354 1355
        if nanny:
            self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
        else:
            self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
1356

1357
    def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
William Stein's avatar
William Stein committed
1358 1359
        code = template % entry.cname
        #if entry.type.is_extension_type:
Robert Bradshaw's avatar
Robert Bradshaw committed
1360
        #    code = "((PyObject*)%s)" % code
1361
        self.put_init_to_py_none(code, entry.type, nanny)
1362
        if entry.in_closure:
Stefan Behnel's avatar
Stefan Behnel committed
1363
            self.put_giveref('Py_None')
William Stein's avatar
William Stein committed
1364

1365
    def put_pymethoddef(self, entry, term, allow_skip=True):
1366
        if entry.is_special or entry.name == '__getattribute__':
1367 1368 1369
            if entry.name not in ['__cinit__', '__dealloc__', '__richcmp__', '__next__', '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__', '__getcharbuffer__', '__getbuffer__', '__releasebuffer__']:
                if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
                    pass
1370 1371 1372
                # Python's typeobject.c will automatically fill in our slot
                # in add_operators() (called by PyType_Ready) with a value
                # that's better than ours.
1373
                elif allow_skip:
1374
                    return
1375
        from TypeSlots import method_coexist
William Stein's avatar
William Stein committed
1376 1377 1378 1379
        if entry.doc:
            doc_code = entry.doc_cname
        else:
            doc_code = 0
1380 1381
        method_flags = entry.signature.method_flags()
        if method_flags:
1382
            if entry.is_special:
1383
                method_flags += [method_coexist]
1384
            self.putln(
1385
                '{__Pyx_NAMESTR("%s"), (PyCFunction)%s, %s, __Pyx_DOCSTR(%s)}%s' % (
1386
                    entry.name,
1387
                    entry.func_cname,
1388
                    "|".join(method_flags),
1389 1390
                    doc_code,
                    term))
1391

1392 1393
    # GIL methods

1394
    def put_ensure_gil(self, declare_gilstate=True):
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
        """
        Acquire the GIL. The generated code is safe even when no PyThreadState
        has been allocated for this thread (for threads not initialized by
        using the Python API). Additionally, the code generated by this method
        may be called recursively.
        """
        from Cython.Compiler import Nodes

        self.globalstate.use_utility_code(Nodes.force_init_threads_utility_code)

        self.putln("#ifdef WITH_THREAD")
1406 1407
        if declare_gilstate:
            self.put("PyGILState_STATE ")
1408
        self.putln("__pyx_gilstate_save = PyGILState_Ensure();")
1409 1410 1411 1412 1413 1414 1415
        self.putln("#endif")

    def put_release_ensured_gil(self):
        """
        Releases the GIL, corresponds to `put_ensure_gil`.
        """
        self.putln("#ifdef WITH_THREAD")
1416
        self.putln("PyGILState_Release(__pyx_gilstate_save);")
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
        self.putln("#endif")

    def put_acquire_gil(self):
        """
        Acquire the GIL. The thread's thread state must have been initialized
        by a previous `put_release_gil`
        """
        self.putln("Py_BLOCK_THREADS")

    def put_release_gil(self):
        "Release the GIL, corresponds to `put_acquire_gil`."
        self.putln("#ifdef WITH_THREAD")
        self.putln("PyThreadState *_save = NULL;")
        self.putln("#endif")
        self.putln("Py_UNBLOCK_THREADS")

1433 1434
    def declare_gilstate(self):
        self.putln("#ifdef WITH_THREAD")
1435
        self.putln("PyGILState_STATE __pyx_gilstate_save;")
1436 1437
        self.putln("#endif")

1438 1439
    # error handling

Robert Bradshaw's avatar
Robert Bradshaw committed
1440 1441 1442 1443
    def put_error_if_neg(self, pos, value):
#        return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos)))  # TODO this path is almost _never_ taken, yet this macro makes is slower!
        return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))

1444
    def put_error_if_unbound(self, pos, entry):
1445
        import ExprNodes
1446
        if entry.from_closure:
1447 1448 1449
            func = '__Pyx_RaiseClosureNameError'
            self.globalstate.use_utility_code(
                ExprNodes.raise_closure_name_error_utility_code)
1450
        else:
1451 1452 1453 1454 1455
            func = '__Pyx_RaiseUnboundLocalError'
            self.globalstate.use_utility_code(
                ExprNodes.raise_unbound_local_error_utility_code)
        self.put('if (unlikely(!%s)) { %s("%s"); %s }' % (
            entry.cname, func, entry.name, self.error_goto(pos)))
1456

1457
    def set_error_info(self, pos):
1458
        self.funcstate.should_declare_error_indicator = True
1459
        if self.c_line_in_traceback:
1460
            cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
Robert Bradshaw's avatar
Robert Bradshaw committed
1461 1462
        else:
            cinfo = ""
1463

1464
        return "%s = %s[%s]; %s = %s;%s" % (
William Stein's avatar
William Stein committed
1465 1466 1467 1468 1469
            Naming.filename_cname,
            Naming.filetable_cname,
            self.lookup_filename(pos[0]),
            Naming.lineno_cname,
            pos[1],
1470
            cinfo)
1471

1472 1473 1474 1475 1476
    def error_goto(self, pos):
        lbl = self.funcstate.error_label
        self.funcstate.use_label(lbl)
        return "{%s goto %s;}" % (
            self.set_error_info(pos),
1477
            lbl)
1478 1479 1480

    def error_goto_if(self, cond, pos):
        return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
1481

Robert Bradshaw's avatar
Robert Bradshaw committed
1482 1483
    def error_goto_if_null(self, cname, pos):
        return self.error_goto_if("!%s" % cname, pos)
1484

Robert Bradshaw's avatar
Robert Bradshaw committed
1485 1486
    def error_goto_if_neg(self, cname, pos):
        return self.error_goto_if("%s < 0" % cname, pos)
1487

Robert Bradshaw's avatar
Robert Bradshaw committed
1488 1489
    def error_goto_if_PyErr(self, pos):
        return self.error_goto_if("PyErr_Occurred()", pos)
1490

William Stein's avatar
William Stein committed
1491
    def lookup_filename(self, filename):
1492
        return self.globalstate.lookup_filename(filename)
William Stein's avatar
William Stein committed
1493

1494
    def put_declare_refcount_context(self):
1495
        self.putln('__Pyx_RefNannyDeclarations')
1496

1497
    def put_setup_refcount_context(self, name):
1498
        self.putln('__Pyx_RefNannySetupContext("%s");' % name)
1499

1500
    def put_finish_refcount_context(self):
1501
        self.putln("__Pyx_RefNannyFinishContext();")
1502

1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516
    def put_add_traceback(self, qualified_name):
        """
        Build a Python traceback for propagating exceptions.

        qualified_name should be the qualified name of the function
        """
        format_tuple = (
            qualified_name,
            Naming.clineno_cname,
            Naming.lineno_cname,
            Naming.filename_cname,
        )
        self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple)

1517 1518
    def put_trace_declarations(self):
        self.putln('__Pyx_TraceDeclarations');
1519

Robert Bradshaw's avatar
Robert Bradshaw committed
1520 1521
    def put_trace_call(self, name, pos):
        self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]));
1522

Robert Bradshaw's avatar
Robert Bradshaw committed
1523 1524
    def put_trace_exception(self):
        self.putln("__Pyx_TraceException();")
1525

Robert Bradshaw's avatar
Robert Bradshaw committed
1526 1527 1528
    def put_trace_return(self, retvalue_cname):
        self.putln("__Pyx_TraceReturn(%s);" % retvalue_cname)

Mark Florisson's avatar
Mark Florisson committed
1529 1530 1531
    def putln_openmp(self, string):
        self.putln("#ifdef _OPENMP")
        self.putln(string)
1532
        self.putln("#endif /* _OPENMP */")
William Stein's avatar
William Stein committed
1533

1534
class PyrexCodeWriter(object):
William Stein's avatar
William Stein committed
1535 1536 1537 1538
    # f                file      output file
    # level            int       indentation level

    def __init__(self, outfile_name):
1539
        self.f = Utils.open_new_file(outfile_name)
William Stein's avatar
William Stein committed
1540
        self.level = 0
1541

William Stein's avatar
William Stein committed
1542 1543
    def putln(self, code):
        self.f.write("%s%s\n" % (" " * self.level, code))
1544

William Stein's avatar
William Stein committed
1545 1546
    def indent(self):
        self.level += 1
1547

William Stein's avatar
William Stein committed
1548 1549 1550
    def dedent(self):
        self.level -= 1

1551 1552

class ClosureTempAllocator(object):
1553
    def __init__(self, klass):
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
        self.klass = klass
        self.temps_allocated = {}
        self.temps_free = {}
        self.temps_count = 0

    def reset(self):
        for type, cnames in self.temps_allocated.items():
            self.temps_free[type] = list(cnames)

    def allocate_temp(self, type):
        if not type in self.temps_allocated:
            self.temps_allocated[type] = []
            self.temps_free[type] = []
        elif self.temps_free[type]:
            return self.temps_free[type].pop(0)
        cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
        self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
        self.temps_allocated[type].append(cname)
        self.temps_count += 1
        return cname