Commit 218d5959 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Introduced code.globalstate and renamed code.func to code.funcstate

global is a reserved word...
parent d28ddc7e
...@@ -209,7 +209,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, ...@@ -209,7 +209,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
lhs_cname, bufstruct)) lhs_cname, bufstruct))
code.end_block() code.end_block()
# Acquire # Acquire
retcode_cname = code.func.allocate_temp(PyrexTypes.c_int_type) retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname)) code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
code.putln('if (%s) ' % (code.unlikely("%s < 0" % retcode_cname))) code.putln('if (%s) ' % (code.unlikely("%s < 0" % retcode_cname)))
# If acquisition failed, attempt to reacquire the old buffer # If acquisition failed, attempt to reacquire the old buffer
...@@ -217,7 +217,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, ...@@ -217,7 +217,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
# will cause the reacquisition exception to be reported, one # will cause the reacquisition exception to be reported, one
# can consider working around this later. # can consider working around this later.
code.begin_block() code.begin_block()
type, value, tb = [code.func.allocate_temp(PyrexTypes.py_object_type) type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type)
for i in range(3)] for i in range(3)]
code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb)) code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
code.put('if (%s) ' % code.unlikely("%s == -1" % (getbuffer % lhs_cname))) code.put('if (%s) ' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
...@@ -227,13 +227,13 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, ...@@ -227,13 +227,13 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
code.putln('} else {') code.putln('} else {')
code.putln('PyErr_Restore(%s, %s, %s);' % (type, value, tb)) code.putln('PyErr_Restore(%s, %s, %s);' % (type, value, tb))
for t in (type, value, tb): for t in (type, value, tb):
code.func.release_temp(t) code.funcstate.release_temp(t)
code.end_block() code.end_block()
# Unpack indices # Unpack indices
code.end_block() code.end_block()
put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code) put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code)
code.putln(code.error_goto_if_neg(retcode_cname, pos)) code.putln(code.error_goto_if_neg(retcode_cname, pos))
code.func.release_temp(retcode_cname) code.funcstate.release_temp(retcode_cname)
else: else:
# Our entry had no previous value, so set to None when acquisition fails. # Our entry had no previous value, so set to None when acquisition fails.
# In this case, auxiliary vars should be set up right in initialization to a zero-buffer, # In this case, auxiliary vars should be set up right in initialization to a zero-buffer,
...@@ -261,7 +261,7 @@ def put_access(entry, index_signeds, index_cnames, pos, code): ...@@ -261,7 +261,7 @@ def put_access(entry, index_signeds, index_cnames, pos, code):
# Check bounds and fix negative indices # Check bounds and fix negative indices
boundscheck = True boundscheck = True
nonegs = True nonegs = True
tmp_cname = code.func.allocate_temp(PyrexTypes.c_int_type) tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
if boundscheck: if boundscheck:
code.putln("%s = -1;" % tmp_cname) code.putln("%s = -1;" % tmp_cname)
for idx, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, for idx, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
...@@ -288,7 +288,7 @@ def put_access(entry, index_signeds, index_cnames, pos, code): ...@@ -288,7 +288,7 @@ def put_access(entry, index_signeds, index_cnames, pos, code):
code.putln('__Pyx_BufferIndexError(%s);' % tmp_cname) code.putln('__Pyx_BufferIndexError(%s);' % tmp_cname)
code.putln(code.error_goto(pos)) code.putln(code.error_goto(pos))
code.end_block() code.end_block()
code.func.release_temp(tmp_cname) code.funcstate.release_temp(tmp_cname)
# Create buffer lookup and return it # Create buffer lookup and return it
params = [] params = []
......
...@@ -12,7 +12,16 @@ from Scanning import SourceDescriptor ...@@ -12,7 +12,16 @@ from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree from Cython.StringIOTree import StringIOTree
from sets import Set as set from sets import Set as set
class FunctionContext(object): class FunctionState(object):
# return_label string function return point label
# error_label string error catch point label
# continue_label string loop continue point label
# break_label string loop break point label
# return_from_error_cleanup_label string
# label_counter integer counter for naming labels
# in_try_finally boolean inside try of try...finally
# exc_vars (string * 3) exception variables for reraise, or None
# Not used for now, perhaps later # Not used for now, perhaps later
def __init__(self, names_taken=set()): def __init__(self, names_taken=set()):
self.names_taken = names_taken self.names_taken = names_taken
...@@ -25,6 +34,9 @@ class FunctionContext(object): ...@@ -25,6 +34,9 @@ class FunctionContext(object):
self.continue_label = None self.continue_label = None
self.break_label = None self.break_label = None
self.in_try_finally = 0
self.exc_vars = None
self.temps_allocated = [] # of (name, type) self.temps_allocated = [] # of (name, type)
self.temps_free = {} # type -> list of free vars self.temps_free = {} # type -> list of free vars
self.temps_used_type = {} # name -> type self.temps_used_type = {} # name -> type
...@@ -118,11 +130,44 @@ class FunctionContext(object): ...@@ -118,11 +130,44 @@ class FunctionContext(object):
self.temps_free[type] = freelist self.temps_free[type] = freelist
freelist.append(name) freelist.append(name)
class GlobalState(object):
# filename_table {string : int} for finding filename table indexes
# filename_list [string] filenames in filename table order
# input_file_contents dict contents (=list of lines) of any file that was used as input
# to create this output C code. This is
# used to annotate the comments.
def __init__(self):
self.filename_table = {}
self.filename_list = []
self.input_file_contents = {}
def lookup_filename(self, filename):
try:
index = self.filename_table[filename]
except KeyError:
index = len(self.filename_list)
self.filename_list.append(filename)
self.filename_table[filename] = index
return index
def commented_file_contents(self, source_desc):
try:
return self.input_file_contents[source_desc]
except KeyError:
F = [u' * ' + line.rstrip().replace(
u'*/', u'*[inserted by cython to avoid comment closer]/'
).encode('ASCII', 'replace') # + Py2 auto-decode to unicode
for line in source_desc.get_lines()]
self.input_file_contents[source_desc] = F
return F
def funccontext_property(name): def funccontext_property(name):
def get(self): def get(self):
return getattr(self.func, name) return getattr(self.funcstate, name)
def set(self, value): def set(self, value):
setattr(self.func, name, value) setattr(self.funcstate, name, value)
return property(get, set) return property(get, set)
class CCodeWriter(object): class CCodeWriter(object):
...@@ -148,47 +193,29 @@ class CCodeWriter(object): ...@@ -148,47 +193,29 @@ class CCodeWriter(object):
# level int indentation level # level int indentation level
# bol bool beginning of line? # bol bool beginning of line?
# marker string comment to emit before next line # marker string comment to emit before next line
# return_label string function return point label # funcstate FunctionState contains state local to a C function used for code
# error_label string error catch point label # generation (labels and temps state etc.)
# continue_label string loop continue point label # globalstate GlobalState contains state global for a C file (input file info,
# break_label string loop break point label # utility code, declared constants etc.)
# return_from_error_cleanup_label string
# label_counter integer counter for naming labels
# in_try_finally boolean inside try of try...finally
# filename_table {string : int} for finding filename table indexes
# filename_list [string] filenames in filename table order
# exc_vars (string * 3) exception variables for reraise, or None
# input_file_contents dict contents (=list of lines) of any file that was used as input
# to create this output C code. This is
# used to annotate the comments.
# func FunctionContext contains labels and temps context info
in_try_finally = 0
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.marker = None self.marker = None
self.last_marker_line = 0 self.last_marker_line = 0
self.func = None
self.funcstate = None # always start with no function state
if create_from is None: if create_from is None:
# Root CCodeWriter # Root CCodeWriter
self.level = 0 self.level = 0
self.bol = 1 self.bol = 1
self.filename_table = {} self.globalstate = GlobalState()
self.filename_list = []
self.exc_vars = None
self.input_file_contents = {}
else: else:
# Use same global state
self.globalstate = create_from.globalstate
# Clone formatting state # Clone formatting state
c = create_from self.level = create_from.level
self.level = c.level self.bol = create_from.bol
self.bol = c.bol
# 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_new(self, create_from, buffer): def create_new(self, create_from, buffer):
# polymorphic constructor -- very slightly more versatile # polymorphic constructor -- very slightly more versatile
...@@ -216,26 +243,26 @@ class CCodeWriter(object): ...@@ -216,26 +243,26 @@ class CCodeWriter(object):
labels_used = funccontext_property("labels_used") labels_used = funccontext_property("labels_used")
continue_label = funccontext_property("continue_label") continue_label = funccontext_property("continue_label")
break_label = funccontext_property("break_label") break_label = funccontext_property("break_label")
return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label")
# Functions delegated to function scope # Functions delegated to function scope
def new_label(self): return self.func.new_label() def new_label(self): return self.funcstate.new_label()
def new_error_label(self): return self.func.new_error_label() def new_error_label(self): return self.funcstate.new_error_label()
def get_loop_labels(self): return self.func.get_loop_labels() def get_loop_labels(self): return self.funcstate.get_loop_labels()
def set_loop_labels(self, labels): return self.func.set_loop_labels(labels) def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
def new_loop_labels(self): return self.func.new_loop_labels() def new_loop_labels(self): return self.funcstate.new_loop_labels()
def get_all_labels(self): return self.func.get_all_labels() def get_all_labels(self): return self.funcstate.get_all_labels()
def set_all_labels(self, labels): return self.func.set_all_labels(labels) def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels)
def all_new_labels(self): return self.func.all_new_labels() def all_new_labels(self): return self.funcstate.all_new_labels()
def use_label(self, lbl): return self.func.use_label(lbl) def use_label(self, lbl): return self.funcstate.use_label(lbl)
def label_used(self, lbl): return self.func.label_used(lbl) def label_used(self, lbl): return self.funcstate.label_used(lbl)
def enter_cfunc_scope(self): def enter_cfunc_scope(self):
self.func = FunctionContext() self.funcstate = FunctionState()
def exit_cfunc_scope(self): def exit_cfunc_scope(self):
self.func = None self.funcstate = None
def putln(self, code = ""): def putln(self, code = ""):
if self.marker and self.bol: if self.marker and self.bol:
...@@ -287,17 +314,6 @@ class CCodeWriter(object): ...@@ -287,17 +314,6 @@ class CCodeWriter(object):
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]
def commented_file_contents(self, source_desc):
try:
return self.input_file_contents[source_desc]
except KeyError:
F = [u' * ' + line.rstrip().replace(
u'*/', u'*[inserted by cython to avoid comment closer]/'
).encode('ASCII', 'replace') # + Py2 auto-decode to unicode
for line in source_desc.get_lines()]
self.input_file_contents[source_desc] = F
return F
def mark_pos(self, pos): def mark_pos(self, pos):
if pos is None: if pos is None:
return return
...@@ -305,7 +321,7 @@ class CCodeWriter(object): ...@@ -305,7 +321,7 @@ class CCodeWriter(object):
if self.last_marker_line == line: if self.last_marker_line == line:
return return
assert isinstance(source_desc, SourceDescriptor) assert isinstance(source_desc, SourceDescriptor)
contents = self.commented_file_contents(source_desc) contents = self.globalstate.commented_file_contents(source_desc)
lines = contents[max(0,line-3):line] # line numbers start at 1 lines = contents[max(0,line-3):line] # line numbers start at 1
lines[-1] += u' # <<<<<<<<<<<<<<' lines[-1] += u' # <<<<<<<<<<<<<<'
...@@ -317,11 +333,11 @@ class CCodeWriter(object): ...@@ -317,11 +333,11 @@ class CCodeWriter(object):
def put_label(self, lbl): def put_label(self, lbl):
if lbl in self.func.labels_used: if lbl in self.funcstate.labels_used:
self.putln("%s:;" % lbl) self.putln("%s:;" % lbl)
def put_goto(self, lbl): def put_goto(self, lbl):
self.func.use_label(lbl) self.funcstate.use_label(lbl)
self.putln("goto %s;" % lbl) self.putln("goto %s;" % lbl)
def put_var_declarations(self, entries, static = 0, dll_linkage = None, def put_var_declarations(self, entries, static = 0, dll_linkage = None,
...@@ -481,8 +497,8 @@ class CCodeWriter(object): ...@@ -481,8 +497,8 @@ class CCodeWriter(object):
return cond return cond
def error_goto(self, pos): def error_goto(self, pos):
lbl = self.func.error_label lbl = self.funcstate.error_label
self.func.use_label(lbl) self.funcstate.use_label(lbl)
if Options.c_line_in_traceback: if Options.c_line_in_traceback:
cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro) cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
else: else:
...@@ -509,13 +525,7 @@ class CCodeWriter(object): ...@@ -509,13 +525,7 @@ class CCodeWriter(object):
return self.error_goto_if("PyErr_Occurred()", pos) return self.error_goto_if("PyErr_Occurred()", pos)
def lookup_filename(self, filename): def lookup_filename(self, filename):
try: return self.globalstate.lookup_filename(filename)
index = self.filename_table[filename]
except KeyError:
index = len(self.filename_list)
self.filename_list.append(filename)
self.filename_table[filename] = index
return index
class PyrexCodeWriter: class PyrexCodeWriter:
......
...@@ -1065,7 +1065,7 @@ class NameNode(AtomicExprNode): ...@@ -1065,7 +1065,7 @@ class NameNode(AtomicExprNode):
rhs.generate_post_assignment_code(code) rhs.generate_post_assignment_code(code)
def generate_acquire_buffer(self, rhs, code): def generate_acquire_buffer(self, rhs, code):
rhstmp = code.func.allocate_temp(self.entry.type) rhstmp = code.funcstate.allocate_temp(self.entry.type)
buffer_aux = self.entry.buffer_aux buffer_aux = self.entry.buffer_aux
bufstruct = buffer_aux.buffer_info_var.cname bufstruct = buffer_aux.buffer_info_var.cname
code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
...@@ -1075,7 +1075,7 @@ class NameNode(AtomicExprNode): ...@@ -1075,7 +1075,7 @@ class NameNode(AtomicExprNode):
is_initialized=not self.skip_assignment_decref, is_initialized=not self.skip_assignment_decref,
pos=self.pos, code=code) pos=self.pos, code=code)
code.putln("%s = 0;" % rhstmp) code.putln("%s = 0;" % rhstmp)
code.func.release_temp(rhstmp) code.funcstate.release_temp(rhstmp)
def generate_deletion_code(self, code): def generate_deletion_code(self, code):
if self.entry is None: if self.entry is None:
...@@ -1520,7 +1520,7 @@ class IndexNode(ExprNode): ...@@ -1520,7 +1520,7 @@ class IndexNode(ExprNode):
def buffer_access_code(self, code): def buffer_access_code(self, code):
# Assign indices to temps # Assign indices to temps
index_temps = [code.func.allocate_temp(i.type) for i in self.indices] index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
for temp, index in zip(index_temps, self.indices): for temp, index in zip(index_temps, self.indices):
code.putln("%s = %s;" % (temp, index.result_code)) code.putln("%s = %s;" % (temp, index.result_code))
# Generate buffer access code using these temps # Generate buffer access code using these temps
......
...@@ -529,8 +529,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -529,8 +529,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_filename_table(self, code): def generate_filename_table(self, code):
code.putln("") code.putln("")
code.putln("static const char *%s[] = {" % Naming.filenames_cname) code.putln("static const char *%s[] = {" % Naming.filenames_cname)
if code.filename_list: if code.globalstate.filename_list:
for source_desc in code.filename_list: for source_desc in code.globalstate.filename_list:
filename = os.path.basename(source_desc.get_filenametable_entry()) filename = os.path.basename(source_desc.get_filenametable_entry())
escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"') escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"')
code.putln('"%s",' % code.putln('"%s",' %
...@@ -1610,7 +1610,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1610,7 +1610,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('}') code.putln('}')
tempdecl_code.put_var_declarations(env.temp_entries) tempdecl_code.put_var_declarations(env.temp_entries)
tempdecl_code.put_temp_declarations(code.func) tempdecl_code.put_temp_declarations(code.funcstate)
code.exit_cfunc_scope() code.exit_cfunc_scope()
......
...@@ -969,7 +969,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -969,7 +969,7 @@ class FuncDefNode(StatNode, BlockNode):
code.putln("}") code.putln("}")
# ----- Go back and insert temp variable declarations # ----- Go back and insert temp variable declarations
tempvardecl_code.put_var_declarations(lenv.temp_entries) tempvardecl_code.put_var_declarations(lenv.temp_entries)
tempvardecl_code.put_temp_declarations(code.func) tempvardecl_code.put_temp_declarations(code.funcstate)
# ----- Python version # ----- Python version
code.exit_cfunc_scope() code.exit_cfunc_scope()
if self.py_func: if self.py_func:
...@@ -2634,7 +2634,7 @@ class ContinueStatNode(StatNode): ...@@ -2634,7 +2634,7 @@ class ContinueStatNode(StatNode):
pass pass
def generate_execution_code(self, code): def generate_execution_code(self, code):
if code.in_try_finally: if code.funcstate.in_try_finally:
error(self.pos, "continue statement inside try of try...finally") error(self.pos, "continue statement inside try of try...finally")
elif not code.continue_label: elif not code.continue_label:
error(self.pos, "continue statement not inside loop") error(self.pos, "continue statement not inside loop")
...@@ -2797,7 +2797,7 @@ class ReraiseStatNode(StatNode): ...@@ -2797,7 +2797,7 @@ class ReraiseStatNode(StatNode):
gil_message = "Raising exception" gil_message = "Raising exception"
def generate_execution_code(self, code): def generate_execution_code(self, code):
vars = code.exc_vars vars = code.funcstate.exc_vars
if vars: if vars:
code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars)) code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
code.putln(code.error_goto(self.pos)) code.putln(code.error_goto(self.pos))
...@@ -3478,10 +3478,10 @@ class ExceptClauseNode(Node): ...@@ -3478,10 +3478,10 @@ class ExceptClauseNode(Node):
self.excinfo_tuple.generate_evaluation_code(code) self.excinfo_tuple.generate_evaluation_code(code)
self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code) self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
old_exc_vars = code.exc_vars old_exc_vars = code.funcstate.exc_vars
code.exc_vars = self.exc_vars code.funcstate.exc_vars = self.exc_vars
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.exc_vars = old_exc_vars code.funcstate.exc_vars = old_exc_vars
for var in self.exc_vars: for var in self.exc_vars:
code.putln("Py_DECREF(%s); %s = 0;" % (var, var)) code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(end_label) code.put_goto(end_label)
...@@ -3556,11 +3556,11 @@ class TryFinallyStatNode(StatNode): ...@@ -3556,11 +3556,11 @@ class TryFinallyStatNode(StatNode):
code.putln( code.putln(
"/*try:*/ {") "/*try:*/ {")
if self.disallow_continue_in_try_finally: if self.disallow_continue_in_try_finally:
was_in_try_finally = code.in_try_finally was_in_try_finally = code.funcstate.in_try_finally
code.in_try_finally = 1 code.funcstate.in_try_finally = 1
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
if self.disallow_continue_in_try_finally: if self.disallow_continue_in_try_finally:
code.in_try_finally = was_in_try_finally code.funcstate.in_try_finally = was_in_try_finally
code.putln( code.putln(
"}") "}")
code.putln( code.putln(
......
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