2 # Pyrex - Code output module
8 from Cython.Utils import open_new_file, open_source_file
9 from PyrexTypes import py_object_type, typecast
10 from TypeSlots import method_coexist
11 from Scanning import SourceDescriptor
12 from Cython.StringIOTree import StringIOTree
17 from sets import Set as set
20 class FunctionState(object):
21 # return_label string function return point label
22 # error_label string error catch point label
23 # continue_label string loop continue point label
24 # break_label string loop break point label
25 # return_from_error_cleanup_label string
26 # label_counter integer counter for naming labels
27 # in_try_finally boolean inside try of try...finally
28 # exc_vars (string * 3) exception variables for reraise, or None
30 # Not used for now, perhaps later
31 def __init__(self, owner, names_taken=set()):
32 self.names_taken = names_taken
35 self.error_label = None
36 self.label_counter = 0
38 self.return_label = self.new_label()
39 self.new_error_label()
40 self.continue_label = None
41 self.break_label = None
43 self.in_try_finally = 0
46 self.temps_allocated = [] # of (name, type, manage_ref)
47 self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
48 self.temps_used_type = {} # name -> (type, manage_ref)
51 def new_label(self, name=None):
52 n = self.label_counter
53 self.label_counter = n + 1
54 label = "%s%d" % (Naming.label_prefix, n)
59 def new_error_label(self):
60 old_err_lbl = self.error_label
61 self.error_label = self.new_label('error')
64 def get_loop_labels(self):
69 def set_loop_labels(self, labels):
71 self.break_label) = labels
73 def new_loop_labels(self):
74 old_labels = self.get_loop_labels()
80 def get_all_labels(self):
87 def set_all_labels(self, labels):
91 self.error_label) = labels
93 def all_new_labels(self):
94 old_labels = self.get_all_labels()
96 for old_label in old_labels:
98 new_labels.append(self.new_label())
100 new_labels.append(old_label)
101 self.set_all_labels(new_labels)
104 def use_label(self, lbl):
105 self.labels_used[lbl] = 1
107 def label_used(self, lbl):
108 return lbl in self.labels_used
110 def allocate_temp(self, type, manage_ref):
112 Allocates a temporary (which may create a new one or get a previously
113 allocated and released one of the same type). Type is simply registered
114 and handed back, but will usually be a PyrexType.
116 If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
117 True, the temp will be decref-ed on return statements and in exception
118 handling clauses. Otherwise the caller has to deal with any reference
119 counting of the variable.
121 If not type.is_pyobject, then manage_ref will be ignored, but it
122 still has to be passed. It is recommended to pass False by convention
123 if it is known that type will never be a Python object.
125 A C string referring to the variable is returned.
127 if not type.is_pyobject:
128 # Make manage_ref canonical, so that manage_ref will always mean
129 # a decref is needed.
131 freelist = self.temps_free.get((type, manage_ref))
132 if freelist is not None and len(freelist) > 0:
133 result = freelist.pop()
136 self.temp_counter += 1
137 result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
138 if not result in self.names_taken: break
139 self.temps_allocated.append((result, type, manage_ref))
140 self.temps_used_type[result] = (type, manage_ref)
141 if DebugFlags.debug_temp_code_comments:
142 self.owner.putln("/* %s allocated */" % result)
145 def release_temp(self, name):
147 Releases a temporary so that it can be reused by other code needing
148 a temp of the same type.
150 type, manage_ref = self.temps_used_type[name]
151 freelist = self.temps_free.get((type, manage_ref))
154 self.temps_free[(type, manage_ref)] = freelist
156 raise RuntimeError("Temp %s freed twice!" % name)
157 freelist.append(name)
158 if DebugFlags.debug_temp_code_comments:
159 self.owner.putln("/* %s released */" % name)
161 def temps_in_use(self):
162 """Return a list of (cname,type,manage_ref) tuples of temp names and their type
163 that are currently in use.
166 for name, type, manage_ref in self.temps_allocated:
167 freelist = self.temps_free.get((type, manage_ref))
168 if freelist is None or name not in freelist:
169 used.append((name, type, manage_ref))
172 def temps_holding_reference(self):
173 """Return a list of (cname,type) tuples of temp names and their type
174 that are currently in use. This includes only temps of a
175 Python object type which owns its reference.
178 for name, type, manage_ref in self.temps_in_use()
181 def all_managed_temps(self):
182 """Return a list of (cname, type) tuples of refcount-managed Python objects.
184 return [(cname, type)
185 for cname, type, manage_ref in self.temps_allocated
188 def all_free_managed_temps(self):
189 """Return a list of (cname, type) tuples of refcount-managed Python
190 objects that are not currently in use. This is used by
191 try-except and try-finally blocks to clean up temps in the
194 return [(cname, type)
195 for (type, manage_ref), freelist in self.temps_free.iteritems()
197 for cname in freelist]
199 class GlobalState(object):
200 # filename_table {string : int} for finding filename table indexes
201 # filename_list [string] filenames in filename table order
202 # input_file_contents dict contents (=list of lines) of any file that was used as input
203 # to create this output C code. This is
204 # used to annotate the comments.
206 # used_utility_code set(string|int) Ids of used utility code (to avoid reinsertion)
207 # utilprotowriter CCodeWriter
208 # utildefwriter CCodeWriter
210 # declared_cnames {string:Entry} used in a transition phase to merge pxd-declared
211 # constants etc. into the pyx-declared ones (i.e,
212 # check if constants are already added).
213 # In time, hopefully the literals etc. will be
214 # supplied directly instead.
223 # directives set Temporary variable used to track
224 # the current set of directives in the code generation
229 def __init__(self, rootwriter, emit_linenums=False):
230 self.filename_table = {}
231 self.filename_list = []
232 self.input_file_contents = {}
233 self.used_utility_code = set()
234 self.declared_cnames = {}
235 self.pystring_table_needed = False
236 self.in_utility_code_generation = False
237 self.emit_linenums = emit_linenums
239 def initwriters(self, rootwriter):
240 self.utilprotowriter = rootwriter.new_writer()
241 self.utildefwriter = rootwriter.new_writer()
242 self.decls_writer = rootwriter.new_writer()
243 self.pystring_table = rootwriter.new_writer()
244 self.init_cached_builtins_writer = rootwriter.new_writer()
245 self.initwriter = rootwriter.new_writer()
246 self.cleanupwriter = rootwriter.new_writer()
248 if Options.cache_builtins:
249 self.init_cached_builtins_writer.enter_cfunc_scope()
250 self.init_cached_builtins_writer.putln("static int __Pyx_InitCachedBuiltins(void) {")
252 self.initwriter.enter_cfunc_scope()
253 self.initwriter.putln("")
254 self.initwriter.putln("static int __Pyx_InitGlobals(void) {")
256 self.cleanupwriter.enter_cfunc_scope()
257 self.cleanupwriter.putln("")
258 self.cleanupwriter.putln("static void __Pyx_CleanupGlobals(void) {")
260 self.pystring_table.putln("")
261 self.pystring_table.putln("static __Pyx_StringTabEntry %s[] = {" %
262 Naming.stringtab_cname)
265 # Global constants, interned objects, etc.
267 def insert_global_var_declarations_into(self, code):
268 code.insert(self.decls_writer)
270 def close_global_decls(self):
271 # This is called when it is known that no more global declarations will
272 # declared (but can be called before or after insert_XXX).
273 if self.pystring_table_needed:
274 self.pystring_table.putln("{0, 0, 0, 0, 0, 0}")
275 self.pystring_table.putln("};")
277 self.use_utility_code(Nodes.init_string_tab_utility_code)
278 self.initwriter.putln(
279 "if (__Pyx_InitStrings(%s) < 0) %s;" % (
280 Naming.stringtab_cname,
281 self.initwriter.error_goto(self.module_pos)))
283 if Options.cache_builtins:
284 w = self.init_cached_builtins_writer
286 w.put_label(w.error_label)
287 w.putln("return -1;")
293 w.put_label(w.error_label)
294 w.putln("return -1;")
298 w = self.cleanupwriter
302 def insert_initcode_into(self, code):
303 if self.pystring_table_needed:
304 code.insert(self.pystring_table)
305 if Options.cache_builtins:
306 code.insert(self.init_cached_builtins_writer)
307 code.insert(self.initwriter)
309 def insert_cleanupcode_into(self, code):
310 code.insert(self.cleanupwriter)
312 def put_pyobject_decl(self, entry):
313 self.decls_writer.putln("static PyObject *%s;" % entry.cname)
315 # The functions below are there in a transition phase only
316 # and will be deprecated. They are called from Nodes.BlockNode.
317 # The copy&paste duplication is intentional in order to be able
318 # to see quickly how BlockNode worked, until this is replaced.
320 def should_declare(self, cname, entry):
321 if cname in self.declared_cnames:
322 other = self.declared_cnames[cname]
323 assert entry.type == other.type
324 assert entry.init == other.init
327 self.declared_cnames[cname] = entry
330 def add_const_definition(self, entry):
331 if self.should_declare(entry.cname, entry):
332 self.decls_writer.put_var_declaration(entry, static = 1)
334 def add_interned_string_decl(self, entry):
335 if self.should_declare(entry.cname, entry):
336 self.decls_writer.put_var_declaration(entry, static = 1)
337 self.add_py_string_decl(entry)
339 def add_py_string_decl(self, entry):
340 if self.should_declare(entry.pystring_cname, entry):
341 self.decls_writer.putln("static PyObject *%s;" % entry.pystring_cname)
342 self.pystring_table_needed = True
343 self.pystring_table.putln("{&%s, %s, sizeof(%s), %d, %d, %d}," % (
344 entry.pystring_cname,
347 entry.type.is_unicode,
352 def add_interned_num_decl(self, entry):
353 if self.should_declare(entry.cname, entry):
354 if entry.init[-1] == "L":
355 self.initwriter.putln('%s = PyLong_FromString((char *)"%s", 0, 0); %s;' % (
358 self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
360 self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % (
363 self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
365 self.put_pyobject_decl(entry)
367 def add_cached_builtin_decl(self, entry):
368 if Options.cache_builtins:
369 if self.should_declare(entry.cname, entry):
370 self.put_pyobject_decl(entry)
371 self.init_cached_builtins_writer.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
373 Naming.builtins_cname,
374 entry.interned_cname,
376 self.init_cached_builtins_writer.error_goto(entry.pos)))
383 def lookup_filename(self, filename):
385 index = self.filename_table[filename]
387 index = len(self.filename_list)
388 self.filename_list.append(filename)
389 self.filename_table[filename] = index
392 def commented_file_contents(self, source_desc):
394 return self.input_file_contents[source_desc]
396 F = [u' * ' + line.rstrip().replace(
397 u'*/', u'*[inserted by cython to avoid comment closer]/'
399 u'/*', u'/[inserted by cython to avoid comment start]*'
400 ).encode('ASCII', 'replace') # + Py2 auto-decode to unicode
401 for line in source_desc.get_lines()]
402 if len(F) == 0: F.append(u'')
403 self.input_file_contents[source_desc] = F
410 def use_utility_code(self, utility_code, name=None):
412 Adds the given utility code to the C file if needed.
414 codetup should unpack into one prototype code part and one
415 definition code part, both strings inserted directly in C.
417 If name is provided, it is used as an identifier to avoid inserting
418 code twice. Otherwise, id(codetup) is used as such an identifier.
420 if name is None: name = id(utility_code)
421 if self.check_utility_code_needed_and_register(name):
422 if utility_code.proto:
423 self.utilprotowriter.put(utility_code.proto)
424 if utility_code.impl:
425 self.utildefwriter.put(utility_code.impl)
426 utility_code.write_init_code(self.initwriter, self.module_pos)
427 utility_code.write_cleanup_code(self.cleanupwriter, self.module_pos)
429 def has_code(self, name):
430 return name in self.used_utility_code
432 def use_code_from(self, func, name, *args, **kw):
434 Requests that the utility code that func can generate is used in the C
435 file. func is called like this:
437 func(proto, definition, name, *args, **kw)
439 where proto and definition are two CCodeWriter instances; the
440 former should have the prototype written to it and the other the definition.
442 The call might happen at some later point (if compiling multiple modules
443 into a cache for instance), and will only happen once per utility code.
445 name is used to identify the utility code, so that it isn't regenerated
446 when the same code is requested again.
448 if self.check_utility_code_needed_and_register(name):
449 func(self.utilprotowriter, self.utildefwriter,
452 def check_utility_code_needed_and_register(self, name):
453 if name in self.used_utility_code:
456 self.used_utility_code.add(name)
459 def put_utility_code_protos(self, writer):
460 writer.insert(self.utilprotowriter)
462 def put_utility_code_defs(self, writer):
463 if self.emit_linenums:
464 writer.write('\n#line 1 "cython_utility"\n')
465 writer.insert(self.utildefwriter)
468 def funccontext_property(name):
470 return getattr(self.funcstate, name)
471 def set(self, value):
472 setattr(self.funcstate, name, value)
473 return property(get, set)
475 class CCodeWriter(object):
477 Utility class to output C code.
479 When creating an insertion point one must care about the state that is
481 - formatting state (level, bol) is cloned and used in insertion points
483 - labels, temps, exc_vars: One must construct a scope in which these can
484 exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
485 sanity checking and forward compatabilty). Created insertion points
486 looses this scope and cannot access it.
487 - marker: Not copied to insertion point
488 - filename_table, filename_list, input_file_contents: All codewriters
489 coming from the same root share the same instances simultaneously.
493 # buffer StringIOTree
495 # level int indentation level
496 # bol bool beginning of line?
497 # marker string comment to emit before next line
498 # funcstate FunctionState contains state local to a C function used for code
499 # generation (labels and temps state etc.)
500 # globalstate GlobalState contains state global for a C file (input file info,
501 # utility code, declared constants etc.)
502 # emit_linenums boolean whether or not to write #line pragmas
504 def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None):
505 if buffer is None: buffer = StringIOTree()
508 self.last_marker_line = 0
509 self.source_desc = ""
511 self.funcstate = None
514 if create_from is None:
516 self.globalstate = GlobalState(self, emit_linenums=emit_linenums)
517 self.globalstate.initwriters(self)
518 # ^^^ need seperate step because this will reference self.globalstate
520 # Use same global state
521 self.globalstate = create_from.globalstate
522 # Clone formatting state
524 self.level = create_from.level
525 self.bol = create_from.bol
526 if emit_linenums is None:
527 self.emit_linenums = self.globalstate.emit_linenums
529 self.emit_linenums = emit_linenums
531 def create_new(self, create_from, buffer, copy_formatting):
532 # polymorphic constructor -- very slightly more versatile
533 # than using __class__
534 return CCodeWriter(create_from, buffer, copy_formatting)
537 self.buffer.copyto(f)
540 return self.buffer.getvalue()
545 def insertion_point(self):
546 other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
549 def new_writer(self):
551 Creates a new CCodeWriter connected to the same global state, which
552 can later be inserted using insert.
554 return CCodeWriter(create_from=self)
556 def insert(self, writer):
558 Inserts the contents of another code writer (created with
559 the same global state) in the current location.
561 It is ok to write to the inserted writer also after insertion.
563 assert writer.globalstate is self.globalstate
564 self.buffer.insert(writer.buffer)
566 # Properties delegated to function scope
567 label_counter = funccontext_property("label_counter")
568 return_label = funccontext_property("return_label")
569 error_label = funccontext_property("error_label")
570 labels_used = funccontext_property("labels_used")
571 continue_label = funccontext_property("continue_label")
572 break_label = funccontext_property("break_label")
573 return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
575 # Functions delegated to function scope
576 def new_label(self, name=None): return self.funcstate.new_label(name)
577 def new_error_label(self): return self.funcstate.new_error_label()
578 def get_loop_labels(self): return self.funcstate.get_loop_labels()
579 def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
580 def new_loop_labels(self): return self.funcstate.new_loop_labels()
581 def get_all_labels(self): return self.funcstate.get_all_labels()
582 def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels)
583 def all_new_labels(self): return self.funcstate.all_new_labels()
584 def use_label(self, lbl): return self.funcstate.use_label(lbl)
585 def label_used(self, lbl): return self.funcstate.label_used(lbl)
588 def enter_cfunc_scope(self):
589 self.funcstate = FunctionState(self)
591 def exit_cfunc_scope(self):
592 self.funcstate = None
594 def putln(self, code = ""):
595 if self.marker and self.bol:
597 if self.emit_linenums and self.last_marker_line != 0:
598 self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
604 def emit_marker(self):
607 self.write("/* %s */\n" % self.marker[1])
608 self.last_marker_line = self.marker[0]
611 def put_safe(self, code):
612 # put code, but ignore {}
623 dl -= code.count("}")
626 elif dl == 0 and code[0] == "}":
627 # special cases like "} else {" need a temporary dedent
639 def increase_indent(self):
640 self.level = self.level + 1
642 def decrease_indent(self):
643 self.level = self.level - 1
645 def begin_block(self):
647 self.increase_indent()
650 self.decrease_indent()
654 self.write(" " * self.level)
656 def get_py_version_hex(self, pyversion):
657 return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
659 def mark_pos(self, pos):
662 source_desc, line, col = pos
663 if self.last_marker_line == line:
665 assert isinstance(source_desc, SourceDescriptor)
666 contents = self.globalstate.commented_file_contents(source_desc)
667 lines = contents[max(0,line-3):line] # line numbers start at 1
668 lines[-1] += u' # <<<<<<<<<<<<<<'
669 lines += contents[line:line+2]
671 marker = u'"%s":%d\n%s\n' % (
672 source_desc.get_escaped_description(), line, u'\n'.join(lines))
673 self.marker = (line, marker)
674 if self.emit_linenums:
675 self.source_desc = source_desc.get_escaped_description()
677 def put_label(self, lbl):
678 if lbl in self.funcstate.labels_used:
679 self.putln("%s:;" % lbl)
681 def put_goto(self, lbl):
682 self.funcstate.use_label(lbl)
683 self.putln("goto %s;" % lbl)
685 def put_var_declarations(self, entries, static = 0, dll_linkage = None,
687 for entry in entries:
688 if not entry.in_cinclude:
689 self.put_var_declaration(entry, static, dll_linkage, definition)
691 def put_var_declaration(self, entry, static = 0, dll_linkage = None,
693 #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
696 visibility = entry.visibility
697 if visibility == 'private' and not definition:
698 #print "...private and not definition, skipping" ###
700 if not entry.used and visibility == "private":
701 #print "not used and private, skipping", entry.cname ###
704 if visibility == 'extern':
705 storage_class = Naming.extern_c_macro
706 elif visibility == 'public':
708 storage_class = Naming.extern_c_macro
709 elif visibility == 'private':
711 storage_class = "static"
713 self.put("%s " % storage_class)
714 if visibility != 'public':
716 self.put(entry.type.declaration_code(entry.cname,
717 dll_linkage = dll_linkage))
718 if entry.init is not None:
719 self.put_safe(" = %s" % entry.type.literal_code(entry.init))
722 def put_temp_declarations(self, func_context):
723 for name, type, manage_ref in func_context.temps_allocated:
724 decl = type.declaration_code(name)
726 self.putln("%s = NULL;" % decl)
728 self.putln("%s;" % decl)
730 def entry_as_pyobject(self, entry):
732 if (not entry.is_self_arg and not entry.type.is_complete()) \
733 or (entry.type.is_extension_type and entry.type.base_type):
734 return "(PyObject *)" + entry.cname
738 def as_pyobject(self, cname, type):
739 return typecast(py_object_type, type, cname)
741 def put_gotref(self, cname):
742 self.putln("__Pyx_GOTREF(%s);" % cname)
744 def put_giveref(self, cname):
745 self.putln("__Pyx_GIVEREF(%s);" % cname)
747 def put_incref(self, cname, type):
748 self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
750 def put_decref(self, cname, type):
751 self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
753 def put_var_incref(self, entry):
754 if entry.type.is_pyobject:
755 self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
757 def put_decref_clear(self, cname, type):
758 self.putln("__Pyx_DECREF(%s); %s = 0;" % (
759 typecast(py_object_type, type, cname), cname))
760 #self.as_pyobject(cname, type), cname))
762 def put_xdecref(self, cname, type):
763 self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
765 def put_xdecref_clear(self, cname, type):
766 self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
767 self.as_pyobject(cname, type), cname))
769 def put_var_decref(self, entry):
770 if entry.type.is_pyobject:
771 if entry.init_to_none is False:
772 self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
774 self.putln("__Pyx_DECREF(%s);" % self.entry_as_pyobject(entry))
776 def put_var_decref_clear(self, entry):
777 if entry.type.is_pyobject:
778 self.putln("__Pyx_DECREF(%s); %s = 0;" % (
779 self.entry_as_pyobject(entry), entry.cname))
781 def put_var_xdecref(self, entry):
782 if entry.type.is_pyobject:
783 self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
785 def put_var_xdecref_clear(self, entry):
786 if entry.type.is_pyobject:
787 self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
788 self.entry_as_pyobject(entry), entry.cname))
790 def put_var_decrefs(self, entries, used_only = 0):
791 for entry in entries:
792 if not used_only or entry.used:
793 if entry.xdecref_cleanup:
794 self.put_var_xdecref(entry)
796 self.put_var_decref(entry)
798 def put_var_xdecrefs(self, entries):
799 for entry in entries:
800 self.put_var_xdecref(entry)
802 def put_var_xdecrefs_clear(self, entries):
803 for entry in entries:
804 self.put_var_xdecref_clear(entry)
806 def put_init_to_py_none(self, cname, type):
807 py_none = typecast(type, py_object_type, "Py_None")
808 self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
810 def put_init_var_to_py_none(self, entry, template = "%s"):
811 code = template % entry.cname
812 #if entry.type.is_extension_type:
813 # code = "((PyObject*)%s)" % code
814 self.put_init_to_py_none(code, entry.type)
816 def put_pymethoddef(self, entry, term):
818 doc_code = entry.doc_cname
821 method_flags = entry.signature.method_flags()
824 method_flags += [method_coexist]
826 '{__Pyx_NAMESTR("%s"), (PyCFunction)%s, %s, __Pyx_DOCSTR(%s)}%s' % (
829 "|".join(method_flags),
833 def put_error_if_neg(self, pos, value):
834 # 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!
835 return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
837 def put_h_guard(self, guard):
838 self.putln("#ifndef %s" % guard)
839 self.putln("#define %s" % guard)
841 def unlikely(self, cond):
842 if Options.gcc_branch_hints:
843 return 'unlikely(%s)' % cond
847 def set_error_info(self, pos):
848 if Options.c_line_in_traceback:
849 cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
852 return "%s = %s[%s]; %s = %s;%s" % (
853 Naming.filename_cname,
854 Naming.filetable_cname,
855 self.lookup_filename(pos[0]),
860 def error_goto(self, pos):
861 lbl = self.funcstate.error_label
862 self.funcstate.use_label(lbl)
863 return "{%s goto %s;}" % (
864 self.set_error_info(pos),
867 def error_goto_if(self, cond, pos):
868 return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
870 def error_goto_if_null(self, cname, pos):
871 return self.error_goto_if("!%s" % cname, pos)
873 def error_goto_if_neg(self, cname, pos):
874 return self.error_goto_if("%s < 0" % cname, pos)
876 def error_goto_if_PyErr(self, pos):
877 return self.error_goto_if("PyErr_Occurred()", pos)
879 def lookup_filename(self, filename):
880 return self.globalstate.lookup_filename(filename)
883 class PyrexCodeWriter:
885 # level int indentation level
887 def __init__(self, outfile_name):
888 self.f = open_new_file(outfile_name)
891 def putln(self, code):
892 self.f.write("%s%s\n" % (" " * self.level, code))