Commit ace9e7f1 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Forking CCodeWriter done (and used for module header generation)

parent 6dcb9c6e
...@@ -17,32 +17,34 @@ special_chars = [(u'<', u'\xF0', u'&lt;'), ...@@ -17,32 +17,34 @@ special_chars = [(u'<', u'\xF0', u'&lt;'),
class AnnotationCCodeWriter(CCodeWriter): class AnnotationCCodeWriter(CCodeWriter):
def __init__(self, f): def __init__(self, create_from=None, buffer=None):
CCodeWriter.__init__(self, self) CCodeWriter.__init__(self, create_from, buffer)
self.buffer = StringIO() self.annotation_buffer = StringIO()
self.real_f = f if create_from is None:
self.annotations = [] self.annotations = []
self.last_pos = None self.last_pos = None
self.code = {} self.code = {}
else:
def getvalue(self): # When forking, keep references to the same database
return self.real_f.getvalue() 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): def write(self, s):
self.real_f.write(s) CCodeWriter.write(self, s)
self.buffer.write(s) self.annotation_buffer.write(s)
def mark_pos(self, pos): def mark_pos(self, pos):
# if pos is not None: # if pos is not None:
# CCodeWriter.mark_pos(self, pos) # CCodeWriter.mark_pos(self, pos)
# return # return
if self.last_pos: if self.last_pos:
try: code = self.code.get(self.last_pos[1], "")
code = self.code[self.last_pos[1]] self.code[self.last_pos[1]] = code + self.annotation_buffer.getvalue()
except KeyError: self.annotation_buffer = StringIO()
code = ""
self.code[self.last_pos[1]] = code + self.buffer.getvalue()
self.buffer = StringIO()
self.last_pos = pos self.last_pos = pos
def annotate(self, pos, item): def annotate(self, pos, item):
......
...@@ -11,18 +11,7 @@ from TypeSlots import method_coexist ...@@ -11,18 +11,7 @@ from TypeSlots import method_coexist
from Scanning import SourceDescriptor from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree from Cython.StringIOTree import StringIOTree
class CCodeWriter(object):
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:
""" """
Utility class to output C code. Each codewriter is forkable (see Utility class to output C code. Each codewriter is forkable (see
StringIOTree). StringIOTree).
...@@ -40,7 +29,9 @@ class CCodeWriter: ...@@ -40,7 +29,9 @@ class CCodeWriter:
- utility code: Same story as with labels and temps; use enter_implementation - utility code: Same story as with labels and temps; use enter_implementation
and exit_implementation. and exit_implementation.
- marker: Only kept in last fork. - 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 # f file output file
...@@ -68,12 +59,12 @@ class CCodeWriter: ...@@ -68,12 +59,12 @@ class CCodeWriter:
def __init__(self, create_from=None, buffer=None): def __init__(self, create_from=None, buffer=None):
if buffer is None: buffer = StringIOTree() if buffer is None: buffer = StringIOTree()
self.buffer = buffer self.buffer = buffer
self._write = self.buffer.write self.marker = None
self.last_marker_line = 0
if create_from is None: if create_from is None:
# Root CCodeWriter
self.level = 0 self.level = 0
self.bol = 1 self.bol = 1
self.marker = None
self.last_marker_line = 0
self.filename_table = {} self.filename_table = {}
self.filename_list = [] self.filename_list = []
self.exc_vars = None self.exc_vars = None
...@@ -84,16 +75,29 @@ class CCodeWriter: ...@@ -84,16 +75,29 @@ class CCodeWriter:
c = create_from c = create_from
self.level = c.level self.level = c.level
self.bol = c.bol 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 # Leave other state alone
def create_fork_spinoff(self, buffer): def create_new(self, create_from, buffer):
result = CCodeWriter # polymorphic constructor -- very slightly more versatile
# than using __class__
return CCodeWriter(create_from, buffer)
def copyto(self, f): def copyto(self, f):
self.buffer.copyto(f) self.buffer.copyto(f)
def getvalue(self):
return self.buffer.getvalue()
def write(self, s):
self.buffer.write(s)
def fork(self): 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 # If we need to do something with our own state on fork, do it here
return other return other
...@@ -122,13 +126,13 @@ class CCodeWriter: ...@@ -122,13 +126,13 @@ class CCodeWriter:
self.emit_marker() self.emit_marker()
if code: if code:
self.put(code) self.put(code)
self._write("\n"); self.write("\n");
self.bol = 1 self.bol = 1
def emit_marker(self): def emit_marker(self):
self._write("\n"); self.write("\n");
self.indent() self.indent()
self._write("/* %s */\n" % self.marker[1]) self.write("/* %s */\n" % self.marker[1])
self.last_marker_line = self.marker[0] self.last_marker_line = self.marker[0]
self.marker = None self.marker = None
...@@ -140,7 +144,7 @@ class CCodeWriter: ...@@ -140,7 +144,7 @@ class CCodeWriter:
self.level -= 1 self.level -= 1
if self.bol: if self.bol:
self.indent() self.indent()
self._write(code) self.write(code)
self.bol = 0 self.bol = 0
if dl > 0: if dl > 0:
self.level += dl self.level += dl
...@@ -162,7 +166,7 @@ class CCodeWriter: ...@@ -162,7 +166,7 @@ class CCodeWriter:
self.putln("}") self.putln("}")
def indent(self): def indent(self):
self._write(" " * self.level) self.write(" " * self.level)
def get_py_version_hex(self, pyversion): def get_py_version_hex(self, pyversion):
return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4] return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
......
...@@ -212,7 +212,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -212,7 +212,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code.putln("") h_code.putln("")
h_code.putln("#endif") 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): def generate_cclass_header_code(self, type, h_code):
h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % ( h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
...@@ -239,8 +239,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -239,8 +239,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code = Annotate.AnnotationCCodeWriter() code = Annotate.AnnotationCCodeWriter()
else: else:
code = Code.CCodeWriter() code = Code.CCodeWriter()
code.h = Code.CCodeWriter() h_code = code.fork()
self.generate_module_preamble(env, modules, code.h) self.generate_module_preamble(env, modules, h_code)
code.putln("") code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name) code.putln("/* Implementation of %s */" % env.qualified_name)
...@@ -262,13 +262,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -262,13 +262,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.mark_pos(None) code.mark_pos(None)
self.generate_module_cleanup_func(env, code) self.generate_module_cleanup_func(env, code)
self.generate_filename_table(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) f = open_new_file(result.c_file)
code.h.copyto(f)
f.write("\n")
code.copyto(f) code.copyto(f)
f.close() f.close()
result.c_file_generated = 1 result.c_file_generated = 1
...@@ -1947,7 +1946,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1947,7 +1946,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s = &%s;" % ( "%s = &%s;" % (
type.typeptr_cname, type.typeobj_cname)) 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("")
code.putln("/* Runtime support code */") code.putln("/* Runtime support code */")
code.putln("") code.putln("")
...@@ -1956,7 +1955,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1956,7 +1955,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
(Naming.filetable_cname, Naming.filenames_cname)) (Naming.filetable_cname, Naming.filenames_cname))
code.putln("}") code.putln("}")
for utility_code in env.utility_code_used: 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(utility_code[1])
code.put(PyrexTypes.type_conversion_functions) code.put(PyrexTypes.type_conversion_functions)
code.putln("") code.putln("")
......
...@@ -967,10 +967,10 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -967,10 +967,10 @@ class FuncDefNode(StatNode, BlockNode):
code.putln("return %s;" % Naming.retval_cname) code.putln("return %s;" % Naming.retval_cname)
code.putln("}") code.putln("}")
# ----- Python version # ----- Python version
code.exit_cfunc_scope()
if self.py_func: if self.py_func:
self.py_func.generate_function_definitions(env, code, transforms) self.py_func.generate_function_definitions(env, code, transforms)
self.generate_optarg_wrapper_function(env, code) self.generate_optarg_wrapper_function(env, code)
code.exit_cfunc_scope()
def put_stararg_decrefs(self, code): def put_stararg_decrefs(self, code):
pass pass
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment