1.1 --- a/deducer.py Thu Oct 20 15:00:27 2016 +0200
1.2 +++ b/deducer.py Thu Oct 20 22:43:48 2016 +0200
1.3 @@ -83,9 +83,10 @@
1.4
1.5 self.modified_attributes = {}
1.6
1.7 - # Accesses that are assignments.
1.8 + # Accesses that are assignments or invocations.
1.9
1.10 self.reference_assignments = set()
1.11 + self.reference_invocations = set()
1.12
1.13 # Map locations to types, constrained indicators and attributes.
1.14
1.15 @@ -796,8 +797,8 @@
1.16 # For each access, determine the name versions affected by
1.17 # assignments.
1.18
1.19 - for access_number, assignment in enumerate(modifiers):
1.20 - if not assignment:
1.21 + for access_number, (assignment, invocation) in enumerate(modifiers):
1.22 + if not assignment and not invocation:
1.23 continue
1.24
1.25 if name:
1.26 @@ -805,6 +806,10 @@
1.27 else:
1.28 access_location = (path, None, attrname_str, 0)
1.29
1.30 + if invocation:
1.31 + self.reference_invocations.add(access_location)
1.32 + continue
1.33 +
1.34 self.reference_assignments.add(access_location)
1.35
1.36 # Associate assignments with usage.
1.37 @@ -1955,6 +1960,7 @@
1.38 # Determine the method of access.
1.39
1.40 is_assignment = location in self.reference_assignments
1.41 + is_invocation = location in self.reference_invocations
1.42
1.43 # Identified attribute that must be accessed via its parent.
1.44
1.45 @@ -1964,7 +1970,9 @@
1.46 # Static, identified attribute.
1.47
1.48 elif attr and attr.static():
1.49 - final_method = is_assignment and "static-assign" or "static"
1.50 + final_method = is_assignment and "static-assign" or \
1.51 + is_invocation and "static-invoke" or \
1.52 + "static"
1.53 origin = attr.final()
1.54
1.55 # All other methods of access involve traversal.
2.1 --- a/encoders.py Thu Oct 20 15:00:27 2016 +0200
2.2 +++ b/encoders.py Thu Oct 20 22:43:48 2016 +0200
2.3 @@ -89,14 +89,14 @@
2.4
2.5 "Encode modifier 't' representing assignment status."
2.6
2.7 - assignment = t
2.8 - return assignment and "A" or "_"
2.9 + assignment, invocation = t
2.10 + return assignment and "=" or invocation and "!" or "_"
2.11
2.12 def decode_modifier_term(s):
2.13
2.14 "Decode modifier term 's' representing assignment status."
2.15
2.16 - return s == "A"
2.17 + return (s == "=", s == "!")
2.18
2.19
2.20
2.21 @@ -181,6 +181,10 @@
2.22 "__test_common_instance",
2.23 )
2.24
2.25 +encoding_ops = (
2.26 + "__encode_callable",
2.27 + )
2.28 +
2.29 def encode_access_instruction(instruction, subs):
2.30
2.31 """
2.32 @@ -227,6 +231,14 @@
2.33 a[1] = encode_symbol("pos", arg)
2.34 a.insert(2, encode_symbol("code", arg))
2.35
2.36 + # Replace encoded operations.
2.37 +
2.38 + elif op in encoding_ops:
2.39 + origin = a[0]
2.40 + kind = a[1]
2.41 + op = "__load_function"
2.42 + a = [kind == "<class>" and encode_instantiator_pointer(origin) or encode_function_pointer(origin)]
2.43 +
2.44 argstr = "(%s)" % ", ".join(a)
2.45
2.46 # Substitute the first element of the instruction, which may not be an
3.1 --- a/inspector.py Thu Oct 20 15:00:27 2016 +0200
3.2 +++ b/inspector.py Thu Oct 20 22:43:48 2016 +0200
3.3 @@ -401,12 +401,11 @@
3.4
3.5 if not isinstance(name_ref, NameRef): # includes ResolvedNameRef
3.6
3.7 - assignment = isinstance(n, compiler.ast.AssAttr)
3.8 -
3.9 init_item(self.attr_accesses, path, set)
3.10 self.attr_accesses[path].add(attrnames)
3.11
3.12 - self.record_access_details(None, attrnames, assignment)
3.13 + self.record_access_details(None, attrnames, self.in_assignment,
3.14 + self.in_invocation)
3.15 del self.attrs[0]
3.16 return
3.17
3.18 @@ -460,7 +459,8 @@
3.19 name, attrname), path, n)
3.20
3.21 self.record_branches_for_access(branches, name, attrnames)
3.22 - access_number = self.record_access_details(name, attrnames, self.in_assignment)
3.23 + access_number = self.record_access_details(name, attrnames,
3.24 + self.in_assignment, self.in_invocation)
3.25
3.26 del self.attrs[0]
3.27 return AccessRef(name, attrnames, access_number)
3.28 @@ -844,7 +844,7 @@
3.29
3.30 if branches:
3.31 self.record_branches_for_access(branches, n.name, None)
3.32 - access_number = self.record_access_details(n.name, None, False)
3.33 + access_number = self.record_access_details(n.name, None, False, False)
3.34 return LocalNameRef(n.name, access_number)
3.35
3.36 # Possible global or built-in name.
3.37 @@ -1118,7 +1118,7 @@
3.38 init_item(attr_accessor_branches, access, list)
3.39 attr_accessor_branches[access].append(branches)
3.40
3.41 - def record_access_details(self, name, attrnames, assignment):
3.42 + def record_access_details(self, name, attrnames, assignment, invocation):
3.43
3.44 """
3.45 For the given 'name' and 'attrnames', record an access indicating
3.46 @@ -1135,7 +1135,7 @@
3.47 init_item(self.attr_access_modifiers[path], access, list)
3.48
3.49 access_number = len(self.attr_access_modifiers[path][access])
3.50 - self.attr_access_modifiers[path][access].append(assignment)
3.51 + self.attr_access_modifiers[path][access].append((assignment, invocation))
3.52 return access_number
3.53
3.54 def record_global_access_details(self, name, attrnames):