code.put_goto(code.return_label)
code.put_label(code.error_label)
- code.put_var_xdecrefs(env.temp_entries)
+ # TODO: Should new temps be freed here?
code.putln('__Pyx_AddTraceback("%s");' % env.qualified_name)
env.use_utility_code(Nodes.traceback_utility_code)
code.put_decref_clear(env.module_cname, py_object_type, nanny=False)
code.putln("#endif")
code.putln('}')
- tempdecl_code.put_var_declarations(env.temp_entries)
tempdecl_code.put_temp_declarations(code.funcstate)
code.exit_cfunc_scope()
if code.error_label in code.labels_used:
code.put_goto(code.return_label)
code.put_label(code.error_label)
- # cleanup temps the old way
- code.put_var_xdecrefs(lenv.temp_entries)
- # cleanup temps the new way
for cname, type in code.funcstate.all_managed_temps():
code.put_xdecref(cname, type)
code.putln("}")
# ----- Go back and insert temp variable declarations
- tempvardecl_code.put_var_declarations(lenv.temp_entries)
tempvardecl_code.put_temp_declarations(code.funcstate)
# ----- Python version
code.exit_cfunc_scope()
if type.return_type.is_pyobject:
error(self.pos,
"Function with Python return type cannot be declared nogil")
- for entry in env.var_entries + env.temp_entries:
+ for entry in env.var_entries:
if entry.type.is_pyobject:
error(self.pos, "Function declared nogil has Python locals or temporaries")
#
# value ExprNode or None
# return_type PyrexType
- # temps_in_use [Entry] Temps in use at time of return
child_attrs = ["value"]
def analyse_expressions(self, env):
return_type = env.return_type
self.return_type = return_type
- self.temps_in_use = env.temps_in_use()
if not return_type:
error(self.pos, "Return not inside a function body")
return
"%s = %s;" % (
Naming.retval_cname,
self.return_type.default_value))
- # free temps the old way
- for entry in self.temps_in_use:
- code.put_var_decref_clear(entry)
- # free temps the new way
for cname, type in code.funcstate.temps_holding_reference():
code.put_decref_clear(cname, type)
- #code.putln(
- # "goto %s;" %
- # code.return_label)
code.put_goto(code.return_label)
def annotate(self, code):
# body StatNode
# except_clauses [ExceptClauseNode]
# else_clause StatNode or None
- # cleanup_list [Entry] old style temps to clean up on error
child_attrs = ["body", "except_clauses", "else_clause"]
def analyse_expressions(self, env):
self.body.analyse_expressions(env)
- self.cleanup_list = env.free_temp_entries[:]
default_clause_seen = 0
for except_clause in self.except_clauses:
except_clause.analyse_expressions(env)
code.put_xdecref_clear(var, py_object_type)
code.put_goto(old_return_label)
code.put_label(our_error_label)
- code.put_var_xdecrefs_clear(self.cleanup_list)
for temp_name, type in temps_to_clean_up:
code.put_xdecref_clear(temp_name, type)
for except_clause in self.except_clauses:
# body StatNode
# finally_clause StatNode
#
- # cleanup_list [Entry] old_style temps to clean up on error
- #
# The plan is that we funnel all continue, break
# return and error gotos into the beginning of the
# finally block, setting a variable to remember which
def create_analysed(pos, env, body, finally_clause):
node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
- node.cleanup_list = []
return node
create_analysed = staticmethod(create_analysed)
def analyse_expressions(self, env):
self.body.analyse_expressions(env)
- self.cleanup_list = env.free_temp_entries[:]
self.finally_clause.analyse_expressions(env)
gil_check = StatNode._gil_check
code.putln(
"__pyx_why = %s;" %
i)
- code.put_var_xdecrefs_clear(self.cleanup_list)
for temp_name, type in temps_to_clean_up:
code.put_xdecref_clear(temp_name, type)
code.putln(
# pyfunc_entries [Entry] Python function entries
# cfunc_entries [Entry] C function entries
# c_class_entries [Entry] All extension type entries
- # temp_entries [Entry] Temporary variable entries
- # free_temp_entries [Entry] Temp variables currently unused
- # temp_counter integer Counter for naming temp vars
# cname_to_entry {string : Entry} Temp cname to entry mapping
# int_to_entry {int : Entry} Temp cname to entry mapping
# return_type PyrexType or None Return type of function owning scope
nogil = 0
directives = {}
- temp_prefix = Naming.pyrex_prefix
-
def __init__(self, name, outer_scope, parent_scope):
# The outer_scope is the next scope in the lookup chain.
# The parent_scope is used to derive the qualified name of this scope.
self.c_class_entries = []
self.defined_c_classes = []
self.imported_c_classes = {}
- self.temp_entries = []
- self.free_temp_entries = []
- #self.pending_temp_entries = [] # TEMPORARY
- self.temp_counter = 1
self.cname_to_entry = {}
self.string_to_entry = {}
self.identifier_to_entry = {}
if entry and entry.is_type:
return entry.type
- def allocate_temp(self, type):
- # Allocate a temporary variable of the given type from the
- # free list if available, otherwise create a new one.
- # Returns the cname of the variable.
- for entry in self.free_temp_entries:
- if entry.type == type:
- self.free_temp_entries.remove(entry)
- return entry.cname
- n = self.temp_counter
- self.temp_counter = n + 1
- cname = "%s%d" % (self.temp_prefix, n)
- entry = Entry("", cname, type)
- entry.used = 1
- if type.is_pyobject or type == PyrexTypes.c_py_ssize_t_type:
- entry.init = "0"
- self.cname_to_entry[entry.cname] = entry
- self.temp_entries.append(entry)
- return entry.cname
-
- def allocate_temp_pyobject(self):
- # Allocate a temporary PyObject variable.
- return self.allocate_temp(py_object_type)
-
- def release_temp(self, cname):
- # Release a temporary variable for re-use.
- if not cname: # can happen when type of an expr is void
- return
- entry = self.cname_to_entry[cname]
- if entry in self.free_temp_entries:
- raise InternalError("Temporary variable %s released more than once"
- % cname)
- self.free_temp_entries.append(entry)
-
- def temps_in_use(self):
- # Return a new list of temp entries currently in use.
- return [entry for entry in self.temp_entries
- if entry not in self.free_temp_entries]
-
def use_utility_code(self, new_code, name=None):
self.global_scope().use_utility_code(new_code, name)
class GeneratorLocalScope(LocalScope):
- temp_prefix = Naming.cur_scope_cname + "->" + LocalScope.temp_prefix
-
def mangle_closure_cnames(self, scope_var):
- for entry in self.entries.values() + self.temp_entries:
- entry.in_closure = 1
+# for entry in self.entries.values() + self.temp_entries:
+# entry.in_closure = 1
LocalScope.mangle_closure_cnames(self, scope_var)
# def mangle(self, prefix, name):
entry.is_pyglobal = 1
return entry
- def allocate_temp(self, type):
- return self.outer_scope.allocate_temp(type)
-
- def release_temp(self, cname):
- self.outer_scope.release_temp(cname)
-
- #def recycle_pending_temps(self):
- # self.outer_scope.recycle_pending_temps()
-
def add_default_value(self, type):
return self.outer_scope.add_default_value(type)
base_entry.visibility, base_entry.func_modifiers)
entry.is_inherited = 1
- def allocate_temp(self, type):
- return Scope.allocate_temp(self.global_scope(), type)
-
- def release_temp(self, cname):
- return Scope.release_temp(self.global_scope(), cname)
-
class PropertyScope(Scope):
# Scope holding the __get__, __set__ and __del__ methods for