class AnnotationCCodeWriter(CCodeWriter):
- def __init__(self, f):
- CCodeWriter.__init__(self, self)
- self.buffer = StringIO()
- self.real_f = f
- self.annotations = []
- self.last_pos = None
- self.code = {}
-
- def getvalue(self):
- return self.real_f.getvalue()
-
+ def __init__(self, create_from=None, buffer=None):
+ CCodeWriter.__init__(self, create_from, buffer)
+ self.annotation_buffer = StringIO()
+ if create_from is None:
+ self.annotations = []
+ self.last_pos = None
+ self.code = {}
+ else:
+ # When forking, keep references to the same database
+ self.annotation_buffer = create_from.annotation_buffer
+ self.annotations = create_from.annotations
+ self.code = create_from.code
+
+ def create_new(self, create_from, buffer):
+ return AnnotationCCodeWriter(create_from, buffer)
+
def write(self, s):
- self.real_f.write(s)
- self.buffer.write(s)
+ CCodeWriter.write(self, s)
+ self.annotation_buffer.write(s)
def mark_pos(self, pos):
# if pos is not None:
# CCodeWriter.mark_pos(self, pos)
# return
if self.last_pos:
- try:
- code = self.code[self.last_pos[1]]
- except KeyError:
- code = ""
- self.code[self.last_pos[1]] = code + self.buffer.getvalue()
- self.buffer = StringIO()
+ code = self.code.get(self.last_pos[1], "")
+ self.code[self.last_pos[1]] = code + self.annotation_buffer.getvalue()
+ self.annotation_buffer = StringIO()
self.last_pos = pos
def annotate(self, pos, item):
from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree
-
-class CFunctionScope:
- """
- Used by CCodeWriters to keep track of state within a
- C function. This means:
- - labels
- - temporary variables
-
- When a code writer forks, it inherits the same scope.
- """
-
-class CCodeWriter:
+class CCodeWriter(object):
"""
Utility class to output C code. Each codewriter is forkable (see
StringIOTree).
- utility code: Same story as with labels and temps; use enter_implementation
and exit_implementation.
- marker: Only kept in last fork.
- - filename_table, filename_list: Decision to be made.
+ - filename_table, filename_list, input_file_contents: All forks share
+ the same instances simultaneously.
+ -
"""
# f file output file
def __init__(self, create_from=None, buffer=None):
if buffer is None: buffer = StringIOTree()
self.buffer = buffer
- self._write = self.buffer.write
+ self.marker = None
+ self.last_marker_line = 0
if create_from is None:
+ # Root CCodeWriter
self.level = 0
self.bol = 1
- self.marker = None
- self.last_marker_line = 0
self.filename_table = {}
self.filename_list = []
self.exc_vars = None
c = create_from
self.level = c.level
self.bol = c.bol
+ self.in_cfunc = c.in_cfunc
+ # Note: NOT copying but sharing instance
+ self.filename_table = c.filename_table
+ self.filename_list = []
+ self.input_file_contents = c.input_file_contents
# Leave other state alone
- def create_fork_spinoff(self, buffer):
- result = CCodeWriter
+ def create_new(self, create_from, buffer):
+ # polymorphic constructor -- very slightly more versatile
+ # than using __class__
+ return CCodeWriter(create_from, buffer)
def copyto(self, f):
self.buffer.copyto(f)
+ def getvalue(self):
+ return self.buffer.getvalue()
+
+ def write(self, s):
+ self.buffer.write(s)
+
def fork(self):
- other = CCodeWriter(create_from=self, buffer=self.buffer.fork())
+ other = self.create_new(create_from=self, buffer=self.buffer.fork())
# If we need to do something with our own state on fork, do it here
return other
self.emit_marker()
if code:
self.put(code)
- self._write("\n");
+ self.write("\n");
self.bol = 1
def emit_marker(self):
- self._write("\n");
+ self.write("\n");
self.indent()
- self._write("/* %s */\n" % self.marker[1])
+ self.write("/* %s */\n" % self.marker[1])
self.last_marker_line = self.marker[0]
self.marker = None
self.level -= 1
if self.bol:
self.indent()
- self._write(code)
+ self.write(code)
self.bol = 0
if dl > 0:
self.level += dl
self.putln("}")
def indent(self):
- self._write(" " * self.level)
+ self.write(" " * self.level)
def get_py_version_hex(self, pyversion):
return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
h_code.putln("")
h_code.putln("#endif")
- h_code.copy_to(open_new_file(result.api_file))
+ h_code.copyto(open_new_file(result.api_file))
def generate_cclass_header_code(self, type, h_code):
h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
code = Annotate.AnnotationCCodeWriter()
else:
code = Code.CCodeWriter()
- code.h = Code.CCodeWriter()
- self.generate_module_preamble(env, modules, code.h)
+ h_code = code.fork()
+ self.generate_module_preamble(env, modules, h_code)
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
code.mark_pos(None)
self.generate_module_cleanup_func(env, code)
self.generate_filename_table(code)
- self.generate_utility_functions(env, code)
+ self.generate_utility_functions(env, code, h_code)
- self.generate_declarations_for_modules(env, modules, code.h)
+ self.generate_declarations_for_modules(env, modules, h_code)
+ h_code.write('\n')
f = open_new_file(result.c_file)
- code.h.copyto(f)
- f.write("\n")
code.copyto(f)
f.close()
result.c_file_generated = 1
"%s = &%s;" % (
type.typeptr_cname, type.typeobj_cname))
- def generate_utility_functions(self, env, code):
+ def generate_utility_functions(self, env, code, h_code):
code.putln("")
code.putln("/* Runtime support code */")
code.putln("")
(Naming.filetable_cname, Naming.filenames_cname))
code.putln("}")
for utility_code in env.utility_code_used:
- code.h.put(utility_code[0])
+ h_code.put(utility_code[0])
code.put(utility_code[1])
code.put(PyrexTypes.type_conversion_functions)
code.putln("")
code.putln("return %s;" % Naming.retval_cname)
code.putln("}")
# ----- Python version
+ code.exit_cfunc_scope()
if self.py_func:
self.py_func.generate_function_definitions(env, code, transforms)
self.generate_optarg_wrapper_function(env, code)
- code.exit_cfunc_scope()
def put_stararg_decrefs(self, code):
pass