Commit af626302 authored by Robert Bradshaw's avatar Robert Bradshaw

Add indirection to closure variables

parent 4510e2ef
...@@ -200,6 +200,8 @@ class CCodeWriter: ...@@ -200,6 +200,8 @@ class CCodeWriter:
def put_var_declaration(self, entry, static = 0, dll_linkage = None, def put_var_declaration(self, entry, static = 0, dll_linkage = None,
definition = True): definition = True):
#print "Code.put_var_declaration:", entry.name, "definition =", definition ### #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
if entry.in_closure:
return
visibility = entry.visibility visibility = entry.visibility
if visibility == 'private' and not definition: if visibility == 'private' and not definition:
#print "...private and not definition, skipping" ### #print "...private and not definition, skipping" ###
......
...@@ -72,7 +72,8 @@ optional_args_cname = pyrex_prefix + "optional_args" ...@@ -72,7 +72,8 @@ optional_args_cname = pyrex_prefix + "optional_args"
no_opt_args = pyrex_prefix + "no_opt_args" no_opt_args = pyrex_prefix + "no_opt_args"
import_star = pyrex_prefix + "import_star" import_star = pyrex_prefix + "import_star"
import_star_set = pyrex_prefix + "import_star_set" import_star_set = pyrex_prefix + "import_star_set"
scope_obj_cname = pyrex_prefix + "scope" cur_scope_cname = pyrex_prefix + "cur_scope"
enc_scope_cname = pyrex_prefix + "enc_scope"
line_c_macro = "__LINE__" line_c_macro = "__LINE__"
......
...@@ -10,7 +10,7 @@ import Naming ...@@ -10,7 +10,7 @@ import Naming
import PyrexTypes import PyrexTypes
import TypeSlots import TypeSlots
from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType 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 StructOrUnionScope, PyClassScope, CClassScope
from Cython.Utils import open_new_file, replace_suffix, EncodedString from Cython.Utils import open_new_file, replace_suffix, EncodedString
import Options import Options
...@@ -810,7 +810,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -810,7 +810,7 @@ class FuncDefNode(StatNode, BlockNode):
while env.is_py_class_scope or env.is_c_class_scope: while env.is_py_class_scope or env.is_c_class_scope:
env = env.outer_scope env = env.outer_scope
if self.needs_closure: if self.needs_closure:
lenv = PersistentLocalScope(name = self.entry.name, outer_scope = genv) lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
else: else:
lenv = LocalScope(name = self.entry.name, outer_scope = genv) lenv = LocalScope(name = self.entry.name, outer_scope = genv)
lenv.return_type = self.return_type lenv.return_type = self.return_type
...@@ -842,7 +842,10 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -842,7 +842,10 @@ class FuncDefNode(StatNode, BlockNode):
self.generate_function_header(code, self.generate_function_header(code,
with_pymethdef = env.is_py_class_scope) with_pymethdef = env.is_py_class_scope)
# ----- Local variable declarations # ----- Local variable declarations
lenv.mangle_closure_cnames(Naming.cur_scope_cname)
self.generate_argument_declarations(lenv, code) 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) code.put_var_declarations(lenv.var_entries)
init = "" init = ""
if not self.return_type.is_void: if not self.return_type.is_void:
...@@ -923,6 +926,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -923,6 +926,7 @@ class FuncDefNode(StatNode, BlockNode):
self.put_stararg_decrefs(code) self.put_stararg_decrefs(code)
if acquire_gil: if acquire_gil:
code.putln("PyGILState_Release(_save);") code.putln("PyGILState_Release(_save);")
code.putln("/* TODO: decref scope object */")
# ----- Return # ----- Return
if not self.return_type.is_void: if not self.return_type.is_void:
code.putln("return %s;" % Naming.retval_cname) code.putln("return %s;" % Naming.retval_cname)
......
...@@ -1386,8 +1386,8 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1386,8 +1386,8 @@ def p_statement(s, ctx, first_statement = 0):
if ctx.api: if ctx.api:
error(s.pos, "'api' not allowed with this statement") error(s.pos, "'api' not allowed with this statement")
elif s.sy == 'def': elif s.sy == 'def':
if ctx.level not in ('module', 'class', 'c_class', 'property'): # if ctx.level not in ('module', 'class', 'c_class', 'property'):
s.error('def statement not allowed here') # s.error('def statement not allowed here')
s.level = ctx.level s.level = ctx.level
return p_def_statement(s) return p_def_statement(s)
elif s.sy == 'class': elif s.sy == 'class':
......
...@@ -47,6 +47,7 @@ class Entry: ...@@ -47,6 +47,7 @@ class Entry:
# is_self_arg boolean Is the "self" arg of an exttype method # is_self_arg boolean Is the "self" arg of an exttype method
# is_arg boolean Is the arg of a method # is_arg boolean Is the arg of a method
# is_local boolean Is a local variable # is_local boolean Is a local variable
# in_closure boolean Is referenced in an inner scope
# is_readonly boolean Can't be assigned to # is_readonly boolean Can't be assigned to
# func_cname string C func implementing Python func # func_cname string C func implementing Python func
# pos position Source position where declared # pos position Source position where declared
...@@ -96,6 +97,7 @@ class Entry: ...@@ -96,6 +97,7 @@ class Entry:
is_self_arg = 0 is_self_arg = 0
is_arg = 0 is_arg = 0
is_local = 0 is_local = 0
in_closure = 0
is_declared_generic = 0 is_declared_generic = 0
is_readonly = 0 is_readonly = 0
func_cname = None func_cname = None
...@@ -163,6 +165,8 @@ class Scope: ...@@ -163,6 +165,8 @@ class Scope:
in_cinclude = 0 in_cinclude = 0
nogil = 0 nogil = 0
temp_prefix = Naming.pyrex_prefix
def __init__(self, name, outer_scope, parent_scope): def __init__(self, name, outer_scope, parent_scope):
# The outer_scope is the next scope in the lookup chain. # The outer_scope is the next scope in the lookup chain.
# The parent_scope is used to derive the qualified name of this scope. # The parent_scope is used to derive the qualified name of this scope.
...@@ -447,7 +451,14 @@ class Scope: ...@@ -447,7 +451,14 @@ class Scope:
# Look up name in this scope or an enclosing one. # Look up name in this scope or an enclosing one.
# Return None if not found. # Return None if not found.
return (self.lookup_here(name) 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) or None)
def lookup_here(self, name): def lookup_here(self, name):
...@@ -562,7 +573,7 @@ class Scope: ...@@ -562,7 +573,7 @@ class Scope:
return entry.cname return entry.cname
n = self.temp_counter n = self.temp_counter
self.temp_counter = n + 1 self.temp_counter = n + 1
cname = "%s%d" % (Naming.pyrex_prefix, n) cname = "%s%d" % (self.temp_prefix, n)
entry = Entry("", cname, type) entry = Entry("", cname, type)
entry.used = 1 entry.used = 1
if type.is_pyobject or type == PyrexTypes.c_py_ssize_t_type: if type.is_pyobject or type == PyrexTypes.c_py_ssize_t_type:
...@@ -1120,11 +1131,33 @@ class LocalScope(Scope): ...@@ -1120,11 +1131,33 @@ class LocalScope(Scope):
entry = self.global_scope().lookup_target(name) entry = self.global_scope().lookup_target(name)
self.entries[name] = entry 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): def mangle_closure_cnames(self, scope_var):
return "%s->%s" % (scope_obj_cname, name) 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): class StructOrUnionScope(Scope):
# Namespace of a C struct or union. # Namespace of a C struct or union.
......
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