import PyrexTypes
import TypeSlots
from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
-from Symtab import ModuleScope, LocalScope, PersistentLocalScope, \
+from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
StructOrUnionScope, PyClassScope, CClassScope
from Cython.Utils import open_new_file, replace_suffix, EncodedString
import Options
while env.is_py_class_scope or env.is_c_class_scope:
env = env.outer_scope
if self.needs_closure:
- lenv = PersistentLocalScope(name = self.entry.name, outer_scope = genv)
+ lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
else:
lenv = LocalScope(name = self.entry.name, outer_scope = genv)
lenv.return_type = self.return_type
self.generate_function_header(code,
with_pymethdef = env.is_py_class_scope)
# ----- Local variable declarations
+ lenv.mangle_closure_cnames(Naming.cur_scope_cname)
self.generate_argument_declarations(lenv, code)
+ if self.needs_closure:
+ code.putln("/* TODO: declare and create scope object */")
code.put_var_declarations(lenv.var_entries)
init = ""
if not self.return_type.is_void:
self.put_stararg_decrefs(code)
if acquire_gil:
code.putln("PyGILState_Release(_save);")
+ code.putln("/* TODO: decref scope object */")
# ----- Return
if not self.return_type.is_void:
code.putln("return %s;" % Naming.retval_cname)
# is_self_arg boolean Is the "self" arg of an exttype method
# is_arg boolean Is the arg of a method
# is_local boolean Is a local variable
+ # in_closure boolean Is referenced in an inner scope
# is_readonly boolean Can't be assigned to
# func_cname string C func implementing Python func
# pos position Source position where declared
is_self_arg = 0
is_arg = 0
is_local = 0
+ in_closure = 0
is_declared_generic = 0
is_readonly = 0
func_cname = None
in_cinclude = 0
nogil = 0
+ 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.
# Look up name in this scope or an enclosing one.
# Return None if not found.
return (self.lookup_here(name)
- or (self.outer_scope and self.outer_scope.lookup(name))
+ or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
+ or None)
+
+ def lookup_from_inner(self, name):
+ # Look up name in this scope or an enclosing one.
+ # This is only called from enclosing scopes.
+ return (self.lookup_here(name)
+ or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
or None)
def lookup_here(self, name):
return entry.cname
n = self.temp_counter
self.temp_counter = n + 1
- cname = "%s%d" % (Naming.pyrex_prefix, n)
+ 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 = self.global_scope().lookup_target(name)
self.entries[name] = entry
+ def lookup_from_inner(self, name):
+ entry = self.lookup_here(name)
+ if entry:
+ entry.in_closure = 1
+ return entry
+ else:
+ return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
+
+ def mangle_closure_cnames(self, scope_var):
+ for entry in self.entries.values():
+ if entry.in_closure:
+ if not hasattr(entry, 'orig_cname'):
+ entry.orig_cname = entry.cname
+ entry.cname = scope_var + "->" + entry.cname
+
-class PersistentLocalScope(LocalScope):
+class GeneratorLocalScope(LocalScope):
+
+ temp_prefix = Naming.cur_scope_cname + "->" + LocalScope.temp_prefix
- def mangle(self, prefix, name):
- return "%s->%s" % (scope_obj_cname, name)
+ def mangle_closure_cnames(self, scope_var):
+ 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):
+# return "%s->%s" % (Naming.scope_obj_cname, name)
class StructOrUnionScope(Scope):
# Namespace of a C struct or union.