1.1 --- a/encoders.py Fri Jan 20 17:39:52 2017 +0100
1.2 +++ b/encoders.py Fri Jan 20 18:39:33 2017 +0100
1.3 @@ -194,10 +194,13 @@
1.4
1.5 The 'subs' parameter defines a mapping of substitutions for special values
1.6 used in instructions.
1.7 +
1.8 + Return both the encoded instruction and a collection of substituted names.
1.9 """
1.10
1.11 op = instruction[0]
1.12 args = instruction[1:]
1.13 + substituted = set()
1.14
1.15 if not args:
1.16 argstr = ""
1.17 @@ -208,7 +211,9 @@
1.18 a = []
1.19 converting_op = op
1.20 for arg in args:
1.21 - a.append(encode_access_instruction_arg(arg, subs, converting_op))
1.22 + s, _substituted = encode_access_instruction_arg(arg, subs, converting_op)
1.23 + substituted.update(_substituted)
1.24 + a.append(s)
1.25 converting_op = None
1.26
1.27 # Modify certain arguments.
1.28 @@ -250,40 +255,45 @@
1.29 # operation at all.
1.30
1.31 if subs.has_key(op):
1.32 + substituted.add(op)
1.33 op = subs[op]
1.34 elif not args:
1.35 op = "&%s" % encode_path(op)
1.36
1.37 - return "%s%s" % (op, argstr)
1.38 + return "%s%s" % (op, argstr), substituted
1.39
1.40 def encode_access_instruction_arg(arg, subs, op):
1.41
1.42 - "Encode 'arg' using 'subs' to define substitutions."
1.43 + """
1.44 + Encode 'arg' using 'subs' to define substitutions, returning a tuple
1.45 + containing the encoded form of 'arg' along with a collection of any
1.46 + substituted values.
1.47 + """
1.48
1.49 if isinstance(arg, tuple):
1.50 - encoded = encode_access_instruction(arg, subs)
1.51 + encoded, substituted = encode_access_instruction(arg, subs)
1.52
1.53 # Convert attribute results to references where required.
1.54
1.55 if op and op in reference_acting_ops and arg[0] in attribute_producing_ops:
1.56 - return "%s.value" % encoded
1.57 + return "%s.value" % encoded, substituted
1.58 else:
1.59 - return encoded
1.60 + return encoded, substituted
1.61
1.62 # Special values only need replacing, not encoding.
1.63
1.64 elif subs.has_key(arg):
1.65 - return subs.get(arg)
1.66 + return subs.get(arg), set([arg])
1.67
1.68 # Convert static references to the appropriate type.
1.69
1.70 elif op and op in reference_acting_ops and arg != "<accessor>":
1.71 - return "&%s" % encode_path(arg)
1.72 + return "&%s" % encode_path(arg), set()
1.73
1.74 # Other values may need encoding.
1.75
1.76 else:
1.77 - return encode_path(arg)
1.78 + return encode_path(arg), set()
1.79
1.80 def encode_bound_reference(path):
1.81