# HG changeset patch # User Paul Boddie # Date 1473363418 -7200 # Node ID 7aeee828e698ecfa72410540c5380820f64ef9ad # Parent 4e9d8939478738eecc945b8dc5d283b1de740728# Parent 84cd26e51a791562edb09cd0ba862568dd6cc084 Merged remove-name-inheritance branch. diff -r 4e9d89394787 -r 7aeee828e698 branching.py --- a/branching.py Thu Sep 08 18:39:38 2016 +0200 +++ b/branching.py Thu Sep 08 21:36:58 2016 +0200 @@ -180,10 +180,6 @@ self.loop_branches = [] - # Inherited usage. - - self.inherited = None - # Structure assembly methods. def new_branchpoint(self, loop_node=False): @@ -452,63 +448,6 @@ for branch in branches: branch.contributors.add(contributor) - # Namespace methods. - - def inherit_branches(self, tracker, names): - - """ - Propagate branches from the given 'tracker' excluding those associated - with 'names'. - """ - - # For each inherited name, create a branch connected to the inherited - # branches. - - self.inherited = {} - - for name, branches in tracker.attribute_branches[-1].items(): - - # Do not inherit any listed names (typically parameters) or any - # special names. - - if name in names or name.startswith("$"): - continue - - # Make a tentative assignment for the name. - - contributor = Branch([name], True) - init_item(self.assignments, name, list) - self.assignments[name].append(contributor) - - # Connect the inherited branch to the new one. - - for branch in branches: - init_item(contributor.suppliers, name, set) - contributor.suppliers[name].add(branch) - branch.contributors.add(contributor) - - # Record the inherited branch. - - self.inherited[name] = [contributor] - - self.attribute_branches[-1].update(self.inherited) - - def disconnect_name(self, name): - - "Disconnect inherited branches for 'name'." - - if not self.inherited or not self.inherited.has_key(name): - return - - # Remove the new branch from the inherited branches for the name. - - for contributor in self.inherited[name]: - for supplier in contributor.suppliers[name]: - supplier.contributors.remove(contributor) - del contributor.suppliers[name] - - del self.inherited[name] - # Attribute usage methods. def tracking_name(self, name): @@ -518,13 +457,11 @@ if it is. """ - return self.assignments.has_key(name) and \ - (not self.inherited or not self.inherited.has_key(name)) and \ - self.have_name(name) + return self.assignments.has_key(name) and self.have_name(name) def have_name(self, name): - "Return whether 'name' is known, perhaps having been inherited." + "Return whether 'name' is known." return self.attribute_branches[-1].get(name) @@ -539,8 +476,6 @@ branch = Branch(names, True, values) for name in names: - self.disconnect_name(name) - branches[name] = [branch] init_item(self.assignments, name, list) self.assignments[name].append(branch) diff -r 4e9d89394787 -r 7aeee828e698 common.py --- a/common.py Thu Sep 08 18:39:38 2016 +0200 +++ b/common.py Thu Sep 08 21:36:58 2016 +0200 @@ -472,125 +472,6 @@ self.next_iterator() self.process_structure_node(node) - # Node rewriting, without processing. - - def convert_ifexp_node(self, n): - - """ - Convert the given if expression node 'n'. An if expression is considered - as mapping to a function body containing an if statement as follows: - - if else - - lambda : - if : - return - else: - return - - The are populated with defaults after the node has been - processed. - """ - - node = compiler.ast.Lambda( - [], [], 0, - compiler.ast.If([ - (n.test, compiler.ast.Return(n.then)) - ], - compiler.ast.Return(n.else_) - )) - - return node - - def convert_listcomp_node(self, n): - - """ - Convert the given list comprehension node 'n'. A list comprehension is - considered as mapping to a function body containing a for loop as - follows: - - [ for in if for in if if ] - - lambda : - = [] - for in : - if : - for in : - if : - if : - .append() - return - - The are populated with defaults after the node has been - processed. - """ - - temp = "$tr" - - node = compiler.ast.Lambda( - [], [], 0, - compiler.ast.Stmt([ - - # = [] - - compiler.ast.Assign([compiler.ast.AssName(temp, "OP_ASSIGN")], - compiler.ast.List([]) - ), - - # for ... - - self.convert_listcomp_for_node(n.quals[0], n.quals[1:], n.expr, temp), - - # return - - compiler.ast.Return(compiler.ast.Name(temp)) - ])) - - return node - - def convert_listcomp_for_node(self, loop, following_loops, expr, temp): - - """ - Return a node representing 'loop', encapsulating 'following_loops' and - employing 'expr' in the innermost loop body appending to 'temp'. - """ - - if loop.ifs: - body = self.convert_listcomp_if_node(loop.ifs[0], loop.ifs[1:], following_loops, expr, temp) - elif following_loops: - body = self.convert_listcomp_for_node(following_loops[0], following_loops[1:], expr, temp) - else: - body = self.convert_listcomp_body_node(expr, temp) - - return compiler.ast.For(loop.assign, loop.list, compiler.ast.Stmt([body]), None) - - def convert_listcomp_if_node(self, if_, following_ifs, following_loops, expr, temp): - - """ - Return a node representing 'if_', encapsulating the 'following_ifs' and - 'following_loops' and employing 'expr' in the innermost loop body - appending to 'temp'. - """ - - if following_ifs: - body = self.convert_listcomp_if_node(following_ifs[0], following_ifs[1:], following_loops, expr, temp) - elif following_loops: - body = self.convert_listcomp_for_node(following_loops[0], following_loops[1:], expr, temp) - else: - body = self.convert_listcomp_body_node(expr, temp) - - return compiler.ast.If([(if_.test, compiler.ast.Stmt([body]))], None) - - def convert_listcomp_body_node(self, expr, temp): - - "Return a node appending 'expr' to 'temp'." - - return compiler.ast.Discard( - compiler.ast.CallFunc( - compiler.ast.Getattr(compiler.ast.Name(temp), "append"), [expr])) - - # More node processing. - def process_literal_sequence_node(self, n, name, ref, cls): """ diff -r 4e9d89394787 -r 7aeee828e698 inspector.py --- a/inspector.py Thu Sep 08 18:39:38 2016 +0200 +++ b/inspector.py Thu Sep 08 21:36:58 2016 +0200 @@ -23,6 +23,7 @@ from branching import BranchTracker from common import get_argnames, init_item, predefined_constants from modules import BasicModule, CacheWritingModule, InspectionNaming +from errors import InspectError from referencing import Reference from resolving import NameResolving from results import AccessRef, InstanceRef, InvocationRef, LiteralSequenceRef, \ @@ -44,11 +45,6 @@ self.in_conditional = False self.global_attr_accesses = {} - # Nested scope handling. - - self.parent_function = None - self.propagated_names = {} - # Usage tracking. self.trackers = [] @@ -300,13 +296,16 @@ elif isinstance(n, compiler.ast.Tuple): return self.get_literal_instance(n, "tuple") - # List comprehensions and if expressions. + # Unsupported nodes. + + elif isinstance(n, compiler.ast.GenExpr): + raise InspectError("Generator expressions are not supported.", self.get_namespace_path(), n) + + elif isinstance(n, compiler.ast.IfExp): + raise InspectError("If-else expressions are not supported.", self.get_namespace_path(), n) elif isinstance(n, compiler.ast.ListComp): - self.process_listcomp_node(n) - - elif isinstance(n, compiler.ast.IfExp): - self.process_ifexp_node(n) + raise InspectError("List comprehensions are not supported.", self.get_namespace_path(), n) # All other nodes are processed depth-first. @@ -580,9 +579,6 @@ # Reset conditional tracking to focus on the function contents. - parent_function = self.parent_function - self.parent_function = self.in_function and self.get_namespace_path() or None - in_conditional = self.in_conditional self.in_conditional = False @@ -594,34 +590,19 @@ # Track attribute usage within the namespace. path = self.get_namespace_path() - init_item(self.propagated_names, path, set) self.start_tracking(locals) self.process_structure_node(n.code) self.stop_tracking() - # Propagate names from parent scopes. - - for local in self.propagated_names[path]: - if not local in argnames and self.trackers[-1].have_name(local): - argnames.append(local) - defaults.append((local, Reference(""))) - self.set_function_local(local) - - # Exit to the parent and note propagated names. + # Exit to the parent. self.exit_namespace() - parent = self.get_namespace_path() - if self.propagated_names.has_key(parent): - for local in self.propagated_names[path]: - self.propagated_names[parent].add(local) - # Update flags. self.in_function = in_function self.in_conditional = in_conditional - self.parent_function = parent_function # Define the function using the appropriate name. @@ -673,18 +654,6 @@ tracker.merge_branches() - def process_ifexp_node(self, n): - - "Process the given if expression node 'n'." - - name_ref = self.process_structure_node(self.convert_ifexp_node(n)) - - path = self.get_namespace_path() - self.allocate_arguments(path, self.function_defaults[name_ref.get_origin()]) - self.deallocate_arguments(path, self.function_defaults[name_ref.get_origin()]) - - return InvocationRef(name_ref) - def process_import_node(self, n): "Process the given import node 'n'." @@ -743,18 +712,6 @@ origin = self.get_object_path(name) return ResolvedNameRef(name, Reference("", origin)) - def process_listcomp_node(self, n): - - "Process the given list comprehension node 'n'." - - name_ref = self.process_structure_node(self.convert_listcomp_node(n)) - - path = self.get_namespace_path() - self.allocate_arguments(path, self.function_defaults[name_ref.get_origin()]) - self.deallocate_arguments(path, self.function_defaults[name_ref.get_origin()]) - - return InvocationRef(name_ref) - def process_logical_node(self, n): "Process the given operator node 'n'." @@ -820,14 +777,7 @@ branches = tracker.tracking_name(n.name) - # Find names inherited from a parent scope. - - if not branches and self.parent_function: - branches = tracker.have_name(n.name) - if branches: - self.propagate_name(n.name) - - # Local or inherited name. + # Local name. if branches: self.record_branches_for_access(branches, n.name, None) @@ -990,12 +940,6 @@ tracker = BranchTracker() self.trackers.append(tracker) - # For functions created from expressions or for functions within - # functions, propagate usage to the new namespace. - - if self.parent_function: - tracker.inherit_branches(parent, names) - # Record the given names established as new branches. tracker.assign_names(names) @@ -1037,13 +981,6 @@ self.attr_usage[self.name] = tracker.get_all_usage() self.name_initialisers[self.name] = tracker.get_all_values() - def propagate_name(self, name): - - "Propagate the given 'name' into the current namespace." - - path = self.get_namespace_path() - self.propagated_names[path].add(name) - def record_assignments_for_access(self, tracker): """