# HG changeset patch # User Paul Boddie # Date 1477227393 -7200 # Node ID b881a39ca2fd634a7845f3ae433af31d8e5a5f46 # Parent 1532a76a0d998c2acf0fa1068c4b77dc9f5f46b9 Fixed assignment value propagation for attribute chains. Moved assignment and invocation state tracking to the common module abstraction. diff -r 1532a76a0d99 -r b881a39ca2fd common.py --- a/common.py Sun Oct 23 14:54:04 2016 +0200 +++ b/common.py Sun Oct 23 14:56:33 2016 +0200 @@ -109,9 +109,16 @@ self.namespace_path = [] self.in_function = False - # Attribute chains. + # Retain the assignment value expression and track invocations. + + self.in_assignment = None + self.in_invocation = False + + # Attribute chain state management. self.attrs = [] + self.chain_assignment = [] + self.chain_invocation = [] def __repr__(self): return "CommonModule(%r, %r)" % (self.name, self.importer) @@ -580,17 +587,25 @@ return name_ref + # Attribute chain handling. + def reset_attribute_chain(self): "Reset the attribute chain for a subexpression of an attribute access." self.attrs = [] + self.chain_assignment.append(self.in_assignment) + self.chain_invocation.append(self.in_invocation) + self.in_assignment = None + self.in_invocation = False def restore_attribute_chain(self, attrs): "Restore the attribute chain for an attribute access." self.attrs = attrs + self.in_assignment = self.chain_assignment.pop() + self.in_invocation = self.chain_invocation.pop() def have_access_expression(self, node): diff -r 1532a76a0d99 -r b881a39ca2fd inspector.py --- a/inspector.py Sun Oct 23 14:54:04 2016 +0200 +++ b/inspector.py Sun Oct 23 14:56:33 2016 +0200 @@ -41,15 +41,8 @@ BasicModule.__init__(self, name, importer) - self.in_assignment = False self.in_class = False self.in_conditional = False - self.in_invocation = False - - # Attribute chain state management. - - self.chain_assignment = [] - self.chain_invocation = [] # Accesses to global attributes. @@ -350,10 +343,11 @@ self.record_name(n.name) elif isinstance(n, compiler.ast.AssAttr): - if expr: self.process_structure_node(expr) + if expr: + expr = self.process_structure_node(expr) in_assignment = self.in_assignment - self.in_assignment = True + self.in_assignment = expr self.process_attribute_access(n) self.in_assignment = in_assignment @@ -989,26 +983,6 @@ tracker.resume_broken_branches() - # Attribute chain handling. - - def reset_attribute_chain(self): - - "Reset the attribute chain for a subexpression of an attribute access." - - CommonModule.reset_attribute_chain(self) - self.chain_assignment.append(self.in_assignment) - self.chain_invocation.append(self.in_invocation) - self.in_assignment = False - self.in_invocation = False - - def restore_attribute_chain(self, attrs): - - "Restore the attribute chain for an attribute access." - - CommonModule.restore_attribute_chain(self, attrs) - self.in_assignment = self.chain_assignment.pop() - self.in_invocation = self.chain_invocation.pop() - # Branch tracking methods. def start_tracking(self, names): diff -r 1532a76a0d99 -r b881a39ca2fd translator.py --- a/translator.py Sun Oct 23 14:54:04 2016 +0200 +++ b/translator.py Sun Oct 23 14:56:33 2016 +0200 @@ -501,7 +501,10 @@ self.statement(name_ref) elif isinstance(n, compiler.ast.AssAttr): - self.statement(self.process_attribute_access(n, self.process_structure_node(expr))) + in_assignment = self.in_assignment + self.in_assignment = self.process_structure_node(expr) + self.statement(self.process_attribute_access(n)) + self.in_assignment = in_assignment # Lists and tuples are matched against the expression and their # items assigned to expression items. @@ -517,7 +520,7 @@ elif isinstance(n, compiler.ast.Subscript): self.statement(self.process_subscript_node(n, expr)) - def process_attribute_access(self, n, expr=None): + def process_attribute_access(self, n): """ Process the given attribute access node 'n'. @@ -553,7 +556,7 @@ subs = { "" : str(attr_expr), - "" : str(expr), + "" : str(self.in_assignment), "" : "__tmp_context", "" : "__tmp_value", }