From: Vitja Makarov Date: Sun, 19 Dec 2010 07:17:35 +0000 (+0300) Subject: Merge remote branch 'upstream/master' X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c0643507a7b283fc349e63518dc27685be47fda8;p=cython.git Merge remote branch 'upstream/master' Conflicts: Cython/Compiler/ExprNodes.py Cython/Compiler/Nodes.py Cython/Compiler/ParseTreeTransforms.py Cython/Compiler/Symtab.py --- c0643507a7b283fc349e63518dc27685be47fda8 diff --cc Cython/Compiler/ExprNodes.py index 4bcee405,2ecddeb4..2a744a0f --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@@ -492,13 -486,13 +492,13 @@@ class ExprNode(Node) def generate_subexpr_evaluation_code(self, code): for node in self.subexpr_nodes(): node.generate_evaluation_code(code) - + def generate_result_code(self, code): self.not_implemented("generate_result_code") - + def generate_disposal_code(self, code): if self.is_temp: - if self.type.is_pyobject: + if self.type.is_pyobject and self.result(): code.put_decref_clear(self.result(), self.ctype()) else: # Already done if self.is_temp diff --cc Cython/Compiler/Nodes.py index 5ab4e598,ff130a48..c09a7d47 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@@ -1166,9 -1166,8 +1166,9 @@@ class FuncDefNode(StatNode, BlockNode) assmt = None needs_closure = False needs_outer_scope = False + is_generator = False modifiers = [] - + def analyse_default_values(self, env): genv = env.global_scope() default_seen = 0 @@@ -1519,38 -1513,6 +1519,38 @@@ self.py_func.generate_function_definitions(env, code) self.generate_wrapper_functions(code) + if self.is_generator: + self.generator.generate_function_body(self.local_scope, code) + + def generate_preamble(self, env, code): + """Parse arguments and prepare scope""" + import Buffer + + lenv = self.local_scope + + self.generate_argument_parsing_code(env, code) - # If an argument is assigned to in the body, we must ++ # If an argument is assigned to in the body, we must + # incref it to properly keep track of refcounts. + for entry in lenv.arg_entries: + if entry.type.is_pyobject: + if entry.assignments and not entry.in_closure: + code.put_var_incref(entry) - # ----- Initialise local variables ++ # ----- Initialise local variables + for entry in lenv.var_entries: + if entry.type.is_pyobject and entry.init_to_none and entry.used: + code.put_init_var_to_py_none(entry) + # ----- Initialise local buffer auxiliary variables + for entry in lenv.var_entries + lenv.arg_entries: + if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used: + code.putln("%s.buf = NULL;" % + entry.buffer_aux.buffer_info_var.cname) + # ----- Check and convert arguments + self.generate_argument_type_tests(code) + # ----- Acquire buffer arguments + for entry in lenv.arg_entries: + if entry.type.is_buffer: + Buffer.put_acquire_arg_buffer(entry, code, self.pos) + def declare_argument(self, env, arg): if arg.type.is_void: error(arg.pos, "Invalid use of 'void'") @@@ -2397,18 -2300,10 +2397,18 @@@ class DefNode(FuncDefNode) "struct wrapperbase %s;" % self.entry.wrapperbase_cname) if with_pymethdef: code.put( - "static PyMethodDef %s = " % + "static PyMethodDef %s = " % self.entry.pymethdef_cname) code.put_pymethoddef(self.entry, ";", allow_skip=False) - code.putln("%s {" % header) + if self.is_generator: + code.putln("static PyObject *%s(PyObject *%s, PyObject *%s) /* generator body */\n{" % + (self.generator_body_cname, Naming.self_cname, Naming.sent_value_cname)) + self.generator = GeneratorWrapperNode(self, + func_cname=self.entry.func_cname, + body_cname=self.generator_body_cname, + header=header) + else: + code.putln("%s {" % header) def generate_argument_declarations(self, env, code): for arg in self.args: @@@ -2537,14 -2422,14 +2537,14 @@@ code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos))) else: error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type) - + def generate_arg_xdecref(self, arg, code): if arg: - code.put_var_xdecref(arg.entry) + code.put_var_xdecref_clear(arg.entry) - + def generate_arg_decref(self, arg, code): if arg: - code.put_var_decref(arg.entry) + code.put_var_decref_clear(arg.entry) def generate_stararg_copy_code(self, code): if not self.star_arg: @@@ -3474,11 -3342,10 +3474,11 @@@ class ExprStatNode(StatNode) else: env.declare_var(var.value, type, var.pos, is_cdef = True) self.__class__ = PassStatNode - + def analyse_expressions(self, env): + self.expr.result_is_used = False # hint that .result() may safely be left empty self.expr.analyse_expressions(env) - + def generate_execution_code(self, code): self.expr.generate_evaluation_code(code) if not self.expr.is_temp and self.expr.result(): diff --cc Cython/Compiler/Symtab.py index 34b2d0d0,c8683499..036c597e --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@@ -1272,16 -1298,6 +1298,16 @@@ class LocalScope(Scope) entry = self.global_scope().lookup_target(name) self.entries[name] = entry + def declare_nonlocal(self, name, pos): + # Pull entry from outer scope into local scope + orig_entry = self.lookup_here(name) + if orig_entry and orig_entry.scope is self and not orig_entry.from_closure: + error(pos, "'%s' redeclared as nonlocal" % name) + else: + entry = self.lookup(name) + if entry is None or not entry.from_closure: + error(pos, "no binding for nonlocal '%s' found" % name) - ++ def lookup(self, name): # Look up name in this scope or an enclosing one. # Return None if not found.