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