1.1 --- a/encoders.py Wed Oct 19 22:16:27 2016 +0200
1.2 +++ b/encoders.py Wed Oct 19 23:40:41 2016 +0200
1.3 @@ -153,11 +153,11 @@
1.4
1.5 if args:
1.6 a = []
1.7 - for i in args:
1.8 - if isinstance(i, tuple):
1.9 - a.append(encode_instruction(i))
1.10 + for arg in args:
1.11 + if isinstance(arg, tuple):
1.12 + a.append(encode_instruction(arg))
1.13 else:
1.14 - a.append(i or "{}")
1.15 + a.append(arg or "{}")
1.16 argstr = "(%s)" % ", ".join(a)
1.17 return "%s%s" % (op, argstr)
1.18 else:
1.19 @@ -167,6 +167,90 @@
1.20
1.21 # Output program encoding.
1.22
1.23 +attribute_ops = (
1.24 + "__load_via_class", "__load_via_object",
1.25 + "__store_via_object",
1.26 + )
1.27 +
1.28 +checked_ops = (
1.29 + "__check_and_load_via_class", "__check_and_load_via_object", "__check_and_load_via_any",
1.30 + "__check_and_store_via_class", "__check_and_store_via_object", "__check_and_store_via_any",
1.31 + )
1.32 +
1.33 +typename_ops = (
1.34 + "__test_common_instance",
1.35 + )
1.36 +
1.37 +def encode_access_instruction(instruction, subs):
1.38 +
1.39 + """
1.40 + Encode the 'instruction' - a sequence starting with an operation and
1.41 + followed by arguments, each of which may be an instruction sequence or a
1.42 + plain value - to produce a function call string representation.
1.43 +
1.44 + The 'subs' parameter defines a mapping of substitutions for special values
1.45 + used in instructions.
1.46 + """
1.47 +
1.48 + op = instruction[0]
1.49 + args = instruction[1:]
1.50 +
1.51 + if not args:
1.52 + argstr = ""
1.53 +
1.54 + else:
1.55 + # Encode the arguments.
1.56 +
1.57 + a = []
1.58 + for arg in args:
1.59 + a.append(encode_access_instruction_arg(arg, subs))
1.60 +
1.61 + # Modify certain arguments.
1.62 +
1.63 + # Convert attribute name arguments to position symbols.
1.64 +
1.65 + if op in attribute_ops:
1.66 + arg = a[1]
1.67 + a[1] = encode_symbol("pos", arg)
1.68 +
1.69 + # Convert attribute name arguments to position and code symbols.
1.70 +
1.71 + elif op in checked_ops:
1.72 + arg = a[1]
1.73 + a[1] = encode_symbol("pos", arg)
1.74 + a.insert(2, encode_symbol("code", arg))
1.75 +
1.76 + # Convert type name arguments to position and code symbols.
1.77 +
1.78 + elif op in typename_ops:
1.79 + arg = "#" % a[1]
1.80 + a[1] = encode_symbol("pos", arg)
1.81 + a.insert(2, encode_symbol("code", arg))
1.82 +
1.83 + argstr = "(%s)" % ", ".join(a)
1.84 +
1.85 + # Substitute the first element of the instruction, which may not be an
1.86 + # operation at all.
1.87 +
1.88 + return "%s%s" % (subs.get(op, op), argstr)
1.89 +
1.90 +def encode_access_instruction_arg(arg, subs):
1.91 +
1.92 + "Encode 'arg' using 'subs' to define substitutions."
1.93 +
1.94 + if isinstance(arg, tuple):
1.95 + return encode_access_instruction(arg, subs)
1.96 +
1.97 + # Special values only need replacing, not encoding.
1.98 +
1.99 + elif subs.has_key(arg):
1.100 + return subs.get(arg)
1.101 +
1.102 + # Other values may need encoding.
1.103 +
1.104 + else:
1.105 + return encode_path(arg)
1.106 +
1.107 def encode_function_pointer(path):
1.108
1.109 "Encode 'path' as a reference to an output program function."