Commit b3e44611 authored by Robert Bradshaw's avatar Robert Bradshaw

Transform nodes for analyse_declarations and analyse_expressions.

parent ff81f222
...@@ -972,7 +972,7 @@ class NameNode(AtomicExprNode): ...@@ -972,7 +972,7 @@ class NameNode(AtomicExprNode):
if entry.is_builtin: if entry.is_builtin:
namespace = Naming.builtins_cname namespace = Naming.builtins_cname
else: # entry.is_pyglobal else: # entry.is_pyglobal
namespace = entry.namespace_cname namespace = entry.scope.namespace_cname
code.putln( code.putln(
'%s = __Pyx_GetName(%s, %s); %s' % ( '%s = __Pyx_GetName(%s, %s); %s' % (
self.result_code, self.result_code,
...@@ -997,7 +997,7 @@ class NameNode(AtomicExprNode): ...@@ -997,7 +997,7 @@ class NameNode(AtomicExprNode):
# is_pyglobal seems to be True for module level-globals only. # is_pyglobal seems to be True for module level-globals only.
# We use this to access class->tp_dict if necessary. # We use this to access class->tp_dict if necessary.
if entry.is_pyglobal: if entry.is_pyglobal:
namespace = self.entry.namespace_cname namespace = self.entry.scope.namespace_cname
if entry.is_member: if entry.is_member:
# if the entry is a member we have to cheat: SetAttr does not work # if the entry is a member we have to cheat: SetAttr does not work
# on types, so we create a descriptor which is then added to tp_dict # on types, so we create a descriptor which is then added to tp_dict
......
...@@ -45,9 +45,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -45,9 +45,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.body.analyse_declarations(env) self.body.analyse_declarations(env)
def process_implementation(self, env, options, result): def process_implementation(self, env, options, result):
self.analyse_declarations(env) self.scope = env
from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
AnalyseDeclarationsTransform(env).visit_ModuleNode(self) # self.analyse_declarations(env)
env.check_c_classes() env.check_c_classes()
self.body.analyse_expressions(env) AnalyseExpressionsTransform().visit_ModuleNode(self) # self.body.analyse_expressions(env)
env.return_type = PyrexTypes.c_void_type env.return_type = PyrexTypes.c_void_type
self.referenced_modules = [] self.referenced_modules = []
self.find_referenced_modules(env, self.referenced_modules, {}) self.find_referenced_modules(env, self.referenced_modules, {})
......
...@@ -803,25 +803,24 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -803,25 +803,24 @@ class FuncDefNode(StatNode, BlockNode):
def need_gil_acquisition(self, lenv): def need_gil_acquisition(self, lenv):
return 0 return 0
def generate_function_definitions(self, env, code, transforms): def create_local_scope(self, env):
code.mark_pos(self.pos) genv = env
# Generate C code for header and body of function while env.is_py_class_scope or env.is_c_class_scope:
genv = env.global_scope() env = env.outer_scope
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
type = self.entry.type type = self.entry.type
if type.is_cfunction: if type.is_cfunction:
lenv.nogil = type.nogil and not type.with_gil lenv.nogil = type.nogil and not type.with_gil
self.local_scope = lenv
return lenv
def generate_function_definitions(self, env, code, transforms):
# Generate C code for header and body of function
code.init_labels() code.init_labels()
self.declare_arguments(lenv) lenv = self.local_scope
transforms.run('before_analyse_function', self, env=env, lenv=lenv, genv=genv)
self.body.analyse_control_flow(lenv)
self.body.analyse_declarations(lenv)
self.body.analyse_expressions(lenv)
transforms.run('after_analyse_function', self, env=env, lenv=lenv, genv=genv)
# Code for nested function definitions would go here
# if we supported them, which we probably won't.
# ----- Top-level constants used by this function # ----- Top-level constants used by this function
code.mark_pos(self.pos)
self.generate_interned_num_decls(lenv, code) self.generate_interned_num_decls(lenv, code)
self.generate_interned_string_decls(lenv, code) self.generate_interned_string_decls(lenv, code)
self.generate_py_string_decls(lenv, code) self.generate_py_string_decls(lenv, code)
...@@ -975,8 +974,9 @@ class CFuncDefNode(FuncDefNode): ...@@ -975,8 +974,9 @@ class CFuncDefNode(FuncDefNode):
# #
# with_gil boolean Acquire GIL around body # with_gil boolean Acquire GIL around body
# type CFuncType # type CFuncType
# py_func wrapper for calling from Python
child_attrs = ["base_type", "declarator", "body"] child_attrs = ["base_type", "declarator", "body", "py_func"]
def unqualified_name(self): def unqualified_name(self):
return self.entry.name return self.entry.name
...@@ -1839,6 +1839,8 @@ class OverrideCheckNode(StatNode): ...@@ -1839,6 +1839,8 @@ class OverrideCheckNode(StatNode):
child_attrs = ['body'] child_attrs = ['body']
body = None
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.args = env.arg_entries self.args = env.arg_entries
if self.py_func.is_module_scope: if self.py_func.is_module_scope:
...@@ -1916,18 +1918,26 @@ class PyClassDefNode(StatNode, BlockNode): ...@@ -1916,18 +1918,26 @@ class PyClassDefNode(StatNode, BlockNode):
bases = bases, dict = self.dict, doc = doc_node) bases = bases, dict = self.dict, doc = doc_node)
self.target = ExprNodes.NameNode(pos, name = name) self.target = ExprNodes.NameNode(pos, name = name)
def create_scope(self, env):
genv = env
while env.is_py_class_scope or env.is_c_class_scope:
env = env.outer_scope
cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
return cenv
def analyse_declarations(self, env): def analyse_declarations(self, env):
self.target.analyse_target_declaration(env) self.target.analyse_target_declaration(env)
cenv = self.create_scope(env)
cenv.class_obj_cname = self.target.entry.cname
self.body.analyse_declarations(cenv)
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.dict.analyse_expressions(env) self.dict.analyse_expressions(env)
self.classobj.analyse_expressions(env) self.classobj.analyse_expressions(env)
genv = env.global_scope() genv = env.global_scope()
cenv = PyClassScope(name = self.name, outer_scope = genv) cenv = self.scope
cenv.class_dict_cname = self.dict.result_code cenv.class_dict_cname = self.dict.result_code
cenv.class_obj_cname = self.classobj.result_code cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result_code
self.scope = cenv
self.body.analyse_declarations(cenv)
self.body.analyse_expressions(cenv) self.body.analyse_expressions(cenv)
self.target.analyse_target_expression(env, self.classobj) self.target.analyse_target_expression(env, self.classobj)
self.dict.release_temp(env) self.dict.release_temp(env)
......
...@@ -142,3 +142,46 @@ class WithTransform(VisitorTransform): ...@@ -142,3 +142,46 @@ class WithTransform(VisitorTransform):
result.stats[4].body.stats[0].except_clauses[0].excinfo_target = excinfo_target result.stats[4].body.stats[0].except_clauses[0].excinfo_target = excinfo_target
return result.stats return result.stats
class AnalyseDeclarationsTransform(VisitorTransform):
def __init__(self, env):
VisitorTransform.__init__(self)
self.env_stack = [env]
def visit_ModuleNode(self, node):
node.analyse_declarations(self.env_stack[-1])
self.visitchildren(node)
return node
def visit_FuncDefNode(self, node):
lenv = node.create_local_scope(self.env_stack[-1])
node.body.analyse_control_flow(lenv) # this will be totally refactored
node.declare_arguments(lenv)
node.body.analyse_declarations(lenv)
self.env_stack.append(lenv)
self.visitchildren(node)
self.env_stack.pop()
return node
def visit_Node(self, node):
self.visitchildren(node)
return node
class AnalyseExpressionsTransform(VisitorTransform):
def visit_ModuleNode(self, node):
node.body.analyse_expressions(node.scope)
self.visitchildren(node)
return node
def visit_FuncDefNode(self, node):
node.body.analyse_expressions(node.local_scope)
self.visitchildren(node)
return node
def visit_Node(self, node):
self.visitchildren(node)
return node
...@@ -608,6 +608,9 @@ class Scope: ...@@ -608,6 +608,9 @@ class Scope:
return 0 return 0
class PreImportScope(Scope): class PreImportScope(Scope):
namespace_cname = Naming.preimport_cname
def __init__(self): def __init__(self):
Scope.__init__(self, Options.pre_import, None, None) Scope.__init__(self, Options.pre_import, None, None)
...@@ -615,7 +618,6 @@ class PreImportScope(Scope): ...@@ -615,7 +618,6 @@ class PreImportScope(Scope):
entry = self.declare(name, name, py_object_type, pos) entry = self.declare(name, name, py_object_type, pos)
entry.is_variable = True entry.is_variable = True
entry.is_pyglobal = True entry.is_pyglobal = True
entry.namespace_cname = Naming.preimport_cname
return entry return entry
...@@ -761,6 +763,7 @@ class ModuleScope(Scope): ...@@ -761,6 +763,7 @@ class ModuleScope(Scope):
self.has_extern_class = 0 self.has_extern_class = 0
self.cached_builtins = [] self.cached_builtins = []
self.undeclared_cached_builtins = [] self.undeclared_cached_builtins = []
self.namespace_cname = self.module_cname
def qualifying_scope(self): def qualifying_scope(self):
return self.parent_module return self.parent_module
...@@ -876,7 +879,6 @@ class ModuleScope(Scope): ...@@ -876,7 +879,6 @@ class ModuleScope(Scope):
raise InternalError( raise InternalError(
"Non-cdef global variable is not a generic Python object") "Non-cdef global variable is not a generic Python object")
entry.is_pyglobal = 1 entry.is_pyglobal = 1
entry.namespace_cname = self.module_cname
else: else:
entry.is_cglobal = 1 entry.is_cglobal = 1
self.var_entries.append(entry) self.var_entries.append(entry)
...@@ -1197,7 +1199,6 @@ class PyClassScope(ClassScope): ...@@ -1197,7 +1199,6 @@ class PyClassScope(ClassScope):
entry = Scope.declare_var(self, name, type, pos, entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef) cname, visibility, is_cdef)
entry.is_pyglobal = 1 entry.is_pyglobal = 1
entry.namespace_cname = self.class_obj_cname
return entry return entry
def allocate_temp(self, type): def allocate_temp(self, type):
...@@ -1294,7 +1295,7 @@ class CClassScope(ClassScope): ...@@ -1294,7 +1295,7 @@ class CClassScope(ClassScope):
entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
# I keep it in for now. is_member should be enough # I keep it in for now. is_member should be enough
# later on # later on
entry.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
entry.interned_cname = self.intern_identifier(name) entry.interned_cname = self.intern_identifier(name)
return entry return entry
......
...@@ -158,7 +158,7 @@ INDENT_RE = re.compile(ur"^ *") ...@@ -158,7 +158,7 @@ INDENT_RE = re.compile(ur"^ *")
def strip_common_indent(lines): def strip_common_indent(lines):
"Strips empty lines and common indentation from the list of strings given in lines" "Strips empty lines and common indentation from the list of strings given in lines"
lines = [x for x in lines if x.strip() != u""] lines = [x for x in lines if x.strip() != u""]
minindent = min(len(INDENT_RE.match(x).group(0)) for x in lines) minindent = min([len(INDENT_RE.match(x).group(0)) for x in lines])
lines = [x[minindent:] for x in lines] lines = [x[minindent:] for x in lines]
return lines return lines
......
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