From: Dag Sverre Seljebotn Date: Fri, 1 Aug 2008 09:51:00 +0000 (+0200) Subject: Introduced code.globalstate and renamed code.func to code.funcstate X-Git-Tag: 0.9.8.1~49^2~40^2~1 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=218d595989e18bb758cdf5cbd71f75dd88985c3f;p=cython.git Introduced code.globalstate and renamed code.func to code.funcstate global is a reserved word... --- diff --git a/Cython/Compiler/Buffer.py b/Cython/Compiler/Buffer.py index 3e8f5ac4..894494cc 100644 --- a/Cython/Compiler/Buffer.py +++ b/Cython/Compiler/Buffer.py @@ -209,7 +209,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, lhs_cname, bufstruct)) code.end_block() # 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('if (%s) ' % (code.unlikely("%s < 0" % retcode_cname))) # 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, # will cause the reacquisition exception to be reported, one # can consider working around this later. 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)] code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb)) 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, code.putln('} else {') code.putln('PyErr_Restore(%s, %s, %s);' % (type, value, tb)) for t in (type, value, tb): - code.func.release_temp(t) + code.funcstate.release_temp(t) code.end_block() # Unpack indices code.end_block() put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code) code.putln(code.error_goto_if_neg(retcode_cname, pos)) - code.func.release_temp(retcode_cname) + code.funcstate.release_temp(retcode_cname) else: # 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, @@ -261,7 +261,7 @@ def put_access(entry, index_signeds, index_cnames, pos, code): # Check bounds and fix negative indices boundscheck = 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: code.putln("%s = -1;" % tmp_cname) 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): code.putln('__Pyx_BufferIndexError(%s);' % tmp_cname) code.putln(code.error_goto(pos)) code.end_block() - code.func.release_temp(tmp_cname) + code.funcstate.release_temp(tmp_cname) # Create buffer lookup and return it params = [] diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 79aa5c2e..f5088e84 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -12,7 +12,16 @@ from Scanning import SourceDescriptor from Cython.StringIOTree import StringIOTree 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 def __init__(self, names_taken=set()): self.names_taken = names_taken @@ -25,6 +34,9 @@ class FunctionContext(object): self.continue_label = None self.break_label = None + self.in_try_finally = 0 + self.exc_vars = None + self.temps_allocated = [] # of (name, type) self.temps_free = {} # type -> list of free vars self.temps_used_type = {} # name -> type @@ -118,11 +130,44 @@ class FunctionContext(object): self.temps_free[type] = freelist 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 get(self): - return getattr(self.func, name) + return getattr(self.funcstate, name) def set(self, value): - setattr(self.func, name, value) + setattr(self.funcstate, name, value) return property(get, set) class CCodeWriter(object): @@ -148,47 +193,29 @@ class CCodeWriter(object): # level int indentation level # bol bool beginning of line? # marker string comment to emit before next line - # 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 - # 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 + # funcstate FunctionState contains state local to a C function used for code + # generation (labels and temps state etc.) + # globalstate GlobalState contains state global for a C file (input file info, + # utility code, declared constants etc.) - in_try_finally = 0 - def __init__(self, create_from=None, buffer=None): if buffer is None: buffer = StringIOTree() self.buffer = buffer self.marker = None self.last_marker_line = 0 - self.func = None + + self.funcstate = None # always start with no function state if create_from is None: # Root CCodeWriter self.level = 0 self.bol = 1 - self.filename_table = {} - self.filename_list = [] - self.exc_vars = None - self.input_file_contents = {} + self.globalstate = GlobalState() else: + # Use same global state + self.globalstate = create_from.globalstate # Clone formatting state - c = create_from - self.level = c.level - 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 + self.level = create_from.level + self.bol = create_from.bol def create_new(self, create_from, buffer): # polymorphic constructor -- very slightly more versatile @@ -216,26 +243,26 @@ class CCodeWriter(object): labels_used = funccontext_property("labels_used") continue_label = funccontext_property("continue_label") break_label = funccontext_property("break_label") - + return_from_error_cleanup_label = funccontext_property("return_from_error_cleanup_label") # Functions delegated to function scope - def new_label(self): return self.func.new_label() - def new_error_label(self): return self.func.new_error_label() - def get_loop_labels(self): return self.func.get_loop_labels() - def set_loop_labels(self, labels): return self.func.set_loop_labels(labels) - def new_loop_labels(self): return self.func.new_loop_labels() - def get_all_labels(self): return self.func.get_all_labels() - def set_all_labels(self, labels): return self.func.set_all_labels(labels) - def all_new_labels(self): return self.func.all_new_labels() - def use_label(self, lbl): return self.func.use_label(lbl) - def label_used(self, lbl): return self.func.label_used(lbl) + def new_label(self): return self.funcstate.new_label() + def new_error_label(self): return self.funcstate.new_error_label() + def get_loop_labels(self): return self.funcstate.get_loop_labels() + def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels) + def new_loop_labels(self): return self.funcstate.new_loop_labels() + def get_all_labels(self): return self.funcstate.get_all_labels() + def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels) + def all_new_labels(self): return self.funcstate.all_new_labels() + def use_label(self, lbl): return self.funcstate.use_label(lbl) + def label_used(self, lbl): return self.funcstate.label_used(lbl) def enter_cfunc_scope(self): - self.func = FunctionContext() + self.funcstate = FunctionState() def exit_cfunc_scope(self): - self.func = None + self.funcstate = None def putln(self, code = ""): if self.marker and self.bol: @@ -287,17 +314,6 @@ class CCodeWriter(object): def get_py_version_hex(self, pyversion): 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): if pos is None: return @@ -305,7 +321,7 @@ class CCodeWriter(object): if self.last_marker_line == line: return 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[-1] += u' # <<<<<<<<<<<<<<' @@ -317,11 +333,11 @@ class CCodeWriter(object): def put_label(self, lbl): - if lbl in self.func.labels_used: + if lbl in self.funcstate.labels_used: self.putln("%s:;" % lbl) def put_goto(self, lbl): - self.func.use_label(lbl) + self.funcstate.use_label(lbl) self.putln("goto %s;" % lbl) def put_var_declarations(self, entries, static = 0, dll_linkage = None, @@ -481,8 +497,8 @@ class CCodeWriter(object): return cond def error_goto(self, pos): - lbl = self.func.error_label - self.func.use_label(lbl) + lbl = self.funcstate.error_label + self.funcstate.use_label(lbl) if Options.c_line_in_traceback: cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro) else: @@ -509,13 +525,7 @@ class CCodeWriter(object): return self.error_goto_if("PyErr_Occurred()", pos) 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 + return self.globalstate.lookup_filename(filename) class PyrexCodeWriter: diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 699200d1..6fb5744d 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1065,7 +1065,7 @@ class NameNode(AtomicExprNode): rhs.generate_post_assignment_code(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 bufstruct = buffer_aux.buffer_info_var.cname code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) @@ -1075,7 +1075,7 @@ class NameNode(AtomicExprNode): is_initialized=not self.skip_assignment_decref, pos=self.pos, code=code) code.putln("%s = 0;" % rhstmp) - code.func.release_temp(rhstmp) + code.funcstate.release_temp(rhstmp) def generate_deletion_code(self, code): if self.entry is None: @@ -1520,7 +1520,7 @@ class IndexNode(ExprNode): def buffer_access_code(self, code): # 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): code.putln("%s = %s;" % (temp, index.result_code)) # Generate buffer access code using these temps diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 26b778e3..7c1b950c 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -529,8 +529,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): def generate_filename_table(self, code): code.putln("") code.putln("static const char *%s[] = {" % Naming.filenames_cname) - if code.filename_list: - for source_desc in code.filename_list: + if code.globalstate.filename_list: + for source_desc in code.globalstate.filename_list: filename = os.path.basename(source_desc.get_filenametable_entry()) escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"') code.putln('"%s",' % @@ -1610,7 +1610,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln('}') 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() diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 9911ae4b..86151643 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -969,7 +969,7 @@ class FuncDefNode(StatNode, BlockNode): code.putln("}") # ----- Go back and insert temp variable declarations tempvardecl_code.put_var_declarations(lenv.temp_entries) - tempvardecl_code.put_temp_declarations(code.func) + tempvardecl_code.put_temp_declarations(code.funcstate) # ----- Python version code.exit_cfunc_scope() if self.py_func: @@ -2634,7 +2634,7 @@ class ContinueStatNode(StatNode): pass 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") elif not code.continue_label: error(self.pos, "continue statement not inside loop") @@ -2797,7 +2797,7 @@ class ReraiseStatNode(StatNode): gil_message = "Raising exception" def generate_execution_code(self, code): - vars = code.exc_vars + vars = code.funcstate.exc_vars if vars: code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars)) code.putln(code.error_goto(self.pos)) @@ -3478,10 +3478,10 @@ class ExceptClauseNode(Node): self.excinfo_tuple.generate_evaluation_code(code) self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code) - old_exc_vars = code.exc_vars - code.exc_vars = self.exc_vars + old_exc_vars = code.funcstate.exc_vars + code.funcstate.exc_vars = self.exc_vars 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: code.putln("Py_DECREF(%s); %s = 0;" % (var, var)) code.put_goto(end_label) @@ -3556,11 +3556,11 @@ class TryFinallyStatNode(StatNode): code.putln( "/*try:*/ {") if self.disallow_continue_in_try_finally: - was_in_try_finally = code.in_try_finally - code.in_try_finally = 1 + was_in_try_finally = code.funcstate.in_try_finally + code.funcstate.in_try_finally = 1 self.body.generate_execution_code(code) 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(