1.1 --- a/results.py Tue May 21 19:20:45 2024 +0200
1.2 +++ b/results.py Sat May 25 15:52:31 2024 +0200
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Result abstractions.
1.6
1.7 -Copyright (C) 2016, 2017, 2023 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:20:45 2024 +0200
2.2 +++ b/translator.py Sat May 25 15:52:31 2024 +0200
2.3 @@ -1318,21 +1318,24 @@
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 # Employ result targets only in functions.
2.12
2.13 + result_target = None
2.14 +
2.15 if self.in_function:
2.16 if self.result_target_name:
2.17 result_target = self.result_target_name
2.18 self.result_target_name = None
2.19 - else:
2.20 +
2.21 + # Reserve a temporary result target only if it will be used.
2.22 +
2.23 + elif not literal_instantiation and not yields_integer:
2.24 result_target = "__tmp_results[%d]" % self.result_target
2.25 -
2.26 - # Reserve a temporary result target only if it will be used.
2.27 -
2.28 - if not literal_instantiation:
2.29 - self.next_temp("__tmp_results")
2.30 - else:
2.31 - result_target = None
2.32 + self.next_temp("__tmp_results")
2.33
2.34 # Arguments are presented in a temporary frame array with any context
2.35 # always being the first argument. Where it would be unused, it may be
2.36 @@ -1467,9 +1470,17 @@
2.37 # the number of values. The result target and context are excluded.
2.38
2.39 if literal_instantiation:
2.40 - argstr = "%d, %s" % (len(args) - reserved_args, ", ".join(args[reserved_args:]))
2.41 + final_args = args[reserved_args:]
2.42 + argstr = "%d, %s" % (len(final_args), ", ".join(final_args))
2.43 else:
2.44 - argstr = ", ".join(args)
2.45 + # NOTE: Special case for optimisation.
2.46 +
2.47 + if yields_integer:
2.48 + final_args = args[reserved_args:]
2.49 + else:
2.50 + final_args = args
2.51 +
2.52 + argstr = ", ".join(final_args)
2.53
2.54 kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0"
2.55 kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0"
2.56 @@ -1543,7 +1554,11 @@
2.57 if instantiation:
2.58 return InstantiationResult(instantiation, stages)
2.59 else:
2.60 - return InvocationResult(result_target, stages)
2.61 + # Provide the parameter details for possible optimisation when
2.62 + # translating the result.
2.63 +
2.64 + return InvocationResult(result_target, stages,
2.65 + yields_integer and final_args or None)
2.66
2.67 # With unknown targets, the generic invocation function is applied to
2.68 # the callable and argument collections.
2.69 @@ -2354,7 +2369,7 @@
2.70 if temps:
2.71 self.remove_temps(temps)
2.72 else:
2.73 - self.writeline("%s (__BOOL(%s))" % (statement, test_ref))
2.74 + self.writeline("%s (%s)" % (statement, test_ref.apply_test()))
2.75
2.76 self.writeline("{")
2.77 self.indent += 1
3.1 --- a/transresults.py Tue May 21 19:20:45 2024 +0200
3.2 +++ b/transresults.py Sat May 25 15:52:31 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, 2023 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 @@ -295,15 +295,23 @@
3.13
3.14 "A translation result for an invocation."
3.15
3.16 - def __init__(self, result_target, instructions):
3.17 + def __init__(self, result_target, instructions, args=None):
3.18 InstructionSequence.__init__(self, instructions)
3.19 self.result_target = result_target
3.20 + self.args = args
3.21 +
3.22 + def yields_integer(self):
3.23 + return self.args and True or False
3.24
3.25 def __str__(self):
3.26 - return encode_instructions(self.instructions)
3.27 + if self.yields_integer():
3.28 + return ", ".join(self.args)
3.29 + else:
3.30 + return encode_instructions(self.instructions)
3.31
3.32 def __repr__(self):
3.33 - return "InvocationResult(%r, %r)" % (self.result_target, self.instructions)
3.34 + return "InvocationResult(%r, %r, %r)" % (self.result_target,
3.35 + self.instructions, self.args)
3.36
3.37 class InstantiationResult(InvocationResult, TrInstanceRef):
3.38
3.39 @@ -349,14 +357,7 @@
3.40
3.41 "A logical expression result."
3.42
3.43 - def _convert(self, expr):
3.44 -
3.45 - "Return 'expr' converted to a testable value."
3.46 -
3.47 - if isinstance(expr, LogicalResult):
3.48 - return expr.apply_test()
3.49 - else:
3.50 - return "__BOOL(%s)" % expr
3.51 + pass
3.52
3.53 class NegationResult(LogicalResult):
3.54
3.55 @@ -369,8 +370,7 @@
3.56
3.57 "Return the result in a form suitable for direct testing."
3.58
3.59 - expr = self._convert(self.expr)
3.60 - return "(!%s)" % expr
3.61 + return "(!%s)" % self.expr.apply_test()
3.62
3.63 def discards_temporary(self, test=True):
3.64
3.65 @@ -381,9 +381,12 @@
3.66
3.67 return None
3.68
3.69 + def yields_integer(self):
3.70 + return self.expr.yields_integer()
3.71 +
3.72 def __str__(self):
3.73 return "(%s ? %s : %s)" % (
3.74 - self._convert(self.expr),
3.75 + self.expr.apply_test(),
3.76 PredefinedConstantRef("False"),
3.77 PredefinedConstantRef("True"))
3.78
3.79 @@ -414,7 +417,7 @@
3.80
3.81 results = []
3.82 for expr in self.exprs:
3.83 - results.append(self._convert(expr))
3.84 + results.append(expr.apply_test())
3.85
3.86 if self.conjunction:
3.87 return "(%s)" % " && ".join(results)
3.88 @@ -440,6 +443,12 @@
3.89
3.90 return temps
3.91
3.92 + def yields_integer(self):
3.93 + for expr in self.exprs:
3.94 + if not expr.yields_integer():
3.95 + return False
3.96 + return True
3.97 +
3.98 def __str__(self):
3.99
3.100 """