X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=Cython%2FCompiler%2FParseTreeTransforms.py;h=2ba5aadcf0d12d3700c085032de82c6a55bfd7ed;hb=9ce66875046c03b6123280ab56149c1536d3edff;hp=92b002569e1683fdca9f121a32215a22ba6e1436;hpb=72f8a46e52496a1a18d2a34e130acbce420bea8f;p=cython.git diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 92b00256..2ba5aadc 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -193,9 +193,8 @@ class PostParse(ScopeTrackingTransform): collector = YieldNodeCollector() collector.visitchildren(node.result_expr) if collector.yields or isinstance(node.result_expr, ExprNodes.YieldExprNode): - body = ExprNodes.YieldExprNode( - node.result_expr.pos, arg=node.result_expr) - body = Nodes.ExprStatNode(node.result_expr.pos, expr=body) + body = Nodes.ExprStatNode( + node.result_expr.pos, expr=node.result_expr) else: body = Nodes.ReturnStatNode( node.result_expr.pos, value=node.result_expr) @@ -320,6 +319,20 @@ class PostParse(ScopeTrackingTransform): return assign_node + def _flatten_sequence(self, seq, result): + for arg in seq.args: + if arg.is_sequence_constructor: + self._flatten_sequence(arg, result) + else: + result.append(arg) + return result + + def visit_DelStatNode(self, node): + self.visitchildren(node) + node.args = self._flatten_sequence(node, []) + return node + + def eliminate_rhs_duplicates(expr_list_list, ref_node_sequence): """Replace rhs items by LetRefNodes if they appear more than once. Creates a sequence of LetRefNodes that set up the required temps @@ -605,7 +618,7 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): super(InterpretCompilerDirectives, self).__init__(context) self.compilation_directive_defaults = {} for key, value in compilation_directive_defaults.items(): - self.compilation_directive_defaults[unicode(key)] = value + self.compilation_directive_defaults[unicode(key)] = copy.deepcopy(value) self.cython_module_names = cython.set() self.directive_names = {} @@ -625,8 +638,8 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): self.wrong_scope_error(node.pos, key, 'module') del node.directive_comments[key] - directives = copy.copy(Options.directive_defaults) - directives.update(self.compilation_directive_defaults) + directives = copy.deepcopy(Options.directive_defaults) + directives.update(copy.deepcopy(self.compilation_directive_defaults)) directives.update(node.directive_comments) self.directives = directives node.directives = directives @@ -1198,7 +1211,7 @@ if VALUE is not None: arg = copy.deepcopy(arg_template) arg.declarator.name = entry.name init_method.args.append(arg) - + # setters/getters for entry, attr in zip(var_entries, attributes): # TODO: branch on visibility @@ -1211,7 +1224,7 @@ if VALUE is not None: }, pos = entry.pos).stats[0] property.name = entry.name wrapper_class.body.stats.append(property) - + wrapper_class.analyse_declarations(self.env_stack[-1]) return self.visit_CClassDefNode(wrapper_class) @@ -1239,7 +1252,8 @@ if VALUE is not None: def visit_CNameDeclaratorNode(self, node): if node.name in self.seen_vars_stack[-1]: entry = self.env_stack[-1].lookup(node.name) - if entry is None or entry.visibility != 'extern': + if (entry is None or entry.visibility != 'extern' + and not entry.scope.is_c_class_scope): warning(node.pos, "cdef variable '%s' declared after it is used" % node.name, 2) self.visitchildren(node) return node @@ -1384,7 +1398,8 @@ class AlignFunctionDefinitions(CythonTransform): return self.visit_CClassDefNode(node.as_cclass(), pxd_def) else: error(node.pos, "'%s' redeclared" % node.name) - error(pxd_def.pos, "previous declaration here") + if pxd_def.pos: + error(pxd_def.pos, "previous declaration here") return None else: return node @@ -1402,15 +1417,17 @@ class AlignFunctionDefinitions(CythonTransform): def visit_DefNode(self, node): pxd_def = self.scope.lookup(node.name) - if pxd_def: + if pxd_def and (not pxd_def.scope or not pxd_def.scope.is_builtin_scope): if not pxd_def.is_cfunction: error(node.pos, "'%s' redeclared" % node.name) - error(pxd_def.pos, "previous declaration here") + if pxd_def.pos: + error(pxd_def.pos, "previous declaration here") return None node = node.as_cfunction(pxd_def) - elif self.scope.is_module_scope and self.directives['auto_cpdef']: + elif (self.scope.is_module_scope and self.directives['auto_cpdef'] + and node.is_cdef_func_compatible()): node = node.as_cfunction(scope=self.scope) - # Enable this when internal def functions are allowed. + # Enable this when nested cdef functions are allowed. # self.visitchildren(node) return node @@ -1442,7 +1459,7 @@ class YieldNodeCollector(TreeVisitor): def visit_ClassDefNode(self, node): pass - def visit_DefNode(self, node): + def visit_FuncDefNode(self, node): pass def visit_LambdaNode(self, node): @@ -1540,6 +1557,12 @@ class CreateClosureClasses(CythonTransform): is_cdef=True) klass.declare_var(pos=pos, name='resume_label', cname='resume_label', type=PyrexTypes.c_int_type, is_cdef=True) + klass.declare_var(pos=pos, name='exc_type', cname='exc_type', + type=PyrexTypes.py_object_type, is_cdef=True) + klass.declare_var(pos=pos, name='exc_value', cname='exc_value', + type=PyrexTypes.py_object_type, is_cdef=True) + klass.declare_var(pos=pos, name='exc_traceback', cname='exc_traceback', + type=PyrexTypes.py_object_type, is_cdef=True) import TypeSlots e = klass.declare_pyfunction('send', pos) @@ -1603,8 +1626,9 @@ class CreateClosureClasses(CythonTransform): inner_node.needs_self_code = False node.needs_outer_scope = False + base_type = None if node.is_generator: - generator_class = self.create_generator_class(target_module_scope, node.pos) + base_type = self.create_generator_class(target_module_scope, node.pos) elif not in_closure and not from_closure: return elif not in_closure: @@ -1615,12 +1639,10 @@ class CreateClosureClasses(CythonTransform): as_name = '%s_%s' % (target_module_scope.next_id(Naming.closure_class_prefix), node.entry.cname) - if node.is_generator: - entry = target_module_scope.declare_c_class(name = as_name, - pos = node.pos, defining = True, implementing = True, base_type=generator_class) - else: - entry = target_module_scope.declare_c_class(name = as_name, - pos = node.pos, defining = True, implementing = True) + entry = target_module_scope.declare_c_class( + name=as_name, pos=node.pos, defining=True, + implementing=True, base_type=base_type) + func_scope.scope_class = entry class_scope = entry.type.scope class_scope.is_internal = True @@ -1734,25 +1756,40 @@ class TransformBuiltinMethods(EnvTransform): error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute) return node - def visit_SimpleCallNode(self, node): + def _inject_locals(self, node, func_name): + # locals()/dir() builtins + lenv = self.current_env() + entry = lenv.lookup_here(func_name) + if entry: + # not the builtin + return node + pos = node.pos + if func_name == 'locals': + if len(node.args) > 0: + error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" + % len(node.args)) + return node + items = [ ExprNodes.DictItemNode(pos, + key=ExprNodes.StringNode(pos, value=var), + value=ExprNodes.NameNode(pos, name=var)) + for var in lenv.entries ] + return ExprNodes.DictNode(pos, key_value_pairs=items) + else: + if len(node.args) > 1: + error(self.pos, "Builtin 'dir()' called with wrong number of args, expected 0-1, got %d" + % len(node.args)) + return node + elif len(node.args) == 1: + # optimised in Builtin.py + return node + items = [ ExprNodes.StringNode(pos, value=var) for var in lenv.entries ] + return ExprNodes.ListNode(pos, args=items) - # locals builtin + def visit_SimpleCallNode(self, node): if isinstance(node.function, ExprNodes.NameNode): - if node.function.name == 'locals': - lenv = self.current_env() - entry = lenv.lookup_here('locals') - if entry: - # not the builtin 'locals' - return node - if len(node.args) > 0: - error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" % len(node.args)) - return node - pos = node.pos - items = [ ExprNodes.DictItemNode(pos, - key=ExprNodes.StringNode(pos, value=var), - value=ExprNodes.NameNode(pos, name=var)) - for var in lenv.entries ] - return ExprNodes.DictNode(pos, key_value_pairs=items) + func_name = node.function.name + if func_name in ('dir', 'locals'): + return self._inject_locals(node, func_name) # cython.foo function = node.function.as_cython_attribute()