1.1 --- a/results.py Tue May 21 19:04:20 2024 +0200
1.2 +++ b/results.py Fri May 24 00:11:20 2024 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Result abstractions.
1.6
1.7 -Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2016, 2017, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -69,6 +69,20 @@
1.13 def has_kind(self, kinds):
1.14 return False
1.15
1.16 + # Support for formulating expressions for direct testing.
1.17 +
1.18 + def yields_integer(self):
1.19 + return False
1.20 +
1.21 + def apply_test(self):
1.22 +
1.23 + "Return the result in a form suitable for direct testing."
1.24 +
1.25 + if self.yields_integer():
1.26 + return "__INTEGER(%s)" % self
1.27 + else:
1.28 + return "__BOOL(%s)" % self
1.29 +
1.30 class AccessRef(Result):
1.31
1.32 """
2.1 --- a/translator.py Tue May 21 19:04:20 2024 +0200
2.2 +++ b/translator.py Fri May 24 00:11:20 2024 +0200
2.3 @@ -1285,6 +1285,10 @@
2.4 if stores_accessor:
2.5 self.record_temp("__tmp_values")
2.6
2.7 + # NOTE: Special case for optimisation.
2.8 +
2.9 + yields_integer = target and objpath == "native.int.is_int"
2.10 +
2.11 # Arguments are presented in a temporary frame array with any context
2.12 # always being the first argument. Where it would be unused, it may be
2.13 # set to null.
2.14 @@ -1409,9 +1413,17 @@
2.15 # the number of values. The context is excluded.
2.16
2.17 if literal_instantiation:
2.18 - argstr = "%d, %s" % (len(args) - reserved_args, ", ".join(args[reserved_args:]))
2.19 + final_args = args[reserved_args:]
2.20 + argstr = "%d, %s" % (len(final_args), ", ".join(final_args))
2.21 else:
2.22 - argstr = ", ".join(args)
2.23 + # NOTE: Special case for optimisation.
2.24 +
2.25 + if yields_integer:
2.26 + final_args = args[reserved_args:]
2.27 + else:
2.28 + final_args = args
2.29 +
2.30 + argstr = ", ".join(final_args)
2.31
2.32 kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0"
2.33 kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0"
2.34 @@ -1485,7 +1497,11 @@
2.35 if instantiation:
2.36 return InstantiationResult(instantiation, stages)
2.37 else:
2.38 - return InvocationResult(stages)
2.39 + # Provide the parameter details for possible optimisation when
2.40 + # translating the result.
2.41 +
2.42 + return InvocationResult(stages,
2.43 + yields_integer and final_args or None)
2.44
2.45 # With unknown targets, the generic invocation function is applied to
2.46 # the callable and argument collections.
2.47 @@ -2227,7 +2243,7 @@
2.48 if temps:
2.49 self.remove_temps(temps)
2.50 else:
2.51 - self.writeline("%s (__BOOL(%s))" % (statement, test_ref))
2.52 + self.writeline("%s (%s)" % (statement, test_ref.apply_test()))
2.53
2.54 self.writeline("{")
2.55 self.indent += 1
3.1 --- a/transresults.py Tue May 21 19:04:20 2024 +0200
3.2 +++ b/transresults.py Fri May 24 00:11:20 2024 +0200
3.3 @@ -3,7 +3,7 @@
3.4 """
3.5 Translation result abstractions.
3.6
3.7 -Copyright (C) 2016, 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk>
3.8 +Copyright (C) 2016-2018, 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk>
3.9
3.10 This program is free software; you can redistribute it and/or modify it under
3.11 the terms of the GNU General Public License as published by the Free Software
3.12 @@ -285,11 +285,21 @@
3.13
3.14 "A translation result for an invocation."
3.15
3.16 + def __init__(self, instructions, args=None):
3.17 + InstructionSequence.__init__(self, instructions)
3.18 + self.args = args
3.19 +
3.20 + def yields_integer(self):
3.21 + return self.args and True or False
3.22 +
3.23 def __str__(self):
3.24 - return encode_instructions(self.instructions)
3.25 + if self.yields_integer():
3.26 + return ", ".join(self.args)
3.27 + else:
3.28 + return encode_instructions(self.instructions)
3.29
3.30 def __repr__(self):
3.31 - return "InvocationResult(%r)" % self.instructions
3.32 + return "InvocationResult(%r, %r)" % (self.instructions, self.args)
3.33
3.34 class InstantiationResult(InvocationResult, TrInstanceRef):
3.35
3.36 @@ -335,14 +345,7 @@
3.37
3.38 "A logical expression result."
3.39
3.40 - def _convert(self, expr):
3.41 -
3.42 - "Return 'expr' converted to a testable value."
3.43 -
3.44 - if isinstance(expr, LogicalResult):
3.45 - return expr.apply_test()
3.46 - else:
3.47 - return "__BOOL(%s)" % expr
3.48 + pass
3.49
3.50 class NegationResult(LogicalResult):
3.51
3.52 @@ -355,8 +358,7 @@
3.53
3.54 "Return the result in a form suitable for direct testing."
3.55
3.56 - expr = self._convert(self.expr)
3.57 - return "(!%s)" % expr
3.58 + return "(!%s)" % self.expr.apply_test()
3.59
3.60 def discards_temporary(self, test=True):
3.61
3.62 @@ -367,9 +369,12 @@
3.63
3.64 return None
3.65
3.66 + def yields_integer(self):
3.67 + return self.expr.yields_integer()
3.68 +
3.69 def __str__(self):
3.70 return "(%s ? %s : %s)" % (
3.71 - self._convert(self.expr),
3.72 + self.expr.apply_test(),
3.73 PredefinedConstantRef("False"),
3.74 PredefinedConstantRef("True"))
3.75
3.76 @@ -400,7 +405,7 @@
3.77
3.78 results = []
3.79 for expr in self.exprs:
3.80 - results.append(self._convert(expr))
3.81 + results.append(expr.apply_test())
3.82
3.83 if self.conjunction:
3.84 return "(%s)" % " && ".join(results)
3.85 @@ -426,6 +431,12 @@
3.86
3.87 return temps
3.88
3.89 + def yields_integer(self):
3.90 + for expr in self.exprs:
3.91 + if not expr.yields_integer():
3.92 + return False
3.93 + return True
3.94 +
3.95 def __str__(self):
3.96
3.97 """