fix unprefixed strings with non-UTF8 source code encoding in Py3
[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
335     def get_py_string_const(self, encoding, identifier=None,
336                             is_str=False, py3str_cstring=None):
337         py_strings = self.py_strings
338         text = self.text
339
340         is_str = bool(identifier or is_str)
341         is_unicode = encoding is None and not is_str
342
343         if encoding is None:
344             # unicode string
345             encoding_key = None
346         else:
347             # bytes or str
348             encoding = encoding.lower()
349             if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
350                 encoding = None
351                 encoding_key = None
352             else:
353                 encoding_key = ''.join(find_alphanums(encoding))
354
355         key = (is_str, is_unicode, encoding_key, py3str_cstring)
356         if py_strings is not None:
357             try:
358                 return py_strings[key]
359             except KeyError:
360                 pass
361         else:
362             self.py_strings = {}
363
364         if identifier:
365             intern = True
366         elif identifier is None:
367             if isinstance(text, unicode):
368                 intern = bool(possible_unicode_identifier(text))
369             else:
370                 intern = bool(possible_bytes_identifier(text))
371         else:
372             intern = False
373         if intern:
374             prefix = Naming.interned_str_prefix
375         else:
376             prefix = Naming.py_const_prefix
377         pystring_cname = "%s%s_%s" % (
378             prefix,
379             (is_str and 's') or (is_unicode and 'u') or 'b',
380             self.cname[len(Naming.const_prefix):])
381
382         py_string = PyStringConst(
383             pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
384         self.py_strings[key] = py_string
385         return py_string
386
387 class PyStringConst(object):
388     """Global info about a Python string constant held by GlobalState.
389     """
390     # cname       string
391     # py3str_cstring string
392     # encoding    string
393     # intern      boolean
394     # is_unicode  boolean
395     # is_str      boolean
396
397     def __init__(self, cname, encoding, is_unicode, is_str=False,
398                  py3str_cstring=None, intern=False):
399         self.cname = cname
400         self.py3str_cstring = py3str_cstring
401         self.encoding = encoding
402         self.is_str = is_str
403         self.is_unicode = is_unicode
404         self.intern = intern
405
406     def __lt__(self, other):
407         return self.cname < other.cname
408
409
410 class GlobalState(object):
411     # filename_table   {string : int}  for finding filename table indexes
412     # filename_list    [string]        filenames in filename table order
413     # input_file_contents dict         contents (=list of lines) of any file that was used as input
414     #                                  to create this output C code.  This is
415     #                                  used to annotate the comments.
416     #
417     # utility_codes   set                IDs of used utility code (to avoid reinsertion)
418     #
419     # declared_cnames  {string:Entry}  used in a transition phase to merge pxd-declared
420     #                                  constants etc. into the pyx-declared ones (i.e,
421     #                                  check if constants are already added).
422     #                                  In time, hopefully the literals etc. will be
423     #                                  supplied directly instead.
424     #
425     # const_cname_counter int          global counter for constant identifiers
426     #
427
428     # parts            {string:CCodeWriter}
429
430
431     # interned_strings
432     # consts
433     # interned_nums
434
435     # directives       set             Temporary variable used to track
436     #                                  the current set of directives in the code generation
437     #                                  process.
438
439     directives = {}
440
441     code_layout = [
442         'h_code',
443         'filename_table',
444         'utility_code_proto_before_types',
445         'numeric_typedefs',          # Let these detailed individual parts stay!,
446         'complex_type_declarations', # as the proper solution is to make a full DAG...
447         'type_declarations',         # More coarse-grained blocks would simply hide
448         'utility_code_proto',        # the ugliness, not fix it
449         'module_declarations',
450         'typeinfo',
451         'before_global_var',
452         'global_var',
453         'decls',
454         'all_the_rest',
455         'pystring_table',
456         'cached_builtins',
457         'cached_constants',
458         'init_globals',
459         'init_module',
460         'cleanup_globals',
461         'cleanup_module',
462         'main_method',
463         'utility_code_def',
464         'end'
465     ]
466
467
468     def __init__(self, writer, emit_linenums=False):
469         self.filename_table = {}
470         self.filename_list = []
471         self.input_file_contents = {}
472         self.utility_codes = cython.set()
473         self.declared_cnames = {}
474         self.in_utility_code_generation = False
475         self.emit_linenums = emit_linenums
476         self.parts = {}
477
478         self.const_cname_counter = 1
479         self.string_const_index = {}
480         self.int_const_index = {}
481         self.py_constants = []
482
483         assert writer.globalstate is None
484         writer.globalstate = self
485         self.rootwriter = writer
486
487     def initialize_main_c_code(self):
488         rootwriter = self.rootwriter
489         for part in self.code_layout:
490             self.parts[part] = rootwriter.insertion_point()
491
492         if not Options.cache_builtins:
493             del self.parts['cached_builtins']
494         else:
495             w = self.parts['cached_builtins']
496             w.enter_cfunc_scope()
497             w.putln("static int __Pyx_InitCachedBuiltins(void) {")
498
499         w = self.parts['cached_constants']
500         w.enter_cfunc_scope()
501         w.putln("")
502         w.putln("static int __Pyx_InitCachedConstants(void) {")
503         w.put_declare_refcount_context()
504         w.put_setup_refcount_context("__Pyx_InitCachedConstants")
505
506         w = self.parts['init_globals']
507         w.enter_cfunc_scope()
508         w.putln("")
509         w.putln("static int __Pyx_InitGlobals(void) {")
510
511         if not Options.generate_cleanup_code:
512             del self.parts['cleanup_globals']
513         else:
514             w = self.parts['cleanup_globals']
515             w.enter_cfunc_scope()
516             w.putln("")
517             w.putln("static void __Pyx_CleanupGlobals(void) {")
518
519         #
520         # utility_code_def
521         #
522         code = self.parts['utility_code_def']
523         if self.emit_linenums:
524             code.write('\n#line 1 "cython_utility"\n')
525         code.putln("")
526         code.putln("/* Runtime support code */")
527
528     def finalize_main_c_code(self):
529         self.close_global_decls()
530
531         #
532         # utility_code_def
533         #
534         code = self.parts['utility_code_def']
535         import PyrexTypes
536         code.put(PyrexTypes.type_conversion_functions)
537         code.putln("")
538
539     def __getitem__(self, key):
540         return self.parts[key]
541
542     #
543     # Global constants, interned objects, etc.
544     #
545     def close_global_decls(self):
546         # This is called when it is known that no more global declarations will
547         # declared.
548         self.generate_const_declarations()
549         if Options.cache_builtins:
550             w = self.parts['cached_builtins']
551             w.putln("return 0;")
552             if w.label_used(w.error_label):
553                 w.put_label(w.error_label)
554                 w.putln("return -1;")
555             w.putln("}")
556             w.exit_cfunc_scope()
557
558         w = self.parts['cached_constants']
559         w.put_finish_refcount_context()
560         w.putln("return 0;")
561         if w.label_used(w.error_label):
562             w.put_label(w.error_label)
563             w.put_finish_refcount_context()
564             w.putln("return -1;")
565         w.putln("}")
566         w.exit_cfunc_scope()
567
568         w = self.parts['init_globals']
569         w.putln("return 0;")
570         if w.label_used(w.error_label):
571             w.put_label(w.error_label)
572             w.putln("return -1;")
573         w.putln("}")
574         w.exit_cfunc_scope()
575
576         if Options.generate_cleanup_code:
577             w = self.parts['cleanup_globals']
578             w.putln("}")
579             w.exit_cfunc_scope()
580
581         if Options.generate_cleanup_code:
582             w = self.parts['cleanup_module']
583             w.putln("}")
584             w.exit_cfunc_scope()
585
586     def put_pyobject_decl(self, entry):
587         self['global_var'].putln("static PyObject *%s;" % entry.cname)
588
589     # constant handling at code generation time
590
591     def get_cached_constants_writer(self):
592         return self.parts['cached_constants']
593
594     def get_int_const(self, str_value, longness=False):
595         longness = bool(longness)
596         try:
597             c = self.int_const_index[(str_value, longness)]
598         except KeyError:
599             c = self.new_int_const(str_value, longness)
600         return c
601
602     def get_py_const(self, type, prefix='', cleanup_level=None):
603         # create a new Python object constant
604         const = self.new_py_const(type, prefix)
605         if cleanup_level is not None \
606                and cleanup_level <= Options.generate_cleanup_code:
607             cleanup_writer = self.parts['cleanup_globals']
608             cleanup_writer.put_xdecref_clear(const.cname, type, nanny=False)
609         return const
610
611     def get_string_const(self, text):
612         # return a C string constant, creating a new one if necessary
613         if text.is_unicode:
614             byte_string = text.utf8encode()
615         else:
616             byte_string = text.byteencode()
617         try:
618             c = self.string_const_index[byte_string]
619         except KeyError:
620             c = self.new_string_const(text, byte_string)
621         return c
622
623     def get_py_string_const(self, text, identifier=None,
624                             is_str=False, unicode_value=None):
625         # return a Python string constant, creating a new one if necessary
626         c_string = self.get_string_const(text)
627         py3str_cstring = None
628         if is_str and unicode_value is not None \
629                and unicode_value.utf8encode() != text.byteencode():
630             py3str_cstring = self.get_string_const(unicode_value)
631         py_string = c_string.get_py_string_const(
632             text.encoding, identifier, is_str, py3str_cstring)
633         return py_string
634
635     def get_interned_identifier(self, text):
636         return self.get_py_string_const(text, identifier=True)
637
638     def new_string_const(self, text, byte_string):
639         cname = self.new_string_const_cname(byte_string)
640         c = StringConst(cname, text, byte_string)
641         self.string_const_index[byte_string] = c
642         return c
643
644     def new_int_const(self, value, longness):
645         cname = self.new_int_const_cname(value, longness)
646         c = IntConst(cname, value, longness)
647         self.int_const_index[(value, longness)] = c
648         return c
649
650     def new_py_const(self, type, prefix=''):
651         cname = self.new_const_cname(prefix)
652         c = PyObjectConst(cname, type)
653         self.py_constants.append(c)
654         return c
655
656     def new_string_const_cname(self, bytes_value, intern=None):
657         # Create a new globally-unique nice name for a C string constant.
658         try:
659             value = bytes_value.decode('ASCII')
660         except UnicodeError:
661             return self.new_const_cname()
662
663         if len(value) < 20 and nice_identifier(value):
664             return "%s_%s" % (Naming.const_prefix, value)
665         else:
666             return self.new_const_cname()
667
668     def new_int_const_cname(self, value, longness):
669         if longness:
670             value += 'L'
671         cname = "%s%s" % (Naming.interned_num_prefix, value)
672         cname = cname.replace('-', 'neg_').replace('.','_')
673         return cname
674
675     def new_const_cname(self, prefix=''):
676         n = self.const_cname_counter
677         self.const_cname_counter += 1
678         return "%s%s%d" % (Naming.const_prefix, prefix, n)
679
680     def add_cached_builtin_decl(self, entry):
681         if entry.is_builtin and entry.is_const:
682             if self.should_declare(entry.cname, entry):
683                 self.put_pyobject_decl(entry)
684                 w = self.parts['cached_builtins']
685                 condition = None
686                 if entry.name in non_portable_builtins_map:
687                     condition, replacement = non_portable_builtins_map[entry.name]
688                     w.putln('#if %s' % condition)
689                     self.put_cached_builtin_init(
690                         entry.pos, StringEncoding.EncodedString(replacement),
691                         entry.cname)
692                     w.putln('#else')
693                 self.put_cached_builtin_init(
694                     entry.pos, StringEncoding.EncodedString(entry.name),
695                     entry.cname)
696                 if condition:
697                     w.putln('#endif')
698
699     def put_cached_builtin_init(self, pos, name, cname):
700         w = self.parts['cached_builtins']
701         interned_cname = self.get_interned_identifier(name).cname
702         from ExprNodes import get_name_interned_utility_code
703         self.use_utility_code(get_name_interned_utility_code)
704         w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
705             cname,
706             Naming.builtins_cname,
707             interned_cname,
708             cname,
709             w.error_goto(pos)))
710
711     def generate_const_declarations(self):
712         self.generate_string_constants()
713         self.generate_int_constants()
714         self.generate_object_constant_decls()
715
716     def generate_object_constant_decls(self):
717         consts = [ (len(c.cname), c.cname, c)
718                    for c in self.py_constants ]
719         consts.sort()
720         decls_writer = self.parts['decls']
721         for _, cname, c in consts:
722             decls_writer.putln(
723                 "static %s;" % c.type.declaration_code(cname))
724
725     def generate_string_constants(self):
726         c_consts = [ (len(c.cname), c.cname, c)
727                      for c in self.string_const_index.values() ]
728         c_consts.sort()
729         py_strings = []
730
731         decls_writer = self.parts['decls']
732         for _, cname, c in c_consts:
733             decls_writer.putln('static char %s[] = "%s";' % (
734                 cname, StringEncoding.split_string_literal(c.escaped_value)))
735             if c.py_strings is not None:
736                 for py_string in c.py_strings.values():
737                     py_strings.append((c.cname, len(py_string.cname), py_string))
738
739         if py_strings:
740             import Nodes
741             self.use_utility_code(Nodes.init_string_tab_utility_code)
742
743             py_strings.sort()
744             w = self.parts['pystring_table']
745             w.putln("")
746             w.putln("static __Pyx_StringTabEntry %s[] = {" %
747                                       Naming.stringtab_cname)
748             for c_cname, _, py_string in py_strings:
749                 if not py_string.is_str or not py_string.encoding or \
750                        py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
751                                               'UTF8', 'UTF-8'):
752                     encoding = '0'
753                 else:
754                     encoding = '"%s"' % py_string.encoding.lower()
755
756                 decls_writer.putln(
757                     "static PyObject *%s;" % py_string.cname)
758                 if py_string.py3str_cstring:
759                     w.putln("#if PY_MAJOR_VERSION >= 3")
760                     w.putln(
761                         "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
762                         py_string.cname,
763                         py_string.py3str_cstring.cname,
764                         py_string.py3str_cstring.cname,
765                         '0', 1, 0,
766                         py_string.intern
767                         ))
768                     w.putln("#else")
769                 w.putln(
770                     "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
771                     py_string.cname,
772                     c_cname,
773                     c_cname,
774                     encoding,
775                     py_string.is_unicode,
776                     py_string.is_str,
777                     py_string.intern
778                     ))
779                 if py_string.py3str_cstring:
780                     w.putln("#endif")
781             w.putln("{0, 0, 0, 0, 0, 0, 0}")
782             w.putln("};")
783
784             init_globals = self.parts['init_globals']
785             init_globals.putln(
786                 "if (__Pyx_InitStrings(%s) < 0) %s;" % (
787                     Naming.stringtab_cname,
788                     init_globals.error_goto(self.module_pos)))
789
790     def generate_int_constants(self):
791         consts = [ (len(c.value), c.value, c.is_long, c)
792                    for c in self.int_const_index.values() ]
793         consts.sort()
794         decls_writer = self.parts['decls']
795         for _, value, longness, c in consts:
796             cname = c.cname
797             decls_writer.putln("static PyObject *%s;" % cname)
798             if longness:
799                 function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
800             elif Utils.long_literal(value):
801                 function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;'
802             else:
803                 function = "%s = PyInt_FromLong(%s); %s;"
804             init_globals = self.parts['init_globals']
805             init_globals.putln(function % (
806                 cname,
807                 value,
808                 init_globals.error_goto_if_null(cname, self.module_pos)))
809
810     # The functions below are there in a transition phase only
811     # and will be deprecated. They are called from Nodes.BlockNode.
812     # The copy&paste duplication is intentional in order to be able
813     # to see quickly how BlockNode worked, until this is replaced.
814
815     def should_declare(self, cname, entry):
816         if cname in self.declared_cnames:
817             other = self.declared_cnames[cname]
818             assert str(entry.type) == str(other.type)
819             assert entry.init == other.init
820             return False
821         else:
822             self.declared_cnames[cname] = entry
823             return True
824
825     #
826     # File name state
827     #
828
829     def lookup_filename(self, filename):
830         try:
831             index = self.filename_table[filename]
832         except KeyError:
833             index = len(self.filename_list)
834             self.filename_list.append(filename)
835             self.filename_table[filename] = index
836         return index
837
838     def commented_file_contents(self, source_desc):
839         try:
840             return self.input_file_contents[source_desc]
841         except KeyError:
842             pass
843         source_file = source_desc.get_lines(encoding='ASCII',
844                                             error_handling='ignore')
845         try:
846             F = [u' * ' + line.rstrip().replace(
847                     u'*/', u'*[inserted by cython to avoid comment closer]/'
848                     ).replace(
849                     u'/*', u'/[inserted by cython to avoid comment start]*'
850                     )
851                  for line in source_file]
852         finally:
853             if hasattr(source_file, 'close'):
854                 source_file.close()
855         if not F: F.append(u'')
856         self.input_file_contents[source_desc] = F
857         return F
858
859     #
860     # Utility code state
861     #
862
863     def use_utility_code(self, utility_code):
864         """
865         Adds code to the C file. utility_code should
866         a) implement __eq__/__hash__ for the purpose of knowing whether the same
867            code has already been included
868         b) implement put_code, which takes a globalstate instance
869
870         See UtilityCode.
871         """
872         if utility_code not in self.utility_codes:
873             self.utility_codes.add(utility_code)
874             utility_code.put_code(self)
875
876
877 def funccontext_property(name):
878     try:
879         import operator
880         attribute_of = operator.attrgetter(name)
881     except:
882         def attribute_of(o):
883             return getattr(o, name)
884
885     def get(self):
886         return attribute_of(self.funcstate)
887     def set(self, value):
888         setattr(self.funcstate, name, value)
889     return property(get, set)
890
891
892 class CCodeWriter(object):
893     """
894     Utility class to output C code.
895
896     When creating an insertion point one must care about the state that is
897     kept:
898     - formatting state (level, bol) is cloned and used in insertion points
899       as well
900     - labels, temps, exc_vars: One must construct a scope in which these can
901       exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
902       sanity checking and forward compatabilty). Created insertion points
903       looses this scope and cannot access it.
904     - marker: Not copied to insertion point
905     - filename_table, filename_list, input_file_contents: All codewriters
906       coming from the same root share the same instances simultaneously.
907     """
908
909     # f                   file            output file
910     # buffer              StringIOTree
911
912     # level               int             indentation level
913     # bol                 bool            beginning of line?
914     # marker              string          comment to emit before next line
915     # funcstate           FunctionState   contains state local to a C function used for code
916     #                                     generation (labels and temps state etc.)
917     # globalstate         GlobalState     contains state global for a C file (input file info,
918     #                                     utility code, declared constants etc.)
919     # emit_linenums       boolean         whether or not to write #line pragmas
920     #
921     # c_line_in_traceback boolean         append the c file and line number to the traceback for exceptions
922     #
923     # pyclass_stack       list            used during recursive code generation to pass information
924     #                                     about the current class one is in
925
926     globalstate = None
927
928     def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None, c_line_in_traceback=True):
929         if buffer is None: buffer = StringIOTree()
930         self.buffer = buffer
931         self.marker = None
932         self.last_marker_line = 0
933         self.source_desc = ""
934         self.pyclass_stack = []
935
936         self.funcstate = None
937         self.level = 0
938         self.call_level = 0
939         self.bol = 1
940
941         if create_from is not None:
942             # Use same global state
943             self.globalstate = create_from.globalstate
944             # Clone formatting state
945             if copy_formatting:
946                 self.level = create_from.level
947                 self.bol = create_from.bol
948                 self.call_level = create_from.call_level
949         if emit_linenums is None and self.globalstate:
950             self.emit_linenums = self.globalstate.emit_linenums
951         else:
952             self.emit_linenums = emit_linenums
953         self.c_line_in_traceback = c_line_in_traceback
954
955     def create_new(self, create_from, buffer, copy_formatting):
956         # polymorphic constructor -- very slightly more versatile
957         # than using __class__
958         result = CCodeWriter(create_from, buffer, copy_formatting, c_line_in_traceback=self.c_line_in_traceback)
959         return result
960
961     def copyto(self, f):
962         self.buffer.copyto(f)
963
964     def getvalue(self):
965         return self.buffer.getvalue()
966
967     def write(self, s):
968         # also put invalid markers (lineno 0), to indicate that those lines
969         # have no Cython source code correspondence
970         if self.marker is None:
971             cython_lineno = self.last_marker_line
972         else:
973             cython_lineno = self.marker[0]
974
975         self.buffer.markers.extend([cython_lineno] * s.count('\n'))
976         self.buffer.write(s)
977
978     def insertion_point(self):
979         other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
980         return other
981
982     def new_writer(self):
983         """
984         Creates a new CCodeWriter connected to the same global state, which
985         can later be inserted using insert.
986         """
987         return CCodeWriter(create_from=self, c_line_in_traceback=self.c_line_in_traceback)
988
989     def insert(self, writer):
990         """
991         Inserts the contents of another code writer (created with
992         the same global state) in the current location.
993
994         It is ok to write to the inserted writer also after insertion.
995         """
996         assert writer.globalstate is self.globalstate
997         self.buffer.insert(writer.buffer)
998
999     # Properties delegated to function scope
1000     label_counter = funccontext_property("label_counter")
1001     return_label = funccontext_property("return_label")
1002     error_label = funccontext_property("error_label")
1003     labels_used = funccontext_property("labels_used")
1004     continue_label = funccontext_property("continue_label")
1005     break_label = funccontext_property("break_label")
1006     return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
1007
1008     # Functions delegated to function scope
1009     def new_label(self, name=None):    return self.funcstate.new_label(name)
1010     def new_error_label(self):         return self.funcstate.new_error_label()
1011     def get_loop_labels(self):         return self.funcstate.get_loop_labels()
1012     def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
1013     def new_loop_labels(self):         return self.funcstate.new_loop_labels()
1014     def get_all_labels(self):          return self.funcstate.get_all_labels()
1015     def set_all_labels(self, labels):  return self.funcstate.set_all_labels(labels)
1016     def all_new_labels(self):          return self.funcstate.all_new_labels()
1017     def use_label(self, lbl):          return self.funcstate.use_label(lbl)
1018     def label_used(self, lbl):         return self.funcstate.label_used(lbl)
1019
1020
1021     def enter_cfunc_scope(self):
1022         self.funcstate = FunctionState(self)
1023
1024     def exit_cfunc_scope(self):
1025         self.funcstate = None
1026
1027     # constant handling
1028
1029     def get_py_num(self, str_value, longness):
1030         return self.globalstate.get_int_const(str_value, longness).cname
1031
1032     def get_py_const(self, type, prefix='', cleanup_level=None):
1033         return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
1034
1035     def get_string_const(self, text):
1036         return self.globalstate.get_string_const(text).cname
1037
1038     def get_py_string_const(self, text, identifier=None,
1039                             is_str=False, unicode_value=None):
1040         return self.globalstate.get_py_string_const(
1041             text, identifier, is_str, unicode_value).cname
1042
1043     def get_argument_default_const(self, type):
1044         return self.globalstate.get_py_const(type).cname
1045
1046     def intern(self, text):
1047         return self.get_py_string_const(text)
1048
1049     def intern_identifier(self, text):
1050         return self.get_py_string_const(text, identifier=True)
1051
1052     def get_cached_constants_writer(self):
1053         return self.globalstate.get_cached_constants_writer()
1054
1055     # code generation
1056
1057     def putln(self, code = "", safe=False):
1058         if self.marker and self.bol:
1059             self.emit_marker()
1060         if self.emit_linenums and self.last_marker_line != 0:
1061             self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
1062
1063         if code:
1064             if safe:
1065                 self.put_safe(code)
1066             else:
1067                 self.put(code)
1068         self.write("\n");
1069         self.bol = 1
1070
1071     def emit_marker(self):
1072         self.write("\n");
1073         self.indent()
1074         self.write("/* %s */\n" % self.marker[1])
1075         self.last_marker_line = self.marker[0]
1076         self.marker = None
1077
1078     def put_safe(self, code):
1079         # put code, but ignore {}
1080         self.write(code)
1081         self.bol = 0
1082
1083     def put(self, code):
1084         fix_indent = False
1085         if "{" in code:
1086             dl = code.count("{")
1087         else:
1088             dl = 0
1089         if "}" in code:
1090             dl -= code.count("}")
1091             if dl < 0:
1092                 self.level += dl
1093             elif dl == 0 and code[0] == "}":
1094                 # special cases like "} else {" need a temporary dedent
1095                 fix_indent = True
1096                 self.level -= 1
1097         if self.bol:
1098             self.indent()
1099         self.write(code)
1100         self.bol = 0
1101         if dl > 0:
1102             self.level += dl
1103         elif fix_indent:
1104             self.level += 1
1105
1106     def increase_indent(self):
1107         self.level = self.level + 1
1108
1109     def decrease_indent(self):
1110         self.level = self.level - 1
1111
1112     def begin_block(self):
1113         self.putln("{")
1114         self.increase_indent()
1115
1116     def end_block(self):
1117         self.decrease_indent()
1118         self.putln("}")
1119
1120     def indent(self):
1121         self.write("  " * self.level)
1122
1123     def get_py_version_hex(self, pyversion):
1124         return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
1125
1126     def mark_pos(self, pos):
1127         if pos is None:
1128             return
1129         source_desc, line, col = pos
1130         if self.last_marker_line == line:
1131             return
1132         assert isinstance(source_desc, SourceDescriptor)
1133         contents = self.globalstate.commented_file_contents(source_desc)
1134         lines = contents[max(0,line-3):line] # line numbers start at 1
1135         lines[-1] += u'             # <<<<<<<<<<<<<<'
1136         lines += contents[line:line+2]
1137
1138         marker = u'"%s":%d\n%s\n' % (
1139             source_desc.get_escaped_description(), line, u'\n'.join(lines))
1140         self.marker = (line, marker)
1141         if self.emit_linenums:
1142             self.source_desc = source_desc.get_escaped_description()
1143
1144     def put_label(self, lbl):
1145         if lbl in self.funcstate.labels_used:
1146             self.putln("%s:;" % lbl)
1147
1148     def put_goto(self, lbl):
1149         self.funcstate.use_label(lbl)
1150         self.putln("goto %s;" % lbl)
1151
1152     def put_var_declarations(self, entries, static = 0, dll_linkage = None,
1153             definition = True):
1154         for entry in entries:
1155             if not entry.in_cinclude:
1156                 self.put_var_declaration(entry, static, dll_linkage, definition)
1157
1158     def put_var_declaration(self, entry, static = 0, dll_linkage = None,
1159             definition = True):
1160         #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
1161         if entry.in_closure:
1162             return
1163         visibility = entry.visibility
1164         if visibility == 'private' and not definition:
1165             #print "...private and not definition, skipping" ###
1166             return
1167         if not entry.used and visibility == "private":
1168             #print "not used and private, skipping", entry.cname ###
1169             return
1170         storage_class = ""
1171         if visibility == 'extern':
1172             storage_class = Naming.extern_c_macro
1173         elif visibility == 'public':
1174             if not definition:
1175                 storage_class = Naming.extern_c_macro
1176         elif visibility == 'private':
1177             if static:
1178                 storage_class = "static"
1179         if storage_class:
1180             self.put("%s " % storage_class)
1181         if visibility != 'public':
1182             dll_linkage = None
1183         self.put(entry.type.declaration_code(entry.cname,
1184             dll_linkage = dll_linkage))
1185         if entry.init is not None:
1186             self.put_safe(" = %s" % entry.type.literal_code(entry.init))
1187         self.putln(";")
1188
1189     def put_temp_declarations(self, func_context):
1190         for name, type, manage_ref in func_context.temps_allocated:
1191             decl = type.declaration_code(name)
1192             if type.is_pyobject:
1193                 self.putln("%s = NULL;" % decl)
1194             else:
1195                 self.putln("%s;" % decl)
1196
1197     def put_h_guard(self, guard):
1198         self.putln("#ifndef %s" % guard)
1199         self.putln("#define %s" % guard)
1200
1201     def unlikely(self, cond):
1202         if Options.gcc_branch_hints:
1203             return 'unlikely(%s)' % cond
1204         else:
1205             return cond
1206
1207     # Python objects and reference counting
1208
1209     def entry_as_pyobject(self, entry):
1210         type = entry.type
1211         if (not entry.is_self_arg and not entry.type.is_complete()
1212             or entry.type.is_extension_type):
1213             return "(PyObject *)" + entry.cname
1214         else:
1215             return entry.cname
1216
1217     def as_pyobject(self, cname, type):
1218         from PyrexTypes import py_object_type, typecast
1219         return typecast(py_object_type, type, cname)
1220
1221     def put_gotref(self, cname):
1222         self.putln("__Pyx_GOTREF(%s);" % cname)
1223
1224     def put_giveref(self, cname):
1225         self.putln("__Pyx_GIVEREF(%s);" % cname)
1226
1227     def put_xgiveref(self, cname):
1228         self.putln("__Pyx_XGIVEREF(%s);" % cname)
1229
1230     def put_xgotref(self, cname):
1231         self.putln("__Pyx_XGOTREF(%s);" % cname)
1232
1233     def put_incref(self, cname, type, nanny=True):
1234         if nanny:
1235             self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
1236         else:
1237             self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
1238
1239     def put_decref(self, cname, type, nanny=True):
1240         if nanny:
1241             self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
1242         else:
1243             self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type))
1244
1245     def put_var_gotref(self, entry):
1246         if entry.type.is_pyobject:
1247             self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
1248
1249     def put_var_giveref(self, entry):
1250         if entry.type.is_pyobject:
1251             self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))
1252
1253     def put_var_xgotref(self, entry):
1254         if entry.type.is_pyobject:
1255             self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))
1256
1257     def put_var_xgiveref(self, entry):
1258         if entry.type.is_pyobject:
1259             self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
1260
1261     def put_var_incref(self, entry):
1262         if entry.type.is_pyobject:
1263             self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
1264
1265     def put_decref_clear(self, cname, type, nanny=True):
1266         from PyrexTypes import py_object_type, typecast
1267         if nanny:
1268             self.putln("__Pyx_DECREF(%s); %s = 0;" % (
1269                 typecast(py_object_type, type, cname), cname))
1270         else:
1271             self.putln("Py_DECREF(%s); %s = 0;" % (
1272                 typecast(py_object_type, type, cname), cname))
1273
1274     def put_xdecref(self, cname, type, nanny=True):
1275         if nanny:
1276             self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
1277         else:
1278             self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type))
1279
1280     def put_xdecref_clear(self, cname, type, nanny=True):
1281         if nanny:
1282             self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
1283                 self.as_pyobject(cname, type), cname))
1284         else:
1285             self.putln("Py_XDECREF(%s); %s = 0;" % (
1286                 self.as_pyobject(cname, type), cname))
1287
1288     def put_var_decref(self, entry):
1289         if entry.type.is_pyobject:
1290             if entry.init_to_none is False:  # FIXME: 0 and False are treated differently???
1291                 self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1292             else:
1293                 self.putln("__Pyx_DECREF(%s);" % self.entry_as_pyobject(entry))
1294
1295     def put_var_decref_clear(self, entry):
1296         if entry.type.is_pyobject:
1297             self.putln("__Pyx_DECREF(%s); %s = 0;" % (
1298                 self.entry_as_pyobject(entry), entry.cname))
1299
1300     def put_var_xdecref(self, entry):
1301         if entry.type.is_pyobject:
1302             self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
1303
1304     def put_var_xdecref_clear(self, entry):
1305         if entry.type.is_pyobject:
1306             self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
1307                 self.entry_as_pyobject(entry), entry.cname))
1308
1309     def put_var_decrefs(self, entries, used_only = 0):
1310         for entry in entries:
1311             if not used_only or entry.used:
1312                 if entry.xdecref_cleanup:
1313                     self.put_var_xdecref(entry)
1314                 else:
1315                     self.put_var_decref(entry)
1316
1317     def put_var_xdecrefs(self, entries):
1318         for entry in entries:
1319             self.put_var_xdecref(entry)
1320
1321     def put_var_xdecrefs_clear(self, entries):
1322         for entry in entries:
1323             self.put_var_xdecref_clear(entry)
1324
1325     def put_init_to_py_none(self, cname, type, nanny=True):
1326         from PyrexTypes import py_object_type, typecast
1327         py_none = typecast(type, py_object_type, "Py_None")
1328         if nanny:
1329             self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
1330         else:
1331             self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
1332
1333     def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
1334         code = template % entry.cname
1335         #if entry.type.is_extension_type:
1336         #    code = "((PyObject*)%s)" % code
1337         self.put_init_to_py_none(code, entry.type, nanny)
1338         if entry.in_closure:
1339             self.put_giveref('Py_None')
1340
1341     def put_pymethoddef(self, entry, term, allow_skip=True):
1342         if entry.is_special or entry.name == '__getattribute__':
1343             if entry.name not in ['__cinit__', '__dealloc__', '__richcmp__', '__next__', '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__', '__getcharbuffer__', '__getbuffer__', '__releasebuffer__']:
1344                 if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
1345                     pass
1346                 # Python's typeobject.c will automatically fill in our slot
1347                 # in add_operators() (called by PyType_Ready) with a value
1348                 # that's better than ours.
1349                 elif allow_skip:
1350                     return
1351         from TypeSlots import method_coexist
1352         if entry.doc:
1353             doc_code = entry.doc_cname
1354         else:
1355             doc_code = 0
1356         method_flags = entry.signature.method_flags()
1357         if method_flags:
1358             if entry.is_special:
1359                 method_flags += [method_coexist]
1360             self.putln(
1361                 '{__Pyx_NAMESTR("%s"), (PyCFunction)%s, %s, __Pyx_DOCSTR(%s)}%s' % (
1362                     entry.name,
1363                     entry.func_cname,
1364                     "|".join(method_flags),
1365                     doc_code,
1366                     term))
1367
1368     # error handling
1369
1370     def put_error_if_neg(self, pos, value):
1371 #        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!
1372         return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
1373
1374     def set_error_info(self, pos):
1375         if self.c_line_in_traceback:
1376             cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
1377         else:
1378             cinfo = ""
1379         return "%s = %s[%s]; %s = %s;%s" % (
1380             Naming.filename_cname,
1381             Naming.filetable_cname,
1382             self.lookup_filename(pos[0]),
1383             Naming.lineno_cname,
1384             pos[1],
1385             cinfo)
1386
1387     def error_goto(self, pos):
1388         lbl = self.funcstate.error_label
1389         self.funcstate.use_label(lbl)
1390         return "{%s goto %s;}" % (
1391             self.set_error_info(pos),
1392             lbl)
1393
1394     def error_goto_if(self, cond, pos):
1395         return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
1396
1397     def error_goto_if_null(self, cname, pos):
1398         return self.error_goto_if("!%s" % cname, pos)
1399
1400     def error_goto_if_neg(self, cname, pos):
1401         return self.error_goto_if("%s < 0" % cname, pos)
1402
1403     def error_goto_if_PyErr(self, pos):
1404         return self.error_goto_if("PyErr_Occurred()", pos)
1405
1406     def lookup_filename(self, filename):
1407         return self.globalstate.lookup_filename(filename)
1408
1409     def put_declare_refcount_context(self):
1410         self.putln('__Pyx_RefNannyDeclarations')
1411
1412     def put_setup_refcount_context(self, name):
1413         self.putln('__Pyx_RefNannySetupContext("%s");' % name)
1414
1415     def put_finish_refcount_context(self):
1416         self.putln("__Pyx_RefNannyFinishContext();")
1417
1418     def put_trace_declarations(self):
1419         self.putln('__Pyx_TraceDeclarations');
1420
1421     def put_trace_call(self, name, pos):
1422         self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]));
1423
1424     def put_trace_exception(self):
1425         self.putln("__Pyx_TraceException();")
1426
1427     def put_trace_return(self, retvalue_cname):
1428         self.putln("__Pyx_TraceReturn(%s);" % retvalue_cname)
1429
1430
1431 class PyrexCodeWriter(object):
1432     # f                file      output file
1433     # level            int       indentation level
1434
1435     def __init__(self, outfile_name):
1436         self.f = Utils.open_new_file(outfile_name)
1437         self.level = 0
1438
1439     def putln(self, code):
1440         self.f.write("%s%s\n" % (" " * self.level, code))
1441
1442     def indent(self):
1443         self.level += 1
1444
1445     def dedent(self):
1446         self.level -= 1
1447
1448
1449 class ClosureTempAllocator(object):
1450     def __init__(self, klass):
1451         self.klass = klass
1452         self.temps_allocated = {}
1453         self.temps_free = {}
1454         self.temps_count = 0
1455
1456     def reset(self):
1457         for type, cnames in self.temps_allocated.items():
1458             self.temps_free[type] = list(cnames)
1459
1460     def allocate_temp(self, type):
1461         if not type in self.temps_allocated:
1462             self.temps_allocated[type] = []
1463             self.temps_free[type] = []
1464         elif self.temps_free[type]:
1465             return self.temps_free[type].pop(0)
1466         cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
1467         self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
1468         self.temps_allocated[type].append(cname)
1469         self.temps_count += 1
1470         return cname