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):
if entry.is_builtin:
namespace = Naming.builtins_cname
else: # entry.is_pyglobal
namespace = entry.namespace_cname
namespace = entry.scope.namespace_cname
code.putln(
'%s = __Pyx_GetName(%s, %s); %s' % (
self.result_code,
......@@ -997,7 +997,7 @@ class NameNode(AtomicExprNode):
# is_pyglobal seems to be True for module level-globals only.
# We use this to access class->tp_dict if necessary.
if entry.is_pyglobal:
namespace = self.entry.namespace_cname
namespace = self.entry.scope.namespace_cname
if entry.is_member:
# 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
......
......@@ -45,9 +45,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.body.analyse_declarations(env)
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()
self.body.analyse_expressions(env)
AnalyseExpressionsTransform().visit_ModuleNode(self) # self.body.analyse_expressions(env)
env.return_type = PyrexTypes.c_void_type
self.referenced_modules = []
self.find_referenced_modules(env, self.referenced_modules, {})
......
......@@ -802,26 +802,25 @@ class FuncDefNode(StatNode, BlockNode):
def need_gil_acquisition(self, lenv):
return 0
def generate_function_definitions(self, env, code, transforms):
code.mark_pos(self.pos)
# Generate C code for header and body of function
genv = env.global_scope()
def create_local_scope(self, env):
genv = env
while env.is_py_class_scope or env.is_c_class_scope:
env = env.outer_scope
lenv = LocalScope(name = self.entry.name, outer_scope = genv)
lenv.return_type = self.return_type
type = self.entry.type
if type.is_cfunction:
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()
self.declare_arguments(lenv)
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.
lenv = self.local_scope
# ----- Top-level constants used by this function
code.mark_pos(self.pos)
self.generate_interned_num_decls(lenv, code)
self.generate_interned_string_decls(lenv, code)
self.generate_py_string_decls(lenv, code)
......@@ -975,8 +974,9 @@ class CFuncDefNode(FuncDefNode):
#
# with_gil boolean Acquire GIL around body
# 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):
return self.entry.name
......@@ -1838,6 +1838,8 @@ class OverrideCheckNode(StatNode):
# body
child_attrs = ['body']
body = None
def analyse_expressions(self, env):
self.args = env.arg_entries
......@@ -1915,19 +1917,27 @@ class PyClassDefNode(StatNode, BlockNode):
self.classobj = ExprNodes.ClassNode(pos, name = name,
bases = bases, dict = self.dict, doc = doc_node)
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):
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):
self.dict.analyse_expressions(env)
self.classobj.analyse_expressions(env)
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_obj_cname = self.classobj.result_code
self.scope = cenv
self.body.analyse_declarations(cenv)
cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result_code
self.body.analyse_expressions(cenv)
self.target.analyse_target_expression(env, self.classobj)
self.dict.release_temp(env)
......
......@@ -117,7 +117,7 @@ class WithTransform(VisitorTransform):
def visit_Node(self, node):
self.visitchildren(node)
return node
return node
def visit_WithStatNode(self, node):
excinfo_name = temp_name_handle('EXCINFO')
......@@ -142,3 +142,46 @@ class WithTransform(VisitorTransform):
result.stats[4].body.stats[0].except_clauses[0].excinfo_target = excinfo_target
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:
return 0
class PreImportScope(Scope):
namespace_cname = Naming.preimport_cname
def __init__(self):
Scope.__init__(self, Options.pre_import, None, None)
......@@ -615,7 +618,6 @@ class PreImportScope(Scope):
entry = self.declare(name, name, py_object_type, pos)
entry.is_variable = True
entry.is_pyglobal = True
entry.namespace_cname = Naming.preimport_cname
return entry
......@@ -761,6 +763,7 @@ class ModuleScope(Scope):
self.has_extern_class = 0
self.cached_builtins = []
self.undeclared_cached_builtins = []
self.namespace_cname = self.module_cname
def qualifying_scope(self):
return self.parent_module
......@@ -876,7 +879,6 @@ class ModuleScope(Scope):
raise InternalError(
"Non-cdef global variable is not a generic Python object")
entry.is_pyglobal = 1
entry.namespace_cname = self.module_cname
else:
entry.is_cglobal = 1
self.var_entries.append(entry)
......@@ -1197,7 +1199,6 @@ class PyClassScope(ClassScope):
entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef)
entry.is_pyglobal = 1
entry.namespace_cname = self.class_obj_cname
return entry
def allocate_temp(self, type):
......@@ -1294,7 +1295,7 @@ class CClassScope(ClassScope):
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
# 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)
return entry
......
......@@ -158,7 +158,7 @@ INDENT_RE = re.compile(ur"^ *")
def strip_common_indent(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""]
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]
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