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,
# 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
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, {})
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)
#
# 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
# body
child_attrs = ['body']
+
+ body = None
def analyse_expressions(self, env):
self.args = env.arg_entries
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)
def visit_Node(self, node):
self.visitchildren(node)
- return node
+ return node
def visit_WithStatNode(self, node):
excinfo_name = temp_name_handle('EXCINFO')
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
+
return 0
class PreImportScope(Scope):
+
+ namespace_cname = Naming.preimport_cname
+
def __init__(self):
Scope.__init__(self, Options.pre_import, None, None)
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
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
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)
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):
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
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