Home | History | Annotate | Download | only in Compiler
      1 # cython: language_level = 2
      2 #
      3 #   Code output module
      4 #
      5 
      6 import cython
      7 cython.declare(os=object, re=object, operator=object,
      8                Naming=object, Options=object, StringEncoding=object,
      9                Utils=object, SourceDescriptor=object, StringIOTree=object,
     10                DebugFlags=object, basestring=object)
     11 
     12 import os
     13 import re
     14 import sys
     15 from string import Template
     16 import operator
     17 import textwrap
     18 
     19 try:
     20     import hashlib
     21 except ImportError:
     22     import md5 as hashlib
     23 
     24 import Naming
     25 import Options
     26 import StringEncoding
     27 from Cython import Utils
     28 from Scanning import SourceDescriptor
     29 from Cython.StringIOTree import StringIOTree
     30 import DebugFlags
     31 
     32 try:
     33     from __builtin__ import basestring
     34 except ImportError:
     35     from builtins import str as basestring
     36 
     37 KEYWORDS_MUST_BE_BYTES = sys.version_info < (2,7)
     38 
     39 
     40 non_portable_builtins_map = {
     41     # builtins that have different names in different Python versions
     42     'bytes'         : ('PY_MAJOR_VERSION < 3',  'str'),
     43     'unicode'       : ('PY_MAJOR_VERSION >= 3', 'str'),
     44     'basestring'    : ('PY_MAJOR_VERSION >= 3', 'str'),
     45     'xrange'        : ('PY_MAJOR_VERSION >= 3', 'range'),
     46     'raw_input'     : ('PY_MAJOR_VERSION >= 3', 'input'),
     47     'BaseException' : ('PY_VERSION_HEX < 0x02050000', 'Exception'),
     48     }
     49 
     50 basicsize_builtins_map = {
     51     # builtins whose type has a different tp_basicsize than sizeof(...)
     52     'PyTypeObject' : 'PyHeapTypeObject',
     53     }
     54 
     55 uncachable_builtins = [
     56     # builtin names that cannot be cached because they may or may not
     57     # be available at import time
     58     'WindowsError',
     59     ]
     60 
     61 modifier_output_mapper = {
     62     'inline': 'CYTHON_INLINE'
     63 }.get
     64 
     65 is_self_assignment = re.compile(r" *(\w+) = (\1);\s*$").match
     66 
     67 
     68 def get_utility_dir():
     69     # make this a function and not global variables:
     70     # http://trac.cython.org/cython_trac/ticket/475
     71     Cython_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
     72     return os.path.join(Cython_dir, "Utility")
     73 
     74 
     75 class UtilityCodeBase(object):
     76     """
     77     Support for loading utility code from a file.
     78 
     79     Code sections in the file can be specified as follows:
     80 
     81         ##### MyUtility.proto #####
     82 
     83         [proto declarations]
     84 
     85         ##### MyUtility.init #####
     86 
     87         [code run at module initialization]
     88 
     89         ##### MyUtility #####
     90         #@requires: MyOtherUtility
     91         #@substitute: naming
     92 
     93         [definitions]
     94 
     95     for prototypes and implementation respectively.  For non-python or
     96     -cython files backslashes should be used instead.  5 to 30 comment
     97     characters may be used on either side.
     98 
     99     If the @cname decorator is not used and this is a CythonUtilityCode,
    100     one should pass in the 'name' keyword argument to be used for name
    101     mangling of such entries.
    102     """
    103 
    104     is_cython_utility = False
    105     requires = None
    106     _utility_cache = {}
    107 
    108     @classmethod
    109     def _add_utility(cls, utility, type, lines, begin_lineno, tags=None):
    110         if utility is None:
    111             return
    112 
    113         code = '\n'.join(lines)
    114         if tags and 'substitute' in tags and tags['substitute'] == set(['naming']):
    115             del tags['substitute']
    116             try:
    117                 code = Template(code).substitute(vars(Naming))
    118             except (KeyError, ValueError), e:
    119                 raise RuntimeError("Error parsing templated utility code of type '%s' at line %d: %s" % (
    120                     type, begin_lineno, e))
    121 
    122         # remember correct line numbers at least until after templating
    123         code = '\n' * begin_lineno + code
    124 
    125         if type == 'proto':
    126             utility[0] = code
    127         elif type == 'impl':
    128             utility[1] = code
    129         else:
    130             all_tags = utility[2]
    131             if KEYWORDS_MUST_BE_BYTES:
    132                 type = type.encode('ASCII')
    133             all_tags[type] = code
    134 
    135         if tags:
    136             all_tags = utility[2]
    137             for name, values in tags.items():
    138                 if KEYWORDS_MUST_BE_BYTES:
    139                     name = name.encode('ASCII')
    140                 all_tags.setdefault(name, set()).update(values)
    141 
    142     @classmethod
    143     def load_utilities_from_file(cls, path):
    144         utilities = cls._utility_cache.get(path)
    145         if utilities:
    146             return utilities
    147 
    148         filename = os.path.join(get_utility_dir(), path)
    149         _, ext = os.path.splitext(path)
    150         if ext in ('.pyx', '.py', '.pxd', '.pxi'):
    151             comment = '#'
    152             replace_comments = re.compile(r'^\s*#.*').sub
    153         else:
    154             comment = '/'
    155             replace_comments = re.compile(r'^\s*//.*|^\s*/\*[^*]*\*/').sub
    156         match_special = re.compile(
    157             (r'^%(C)s{5,30}\s*(?P<name>(?:\w|\.)+)\s*%(C)s{5,30}|'
    158              r'^%(C)s+@(?P<tag>\w+)\s*:\s*(?P<value>(?:\w|[.:])+)'
    159                 ) % {'C':comment}).match
    160         match_type = re.compile('(.+)[.](proto|impl|init|cleanup)$').match
    161 
    162         f = Utils.open_source_file(filename, encoding='UTF-8')
    163         try:
    164             all_lines = f.readlines()
    165         finally:
    166             f.close()
    167 
    168         utilities = {}
    169         lines = []
    170         tags = {}
    171         utility = type = None
    172         begin_lineno = 0
    173 
    174         for lineno, line in enumerate(all_lines):
    175             m = match_special(line)
    176             if m:
    177                 if m.group('name'):
    178                     cls._add_utility(utility, type, lines, begin_lineno, tags)
    179 
    180                     begin_lineno = lineno + 1
    181                     del lines[:]
    182                     tags.clear()
    183 
    184                     name = m.group('name')
    185                     mtype = match_type(name)
    186                     if mtype:
    187                         name, type = mtype.groups()
    188                     else:
    189                         type = 'impl'
    190                     utility = utilities.setdefault(name, [None, None, {}])
    191                 else:
    192                     tags.setdefault(m.group('tag'), set()).add(m.group('value'))
    193                     lines.append('') # keep line number correct
    194             else:
    195                 lines.append(replace_comments('', line).rstrip())
    196 
    197         if utility is None:
    198             raise ValueError("Empty utility code file")
    199 
    200         # Don't forget to add the last utility code
    201         cls._add_utility(utility, type, lines, begin_lineno, tags)
    202 
    203         cls._utility_cache[path] = utilities
    204         return utilities
    205 
    206     @classmethod
    207     def load(cls, util_code_name, from_file=None, **kwargs):
    208         """
    209         Load utility code from a file specified by from_file (relative to
    210         Cython/Utility) and name util_code_name.  If from_file is not given,
    211         load it from the file util_code_name.*.  There should be only one
    212         file matched by this pattern.
    213         """
    214         if '::' in util_code_name:
    215             from_file, util_code_name = util_code_name.rsplit('::', 1)
    216         if not from_file:
    217             utility_dir = get_utility_dir()
    218             prefix = util_code_name + '.'
    219             try:
    220                 listing = os.listdir(utility_dir)
    221             except OSError:
    222                 # XXX the code below assumes as 'zipimport.zipimporter' instance
    223                 # XXX should be easy to generalize, but too lazy right now to write it
    224                 import zipfile
    225                 global __loader__
    226                 loader = __loader__
    227                 archive = loader.archive
    228                 fileobj = zipfile.ZipFile(archive)
    229                 listing = [ os.path.basename(name)
    230                             for name in fileobj.namelist()
    231                             if os.path.join(archive, name).startswith(utility_dir)]
    232                 fileobj.close()
    233             files = [ os.path.join(utility_dir, filename)
    234                       for filename in listing
    235                       if filename.startswith(prefix) ]
    236             if not files:
    237                 raise ValueError("No match found for utility code " + util_code_name)
    238             if len(files) > 1:
    239                 raise ValueError("More than one filename match found for utility code " + util_code_name)
    240             from_file = files[0]
    241 
    242         utilities = cls.load_utilities_from_file(from_file)
    243         proto, impl, tags = utilities[util_code_name]
    244 
    245         if tags:
    246             orig_kwargs = kwargs.copy()
    247             for name, values in tags.items():
    248                 if name in kwargs:
    249                     continue
    250                 # only pass lists when we have to: most argument expect one value or None
    251                 if name == 'requires':
    252                     if orig_kwargs:
    253                         values = [cls.load(dep, from_file, **orig_kwargs)
    254                                   for dep in sorted(values)]
    255                     else:
    256                         # dependencies are rarely unique, so use load_cached() when we can
    257                         values = [cls.load_cached(dep, from_file)
    258                                   for dep in sorted(values)]
    259                 elif not values:
    260                     values = None
    261                 elif len(values) == 1:
    262                     values = values[0]
    263                 kwargs[name] = values
    264 
    265         if proto is not None:
    266             kwargs['proto'] = proto
    267         if impl is not None:
    268             kwargs['impl'] = impl
    269 
    270         if 'name' not in kwargs:
    271             kwargs['name'] = util_code_name
    272 
    273         if 'file' not in kwargs and from_file:
    274             kwargs['file'] = from_file
    275         return cls(**kwargs)
    276 
    277     @classmethod
    278     def load_cached(cls, utility_code_name, from_file=None, __cache={}):
    279         """
    280         Calls .load(), but using a per-type cache based on utility name and file name.
    281         """
    282         key = (cls, from_file, utility_code_name)
    283         try:
    284             return __cache[key]
    285         except KeyError:
    286             pass
    287         code = __cache[key] = cls.load(utility_code_name, from_file)
    288         return code
    289 
    290     @classmethod
    291     def load_as_string(cls, util_code_name, from_file=None, **kwargs):
    292         """
    293         Load a utility code as a string. Returns (proto, implementation)
    294         """
    295         util = cls.load(util_code_name, from_file, **kwargs)
    296         proto, impl = util.proto, util.impl
    297         return util.format_code(proto), util.format_code(impl)
    298 
    299     def format_code(self, code_string, replace_empty_lines=re.compile(r'\n\n+').sub):
    300         """
    301         Format a code section for output.
    302         """
    303         if code_string:
    304             code_string = replace_empty_lines('\n', code_string.strip()) + '\n\n'
    305         return code_string
    306 
    307     def __str__(self):
    308         return "<%s(%s)" % (type(self).__name__, self.name)
    309 
    310     def get_tree(self):
    311         pass
    312 
    313 
    314 class UtilityCode(UtilityCodeBase):
    315     """
    316     Stores utility code to add during code generation.
    317 
    318     See GlobalState.put_utility_code.
    319 
    320     hashes/equals by instance
    321 
    322     proto           C prototypes
    323     impl            implemenation code
    324     init            code to call on module initialization
    325     requires        utility code dependencies
    326     proto_block     the place in the resulting file where the prototype should
    327                     end up
    328     name            name of the utility code (or None)
    329     file            filename of the utility code file this utility was loaded
    330                     from (or None)
    331     """
    332 
    333     def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None,
    334                  proto_block='utility_code_proto', name=None, file=None):
    335         # proto_block: Which code block to dump prototype in. See GlobalState.
    336         self.proto = proto
    337         self.impl = impl
    338         self.init = init
    339         self.cleanup = cleanup
    340         self.requires = requires
    341         self._cache = {}
    342         self.specialize_list = []
    343         self.proto_block = proto_block
    344         self.name = name
    345         self.file = file
    346 
    347     def __hash__(self):
    348         return hash((self.proto, self.impl))
    349 
    350     def __eq__(self, other):
    351         if self is other:
    352             return True
    353         if not isinstance(other, type(self)):
    354             return False
    355 
    356         self_proto = getattr(self, 'proto', None)
    357         other_proto = getattr(other, 'proto', None)
    358         return (self_proto, self.impl) == (other_proto, other.impl)
    359 
    360     def none_or_sub(self, s, context):
    361         """
    362         Format a string in this utility code with context. If None, do nothing.
    363         """
    364         if s is None:
    365             return None
    366         return s % context
    367 
    368     def specialize(self, pyrex_type=None, **data):
    369         # Dicts aren't hashable...
    370         if pyrex_type is not None:
    371             data['type'] = pyrex_type.declaration_code('')
    372             data['type_name'] = pyrex_type.specialization_name()
    373         key = tuple(sorted(data.items()))
    374         try:
    375             return self._cache[key]
    376         except KeyError:
    377             if self.requires is None:
    378                 requires = None
    379             else:
    380                 requires = [r.specialize(data) for r in self.requires]
    381 
    382             s = self._cache[key] = UtilityCode(
    383                     self.none_or_sub(self.proto, data),
    384                     self.none_or_sub(self.impl, data),
    385                     self.none_or_sub(self.init, data),
    386                     self.none_or_sub(self.cleanup, data),
    387                     requires,
    388                     self.proto_block)
    389 
    390             self.specialize_list.append(s)
    391             return s
    392 
    393     def inject_string_constants(self, impl, output):
    394         """Replace 'PYIDENT("xyz")' by a constant Python identifier cname.
    395         """
    396         replacements = {}
    397         def externalise(matchobj):
    398             name = matchobj.group(1)
    399             try:
    400                 cname = replacements[name]
    401             except KeyError:
    402                 cname = replacements[name] = output.get_interned_identifier(
    403                     StringEncoding.EncodedString(name)).cname
    404             return cname
    405 
    406         impl = re.sub('PYIDENT\("([^"]+)"\)', externalise, impl)
    407         return bool(replacements), impl
    408 
    409     def put_code(self, output):
    410         if self.requires:
    411             for dependency in self.requires:
    412                 output.use_utility_code(dependency)
    413         if self.proto:
    414             output[self.proto_block].put_or_include(
    415                 self.format_code(self.proto),
    416                 '%s_proto' % self.name)
    417         if self.impl:
    418             impl = self.format_code(self.impl)
    419             is_specialised, impl = self.inject_string_constants(impl, output)
    420             if not is_specialised:
    421                 # no module specific adaptations => can be reused
    422                 output['utility_code_def'].put_or_include(
    423                     impl, '%s_impl' % self.name)
    424             else:
    425                 output['utility_code_def'].put(impl)
    426         if self.init:
    427             writer = output['init_globals']
    428             writer.putln("/* %s.init */" % self.name)
    429             if isinstance(self.init, basestring):
    430                 writer.put(self.format_code(self.init))
    431             else:
    432                 self.init(writer, output.module_pos)
    433             writer.putln(writer.error_goto_if_PyErr(output.module_pos))
    434             writer.putln()
    435         if self.cleanup and Options.generate_cleanup_code:
    436             writer = output['cleanup_globals']
    437             if isinstance(self.cleanup, basestring):
    438                 writer.put_or_include(
    439                     self.format_code(self.cleanup),
    440                     '%s_cleanup' % self.name)
    441             else:
    442                 self.cleanup(writer, output.module_pos)
    443 
    444 
    445 def sub_tempita(s, context, file=None, name=None):
    446     "Run tempita on string s with given context."
    447     if not s:
    448         return None
    449 
    450     if file:
    451         context['__name'] = "%s:%s" % (file, name)
    452     elif name:
    453         context['__name'] = name
    454 
    455     from Cython.Tempita import sub
    456     return sub(s, **context)
    457 
    458 class TempitaUtilityCode(UtilityCode):
    459     def __init__(self, name=None, proto=None, impl=None, init=None, file=None, context=None, **kwargs):
    460         if context is None:
    461             context = {}
    462         proto = sub_tempita(proto, context, file, name)
    463         impl = sub_tempita(impl, context, file, name)
    464         init = sub_tempita(init, context, file, name)
    465         super(TempitaUtilityCode, self).__init__(
    466             proto, impl, init=init, name=name, file=file, **kwargs)
    467 
    468     def none_or_sub(self, s, context):
    469         """
    470         Format a string in this utility code with context. If None, do nothing.
    471         """
    472         if s is None:
    473             return None
    474         return sub_tempita(s, context, self.file, self.name)
    475 
    476 
    477 class LazyUtilityCode(UtilityCodeBase):
    478     """
    479     Utility code that calls a callback with the root code writer when
    480     available. Useful when you only have 'env' but not 'code'.
    481     """
    482 
    483     def __init__(self, callback):
    484         self.callback = callback
    485 
    486     def put_code(self, globalstate):
    487         utility = self.callback(globalstate.rootwriter)
    488         globalstate.use_utility_code(utility)
    489 
    490 
    491 class FunctionState(object):
    492     # return_label     string          function return point label
    493     # error_label      string          error catch point label
    494     # continue_label   string          loop continue point label
    495     # break_label      string          loop break point label
    496     # return_from_error_cleanup_label string
    497     # label_counter    integer         counter for naming labels
    498     # in_try_finally   boolean         inside try of try...finally
    499     # exc_vars         (string * 3)    exception variables for reraise, or None
    500     # can_trace        boolean         line tracing is supported in the current context
    501 
    502     # Not used for now, perhaps later
    503     def __init__(self, owner, names_taken=set()):
    504         self.names_taken = names_taken
    505         self.owner = owner
    506 
    507         self.error_label = None
    508         self.label_counter = 0
    509         self.labels_used = set()
    510         self.return_label = self.new_label()
    511         self.new_error_label()
    512         self.continue_label = None
    513         self.break_label = None
    514         self.yield_labels = []
    515 
    516         self.in_try_finally = 0
    517         self.exc_vars = None
    518         self.can_trace = False
    519 
    520         self.temps_allocated = [] # of (name, type, manage_ref, static)
    521         self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
    522         self.temps_used_type = {} # name -> (type, manage_ref)
    523         self.temp_counter = 0
    524         self.closure_temps = None
    525 
    526         # This is used to collect temporaries, useful to find out which temps
    527         # need to be privatized in parallel sections
    528         self.collect_temps_stack = []
    529 
    530         # This is used for the error indicator, which needs to be local to the
    531         # function. It used to be global, which relies on the GIL being held.
    532         # However, exceptions may need to be propagated through 'nogil'
    533         # sections, in which case we introduce a race condition.
    534         self.should_declare_error_indicator = False
    535         self.uses_error_indicator = False
    536 
    537     # labels
    538 
    539     def new_label(self, name=None):
    540         n = self.label_counter
    541         self.label_counter = n + 1
    542         label = "%s%d" % (Naming.label_prefix, n)
    543         if name is not None:
    544             label += '_' + name
    545         return label
    546 
    547     def new_yield_label(self):
    548         label = self.new_label('resume_from_yield')
    549         num_and_label = (len(self.yield_labels) + 1, label)
    550         self.yield_labels.append(num_and_label)
    551         return num_and_label
    552 
    553     def new_error_label(self):
    554         old_err_lbl = self.error_label
    555         self.error_label = self.new_label('error')
    556         return old_err_lbl
    557 
    558     def get_loop_labels(self):
    559         return (
    560             self.continue_label,
    561             self.break_label)
    562 
    563     def set_loop_labels(self, labels):
    564         (self.continue_label,
    565          self.break_label) = labels
    566 
    567     def new_loop_labels(self):
    568         old_labels = self.get_loop_labels()
    569         self.set_loop_labels(
    570             (self.new_label("continue"),
    571              self.new_label("break")))
    572         return old_labels
    573 
    574     def get_all_labels(self):
    575         return (
    576             self.continue_label,
    577             self.break_label,
    578             self.return_label,
    579             self.error_label)
    580 
    581     def set_all_labels(self, labels):
    582         (self.continue_label,
    583          self.break_label,
    584          self.return_label,
    585          self.error_label) = labels
    586 
    587     def all_new_labels(self):
    588         old_labels = self.get_all_labels()
    589         new_labels = []
    590         for old_label, name in zip(old_labels, ['continue', 'break', 'return', 'error']):
    591             if old_label:
    592                 new_labels.append(self.new_label(name))
    593             else:
    594                 new_labels.append(old_label)
    595         self.set_all_labels(new_labels)
    596         return old_labels
    597 
    598     def use_label(self, lbl):
    599         self.labels_used.add(lbl)
    600 
    601     def label_used(self, lbl):
    602         return lbl in self.labels_used
    603 
    604     # temp handling
    605 
    606     def allocate_temp(self, type, manage_ref, static=False):
    607         """
    608         Allocates a temporary (which may create a new one or get a previously
    609         allocated and released one of the same type). Type is simply registered
    610         and handed back, but will usually be a PyrexType.
    611 
    612         If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
    613         True, the temp will be decref-ed on return statements and in exception
    614         handling clauses. Otherwise the caller has to deal with any reference
    615         counting of the variable.
    616 
    617         If not type.is_pyobject, then manage_ref will be ignored, but it
    618         still has to be passed. It is recommended to pass False by convention
    619         if it is known that type will never be a Python object.
    620 
    621         static=True marks the temporary declaration with "static".
    622         This is only used when allocating backing store for a module-level
    623         C array literals.
    624 
    625         A C string referring to the variable is returned.
    626         """
    627         if type.is_const:
    628             type = type.const_base_type
    629         if not type.is_pyobject and not type.is_memoryviewslice:
    630             # Make manage_ref canonical, so that manage_ref will always mean
    631             # a decref is needed.
    632             manage_ref = False
    633 
    634         freelist = self.temps_free.get((type, manage_ref))
    635         if freelist is not None and len(freelist) > 0:
    636             result = freelist.pop()
    637         else:
    638             while True:
    639                 self.temp_counter += 1
    640                 result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
    641                 if not result in self.names_taken: break
    642             self.temps_allocated.append((result, type, manage_ref, static))
    643         self.temps_used_type[result] = (type, manage_ref)
    644         if DebugFlags.debug_temp_code_comments:
    645             self.owner.putln("/* %s allocated */" % result)
    646 
    647         if self.collect_temps_stack:
    648             self.collect_temps_stack[-1].add((result, type))
    649 
    650         return result
    651 
    652     def release_temp(self, name):
    653         """
    654         Releases a temporary so that it can be reused by other code needing
    655         a temp of the same type.
    656         """
    657         type, manage_ref = self.temps_used_type[name]
    658         freelist = self.temps_free.get((type, manage_ref))
    659         if freelist is None:
    660             freelist = []
    661             self.temps_free[(type, manage_ref)] = freelist
    662         if name in freelist:
    663             raise RuntimeError("Temp %s freed twice!" % name)
    664         freelist.append(name)
    665         if DebugFlags.debug_temp_code_comments:
    666             self.owner.putln("/* %s released */" % name)
    667 
    668     def temps_in_use(self):
    669         """Return a list of (cname,type,manage_ref) tuples of temp names and their type
    670         that are currently in use.
    671         """
    672         used = []
    673         for name, type, manage_ref, static in self.temps_allocated:
    674             freelist = self.temps_free.get((type, manage_ref))
    675             if freelist is None or name not in freelist:
    676                 used.append((name, type, manage_ref and type.is_pyobject))
    677         return used
    678 
    679     def temps_holding_reference(self):
    680         """Return a list of (cname,type) tuples of temp names and their type
    681         that are currently in use. This includes only temps of a
    682         Python object type which owns its reference.
    683         """
    684         return [(name, type)
    685                 for name, type, manage_ref in self.temps_in_use()
    686                 if manage_ref  and type.is_pyobject]
    687 
    688     def all_managed_temps(self):
    689         """Return a list of (cname, type) tuples of refcount-managed Python objects.
    690         """
    691         return [(cname, type)
    692                     for cname, type, manage_ref, static in self.temps_allocated
    693                         if manage_ref]
    694 
    695     def all_free_managed_temps(self):
    696         """Return a list of (cname, type) tuples of refcount-managed Python
    697         objects that are not currently in use.  This is used by
    698         try-except and try-finally blocks to clean up temps in the
    699         error case.
    700         """
    701         return [(cname, type)
    702                     for (type, manage_ref), freelist in self.temps_free.items()
    703                         if manage_ref
    704                             for cname in freelist]
    705 
    706     def start_collecting_temps(self):
    707         """
    708         Useful to find out which temps were used in a code block
    709         """
    710         self.collect_temps_stack.append(set())
    711 
    712     def stop_collecting_temps(self):
    713         return self.collect_temps_stack.pop()
    714 
    715     def init_closure_temps(self, scope):
    716         self.closure_temps = ClosureTempAllocator(scope)
    717 
    718 
    719 class NumConst(object):
    720     """Global info about a Python number constant held by GlobalState.
    721 
    722     cname       string
    723     value       string
    724     py_type     string     int, long, float
    725     value_code  string     evaluation code if different from value
    726     """
    727 
    728     def __init__(self, cname, value, py_type, value_code=None):
    729         self.cname = cname
    730         self.value = value
    731         self.py_type = py_type
    732         self.value_code = value_code or value
    733 
    734 
    735 class PyObjectConst(object):
    736     """Global info about a generic constant held by GlobalState.
    737     """
    738     # cname       string
    739     # type        PyrexType
    740 
    741     def __init__(self, cname, type):
    742         self.cname = cname
    743         self.type = type
    744 
    745 
    746 cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
    747                replace_identifier=object, find_alphanums=object)
    748 possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
    749 possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
    750 replace_identifier = re.compile(r'[^a-zA-Z0-9_]+').sub
    751 find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
    752 
    753 class StringConst(object):
    754     """Global info about a C string constant held by GlobalState.
    755     """
    756     # cname            string
    757     # text             EncodedString or BytesLiteral
    758     # py_strings       {(identifier, encoding) : PyStringConst}
    759 
    760     def __init__(self, cname, text, byte_string):
    761         self.cname = cname
    762         self.text = text
    763         self.escaped_value = StringEncoding.escape_byte_string(byte_string)
    764         self.py_strings = None
    765         self.py_versions = []
    766 
    767     def add_py_version(self, version):
    768         if not version:
    769             self.py_versions = [2,3]
    770         elif version not in self.py_versions:
    771             self.py_versions.append(version)
    772 
    773     def get_py_string_const(self, encoding, identifier=None,
    774                             is_str=False, py3str_cstring=None):
    775         py_strings = self.py_strings
    776         text = self.text
    777 
    778         is_str = bool(identifier or is_str)
    779         is_unicode = encoding is None and not is_str
    780 
    781         if encoding is None:
    782             # unicode string
    783             encoding_key = None
    784         else:
    785             # bytes or str
    786             encoding = encoding.lower()
    787             if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
    788                 encoding = None
    789                 encoding_key = None
    790             else:
    791                 encoding_key = ''.join(find_alphanums(encoding))
    792 
    793         key = (is_str, is_unicode, encoding_key, py3str_cstring)
    794         if py_strings is not None:
    795             try:
    796                 return py_strings[key]
    797             except KeyError:
    798                 pass
    799         else:
    800             self.py_strings = {}
    801 
    802         if identifier:
    803             intern = True
    804         elif identifier is None:
    805             if isinstance(text, unicode):
    806                 intern = bool(possible_unicode_identifier(text))
    807             else:
    808                 intern = bool(possible_bytes_identifier(text))
    809         else:
    810             intern = False
    811         if intern:
    812             prefix = Naming.interned_prefixes['str']
    813         else:
    814             prefix = Naming.py_const_prefix
    815 
    816         if encoding_key:
    817             encoding_prefix = '_%s' % encoding_key
    818         else:
    819             encoding_prefix = ''
    820 
    821         pystring_cname = "%s%s%s_%s" % (
    822             prefix,
    823             (is_str and 's') or (is_unicode and 'u') or 'b',
    824             encoding_prefix,
    825             self.cname[len(Naming.const_prefix):])
    826 
    827         py_string = PyStringConst(
    828             pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
    829         self.py_strings[key] = py_string
    830         return py_string
    831 
    832 class PyStringConst(object):
    833     """Global info about a Python string constant held by GlobalState.
    834     """
    835     # cname       string
    836     # py3str_cstring string
    837     # encoding    string
    838     # intern      boolean
    839     # is_unicode  boolean
    840     # is_str      boolean
    841 
    842     def __init__(self, cname, encoding, is_unicode, is_str=False,
    843                  py3str_cstring=None, intern=False):
    844         self.cname = cname
    845         self.py3str_cstring = py3str_cstring
    846         self.encoding = encoding
    847         self.is_str = is_str
    848         self.is_unicode = is_unicode
    849         self.intern = intern
    850 
    851     def __lt__(self, other):
    852         return self.cname < other.cname
    853 
    854 
    855 class GlobalState(object):
    856     # filename_table   {string : int}  for finding filename table indexes
    857     # filename_list    [string]        filenames in filename table order
    858     # input_file_contents dict         contents (=list of lines) of any file that was used as input
    859     #                                  to create this output C code.  This is
    860     #                                  used to annotate the comments.
    861     #
    862     # utility_codes   set                IDs of used utility code (to avoid reinsertion)
    863     #
    864     # declared_cnames  {string:Entry}  used in a transition phase to merge pxd-declared
    865     #                                  constants etc. into the pyx-declared ones (i.e,
    866     #                                  check if constants are already added).
    867     #                                  In time, hopefully the literals etc. will be
    868     #                                  supplied directly instead.
    869     #
    870     # const_cnames_used  dict          global counter for unique constant identifiers
    871     #
    872 
    873     # parts            {string:CCodeWriter}
    874 
    875 
    876     # interned_strings
    877     # consts
    878     # interned_nums
    879 
    880     # directives       set             Temporary variable used to track
    881     #                                  the current set of directives in the code generation
    882     #                                  process.
    883 
    884     directives = {}
    885 
    886     code_layout = [
    887         'h_code',
    888         'filename_table',
    889         'utility_code_proto_before_types',
    890         'numeric_typedefs',          # Let these detailed individual parts stay!,
    891         'complex_type_declarations', # as the proper solution is to make a full DAG...
    892         'type_declarations',         # More coarse-grained blocks would simply hide
    893         'utility_code_proto',        # the ugliness, not fix it
    894         'module_declarations',
    895         'typeinfo',
    896         'before_global_var',
    897         'global_var',
    898         'decls',
    899         'all_the_rest',
    900         'pystring_table',
    901         'cached_builtins',
    902         'cached_constants',
    903         'init_globals',
    904         'init_module',
    905         'cleanup_globals',
    906         'cleanup_module',
    907         'main_method',
    908         'utility_code_def',
    909         'end'
    910     ]
    911 
    912 
    913     def __init__(self, writer, module_node, emit_linenums=False, common_utility_include_dir=None):
    914         self.filename_table = {}
    915         self.filename_list = []
    916         self.input_file_contents = {}
    917         self.utility_codes = set()
    918         self.declared_cnames = {}
    919         self.in_utility_code_generation = False
    920         self.emit_linenums = emit_linenums
    921         self.common_utility_include_dir = common_utility_include_dir
    922         self.parts = {}
    923         self.module_node = module_node # because some utility code generation needs it
    924                                        # (generating backwards-compatible Get/ReleaseBuffer
    925 
    926         self.const_cnames_used = {}
    927         self.string_const_index = {}
    928         self.pyunicode_ptr_const_index = {}
    929         self.num_const_index = {}
    930         self.py_constants = []
    931 
    932         assert writer.globalstate is None
    933         writer.globalstate = self
    934         self.rootwriter = writer
    935 
    936     def initialize_main_c_code(self):
    937         rootwriter = self.rootwriter
    938         for part in self.code_layout:
    939             self.parts[part] = rootwriter.insertion_point()
    940 
    941         if not Options.cache_builtins:
    942             del self.parts['cached_builtins']
    943         else:
    944             w = self.parts['cached_builtins']
    945             w.enter_cfunc_scope()
    946             w.putln("static int __Pyx_InitCachedBuiltins(void) {")
    947 
    948         w = self.parts['cached_constants']
    949         w.enter_cfunc_scope()
    950         w.putln("")
    951         w.putln("static int __Pyx_InitCachedConstants(void) {")
    952         w.put_declare_refcount_context()
    953         w.put_setup_refcount_context("__Pyx_InitCachedConstants")
    954 
    955         w = self.parts['init_globals']
    956         w.enter_cfunc_scope()
    957         w.putln("")
    958         w.putln("static int __Pyx_InitGlobals(void) {")
    959 
    960         if not Options.generate_cleanup_code:
    961             del self.parts['cleanup_globals']
    962         else:
    963             w = self.parts['cleanup_globals']
    964             w.enter_cfunc_scope()
    965             w.putln("")
    966             w.putln("static void __Pyx_CleanupGlobals(void) {")
    967 
    968         #
    969         # utility_code_def
    970         #
    971         code = self.parts['utility_code_def']
    972         if self.emit_linenums:
    973             code.write('\n#line 1 "cython_utility"\n')
    974         code.putln("")
    975         code.putln("/* Runtime support code */")
    976 
    977     def finalize_main_c_code(self):
    978         self.close_global_decls()
    979 
    980         #
    981         # utility_code_def
    982         #
    983         code = self.parts['utility_code_def']
    984         code.put(UtilityCode.load_as_string("TypeConversions", "TypeConversion.c")[1])
    985         code.putln("")
    986 
    987     def __getitem__(self, key):
    988         return self.parts[key]
    989 
    990     #
    991     # Global constants, interned objects, etc.
    992     #
    993     def close_global_decls(self):
    994         # This is called when it is known that no more global declarations will
    995         # declared.
    996         self.generate_const_declarations()
    997         if Options.cache_builtins:
    998             w = self.parts['cached_builtins']
    999             w.putln("return 0;")
   1000             if w.label_used(w.error_label):
   1001                 w.put_label(w.error_label)
   1002                 w.putln("return -1;")
   1003             w.putln("}")
   1004             w.exit_cfunc_scope()
   1005 
   1006         w = self.parts['cached_constants']
   1007         w.put_finish_refcount_context()
   1008         w.putln("return 0;")
   1009         if w.label_used(w.error_label):
   1010             w.put_label(w.error_label)
   1011             w.put_finish_refcount_context()
   1012             w.putln("return -1;")
   1013         w.putln("}")
   1014         w.exit_cfunc_scope()
   1015 
   1016         w = self.parts['init_globals']
   1017         w.putln("return 0;")
   1018         if w.label_used(w.error_label):
   1019             w.put_label(w.error_label)
   1020             w.putln("return -1;")
   1021         w.putln("}")
   1022         w.exit_cfunc_scope()
   1023 
   1024         if Options.generate_cleanup_code:
   1025             w = self.parts['cleanup_globals']
   1026             w.putln("}")
   1027             w.exit_cfunc_scope()
   1028 
   1029         if Options.generate_cleanup_code:
   1030             w = self.parts['cleanup_module']
   1031             w.putln("}")
   1032             w.exit_cfunc_scope()
   1033 
   1034     def put_pyobject_decl(self, entry):
   1035         self['global_var'].putln("static PyObject *%s;" % entry.cname)
   1036 
   1037     # constant handling at code generation time
   1038 
   1039     def get_cached_constants_writer(self):
   1040         return self.parts['cached_constants']
   1041 
   1042     def get_int_const(self, str_value, longness=False):
   1043         py_type = longness and 'long' or 'int'
   1044         try:
   1045             c = self.num_const_index[(str_value, py_type)]
   1046         except KeyError:
   1047             c = self.new_num_const(str_value, py_type)
   1048         return c
   1049 
   1050     def get_float_const(self, str_value, value_code):
   1051         try:
   1052             c = self.num_const_index[(str_value, 'float')]
   1053         except KeyError:
   1054             c = self.new_num_const(str_value, 'float', value_code)
   1055         return c
   1056 
   1057     def get_py_const(self, type, prefix='', cleanup_level=None):
   1058         # create a new Python object constant
   1059         const = self.new_py_const(type, prefix)
   1060         if cleanup_level is not None \
   1061                 and cleanup_level <= Options.generate_cleanup_code:
   1062             cleanup_writer = self.parts['cleanup_globals']
   1063             cleanup_writer.putln('Py_CLEAR(%s);' % const.cname)
   1064         return const
   1065 
   1066     def get_string_const(self, text, py_version=None):
   1067         # return a C string constant, creating a new one if necessary
   1068         if text.is_unicode:
   1069             byte_string = text.utf8encode()
   1070         else:
   1071             byte_string = text.byteencode()
   1072         try:
   1073             c = self.string_const_index[byte_string]
   1074         except KeyError:
   1075             c = self.new_string_const(text, byte_string)
   1076         c.add_py_version(py_version)
   1077         return c
   1078 
   1079     def get_pyunicode_ptr_const(self, text):
   1080         # return a Py_UNICODE[] constant, creating a new one if necessary
   1081         assert text.is_unicode
   1082         try:
   1083             c = self.pyunicode_ptr_const_index[text]
   1084         except KeyError:
   1085             c = self.pyunicode_ptr_const_index[text] = self.new_const_cname()
   1086         return c
   1087 
   1088     def get_py_string_const(self, text, identifier=None,
   1089                             is_str=False, unicode_value=None):
   1090         # return a Python string constant, creating a new one if necessary
   1091         py3str_cstring = None
   1092         if is_str and unicode_value is not None \
   1093                and unicode_value.utf8encode() != text.byteencode():
   1094             py3str_cstring = self.get_string_const(unicode_value, py_version=3)
   1095             c_string = self.get_string_const(text, py_version=2)
   1096         else:
   1097             c_string = self.get_string_const(text)
   1098         py_string = c_string.get_py_string_const(
   1099             text.encoding, identifier, is_str, py3str_cstring)
   1100         return py_string
   1101 
   1102     def get_interned_identifier(self, text):
   1103         return self.get_py_string_const(text, identifier=True)
   1104 
   1105     def new_string_const(self, text, byte_string):
   1106         cname = self.new_string_const_cname(byte_string)
   1107         c = StringConst(cname, text, byte_string)
   1108         self.string_const_index[byte_string] = c
   1109         return c
   1110 
   1111     def new_num_const(self, value, py_type, value_code=None):
   1112         cname = self.new_num_const_cname(value, py_type)
   1113         c = NumConst(cname, value, py_type, value_code)
   1114         self.num_const_index[(value, py_type)] = c
   1115         return c
   1116 
   1117     def new_py_const(self, type, prefix=''):
   1118         cname = self.new_const_cname(prefix)
   1119         c = PyObjectConst(cname, type)
   1120         self.py_constants.append(c)
   1121         return c
   1122 
   1123     def new_string_const_cname(self, bytes_value):
   1124         # Create a new globally-unique nice name for a C string constant.
   1125         value = bytes_value.decode('ASCII', 'ignore')
   1126         return self.new_const_cname(value=value)
   1127 
   1128     def new_num_const_cname(self, value, py_type):
   1129         if py_type == 'long':
   1130             value += 'L'
   1131             py_type = 'int'
   1132         prefix = Naming.interned_prefixes[py_type]
   1133         cname = "%s%s" % (prefix, value)
   1134         cname = cname.replace('+', '_').replace('-', 'neg_').replace('.', '_')
   1135         return cname
   1136 
   1137     def new_const_cname(self, prefix='', value=''):
   1138         value = replace_identifier('_', value)[:32].strip('_')
   1139         used = self.const_cnames_used
   1140         name_suffix = value
   1141         while name_suffix in used:
   1142             counter = used[value] = used[value] + 1
   1143             name_suffix = '%s_%d' % (value, counter)
   1144         used[name_suffix] = 1
   1145         if prefix:
   1146             prefix = Naming.interned_prefixes[prefix]
   1147         else:
   1148             prefix = Naming.const_prefix
   1149         return "%s%s" % (prefix, name_suffix)
   1150 
   1151     def add_cached_builtin_decl(self, entry):
   1152         if entry.is_builtin and entry.is_const:
   1153             if self.should_declare(entry.cname, entry):
   1154                 self.put_pyobject_decl(entry)
   1155                 w = self.parts['cached_builtins']
   1156                 condition = None
   1157                 if entry.name in non_portable_builtins_map:
   1158                     condition, replacement = non_portable_builtins_map[entry.name]
   1159                     w.putln('#if %s' % condition)
   1160                     self.put_cached_builtin_init(
   1161                         entry.pos, StringEncoding.EncodedString(replacement),
   1162                         entry.cname)
   1163                     w.putln('#else')
   1164                 self.put_cached_builtin_init(
   1165                     entry.pos, StringEncoding.EncodedString(entry.name),
   1166                     entry.cname)
   1167                 if condition:
   1168                     w.putln('#endif')
   1169 
   1170     def put_cached_builtin_init(self, pos, name, cname):
   1171         w = self.parts['cached_builtins']
   1172         interned_cname = self.get_interned_identifier(name).cname
   1173         self.use_utility_code(
   1174             UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c"))
   1175         w.putln('%s = __Pyx_GetBuiltinName(%s); if (!%s) %s' % (
   1176             cname,
   1177             interned_cname,
   1178             cname,
   1179             w.error_goto(pos)))
   1180 
   1181     def generate_const_declarations(self):
   1182         self.generate_string_constants()
   1183         self.generate_num_constants()
   1184         self.generate_object_constant_decls()
   1185 
   1186     def generate_object_constant_decls(self):
   1187         consts = [ (len(c.cname), c.cname, c)
   1188                    for c in self.py_constants ]
   1189         consts.sort()
   1190         decls_writer = self.parts['decls']
   1191         for _, cname, c in consts:
   1192             decls_writer.putln(
   1193                 "static %s;" % c.type.declaration_code(cname))
   1194 
   1195     def generate_string_constants(self):
   1196         c_consts = [ (len(c.cname), c.cname, c)
   1197                      for c in self.string_const_index.values() ]
   1198         c_consts.sort()
   1199         py_strings = []
   1200 
   1201         decls_writer = self.parts['decls']
   1202         for _, cname, c in c_consts:
   1203             conditional = False
   1204             if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
   1205                 conditional = True
   1206                 decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % (
   1207                     (2 in c.py_versions) and '<' or '>='))
   1208             decls_writer.putln('static char %s[] = "%s";' % (
   1209                 cname, StringEncoding.split_string_literal(c.escaped_value)))
   1210             if conditional:
   1211                 decls_writer.putln("#endif")
   1212             if c.py_strings is not None:
   1213                 for py_string in c.py_strings.values():
   1214                     py_strings.append((c.cname, len(py_string.cname), py_string))
   1215 
   1216         for c, cname in self.pyunicode_ptr_const_index.items():
   1217             utf16_array, utf32_array = StringEncoding.encode_pyunicode_string(c)
   1218             if utf16_array:
   1219                 # Narrow and wide representations differ
   1220                 decls_writer.putln("#ifdef Py_UNICODE_WIDE")
   1221             decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf32_array))
   1222             if utf16_array:
   1223                 decls_writer.putln("#else")
   1224                 decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf16_array))
   1225                 decls_writer.putln("#endif")
   1226 
   1227         if py_strings:
   1228             self.use_utility_code(UtilityCode.load_cached("InitStrings", "StringTools.c"))
   1229             py_strings.sort()
   1230             w = self.parts['pystring_table']
   1231             w.putln("")
   1232             w.putln("static __Pyx_StringTabEntry %s[] = {" %
   1233                                       Naming.stringtab_cname)
   1234             for c_cname, _, py_string in py_strings:
   1235                 if not py_string.is_str or not py_string.encoding or \
   1236                        py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
   1237                                               'UTF8', 'UTF-8'):
   1238                     encoding = '0'
   1239                 else:
   1240                     encoding = '"%s"' % py_string.encoding.lower()
   1241 
   1242                 decls_writer.putln(
   1243                     "static PyObject *%s;" % py_string.cname)
   1244                 if py_string.py3str_cstring:
   1245                     w.putln("#if PY_MAJOR_VERSION >= 3")
   1246                     w.putln(
   1247                         "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
   1248                         py_string.cname,
   1249                         py_string.py3str_cstring.cname,
   1250                         py_string.py3str_cstring.cname,
   1251                         '0', 1, 0,
   1252                         py_string.intern
   1253                         ))
   1254                     w.putln("#else")
   1255                 w.putln(
   1256                     "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
   1257                     py_string.cname,
   1258                     c_cname,
   1259                     c_cname,
   1260                     encoding,
   1261                     py_string.is_unicode,
   1262                     py_string.is_str,
   1263                     py_string.intern
   1264                     ))
   1265                 if py_string.py3str_cstring:
   1266                     w.putln("#endif")
   1267             w.putln("{0, 0, 0, 0, 0, 0, 0}")
   1268             w.putln("};")
   1269 
   1270             init_globals = self.parts['init_globals']
   1271             init_globals.putln(
   1272                 "if (__Pyx_InitStrings(%s) < 0) %s;" % (
   1273                     Naming.stringtab_cname,
   1274                     init_globals.error_goto(self.module_pos)))
   1275 
   1276     def generate_num_constants(self):
   1277         consts = [(c.py_type, c.value[0] == '-', len(c.value), c.value, c.value_code, c)
   1278                   for c in self.num_const_index.values()]
   1279         consts.sort()
   1280         decls_writer = self.parts['decls']
   1281         init_globals = self.parts['init_globals']
   1282         for py_type, _, _, value, value_code, c in consts:
   1283             cname = c.cname
   1284             decls_writer.putln("static PyObject *%s;" % cname)
   1285             if py_type == 'float':
   1286                 function = 'PyFloat_FromDouble(%s)'
   1287             elif py_type == 'long':
   1288                 function = 'PyLong_FromString((char *)"%s", 0, 0)'
   1289             elif Utils.long_literal(value):
   1290                 function = 'PyInt_FromString((char *)"%s", 0, 0)'
   1291             elif len(value.lstrip('-')) > 4:
   1292                 function = "PyInt_FromLong(%sL)"
   1293             else:
   1294                 function = "PyInt_FromLong(%s)"
   1295             init_globals.putln('%s = %s; %s' % (
   1296                 cname, function % value_code,
   1297                 init_globals.error_goto_if_null(cname, self.module_pos)))
   1298 
   1299     # The functions below are there in a transition phase only
   1300     # and will be deprecated. They are called from Nodes.BlockNode.
   1301     # The copy&paste duplication is intentional in order to be able
   1302     # to see quickly how BlockNode worked, until this is replaced.
   1303 
   1304     def should_declare(self, cname, entry):
   1305         if cname in self.declared_cnames:
   1306             other = self.declared_cnames[cname]
   1307             assert str(entry.type) == str(other.type)
   1308             assert entry.init == other.init
   1309             return False
   1310         else:
   1311             self.declared_cnames[cname] = entry
   1312             return True
   1313 
   1314     #
   1315     # File name state
   1316     #
   1317 
   1318     def lookup_filename(self, filename):
   1319         try:
   1320             index = self.filename_table[filename]
   1321         except KeyError:
   1322             index = len(self.filename_list)
   1323             self.filename_list.append(filename)
   1324             self.filename_table[filename] = index
   1325         return index
   1326 
   1327     def commented_file_contents(self, source_desc):
   1328         try:
   1329             return self.input_file_contents[source_desc]
   1330         except KeyError:
   1331             pass
   1332         source_file = source_desc.get_lines(encoding='ASCII',
   1333                                             error_handling='ignore')
   1334         try:
   1335             F = [u' * ' + line.rstrip().replace(
   1336                     u'*/', u'*[inserted by cython to avoid comment closer]/'
   1337                     ).replace(
   1338                     u'/*', u'/[inserted by cython to avoid comment start]*'
   1339                     )
   1340                  for line in source_file]
   1341         finally:
   1342             if hasattr(source_file, 'close'):
   1343                 source_file.close()
   1344         if not F: F.append(u'')
   1345         self.input_file_contents[source_desc] = F
   1346         return F
   1347 
   1348     #
   1349     # Utility code state
   1350     #
   1351 
   1352     def use_utility_code(self, utility_code):
   1353         """
   1354         Adds code to the C file. utility_code should
   1355         a) implement __eq__/__hash__ for the purpose of knowing whether the same
   1356            code has already been included
   1357         b) implement put_code, which takes a globalstate instance
   1358 
   1359         See UtilityCode.
   1360         """
   1361         if utility_code not in self.utility_codes:
   1362             self.utility_codes.add(utility_code)
   1363             utility_code.put_code(self)
   1364 
   1365 
   1366 def funccontext_property(name):
   1367     attribute_of = operator.attrgetter(name)
   1368     def get(self):
   1369         return attribute_of(self.funcstate)
   1370     def set(self, value):
   1371         setattr(self.funcstate, name, value)
   1372     return property(get, set)
   1373 
   1374 
   1375 class CCodeWriter(object):
   1376     """
   1377     Utility class to output C code.
   1378 
   1379     When creating an insertion point one must care about the state that is
   1380     kept:
   1381     - formatting state (level, bol) is cloned and used in insertion points
   1382       as well
   1383     - labels, temps, exc_vars: One must construct a scope in which these can
   1384       exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
   1385       sanity checking and forward compatabilty). Created insertion points
   1386       looses this scope and cannot access it.
   1387     - marker: Not copied to insertion point
   1388     - filename_table, filename_list, input_file_contents: All codewriters
   1389       coming from the same root share the same instances simultaneously.
   1390     """
   1391 
   1392     # f                   file            output file
   1393     # buffer              StringIOTree
   1394 
   1395     # level               int             indentation level
   1396     # bol                 bool            beginning of line?
   1397     # marker              string          comment to emit before next line
   1398     # funcstate           FunctionState   contains state local to a C function used for code
   1399     #                                     generation (labels and temps state etc.)
   1400     # globalstate         GlobalState     contains state global for a C file (input file info,
   1401     #                                     utility code, declared constants etc.)
   1402     # emit_linenums       boolean         whether or not to write #line pragmas
   1403     #
   1404     # c_line_in_traceback boolean         append the c file and line number to the traceback for exceptions
   1405     #
   1406     # pyclass_stack       list            used during recursive code generation to pass information
   1407     #                                     about the current class one is in
   1408 
   1409     globalstate = None
   1410 
   1411     def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None, c_line_in_traceback=True):
   1412         if buffer is None: buffer = StringIOTree()
   1413         self.buffer = buffer
   1414         self.marker = None
   1415         self.last_marker_line = 0
   1416         self.source_desc = ""
   1417         self.pyclass_stack = []
   1418 
   1419         self.funcstate = None
   1420         self.level = 0
   1421         self.call_level = 0
   1422         self.bol = 1
   1423 
   1424         if create_from is not None:
   1425             # Use same global state
   1426             self.globalstate = create_from.globalstate
   1427             self.funcstate = create_from.funcstate
   1428             # Clone formatting state
   1429             if copy_formatting:
   1430                 self.level = create_from.level
   1431                 self.bol = create_from.bol
   1432                 self.call_level = create_from.call_level
   1433 
   1434         if emit_linenums is None and self.globalstate:
   1435             self.emit_linenums = self.globalstate.emit_linenums
   1436         else:
   1437             self.emit_linenums = emit_linenums
   1438         self.c_line_in_traceback = c_line_in_traceback
   1439 
   1440     def create_new(self, create_from, buffer, copy_formatting):
   1441         # polymorphic constructor -- very slightly more versatile
   1442         # than using __class__
   1443         result = CCodeWriter(create_from, buffer, copy_formatting,
   1444                              c_line_in_traceback=self.c_line_in_traceback)
   1445         return result
   1446 
   1447     def copyto(self, f):
   1448         self.buffer.copyto(f)
   1449 
   1450     def getvalue(self):
   1451         return self.buffer.getvalue()
   1452 
   1453     def write(self, s):
   1454         # also put invalid markers (lineno 0), to indicate that those lines
   1455         # have no Cython source code correspondence
   1456         if self.marker is None:
   1457             cython_lineno = self.last_marker_line
   1458         else:
   1459             cython_lineno = self.marker[0]
   1460 
   1461         self.buffer.markers.extend([cython_lineno] * s.count('\n'))
   1462         self.buffer.write(s)
   1463 
   1464     def insertion_point(self):
   1465         other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
   1466         return other
   1467 
   1468     def new_writer(self):
   1469         """
   1470         Creates a new CCodeWriter connected to the same global state, which
   1471         can later be inserted using insert.
   1472         """
   1473         return CCodeWriter(create_from=self, c_line_in_traceback=self.c_line_in_traceback)
   1474 
   1475     def insert(self, writer):
   1476         """
   1477         Inserts the contents of another code writer (created with
   1478         the same global state) in the current location.
   1479 
   1480         It is ok to write to the inserted writer also after insertion.
   1481         """
   1482         assert writer.globalstate is self.globalstate
   1483         self.buffer.insert(writer.buffer)
   1484 
   1485     # Properties delegated to function scope
   1486     label_counter = funccontext_property("label_counter")
   1487     return_label = funccontext_property("return_label")
   1488     error_label = funccontext_property("error_label")
   1489     labels_used = funccontext_property("labels_used")
   1490     continue_label = funccontext_property("continue_label")
   1491     break_label = funccontext_property("break_label")
   1492     return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
   1493     yield_labels = funccontext_property("yield_labels")
   1494 
   1495     # Functions delegated to function scope
   1496     def new_label(self, name=None):    return self.funcstate.new_label(name)
   1497     def new_error_label(self):         return self.funcstate.new_error_label()
   1498     def new_yield_label(self):         return self.funcstate.new_yield_label()
   1499     def get_loop_labels(self):         return self.funcstate.get_loop_labels()
   1500     def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
   1501     def new_loop_labels(self):         return self.funcstate.new_loop_labels()
   1502     def get_all_labels(self):          return self.funcstate.get_all_labels()
   1503     def set_all_labels(self, labels):  return self.funcstate.set_all_labels(labels)
   1504     def all_new_labels(self):          return self.funcstate.all_new_labels()
   1505     def use_label(self, lbl):          return self.funcstate.use_label(lbl)
   1506     def label_used(self, lbl):         return self.funcstate.label_used(lbl)
   1507 
   1508 
   1509     def enter_cfunc_scope(self):
   1510         self.funcstate = FunctionState(self)
   1511 
   1512     def exit_cfunc_scope(self):
   1513         self.funcstate = None
   1514 
   1515     # constant handling
   1516 
   1517     def get_py_int(self, str_value, longness):
   1518         return self.globalstate.get_int_const(str_value, longness).cname
   1519 
   1520     def get_py_float(self, str_value, value_code):
   1521         return self.globalstate.get_float_const(str_value, value_code).cname
   1522 
   1523     def get_py_const(self, type, prefix='', cleanup_level=None):
   1524         return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
   1525 
   1526     def get_string_const(self, text):
   1527         return self.globalstate.get_string_const(text).cname
   1528 
   1529     def get_pyunicode_ptr_const(self, text):
   1530         return self.globalstate.get_pyunicode_ptr_const(text)
   1531 
   1532     def get_py_string_const(self, text, identifier=None,
   1533                             is_str=False, unicode_value=None):
   1534         return self.globalstate.get_py_string_const(
   1535             text, identifier, is_str, unicode_value).cname
   1536 
   1537     def get_argument_default_const(self, type):
   1538         return self.globalstate.get_py_const(type).cname
   1539 
   1540     def intern(self, text):
   1541         return self.get_py_string_const(text)
   1542 
   1543     def intern_identifier(self, text):
   1544         return self.get_py_string_const(text, identifier=True)
   1545 
   1546     def get_cached_constants_writer(self):
   1547         return self.globalstate.get_cached_constants_writer()
   1548 
   1549     # code generation
   1550 
   1551     def putln(self, code="", safe=False):
   1552         if self.marker and self.bol:
   1553             self.emit_marker()
   1554         if self.emit_linenums and self.last_marker_line != 0:
   1555             self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
   1556 
   1557         if code:
   1558             if safe:
   1559                 self.put_safe(code)
   1560             else:
   1561                 self.put(code)
   1562         self.write("\n")
   1563         self.bol = 1
   1564 
   1565     def emit_marker(self):
   1566         self.write("\n")
   1567         self.indent()
   1568         self.write("/* %s */\n" % self.marker[1])
   1569         if (self.funcstate and self.funcstate.can_trace
   1570                 and self.globalstate.directives['linetrace']):
   1571             self.indent()
   1572             self.write('__Pyx_TraceLine(%d)\n' % self.marker[0])
   1573         self.last_marker_line = self.marker[0]
   1574         self.marker = None
   1575 
   1576     def put_safe(self, code):
   1577         # put code, but ignore {}
   1578         self.write(code)
   1579         self.bol = 0
   1580 
   1581     def put_or_include(self, code, name):
   1582         include_dir = self.globalstate.common_utility_include_dir
   1583         if include_dir and len(code) > 1024:
   1584             include_file = "%s_%s.h" % (
   1585                 name, hashlib.md5(code.encode('utf8')).hexdigest())
   1586             path = os.path.join(include_dir, include_file)
   1587             if not os.path.exists(path):
   1588                 tmp_path = '%s.tmp%s' % (path, os.getpid())
   1589                 f = Utils.open_new_file(tmp_path)
   1590                 try:
   1591                     f.write(code)
   1592                 finally:
   1593                     f.close()
   1594                 os.rename(tmp_path, path)
   1595             code = '#include "%s"\n' % path
   1596         self.put(code)
   1597 
   1598     def put(self, code):
   1599         if is_self_assignment(code):
   1600             return
   1601         fix_indent = False
   1602         if "{" in code:
   1603             dl = code.count("{")
   1604         else:
   1605             dl = 0
   1606         if "}" in code:
   1607             dl -= code.count("}")
   1608             if dl < 0:
   1609                 self.level += dl
   1610             elif dl == 0 and code[0] == "}":
   1611                 # special cases like "} else {" need a temporary dedent
   1612                 fix_indent = True
   1613                 self.level -= 1
   1614         if self.bol:
   1615             self.indent()
   1616         self.write(code)
   1617         self.bol = 0
   1618         if dl > 0:
   1619             self.level += dl
   1620         elif fix_indent:
   1621             self.level += 1
   1622 
   1623     def putln_tempita(self, code, **context):
   1624         from Cython.Tempita import sub
   1625         self.putln(sub(code, **context))
   1626 
   1627     def put_tempita(self, code, **context):
   1628         from Cython.Tempita import sub
   1629         self.put(sub(code, **context))
   1630 
   1631     def increase_indent(self):
   1632         self.level += 1
   1633 
   1634     def decrease_indent(self):
   1635         self.level -= 1
   1636 
   1637     def begin_block(self):
   1638         self.putln("{")
   1639         self.increase_indent()
   1640 
   1641     def end_block(self):
   1642         self.decrease_indent()
   1643         self.putln("}")
   1644 
   1645     def indent(self):
   1646         self.write("  " * self.level)
   1647 
   1648     def get_py_version_hex(self, pyversion):
   1649         return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
   1650 
   1651     def mark_pos(self, pos):
   1652         if pos is None:
   1653             return
   1654         source_desc, line, col = pos
   1655         if self.last_marker_line == line:
   1656             return
   1657         assert isinstance(source_desc, SourceDescriptor)
   1658         contents = self.globalstate.commented_file_contents(source_desc)
   1659         lines = contents[max(0, line-3):line]  # line numbers start at 1
   1660         lines[-1] += u'             # <<<<<<<<<<<<<<'
   1661         lines += contents[line:line+2]
   1662 
   1663         marker = u'"%s":%d\n%s\n' % (
   1664             source_desc.get_escaped_description(), line, u'\n'.join(lines))
   1665         self.marker = (line, marker)
   1666         if self.emit_linenums:
   1667             self.source_desc = source_desc.get_escaped_description()
   1668 
   1669     def put_label(self, lbl):
   1670         if lbl in self.funcstate.labels_used:
   1671             self.putln("%s:;" % lbl)
   1672 
   1673     def put_goto(self, lbl):
   1674         self.funcstate.use_label(lbl)
   1675         self.putln("goto %s;" % lbl)
   1676 
   1677     def put_var_declaration(self, entry, storage_class="",
   1678                             dll_linkage=None, definition=True):
   1679         #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
   1680         if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
   1681             #print "...private and not definition, skipping", entry.cname ###
   1682             return
   1683         if entry.visibility == "private" and not entry.used:
   1684             #print "...private and not used, skipping", entry.cname ###
   1685             return
   1686         if storage_class:
   1687             self.put("%s " % storage_class)
   1688         if not entry.cf_used:
   1689             self.put('CYTHON_UNUSED ')
   1690         self.put(entry.type.declaration_code(
   1691             entry.cname, dll_linkage=dll_linkage))
   1692         if entry.init is not None:
   1693             self.put_safe(" = %s" % entry.type.literal_code(entry.init))
   1694         elif entry.type.is_pyobject:
   1695             self.put(" = NULL")
   1696         self.putln(";")
   1697 
   1698     def put_temp_declarations(self, func_context):
   1699         for name, type, manage_ref, static in func_context.temps_allocated:
   1700             decl = type.declaration_code(name)
   1701             if type.is_pyobject:
   1702                 self.putln("%s = NULL;" % decl)
   1703             elif type.is_memoryviewslice:
   1704                 import MemoryView
   1705                 self.putln("%s = %s;" % (decl, MemoryView.memslice_entry_init))
   1706             else:
   1707                 self.putln("%s%s;" % (static and "static " or "", decl))
   1708 
   1709         if func_context.should_declare_error_indicator:
   1710             if self.funcstate.uses_error_indicator:
   1711                 unused = ''
   1712             else:
   1713                 unused = 'CYTHON_UNUSED '
   1714             # Initialize these variables to silence compiler warnings
   1715             self.putln("%sint %s = 0;" % (unused, Naming.lineno_cname))
   1716             self.putln("%sconst char *%s = NULL;" % (unused, Naming.filename_cname))
   1717             self.putln("%sint %s = 0;" % (unused, Naming.clineno_cname))
   1718 
   1719     def put_h_guard(self, guard):
   1720         self.putln("#ifndef %s" % guard)
   1721         self.putln("#define %s" % guard)
   1722 
   1723     def unlikely(self, cond):
   1724         if Options.gcc_branch_hints:
   1725             return 'unlikely(%s)' % cond
   1726         else:
   1727             return cond
   1728 
   1729     def build_function_modifiers(self, modifiers, mapper=modifier_output_mapper):
   1730         if not modifiers:
   1731             return ''
   1732         return '%s ' % ' '.join([mapper(m,m) for m in modifiers])
   1733 
   1734     # Python objects and reference counting
   1735 
   1736     def entry_as_pyobject(self, entry):
   1737         type = entry.type
   1738         if (not entry.is_self_arg and not entry.type.is_complete()
   1739             or entry.type.is_extension_type):
   1740             return "(PyObject *)" + entry.cname
   1741         else:
   1742             return entry.cname
   1743 
   1744     def as_pyobject(self, cname, type):
   1745         from PyrexTypes import py_object_type, typecast
   1746         return typecast(py_object_type, type, cname)
   1747 
   1748     def put_gotref(self, cname):
   1749         self.putln("__Pyx_GOTREF(%s);" % cname)
   1750 
   1751     def put_giveref(self, cname):
   1752         self.putln("__Pyx_GIVEREF(%s);" % cname)
   1753 
   1754     def put_xgiveref(self, cname):
   1755         self.putln("__Pyx_XGIVEREF(%s);" % cname)
   1756 
   1757     def put_xgotref(self, cname):
   1758         self.putln("__Pyx_XGOTREF(%s);" % cname)
   1759 
   1760     def put_incref(self, cname, type, nanny=True):
   1761         if nanny:
   1762             self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
   1763         else:
   1764             self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
   1765 
   1766     def put_decref(self, cname, type, nanny=True):
   1767         self._put_decref(cname, type, nanny, null_check=False, clear=False)
   1768 
   1769     def put_var_gotref(self, entry):
   1770         if entry.type.is_pyobject:
   1771             self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
   1772 
   1773     def put_var_giveref(self, entry):
   1774         if entry.type.is_pyobject:
   1775             self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))
   1776 
   1777     def put_var_xgotref(self, entry):
   1778         if entry.type.is_pyobject:
   1779             self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))
   1780 
   1781     def put_var_xgiveref(self, entry):
   1782         if entry.type.is_pyobject:
   1783             self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
   1784 
   1785     def put_var_incref(self, entry):
   1786         if entry.type.is_pyobject:
   1787             self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
   1788 
   1789     def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False):
   1790         self._put_decref(cname, type, nanny, null_check=False,
   1791                          clear=True, clear_before_decref=clear_before_decref)
   1792 
   1793     def put_xdecref(self, cname, type, nanny=True, have_gil=True):
   1794         self._put_decref(cname, type, nanny, null_check=True,
   1795                          have_gil=have_gil, clear=False)
   1796 
   1797     def put_xdecref_clear(self, cname, type, nanny=True, clear_before_decref=False):
   1798         self._put_decref(cname, type, nanny, null_check=True,
   1799                          clear=True, clear_before_decref=clear_before_decref)
   1800 
   1801     def _put_decref(self, cname, type, nanny=True, null_check=False,
   1802                     have_gil=True, clear=False, clear_before_decref=False):
   1803         if type.is_memoryviewslice:
   1804             self.put_xdecref_memoryviewslice(cname, have_gil=have_gil)
   1805             return
   1806 
   1807         prefix = nanny and '__Pyx' or 'Py'
   1808         X = null_check and 'X' or ''
   1809 
   1810         if clear:
   1811             if clear_before_decref:
   1812                 if not nanny:
   1813                     X = ''  # CPython doesn't have a Py_XCLEAR()
   1814                 self.putln("%s_%sCLEAR(%s);" % (prefix, X, cname))
   1815             else:
   1816                 self.putln("%s_%sDECREF(%s); %s = 0;" % (
   1817                     prefix, X, self.as_pyobject(cname, type), cname))
   1818         else:
   1819             self.putln("%s_%sDECREF(%s);" % (
   1820                 prefix, X, self.as_pyobject(cname, type)))
   1821 
   1822     def put_decref_set(self, cname, rhs_cname):
   1823         self.putln("__Pyx_DECREF_SET(%s, %s);" % (cname, rhs_cname))
   1824 
   1825     def put_xdecref_set(self, cname, rhs_cname):
   1826         self.putln("__Pyx_XDECREF_SET(%s, %s);" % (cname, rhs_cname))
   1827 
   1828     def put_var_decref(self, entry):
   1829         if entry.type.is_pyobject:
   1830             self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
   1831 
   1832     def put_var_xdecref(self, entry):
   1833         if entry.type.is_pyobject:
   1834             self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
   1835 
   1836     def put_var_decref_clear(self, entry):
   1837         self._put_var_decref_clear(entry, null_check=False)
   1838 
   1839     def put_var_xdecref_clear(self, entry):
   1840         self._put_var_decref_clear(entry, null_check=True)
   1841 
   1842     def _put_var_decref_clear(self, entry, null_check):
   1843         if entry.type.is_pyobject:
   1844             if entry.in_closure:
   1845                 # reset before DECREF to make sure closure state is
   1846                 # consistent during call to DECREF()
   1847                 self.putln("__Pyx_%sCLEAR(%s);" % (
   1848                     null_check and 'X' or '',
   1849                     entry.cname))
   1850             else:
   1851                 self.putln("__Pyx_%sDECREF(%s); %s = 0;" % (
   1852                     null_check and 'X' or '',
   1853                     self.entry_as_pyobject(entry),
   1854                     entry.cname))
   1855 
   1856     def put_var_decrefs(self, entries, used_only = 0):
   1857         for entry in entries:
   1858             if not used_only or entry.used:
   1859                 if entry.xdecref_cleanup:
   1860                     self.put_var_xdecref(entry)
   1861                 else:
   1862                     self.put_var_decref(entry)
   1863 
   1864     def put_var_xdecrefs(self, entries):
   1865         for entry in entries:
   1866             self.put_var_xdecref(entry)
   1867 
   1868     def put_var_xdecrefs_clear(self, entries):
   1869         for entry in entries:
   1870             self.put_var_xdecref_clear(entry)
   1871 
   1872     def put_incref_memoryviewslice(self, slice_cname, have_gil=False):
   1873         import MemoryView
   1874         self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
   1875         self.putln("__PYX_INC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
   1876 
   1877     def put_xdecref_memoryviewslice(self, slice_cname, have_gil=False):
   1878         import MemoryView
   1879         self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
   1880         self.putln("__PYX_XDEC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
   1881 
   1882     def put_xgiveref_memoryviewslice(self, slice_cname):
   1883         self.put_xgiveref("%s.memview" % slice_cname)
   1884 
   1885     def put_init_to_py_none(self, cname, type, nanny=True):
   1886         from PyrexTypes import py_object_type, typecast
   1887         py_none = typecast(type, py_object_type, "Py_None")
   1888         if nanny:
   1889             self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
   1890         else:
   1891             self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
   1892 
   1893     def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
   1894         code = template % entry.cname
   1895         #if entry.type.is_extension_type:
   1896         #    code = "((PyObject*)%s)" % code
   1897         self.put_init_to_py_none(code, entry.type, nanny)
   1898         if entry.in_closure:
   1899             self.put_giveref('Py_None')
   1900 
   1901     def put_pymethoddef(self, entry, term, allow_skip=True):
   1902         if entry.is_special or entry.name == '__getattribute__':
   1903             if entry.name not in ['__cinit__', '__dealloc__', '__richcmp__', '__next__', '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__', '__getcharbuffer__', '__getbuffer__', '__releasebuffer__']:
   1904                 if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
   1905                     pass
   1906                 # Python's typeobject.c will automatically fill in our slot
   1907                 # in add_operators() (called by PyType_Ready) with a value
   1908                 # that's better than ours.
   1909                 elif allow_skip:
   1910                     return
   1911         from TypeSlots import method_coexist
   1912         if entry.doc:
   1913             doc_code = entry.doc_cname
   1914         else:
   1915             doc_code = 0
   1916         method_flags = entry.signature.method_flags()
   1917         if method_flags:
   1918             if entry.is_special:
   1919                 method_flags += [method_coexist]
   1920             self.putln(
   1921                 '{__Pyx_NAMESTR("%s"), (PyCFunction)%s, %s, __Pyx_DOCSTR(%s)}%s' % (
   1922                     entry.name,
   1923                     entry.func_cname,
   1924                     "|".join(method_flags),
   1925                     doc_code,
   1926                     term))
   1927 
   1928     # GIL methods
   1929 
   1930     def put_ensure_gil(self, declare_gilstate=True, variable=None):
   1931         """
   1932         Acquire the GIL. The generated code is safe even when no PyThreadState
   1933         has been allocated for this thread (for threads not initialized by
   1934         using the Python API). Additionally, the code generated by this method
   1935         may be called recursively.
   1936         """
   1937         self.globalstate.use_utility_code(
   1938             UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
   1939         self.putln("#ifdef WITH_THREAD")
   1940         if not variable:
   1941             variable = '__pyx_gilstate_save'
   1942             if declare_gilstate:
   1943                 self.put("PyGILState_STATE ")
   1944         self.putln("%s = PyGILState_Ensure();" % variable)
   1945         self.putln("#endif")
   1946 
   1947     def put_release_ensured_gil(self, variable=None):
   1948         """
   1949         Releases the GIL, corresponds to `put_ensure_gil`.
   1950         """
   1951         if not variable:
   1952             variable = '__pyx_gilstate_save'
   1953         self.putln("#ifdef WITH_THREAD")
   1954         self.putln("PyGILState_Release(%s);" % variable)
   1955         self.putln("#endif")
   1956 
   1957     def put_acquire_gil(self, variable=None):
   1958         """
   1959         Acquire the GIL. The thread's thread state must have been initialized
   1960         by a previous `put_release_gil`
   1961         """
   1962         self.putln("#ifdef WITH_THREAD")
   1963         if variable:
   1964             self.putln('_save = %s;' % variable)
   1965         self.putln("Py_BLOCK_THREADS")
   1966         self.putln("#endif")
   1967 
   1968     def put_release_gil(self, variable=None):
   1969         "Release the GIL, corresponds to `put_acquire_gil`."
   1970         self.putln("#ifdef WITH_THREAD")
   1971         self.putln("PyThreadState *_save;")
   1972         self.putln("Py_UNBLOCK_THREADS")
   1973         if variable:
   1974             self.putln('%s = _save;' % variable)
   1975         self.putln("#endif")
   1976 
   1977     def declare_gilstate(self):
   1978         self.putln("#ifdef WITH_THREAD")
   1979         self.putln("PyGILState_STATE __pyx_gilstate_save;")
   1980         self.putln("#endif")
   1981 
   1982     # error handling
   1983 
   1984     def put_error_if_neg(self, pos, value):
   1985 #        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!
   1986         return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
   1987 
   1988     def put_error_if_unbound(self, pos, entry, in_nogil_context=False):
   1989         import ExprNodes
   1990         if entry.from_closure:
   1991             func = '__Pyx_RaiseClosureNameError'
   1992             self.globalstate.use_utility_code(
   1993                 ExprNodes.raise_closure_name_error_utility_code)
   1994         elif entry.type.is_memoryviewslice and in_nogil_context:
   1995             func = '__Pyx_RaiseUnboundMemoryviewSliceNogil'
   1996             self.globalstate.use_utility_code(
   1997                 ExprNodes.raise_unbound_memoryview_utility_code_nogil)
   1998         else:
   1999             func = '__Pyx_RaiseUnboundLocalError'
   2000             self.globalstate.use_utility_code(
   2001                 ExprNodes.raise_unbound_local_error_utility_code)
   2002 
   2003         self.putln('if (unlikely(!%s)) { %s("%s"); %s }' % (
   2004                                 entry.type.check_for_null_code(entry.cname),
   2005                                 func,
   2006                                 entry.name,
   2007                                 self.error_goto(pos)))
   2008 
   2009     def set_error_info(self, pos, used=False):
   2010         self.funcstate.should_declare_error_indicator = True
   2011         if used:
   2012             self.funcstate.uses_error_indicator = True
   2013         if self.c_line_in_traceback:
   2014             cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
   2015         else:
   2016             cinfo = ""
   2017 
   2018         return "%s = %s[%s]; %s = %s;%s" % (
   2019             Naming.filename_cname,
   2020             Naming.filetable_cname,
   2021             self.lookup_filename(pos[0]),
   2022             Naming.lineno_cname,
   2023             pos[1],
   2024             cinfo)
   2025 
   2026     def error_goto(self, pos):
   2027         lbl = self.funcstate.error_label
   2028         self.funcstate.use_label(lbl)
   2029         return "{%s goto %s;}" % (
   2030             self.set_error_info(pos),
   2031             lbl)
   2032 
   2033     def error_goto_if(self, cond, pos):
   2034         return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
   2035 
   2036     def error_goto_if_null(self, cname, pos):
   2037         return self.error_goto_if("!%s" % cname, pos)
   2038 
   2039     def error_goto_if_neg(self, cname, pos):
   2040         return self.error_goto_if("%s < 0" % cname, pos)
   2041 
   2042     def error_goto_if_PyErr(self, pos):
   2043         return self.error_goto_if("PyErr_Occurred()", pos)
   2044 
   2045     def lookup_filename(self, filename):
   2046         return self.globalstate.lookup_filename(filename)
   2047 
   2048     def put_declare_refcount_context(self):
   2049         self.putln('__Pyx_RefNannyDeclarations')
   2050 
   2051     def put_setup_refcount_context(self, name, acquire_gil=False):
   2052         if acquire_gil:
   2053             self.globalstate.use_utility_code(
   2054                 UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
   2055         self.putln('__Pyx_RefNannySetupContext("%s", %d);' % (name, acquire_gil and 1 or 0))
   2056 
   2057     def put_finish_refcount_context(self):
   2058         self.putln("__Pyx_RefNannyFinishContext();")
   2059 
   2060     def put_add_traceback(self, qualified_name):
   2061         """
   2062         Build a Python traceback for propagating exceptions.
   2063 
   2064         qualified_name should be the qualified name of the function.
   2065         """
   2066         format_tuple = (
   2067             qualified_name,
   2068             Naming.clineno_cname,
   2069             Naming.lineno_cname,
   2070             Naming.filename_cname,
   2071         )
   2072         self.funcstate.uses_error_indicator = True
   2073         self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple)
   2074 
   2075     def put_unraisable(self, qualified_name):
   2076         """
   2077         Generate code to print a Python warning for an unraisable exception.
   2078 
   2079         qualified_name should be the qualified name of the function.
   2080         """
   2081         format_tuple = (
   2082             qualified_name,
   2083             Naming.clineno_cname,
   2084             Naming.lineno_cname,
   2085             Naming.filename_cname,
   2086             int(self.globalstate.directives['unraisable_tracebacks'])
   2087         )
   2088         self.funcstate.uses_error_indicator = True
   2089         self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %s);' % format_tuple)
   2090         self.globalstate.use_utility_code(
   2091             UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
   2092 
   2093     def put_trace_declarations(self):
   2094         self.putln('__Pyx_TraceDeclarations')
   2095 
   2096     def put_trace_call(self, name, pos):
   2097         self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]))
   2098 
   2099     def put_trace_exception(self):
   2100         self.putln("__Pyx_TraceException();")
   2101 
   2102     def put_trace_return(self, retvalue_cname):
   2103         self.putln("__Pyx_TraceReturn(%s);" % retvalue_cname)
   2104 
   2105     def putln_openmp(self, string):
   2106         self.putln("#ifdef _OPENMP")
   2107         self.putln(string)
   2108         self.putln("#endif /* _OPENMP */")
   2109 
   2110     def undef_builtin_expect(self, cond):
   2111         """
   2112         Redefine the macros likely() and unlikely to no-ops, depending on
   2113         condition 'cond'
   2114         """
   2115         self.putln("#if %s" % cond)
   2116         self.putln("    #undef likely")
   2117         self.putln("    #undef unlikely")
   2118         self.putln("    #define likely(x)   (x)")
   2119         self.putln("    #define unlikely(x) (x)")
   2120         self.putln("#endif")
   2121 
   2122     def redef_builtin_expect(self, cond):
   2123         self.putln("#if %s" % cond)
   2124         self.putln("    #undef likely")
   2125         self.putln("    #undef unlikely")
   2126         self.putln("    #define likely(x)   __builtin_expect(!!(x), 1)")
   2127         self.putln("    #define unlikely(x) __builtin_expect(!!(x), 0)")
   2128         self.putln("#endif")
   2129 
   2130 class PyrexCodeWriter(object):
   2131     # f                file      output file
   2132     # level            int       indentation level
   2133 
   2134     def __init__(self, outfile_name):
   2135         self.f = Utils.open_new_file(outfile_name)
   2136         self.level = 0
   2137 
   2138     def putln(self, code):
   2139         self.f.write("%s%s\n" % (" " * self.level, code))
   2140 
   2141     def indent(self):
   2142         self.level += 1
   2143 
   2144     def dedent(self):
   2145         self.level -= 1
   2146 
   2147 class PyxCodeWriter(object):
   2148     """
   2149     Can be used for writing out some Cython code. To use the indenter
   2150     functionality, the Cython.Compiler.Importer module will have to be used
   2151     to load the code to support python 2.4
   2152     """
   2153 
   2154     def __init__(self, buffer=None, indent_level=0, context=None, encoding='ascii'):
   2155         self.buffer = buffer or StringIOTree()
   2156         self.level = indent_level
   2157         self.context = context
   2158         self.encoding = encoding
   2159 
   2160     def indent(self, levels=1):
   2161         self.level += levels
   2162         return True
   2163 
   2164     def dedent(self, levels=1):
   2165         self.level -= levels
   2166 
   2167     def indenter(self, line):
   2168         """
   2169         Instead of
   2170 
   2171             with pyx_code.indenter("for i in range(10):"):
   2172                 pyx_code.putln("print i")
   2173 
   2174         write
   2175 
   2176             if pyx_code.indenter("for i in range(10);"):
   2177                 pyx_code.putln("print i")
   2178                 pyx_code.dedent()
   2179         """
   2180         self.putln(line)
   2181         self.indent()
   2182         return True
   2183 
   2184     def getvalue(self):
   2185         result = self.buffer.getvalue()
   2186         if not isinstance(result, unicode):
   2187             result = result.decode(self.encoding)
   2188 
   2189         return result
   2190 
   2191     def putln(self, line, context=None):
   2192         context = context or self.context
   2193         if context:
   2194             line = sub_tempita(line, context)
   2195         self._putln(line)
   2196 
   2197     def _putln(self, line):
   2198         self.buffer.write("%s%s\n" % (self.level * "    ", line))
   2199 
   2200     def put_chunk(self, chunk, context=None):
   2201         context = context or self.context
   2202         if context:
   2203             chunk = sub_tempita(chunk, context)
   2204 
   2205         chunk = textwrap.dedent(chunk)
   2206         for line in chunk.splitlines():
   2207             self._putln(line)
   2208 
   2209     def insertion_point(self):
   2210         return PyxCodeWriter(self.buffer.insertion_point(), self.level,
   2211                              self.context)
   2212 
   2213     def named_insertion_point(self, name):
   2214         setattr(self, name, self.insertion_point())
   2215 
   2216 
   2217 class ClosureTempAllocator(object):
   2218     def __init__(self, klass):
   2219         self.klass = klass
   2220         self.temps_allocated = {}
   2221         self.temps_free = {}
   2222         self.temps_count = 0
   2223 
   2224     def reset(self):
   2225         for type, cnames in self.temps_allocated.items():
   2226             self.temps_free[type] = list(cnames)
   2227 
   2228     def allocate_temp(self, type):
   2229         if not type in self.temps_allocated:
   2230             self.temps_allocated[type] = []
   2231             self.temps_free[type] = []
   2232         elif self.temps_free[type]:
   2233             return self.temps_free[type].pop(0)
   2234         cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
   2235         self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
   2236         self.temps_allocated[type].append(cname)
   2237         self.temps_count += 1
   2238         return cname
   2239