fix generators after raise-from merge
[cython.git] / Cython / Compiler / Code.py
1 # cython: language_level = 3, py2_import=True
2 #
3 #   Pyrex - Code output module
4 #
5
6 import cython
7 cython.declare(re=object, Naming=object, Options=object, StringEncoding=object,
8                Utils=object, SourceDescriptor=object, StringIOTree=object,
9                DebugFlags=object, none_or_sub=object, basestring=object)
10
11 import re
12 import Naming
13 import Options
14 import StringEncoding
15 from Cython import Utils
16 from Scanning import SourceDescriptor
17 from Cython.StringIOTree import StringIOTree
18 import DebugFlags
19
20 from Cython.Utils import none_or_sub
21 try:
22     from __builtin__ import basestring
23 except ImportError:
24     from builtins import str as basestring
25
26
27 non_portable_builtins_map = {
28     # builtins that have different names in different Python versions
29     'bytes'         : ('PY_MAJOR_VERSION < 3',  'str'),
30     'unicode'       : ('PY_MAJOR_VERSION >= 3', 'str'),
31     'xrange'        : ('PY_MAJOR_VERSION >= 3', 'range'),
32     'BaseException' : ('PY_VERSION_HEX < 0x02050000', 'Exception'),
33     }
34
35 uncachable_builtins = [
36     # builtin names that cannot be cached because they may or may not
37     # be available at import time
38     'WindowsError',
39     ]
40
41 class UtilityCode(object):
42     # Stores utility code to add during code generation.
43     #
44     # See GlobalState.put_utility_code.
45     #
46     # hashes/equals by instance
47
48     def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None,
49                  proto_block='utility_code_proto'):
50         # proto_block: Which code block to dump prototype in. See GlobalState.
51         self.proto = proto
52         self.impl = impl
53         self.init = init
54         self.cleanup = cleanup
55         self.requires = requires
56         self._cache = {}
57         self.specialize_list = []
58         self.proto_block = proto_block
59
60     def specialize(self, pyrex_type=None, **data):
61         # Dicts aren't hashable...
62         if pyrex_type is not None:
63             data['type'] = pyrex_type.declaration_code('')
64             data['type_name'] = pyrex_type.specialization_name()
65         key = data.items(); key.sort(); key = tuple(key)
66         try:
67             return self._cache[key]
68         except KeyError:
69             if self.requires is None:
70                 requires = None
71             else:
72                 requires = [r.specialize(data) for r in self.requires]
73             s = self._cache[key] = UtilityCode(
74                                         none_or_sub(self.proto, data),
75                                         none_or_sub(self.impl, data),
76                                         none_or_sub(self.init, data),
77                                         none_or_sub(self.cleanup, data),
78                                         requires, self.proto_block)
79             self.specialize_list.append(s)
80             return s
81
82     def put_code(self, output):
83         if self.requires:
84             for dependency in self.requires:
85                 output.use_utility_code(dependency)
86         if self.proto:
87             output[self.proto_block].put(self.proto)
88         if self.impl:
89             output['utility_code_def'].put(self.impl)
90         if self.init:
91             writer = output['init_globals']
92             if isinstance(self.init, basestring):
93                 writer.put(self.init)
94             else:
95                 self.init(writer, output.module_pos)
96         if self.cleanup and Options.generate_cleanup_code:
97             writer = output['cleanup_globals']
98             if isinstance(self.cleanup, basestring):
99                 writer.put(self.cleanup)
100             else:
101                 self.cleanup(writer, output.module_pos)
102
103
104
105 class FunctionState(object):
106     # return_label     string          function return point label
107     # error_label      string          error catch point label
108     # continue_label   string          loop continue point label
109     # break_label      string          loop break point label
110     # return_from_error_cleanup_label string
111     # label_counter    integer         counter for naming labels
112     # in_try_finally   boolean         inside try of try...finally
113     # exc_vars         (string * 3)    exception variables for reraise, or None
114
115     # Not used for now, perhaps later
116     def __init__(self, owner, names_taken=cython.set()):
117         self.names_taken = names_taken
118         self.owner = owner
119
120         self.error_label = None
121         self.label_counter = 0
122         self.labels_used = cython.set()
123         self.return_label = self.new_label()
124         self.new_error_label()
125         self.continue_label = None
126         self.break_label = None
127
128         self.in_try_finally = 0
129         self.exc_vars = None
130
131         self.temps_allocated = [] # of (name, type, manage_ref)
132         self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
133         self.temps_used_type = {} # name -> (type, manage_ref)
134         self.temp_counter = 0
135         self.closure_temps = None
136
137     # labels
138
139     def new_label(self, name=None):
140         n = self.label_counter
141         self.label_counter = n + 1
142         label = "%s%d" % (Naming.label_prefix, n)
143         if name is not None:
144             label += '_' + name
145         return label
146
147     def new_error_label(self):
148         old_err_lbl = self.error_label
149         self.error_label = self.new_label('error')
150         return old_err_lbl
151
152     def get_loop_labels(self):
153         return (
154             self.continue_label,
155             self.break_label)
156
157     def set_loop_labels(self, labels):
158         (self.continue_label,
159          self.break_label) = labels
160
161     def new_loop_labels(self):
162         old_labels = self.get_loop_labels()
163         self.set_loop_labels(
164             (self.new_label("continue"),
165              self.new_label("break")))
166         return old_labels
167
168     def get_all_labels(self):
169         return (
170             self.continue_label,
171             self.break_label,
172             self.return_label,
173             self.error_label)
174
175     def set_all_labels(self, labels):
176         (self.continue_label,
177          self.break_label,
178          self.return_label,
179          self.error_label) = labels
180
181     def all_new_labels(self):
182         old_labels = self.get_all_labels()
183         new_labels = []
184         for old_label in old_labels:
185             if old_label:
186                 new_labels.append(self.new_label())
187             else:
188                 new_labels.append(old_label)
189         self.set_all_labels(new_labels)
190         return old_labels
191
192     def use_label(self, lbl):
193         self.labels_used.add(lbl)
194
195     def label_used(self, lbl):
196         return lbl in self.labels_used
197
198     # temp handling
199
200     def allocate_temp(self, type, manage_ref):
201         """
202         Allocates a temporary (which may create a new one or get a previously
203         allocated and released one of the same type). Type is simply registered
204         and handed back, but will usually be a PyrexType.
205
206         If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
207         True, the temp will be decref-ed on return statements and in exception
208         handling clauses. Otherwise the caller has to deal with any reference
209         counting of the variable.
210
211         If not type.is_pyobject, then manage_ref will be ignored, but it
212         still has to be passed. It is recommended to pass False by convention
213         if it is known that type will never be a Python object.
214
215         A C string referring to the variable is returned.
216         """
217         if not type.is_pyobject:
218             # Make manage_ref canonical, so that manage_ref will always mean
219             # a decref is needed.
220             manage_ref = False
221         freelist = self.temps_free.get((type, manage_ref))
222         if freelist is not None and len(freelist) > 0:
223             result = freelist.pop()
224         else:
225             while True:
226                 self.temp_counter += 1
227                 result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
228                 if not result in self.names_taken: break
229             self.temps_allocated.append((result, type, manage_ref))
230         self.temps_used_type[result] = (type, manage_ref)
231         if DebugFlags.debug_temp_code_comments:
232             self.owner.putln("/* %s allocated */" % result)
233         return result
234
235     def release_temp(self, name):
236         """
237         Releases a temporary so that it can be reused by other code needing
238         a temp of the same type.
239         """
240         type, manage_ref = self.temps_used_type[name]
241         freelist = self.temps_free.get((type, manage_ref))
242         if freelist is None:
243             freelist = []
244             self.temps_free[(type, manage_ref)] = freelist
245         if name in freelist:
246             raise RuntimeError("Temp %s freed twice!" % name)
247         freelist.append(name)
248         if DebugFlags.debug_temp_code_comments:
249             self.owner.putln("/* %s released */" % name)
250
251     def temps_in_use(self):
252         """Return a list of (cname,type,manage_ref) tuples of temp names and their type
253         that are currently in use.
254         """
255         used = []
256         for name, type, manage_ref in self.temps_allocated:
257             freelist = self.temps_free.get((type, manage_ref))
258             if freelist is None or name not in freelist:
259                 used.append((name, type, manage_ref))
260         return used
261
262     def temps_holding_reference(self):
263         """Return a list of (cname,type) tuples of temp names and their type
264         that are currently in use. This includes only temps of a
265         Python object type which owns its reference.
266         """
267         return [(name, type)
268                 for name, type, manage_ref in self.temps_in_use()
269                 if manage_ref]
270
271     def all_managed_temps(self):
272         """Return a list of (cname, type) tuples of refcount-managed Python objects.
273         """
274         return [(cname, type)
275                 for cname, type, manage_ref in self.temps_allocated
276                 if manage_ref]
277
278     def all_free_managed_temps(self):
279         """Return a list of (cname, type) tuples of refcount-managed Python
280         objects that are not currently in use.  This is used by
281         try-except and try-finally blocks to clean up temps in the
282         error case.
283         """
284         return [(cname, type)
285                 for (type, manage_ref), freelist in self.temps_free.items()
286                 if manage_ref
287                 for cname in freelist]
288
289     def init_closure_temps(self, scope):
290         self.closure_temps = ClosureTempAllocator(scope)
291
292
293 class IntConst(object):
294     """Global info about a Python integer constant held by GlobalState.
295     """
296     # cname     string
297     # value     int
298     # is_long   boolean
299
300     def __init__(self, cname, value, is_long):
301         self.cname = cname
302         self.value = value
303         self.is_long = is_long
304
305 class PyObjectConst(object):
306     """Global info about a generic constant held by GlobalState.
307     """
308     # cname       string
309     # type        PyrexType
310
311     def __init__(self, cname, type):
312         self.cname = cname
313         self.type = type
314
315 cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
316                nice_identifier=object, find_alphanums=object)
317 possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
318 possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
319 nice_identifier = re.compile(r'\A[a-zA-Z0-9_]+\Z').match
320 find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
321
322 class StringConst(object):
323     """Global info about a C string constant held by GlobalState.
324     """
325     # cname            string
326     # text             EncodedString or BytesLiteral
327     # py_strings       {(identifier, encoding) : PyStringConst}
328
329     def __init__(self, cname, text, byte_string):
330         self.cname = cname
331         self.text = text
332         self.escaped_value = StringEncoding.escape_byte_string(byte_string)
333         self.py_strings = None
334         self.py_versions = []
335
336     def add_py_version(self, version):
337         if not version:
338             self.py_versions = [2,3]
339         elif version not in self.py_versions:
340             self.py_versions.append(version)
341
342     def get_py_string_const(self, encoding, identifier=None,
343                             is_str=False, py3str_cstring=None):
344         py_strings = self.py_strings
345         text = self.text
346
347         is_str = bool(identifier or is_str)
348         is_unicode = encoding is None and not is_str
349
350         if encoding is None:
351             # unicode string
352             encoding_key = None
353         else:
354             # bytes or str
355             encoding = encoding.lower()
356             if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
357                 encoding = None
358                 encoding_key = None
359             else:
360                 encoding_key = ''.join(find_alphanums(encoding))
361
362         key = (is_str, is_unicode, encoding_key, py3str_cstring)
363         if py_strings is not None:
364             try:
365                 return py_strings[key]
366             except KeyError:
367                 pass
368         else:
369             self.py_strings = {}
370
371         if identifier:
372             intern = True
373         elif identifier is None:
374             if isinstance(text, unicode):
375                 intern = bool(possible_unicode_identifier(text))
376             else:
377                 intern = bool(possible_bytes_identifier(text))
378         else:
379             intern = False
380         if intern:
381             prefix = Naming.interned_str_prefix
382         else:
383             prefix = Naming.py_const_prefix
384         pystring_cname = "%s%s_%s" % (
385             prefix,
386             (is_str and 's') or (is_unicode and 'u') or 'b',
387             self.cname[len(Naming.const_prefix):])
388
389         py_string = PyStringConst(
390             pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
391         self.py_strings[key] = py_string
392         return py_string
393
394 class PyStringConst(object):
395     """Global info about a Python string constant held by GlobalState.
396     """
397     # cname       string
398     # py3str_cstring string
399     # encoding    string
400     # intern      boolean
401     # is_unicode  boolean
402     # is_str      boolean
403
404     def __init__(self, cname, encoding, is_unicode, is_str=False,
405                  py3str_cstring=None, intern=False):
406         self.cname = cname
407         self.py3str_cstring = py3str_cstring
408         self.encoding = encoding
409         self.is_str = is_str
410         self.is_unicode = is_unicode
411         self.intern = intern
412
413     def __lt__(self, other):
414         return self.cname < other.cname
415
416
417 class GlobalState(object):
418     # filename_table   {string : int}  for finding filename table indexes
419     # filename_list    [string]        filenames in filename table order
420     # input_file_contents dict         contents (=list of lines) of any file that was used as input
421     #                                  to create this output C code.  This is
422     #                                  used to annotate the comments.
423     #
424     # utility_codes   set                IDs of used utility code (to avoid reinsertion)
425     #
426     # declared_cnames  {string:Entry}  used in a transition phase to merge pxd-declared
427     #                                  constants etc. into the pyx-declared ones (i.e,
428     #                                  check if constants are already added).
429     #                                  In time, hopefully the literals etc. will be
430     #                                  supplied directly instead.
431     #
432     # const_cname_counter int          global counter for constant identifiers
433     #
434
435     # parts            {string:CCodeWriter}
436
437
438     # interned_strings
439     # consts
440     # interned_nums
441
442     # directives       set             Temporary variable used to track
443     #                                  the current set of directives in the code generation
444     #                                  process.
445
446     directives = {}
447
448     code_layout = [
449         'h_code',
450         'filename_table',
451         'utility_code_proto_before_types',
452         'numeric_typedefs',          # Let these detailed individual parts stay!,
453         'complex_type_declarations', # as the proper solution is to make a full DAG...
454         'type_declarations',         # More coarse-grained blocks would simply hide
455         'utility_code_proto',        # the ugliness, not fix it
456         'module_declarations',
457         'typeinfo',
458         'before_global_var',
459         'global_var',
460         'decls',
461         'all_the_rest',
462         'pystring_table',
463         'cached_builtins',
464         'cached_constants',
465         'init_globals',
466         'init_module',
467         'cleanup_globals',
468         'cleanup_module',
469         'main_method',
470         'utility_code_def',
471         'end'
472     ]
473
474
475     def __init__(self, writer, emit_linenums=False):
476         self.filename_table = {}
477         self.filename_list = []
478         self.input_file_contents = {}
479         self.utility_codes = cython.set()
480         self.declared_cnames = {}
481         self.in_utility_code_generation = False
482         self.emit_linenums = emit_linenums
483         self.parts = {}
484
485         self.const_cname_counter = 1
486         self.string_const_index = {}
487         self.int_const_index = {}
488         self.py_constants = []
489
490         assert writer.globalstate is None
491         writer.globalstate = self
492         self.rootwriter = writer
493
494     def initialize_main_c_code(self):
495         rootwriter = self.rootwriter
496         for part in self.code_layout:
497             self.parts[part] = rootwriter.insertion_point()
498
499         if not Options.cache_builtins:
500             del self.parts['cached_builtins']
501         else:
502             w = self.parts['cached_builtins']
503             w.enter_cfunc_scope()
504             w.putln("static int __Pyx_InitCachedBuiltins(void) {")
505
506         w = self.parts['cached_constants']
507         w.enter_cfunc_scope()
508         w.putln("")
509         w.putln("static int __Pyx_InitCachedConstants(void) {")
510         w.put_declare_refcount_context()
511         w.put_setup_refcount_context("__Pyx_InitCachedConstants")
512
513         w = self.parts['init_globals']
514         w.enter_cfunc_scope()
515         w.putln("")
516         w.putln("static int __Pyx_InitGlobals(void) {")
517
518         if not Options.generate_cleanup_code:
519             del self.parts['cleanup_globals']
520         else:
521             w = self.parts['cleanup_globals']
522             w.enter_cfunc_scope()
523             w.putln("")
524             w.putln("static void __Pyx_CleanupGlobals(void) {")
525
526         #
527         # utility_code_def
528         #
529         code = self.parts['utility_code_def']
530         if self.emit_linenums:
531             code.write('\n#line 1 "cython_utility"\n')
532         code.putln("")
533         code.putln("/* Runtime support code */")
534
535     def finalize_main_c_code(self):
536         self.close_global_decls()
537
538         #
539         # utility_code_def
540         #
541         code = self.parts['utility_code_def']
542         import PyrexTypes
543         code.put(PyrexTypes.type_conversion_functions)
544         code.putln("")
545
546     def __getitem__(self, key):
547         return self.parts[key]
548
549     #
550     # Global constants, interned objects, etc.
551     #
552     def close_global_decls(self):
553         # This is called when it is known that no more global declarations will
554         # declared.
555         self.generate_const_declarations()
556         if Options.cache_builtins:
557             w = self.parts['cached_builtins']
558             w.putln("return 0;")
559             if w.label_used(w.error_label):
560                 w.put_label(w.error_label)
561                 w.putln("return -1;")
562             w.putln("}")
563             w.exit_cfunc_scope()
564
565         w = self.parts['cached_constants']
566         w.put_finish_refcount_context()
567         w.putln("return 0;")
568         if w.label_used(w.error_label):
569             w.put_label(w.error_label)
570             w.put_finish_refcount_context()
571             w.putln("return -1;")
572         w.putln("}")
573         w.exit_cfunc_scope()
574
575         w = self.parts['init_globals']
576         w.putln("return 0;")
577         if w.label_used(w.error_label):
578             w.put_label(w.error_label)
579             w.putln("return -1;")
580         w.putln("}")
581         w.exit_cfunc_scope()
582
583         if Options.generate_cleanup_code:
584             w = self.parts['cleanup_globals']
585             w.putln("}")
586             w.exit_cfunc_scope()
587
588         if Options.generate_cleanup_code:
589             w = self.parts['cleanup_module']
590             w.putln("}")
591             w.exit_cfunc_scope()
592
593     def put_pyobject_decl(self, entry):
594         self['global_var'].putln("static PyObject *%s;" % entry.cname)
595
596     # constant handling at code generation time
597
598     def get_cached_constants_writer(self):
599         return self.parts['cached_constants']
600
601     def get_int_const(self, str_value, longness=False):
602         longness = bool(longness)
603         try:
604             c = self.int_const_index[(str_value, longness)]
605         except KeyError:
606             c = self.new_int_const(str_value, longness)
607         return c
608
609     def get_py_const(self, type, prefix='', cleanup_level=None):
610         # create a new Python object constant
611         const = self.new_py_const(type, prefix)
612         if cleanup_level is not None \
613                and cleanup_level <= Options.generate_cleanup_code:
614             cleanup_writer = self.parts['cleanup_globals']
615             cleanup_writer.put_xdecref_clear(const.cname, type, nanny=False)
616         return const
617
618     def get_string_const(self, text, py_version=None):
619         # return a C string constant, creating a new one if necessary
620         if text.is_unicode:
621             byte_string = text.utf8encode()
622         else:
623             byte_string = text.byteencode()
624         try:
625             c = self.string_const_index[byte_string]
626         except KeyError:
627             c = self.new_string_const(text, byte_string)
628         c.add_py_version(py_version)
629         return c
630
631     def get_py_string_const(self, text, identifier=None,
632                             is_str=False, unicode_value=None):
633         # return a Python string constant, creating a new one if necessary
634         py3str_cstring = None
635         if is_str and unicode_value is not None \
636                and unicode_value.utf8encode() != text.byteencode():
637             py3str_cstring = self.get_string_const(unicode_value, py_version=3)
638             c_string = self.get_string_const(text, py_version=2)
639         else:
640             c_string = self.get_string_const(text)
641         py_string = c_string.get_py_string_const(
642             text.encoding, identifier, is_str, py3str_cstring)
643         return py_string
644
645     def get_interned_identifier(self, text):
646         return self.get_py_string_const(text, identifier=True)
647
648     def new_string_const(self, text, byte_string):
649         cname = self.new_string_const_cname(byte_string)
650         c = StringConst(cname, text, byte_string)
651         self.string_const_index[byte_string] = c
652         return c
653
654     def new_int_const(self, value, longness):
655         cname = self.new_int_const_cname(value, longness)
656         c = IntConst(cname, value, longness)
657         self.int_const_index[(value, longness)] = c
658         return c
659
660     def new_py_const(self, type, prefix=''):
661         cname = self.new_const_cname(prefix)
662         c = PyObjectConst(cname, type)
663         self.py_constants.append(c)
664         return c
665
666     def new_string_const_cname(self, bytes_value, intern=None):
667         # Create a new globally-unique nice name for a C string constant.
668         try:
669             value = bytes_value.decode('ASCII')
670         except UnicodeError:
671             return self.new_const_cname()
672
673         if len(value) < 20 and nice_identifier(value):
674             return "%s_%s" % (Naming.const_prefix, value)
675         else:
676             return self.new_const_cname()
677
678     def new_int_const_cname(self, value, longness):
679         if longness:
680             value += 'L'
681         cname = "%s%s" % (Naming.interned_num_prefix, value)
682         cname = cname.replace('-', 'neg_').replace('.','_')
683         return cname
684
685     def new_const_cname(self, prefix=''):
686         n = self.const_cname_counter
687         self.const_cname_counter += 1
688         return "%s%s%d" % (Naming.const_prefix, prefix, n)
689
690     def add_cached_builtin_decl(self, entry):
691         if entry.is_builtin and entry.is_const:
692             if self.should_declare(entry.cname, entry):
693                 self.put_pyobject_decl(entry)
694                 w = self.parts['cached_builtins']
695                 condition = None
696                 if entry.name in non_portable_builtins_map:
697                     condition, replacement = non_portable_builtins_map[entry.name]
698                     w.putln('#if %s' % condition)
699                     self.put_cached_builtin_init(
700                         entry.pos, StringEncoding.EncodedString(replacement),
701                         entry.cname)
702                     w.putln('#else')
703                 self.put_cached_builtin_init(
704                     entry.pos, StringEncoding.EncodedString(entry.name),
705                     entry.cname)
706                 if condition:
707                     w.putln('#endif')
708
709     def put_cached_builtin_init(self, pos, name, cname):
710         w = self.parts['cached_builtins']
711         interned_cname = self.get_interned_identifier(name).cname
712         from ExprNodes import get_name_interned_utility_code
713         self.use_utility_code(get_name_interned_utility_code)
714         w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
715             cname,
716             Naming.builtins_cname,
717             interned_cname,
718             cname,
719             w.error_goto(pos)))
720
721     def generate_const_declarations(self):
722         self.generate_string_constants()
723         self.generate_int_constants()
724         self.generate_object_constant_decls()
725
726     def generate_object_constant_decls(self):
727         consts = [ (len(c.cname), c.cname, c)
728                    for c in self.py_constants ]
729         consts.sort()
730         decls_writer = self.parts['decls']
731         for _, cname, c in consts:
732             decls_writer.putln(
733                 "static %s;" % c.type.declaration_code(cname))
734
735     def generate_string_constants(self):
736         c_consts = [ (len(c.cname), c.cname, c)
737                      for c in self.string_const_index.values() ]
738         c_consts.sort()
739         py_strings = []
740
741         decls_writer = self.parts['decls']
742         for _, cname, c in c_consts:
743             conditional = False
744             if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
745                 conditional = True
746                 decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % (
747                     (2 in c.py_versions) and '<' or '>='))
748             decls_writer.putln('static char %s[] = "%s";' % (
749                 cname, StringEncoding.split_string_literal(c.escaped_value)))
750             if conditional:
751                 decls_writer.putln("#endif")
752             if c.py_strings is not None:
753                 for py_string in c.py_strings.values():
754                     py_strings.append((c.cname, len(py_string.cname), py_string))
755
756         if py_strings:
757             import Nodes
758             self.use_utility_code(Nodes.init_string_tab_utility_code)
759
760             py_strings.sort()
761             w = self.parts['pystring_table']
762             w.putln("")
763             w.putln("static __Pyx_StringTabEntry %s[] = {" %
764                                       Naming.stringtab_cname)
765             for c_cname, _, py_string in py_strings:
766                 if not py_string.is_str or not py_string.encoding or \
767                        py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
768                                               'UTF8', 'UTF-8'):
769                     encoding = '0'
770                 else:
771                     encoding = '"%s"' % py_string.encoding.lower()
772
773                 decls_writer.putln(
774                     "static PyObject *%s;" % py_string.cname)
775                 if py_string.py3str_cstring:
776                     w.putln("#if PY_MAJOR_VERSION >= 3")
777                     w.putln(
778                         "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
779                         py_string.cname,
780                         py_string.py3str_cstring.cname,
781                         py_string.py3str_cstring.cname,
782                         '0', 1, 0,
783                         py_string.intern
784                         ))
785                     w.putln("#else")
786                 w.putln(
787                     "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
788                     py_string.cname,
789                     c_cname,
790                     c_cname,
791                     encoding,
792                     py_string.is_unicode,
793                     py_string.is_str,
794                     py_string.intern
795                     ))
796                 if py_string.py3str_cstring:
797                     w.putln("#endif")
798             w.putln("{0, 0, 0, 0, 0, 0, 0}")
799             w.putln("};")
800
801             init_globals = self.parts['init_globals']
802             init_globals.putln(
803                 "if (__Pyx_InitStrings(%s) < 0) %s;" % (
804                     Naming.stringtab_cname,
805                     init_globals.error_goto(self.module_pos)))
806
807     def generate_int_constants(self):
808         consts = [ (len(c.value), c.value, c.is_long, c)
809                    for c in self.int_const_index.values() ]
810         consts.sort()
811         decls_writer = self.parts['decls']
812         for _, value, longness, c in consts:
813             cname = c.cname
814             decls_writer.putln("static PyObject *%s;" % cname)
815             if longness:
816                 function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
817             elif Utils.long_literal(value):
818                 function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;'
819             else:
820                 function = "%s = PyInt_FromLong(%s); %s;"
821             init_globals = self.parts['init_globals']
822             init_globals.putln(function % (
823                 cname,
824                 value,
825                 init_globals.error_goto_if_null(cname, self.module_pos)))
826
827     # The functions below are there in a transition phase only
828     # and will be deprecated. They are called from Nodes.BlockNode.
829     # The copy&paste duplication is intentional in order to be able
830     # to see quickly how BlockNode worked, until this is replaced.
831
832     def should_declare(self, cname, entry):
833         if cname in self.declared_cnames:
834             other = self.declared_cnames[cname]
835             assert str(entry.type) == str(other.type)
836             assert entry.init == other.init
837             return False
838         else:
839             self.declared_cnames[cname] = entry
840             return True
841
842     #
843     # File name state
844     #
845
846     def lookup_filename(self, filename):
847         try:
848             index = self.filename_table[filename]
849         except KeyError:
850             index = len(self.filename_list)
851             self.filename_list.append(filename)
852             self.filename_table[filename] = index
853         return index
854
855     def commented_file_contents(self, source_desc):
856         try:
857             return self.input_file_contents[source_desc]
858         except KeyError:
859             pass
860         source_file = source_desc.get_lines(encoding='ASCII',
861                                             error_handling='ignore')
862         try:
863             F = [u' * ' + line.rstrip().replace(
864                     u'*/', u'*[inserted by cython to avoid comment closer]/'
865                     ).replace(
866                     u'/*', u'/[inserted by cython to avoid comment start]*'
867                     )
868                  for line in source_file]
869         finally:
870             if hasattr(source_file, 'close'):
871                 source_file.close()
872         if not F: F.append(u'')
873         self.input_file_contents[source_desc] = F
874         return F
875
876     #
877     # Utility code state
878     #
879
880     def use_utility_code(self, utility_code):
881         """
882         Adds code to the C file. utility_code should
883         a) implement __eq__/__hash__ for the purpose of knowing whether the same
884            code has already been included
885         b) implement put_code, which takes a globalstate instance
886
887         See UtilityCode.
888         """
889         if utility_code not in self.utility_codes:
890             self.utility_codes.add(utility_code)
891             utility_code.put_code(self)
892
893
894 def funccontext_property(name):
895     try:
896         import operator
897         attribute_of = operator.attrgetter(name)
898     except:
899         def attribute_of(o):
900             return getattr(o, name)
901
902     def get(self):
903         return attribute_of(self.funcstate)
904     def set(self, value):
905         setattr(self.funcstate, name, value)
906     return property(get, set)
907
908
909 class CCodeWriter(object):
910     """
911     Utility class to output C code.
912
913     When creating an insertion point one must care about the state that is
914     kept:
915     - formatting state (level, bol) is cloned and used in insertion points
916       as well
917     - labels, temps, exc_vars: One must construct a scope in which these can
918       exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
919       sanity checking and forward compatabilty). Created insertion points
920       looses this scope and cannot access it.
921     - marker: Not copied to insertion point
922     - filename_table, filename_list, input_file_contents: All codewriters
923       coming from the same root share the same instances simultaneously.
924     """
925
926     # f                   file            output file
927     # buffer              StringIOTree
928
929     # level               int             indentation level
930     # bol                 bool            beginning of line?
931     # marker              string          comment to emit before next line
932     # funcstate           FunctionState   contains state local to a C function used for code
933     #                                     generation (labels and temps state etc.)
934     # globalstate         GlobalState     contains state global for a C file (input file info,
935     #                                     utility code, declared constants etc.)
936     # emit_linenums       boolean         whether or not to write #line pragmas
937     #
938     # c_line_in_traceback boolean         append the c file and line number to the traceback for exceptions
939     #
940     # pyclass_stack       list            used during recursive code generation to pass information
941     #                                     about the current class one is in
942
943     globalstate = None
944
945     def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None, c_line_in_traceback=True):
946         if buffer is None: buffer = StringIOTree()
947         self.buffer = buffer
948         self.marker = None
949         self.last_marker_line = 0
950         self.source_desc = ""
951         self.pyclass_stack = []
952
953         self.funcstate = None
954         self.level = 0
955         self.call_level = 0
956         self.bol = 1
957
958         if create_from is not None:
959             # Use same global state
960             self.globalstate = create_from.globalstate
961             # Clone formatting state
962             if copy_formatting:
963                 self.level = create_from.level
964                 self.bol = create_from.bol
965                 self.call_level = create_from.call_level
966         if emit_linenums is None and self.globalstate:
967             self.emit_linenums = self.globalstate.emit_linenums
968         else:
969             self.emit_linenums = emit_linenums
970         self.c_line_in_traceback = c_line_in_traceback
971
972     def create_new(self, create_from, buffer, copy_formatting):
973         # polymorphic constructor -- very slightly more versatile
974         # than using __class__
975         result = CCodeWriter(create_from, buffer, copy_formatting, c_line_in_traceback=self.c_line_in_traceback)
976         return result
977
978     def copyto(self, f):
979         self.buffer.copyto(f)
980
981     def getvalue(self):
982         return self.buffer.getvalue()
983
984     def write(self, s):
985         # also put invalid markers (lineno 0), to indicate that those lines
986         # have no Cython source code correspondence
987         if self.marker is None:
988             cython_lineno = self.last_marker_line
989         else:
990             cython_lineno = self.marker[0]
991
992         self.buffer.markers.extend([cython_lineno] * s.count('\n'))
993         self.buffer.write(s)
994
995     def insertion_point(self):
996         other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
997         return other
998
999     def new_writer(self):
1000         """
1001         Creates a new CCodeWriter connected to the same global state, which
1002         can later be inserted using insert.
1003         """
1004         return CCodeWriter(create_from=self, c_line_in_traceback=self.c_line_in_traceback)
1005
1006     def insert(self, writer):
1007         """
1008         Inserts the contents of another code writer (created with
1009         the same global state) in the current location.
1010
1011         It is ok to write to the inserted writer also after insertion.
1012         """
1013         assert writer.globalstate is self.globalstate
1014         self.buffer.insert(writer.buffer)
1015
1016     # Properties delegated to function scope
1017     label_counter = funccontext_property("label_counter")
1018     return_label = funccontext_property("return_label")
1019     error_label = funccontext_property("error_label")
1020     labels_used = funccontext_property("labels_used")
1021     continue_label = funccontext_property("continue_label")
1022     break_label = funccontext_property("break_label")
1023     return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
1024
1025     # Functions delegated to function scope
1026     def new_label(self, name=None):    return self.funcstate.new_label(name)
1027     def new_error_label(self):         return self.funcstate.new_error_label()
1028     def get_loop_labels(self):         return self.funcstate.get_loop_labels()
1029     def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
1030     def new_loop_labels(self):         return self.funcstate.new_loop_labels()
1031     def get_all_labels(self):          return self.funcstate.get_all_labels()
1032     def set_all_labels(self, labels):  return self.funcstate.set_all_labels(labels)
1033     def all_new_labels(self):          return self.funcstate.all_new_labels()
1034     def use_label(self, lbl):          return self.funcstate.use_label(lbl)
1035     def label_used(self, lbl):         return self.funcstate.label_used(lbl)
1036
1037
1038     def enter_cfunc_scope(self):
1039         self.funcstate = FunctionState(self)
1040
1041     def exit_cfunc_scope(self):
1042         self.funcstate = None
1043
1044     # constant handling
1045
1046     def get_py_num(self, str_value, longness):
1047         return self.globalstate.get_int_const(str_value, longness).cname
1048
1049     def get_py_const(self, type, prefix='', cleanup_level=None):
1050         return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
1051
1052     def get_string_const(self, text):
1053         return self.globalstate.get_string_const(text).cname
1054
1055     def get_py_string_const(self, text, identifier=None,
1056                             is_str=False, unicode_value=None):
1057         return self.globalstate.get_py_string_const(
1058             text, identifier, is_str, unicode_value).cname
1059
1060     def get_argument_default_const(self, type):
1061         return self.globalstate.get_py_const(type).cname
1062
1063     def intern(self, text):
1064         return self.get_py_string_const(text)
1065
1066     def intern_identifier(self, text):
1067         return self.get_py_string_const(text, identifier=True)
1068
1069     def get_cached_constants_writer(self):
1070         return self.globalstate.get_cached_constants_writer()
1071
1072     # code generation
1073
1074     def putln(self, code = "", safe=False):
1075         if self.marker and self.bol:
1076             self.emit_marker()
1077         if self.emit_linenums and self.last_marker_line != 0:
1078             self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
1079
1080         if code:
1081             if safe:
1082                 self.put_safe(code)
1083             else:
1084                 self.put(code)
1085         self.write("\n");
1086         self.bol = 1
1087
1088     def emit_marker(self):
1089         self.write("\n");
1090         self.indent()
1091         self.write("/* %s */\n" % self.marker[1])
1092         self.last_marker_line = self.marker[0]
1093         self.marker = None
1094
1095     def put_safe(self, code):
1096         # put code, but ignore {}
1097         self.write(code)
1098         self.bol = 0
1099
1100     def put(self, code):
1101         fix_indent = False
1102         if "{" in code:
1103             dl = code.count("{")
1104         else:
1105             dl = 0
1106         if "}" in code:
1107             dl -= code.count("}")
1108             if dl < 0:
1109                 self.level += dl
1110             elif dl == 0 and code[0] == "}":
1111                 # special cases like "} else {" need a temporary dedent
1112                 fix_indent = True
1113                 self.level -= 1
1114         if self.bol:
1115             self.indent()
1116         self.write(code)
1117         self.bol = 0
1118         if dl > 0:
1119             self.level += dl
1120         elif fix_indent:
1121             self.level += 1
1122
1123     def increase_indent(self):
1124         self.level = self.level + 1
1125
1126     def decrease_indent(self):
1127         self.level = self.level - 1
1128
1129     def begin_block(self):
1130         self.putln("{")
1131         self.increase_indent()
1132
1133     def end_block(self):
1134         self.decrease_indent()
1135         self.putln("}")
1136
1137     def indent(self):
1138         self.write("  " * self.level)
1139
1140     def get_py_version_hex(self, pyversion):
1141         return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
1142
1143     def mark_pos(self, pos):
1144         if pos is None:
1145             return
1146         source_desc, line, col = pos
1147         if self.last_marker_line == line:
1148             return
1149         assert isinstance(source_desc, SourceDescriptor)
1150         contents = self.globalstate.commented_file_contents(source_desc)
1151         lines = contents[max(0,line-3):line] # line numbers start at 1
1152         lines[-1] += u'             # <<<<<<<<<<<<<<'
1153         lines += contents[line:line+2]
1154
1155         marker = u'"%s":%d\n%s\n' % (
1156             source_desc.get_escaped_description(), line, u'\n'.join(lines))
1157         self.marker = (line, marker)
1158         if self.emit_linenums:
1159             self.source_desc = source_desc.get_escaped_description()
1160
1161     def put_label(self, lbl):
1162         if lbl in self.funcstate.labels_used:
1163             self.putln("%s:;" % lbl)
1164
1165     def put_goto(self, lbl):
1166         self.funcstate.use_label(lbl)
1167         self.putln("goto %s;" % lbl)
1168
1169     def put_var_declarations(self, entries, static = 0, dll_linkage = None,
1170             definition = True):
1171         for entry in entries:
1172             if not entry.in_cinclude:
1173                 self.put_var_declaration(entry, static, dll_linkage, definition)
1174
1175     def put_var_declaration(self, entry, static = 0, dll_linkage = None,
1176             definition = True):
1177         #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
1178         if entry.in_closure:
1179             return
1180         visibility = entry.visibility
1181         if visibility == 'private' and not definition:
1182             #print "...private and not definition, skipping" ###
1183             return
1184         if not entry.used and visibility == "private":
1185             #print "not used and private, skipping", entry.cname ###
1186             return
1187         storage_class = ""
1188         if visibility == 'extern':
1189             storage_class = Naming.extern_c_macro
1190         elif visibility == 'public':
1191             if not definition:
1192                 storage_class = Naming.extern_c_macro
1193         elif visibility == 'private':
1194             if static:
1195                 storage_class = "static"
1196         if storage_class:
1197             self.put("%s " % storage_class)
1198         if visibility != 'public':
1199             dll_linkage = None
1200         self.put(entry.type.declaration_code(entry.cname,
1201             dll_linkage = dll_linkage))
1202         if entry.init is not None:
1203             self.put_safe(" = %s" % entry.type.literal_code(entry.init))
1204         self.putln(";")
1205
1206     def put_temp_declarations(self, func_context):
1207         for name, type, manage_ref in func_context.temps_allocated:
1208             decl = type.declaration_code(name)
1209             if type.is_pyobject:
1210                 self.putln("%s = NULL;" % decl)
1211             else:
1212                 self.putln("%s;" % decl)
1213
1214     def put_h_guard(self, guard):
1215         self.putln("#ifndef %s" % guard)
1216         self.putln("#define %s" % guard)
1217
1218     def unlikely(self, cond):
1219         if Options.gcc_branch_hints:
1220             return 'unlikely(%s)' % cond
1221         else:
1222             return cond
1223
1224     # Python objects and reference counting
1225
1226     def entry_as_pyobject(self, entry):
1227         type = entry.type
1228         if (not entry.is_self_arg and not entry.type.is_complete()
1229             or entry.type.is_extension_type):
1230             return "(PyObject *)" + entry.cname
1231         else:
1232             return entry.cname
1233
1234     def as_pyobject(self, cname, type):
1235         from PyrexTypes import py_object_type, typecast
1236         return typecast(py_object_type, type, cname)
1237
1238     def put_gotref(self, cname):
1239         self.putln("__Pyx_GOTREF(%s);" % cname)
1240
1241     def put_giveref(self, cname):
1242         self.putln("__Pyx_GIVEREF(%s);" % cname)
1243
1244     def put_xgiveref(self, cname):
1245         self.putln("__Pyx_XGIVEREF(%s);" % cname)
1246
1247     def put_xgotref(self, cname):
1248         self.putln("__Pyx_XGOTREF(%s);" % cname)
1249
1250     def put_incref(self, cname, type, nanny=True):
1251         if nanny:
1252             self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
1253         else:
1254             self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
1255
1256     def put_decref(self, cname, type, nanny=True):
1257         if nanny:
1258             self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
1259         else:
1260             self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type))
1261
1262     def put_var_gotref(self, entry):
1263         if entry.type.is_pyobject:
1264             self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
1265
1266     def put_var_giveref(self, entry):
1267         if entry.type.is_pyobject:
1268             self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))
1269
1270     def put_var_xgotref(self, entry):
1271         if entry.type.is_pyobject:
1272             self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))
1273
1274     def put_var_xgiveref(self, entry):
1275         if entry.type.is_pyobject:
1276             self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
1277
1278     def put_var_incref(self, entry):
1279         if entry.type.is_pyobject:
1280             self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
1281
1282     def put_decref_clear(self, cname, type, nanny=True):
1283         from PyrexTypes import py_object_type, typecast
1284         if nanny:
1285             self.putln("__Pyx_DECREF(%s); %s = 0;" % (
1286                 typecast(py_object_type, type, cname), cname))
1287         else:
1288             self.putln("Py_DECREF(%s); %s = 0;" % (
1289                 typecast(py_object_type, type, cname), cname))
1290
1291     def put_xdecref(self, cname, type, nanny=True):
1292         if nanny:
1293             self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
1294         else:
1295             self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type))
1296
1297     def put_xdecref_clear(self, cname, type, nanny=True):
1298         if nanny:
1299             self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
1300                 self.as_pyobject(cname, type), cname))
1301         else:
1302             self.putln("Py_XDECREF(%s); %s = 0;" % (
1303                 self.as_pyobject(cname, type), cname))
1304
1305     def put_var_decref(self, entry):
1306         if entry.type.is_pyobject:
1307             if entry.init_to_none is False:  # FIXME: 0 and False are treated differently???
1308                 self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1309             else:
1310                 self.putln("__Pyx_DECREF(%s);" % self.entry_as_pyobject(entry))
1311
1312     def put_var_decref_clear(self, entry):
1313         if entry.type.is_pyobject:
1314             self.putln("__Pyx_DECREF(%s); %s = 0;" % (
1315                 self.entry_as_pyobject(entry), entry.cname))
1316
1317     def put_var_xdecref(self, entry):
1318         if entry.type.is_pyobject:
1319             self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1320
1321     def put_var_xdecref_clear(self, entry):
1322         if entry.type.is_pyobject:
1323             self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
1324                 self.entry_as_pyobject(entry), entry.cname))
1325
1326     def put_var_decrefs(self, entries, used_only = 0):
1327         for entry in entries:
1328             if not used_only or entry.used:
1329                 if entry.xdecref_cleanup:
1330                     self.put_var_xdecref(entry)
1331                 else:
1332                     self.put_var_decref(entry)
1333
1334     def put_var_xdecrefs(self, entries):
1335         for entry in entries:
1336             self.put_var_xdecref(entry)
1337
1338     def put_var_xdecrefs_clear(self, entries):
1339         for entry in entries:
1340             self.put_var_xdecref_clear(entry)
1341
1342     def put_init_to_py_none(self, cname, type, nanny=True):
1343         from PyrexTypes import py_object_type, typecast
1344         py_none = typecast(type, py_object_type, "Py_None")
1345         if nanny:
1346             self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
1347         else:
1348             self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
1349
1350     def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
1351         code = template % entry.cname
1352         #if entry.type.is_extension_type:
1353         #    code = "((PyObject*)%s)" % code
1354         self.put_init_to_py_none(code, entry.type, nanny)
1355         if entry.in_closure:
1356             self.put_giveref('Py_None')
1357
1358     def put_pymethoddef(self, entry, term, allow_skip=True):
1359         if entry.is_special or entry.name == '__getattribute__':
1360             if entry.name not in ['__cinit__', '__dealloc__', '__richcmp__', '__next__', '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__', '__getcharbuffer__', '__getbuffer__', '__releasebuffer__']:
1361                 if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
1362                     pass
1363                 # Python's typeobject.c will automatically fill in our slot
1364                 # in add_operators() (called by PyType_Ready) with a value
1365                 # that's better than ours.
1366                 elif allow_skip:
1367                     return
1368         from TypeSlots import method_coexist
1369         if entry.doc:
1370             doc_code = entry.doc_cname
1371         else:
1372             doc_code = 0
1373         method_flags = entry.signature.method_flags()
1374         if method_flags:
1375             if entry.is_special:
1376                 method_flags += [method_coexist]
1377             self.putln(
1378                 '{__Pyx_NAMESTR("%s"), (PyCFunction)%s, %s, __Pyx_DOCSTR(%s)}%s' % (
1379                     entry.name,
1380                     entry.func_cname,
1381                     "|".join(method_flags),
1382                     doc_code,
1383                     term))
1384
1385     # error handling
1386
1387     def put_error_if_neg(self, pos, value):
1388 #        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!
1389         return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
1390
1391     def set_error_info(self, pos):
1392         if self.c_line_in_traceback:
1393             cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
1394         else:
1395             cinfo = ""
1396         return "%s = %s[%s]; %s = %s;%s" % (
1397             Naming.filename_cname,
1398             Naming.filetable_cname,
1399             self.lookup_filename(pos[0]),
1400             Naming.lineno_cname,
1401             pos[1],
1402             cinfo)
1403
1404     def error_goto(self, pos):
1405         lbl = self.funcstate.error_label
1406         self.funcstate.use_label(lbl)
1407         return "{%s goto %s;}" % (
1408             self.set_error_info(pos),
1409             lbl)
1410
1411     def error_goto_if(self, cond, pos):
1412         return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
1413
1414     def error_goto_if_null(self, cname, pos):
1415         return self.error_goto_if("!%s" % cname, pos)
1416
1417     def error_goto_if_neg(self, cname, pos):
1418         return self.error_goto_if("%s < 0" % cname, pos)
1419
1420     def error_goto_if_PyErr(self, pos):
1421         return self.error_goto_if("PyErr_Occurred()", pos)
1422
1423     def lookup_filename(self, filename):
1424         return self.globalstate.lookup_filename(filename)
1425
1426     def put_declare_refcount_context(self):
1427         self.putln('__Pyx_RefNannyDeclarations')
1428
1429     def put_setup_refcount_context(self, name):
1430         self.putln('__Pyx_RefNannySetupContext("%s");' % name)
1431
1432     def put_finish_refcount_context(self):
1433         self.putln("__Pyx_RefNannyFinishContext();")
1434
1435     def put_trace_declarations(self):
1436         self.putln('__Pyx_TraceDeclarations');
1437
1438     def put_trace_call(self, name, pos):
1439         self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]));
1440
1441     def put_trace_exception(self):
1442         self.putln("__Pyx_TraceException();")
1443
1444     def put_trace_return(self, retvalue_cname):
1445         self.putln("__Pyx_TraceReturn(%s);" % retvalue_cname)
1446
1447
1448 class PyrexCodeWriter(object):
1449     # f                file      output file
1450     # level            int       indentation level
1451
1452     def __init__(self, outfile_name):
1453         self.f = Utils.open_new_file(outfile_name)
1454         self.level = 0
1455
1456     def putln(self, code):
1457         self.f.write("%s%s\n" % (" " * self.level, code))
1458
1459     def indent(self):
1460         self.level += 1
1461
1462     def dedent(self):
1463         self.level -= 1
1464
1465
1466 class ClosureTempAllocator(object):
1467     def __init__(self, klass):
1468         self.klass = klass
1469         self.temps_allocated = {}
1470         self.temps_free = {}
1471         self.temps_count = 0
1472
1473     def reset(self):
1474         for type, cnames in self.temps_allocated.items():
1475             self.temps_free[type] = list(cnames)
1476
1477     def allocate_temp(self, type):
1478         if not type in self.temps_allocated:
1479             self.temps_allocated[type] = []
1480             self.temps_free[type] = []
1481         elif self.temps_free[type]:
1482             return self.temps_free[type].pop(0)
1483         cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
1484         self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
1485         self.temps_allocated[type].append(cname)
1486         self.temps_count += 1
1487         return cname