# HG changeset patch # User Paul Boddie # Date 1716502823 -7200 # Node ID 5e69d28e5fb0ffcda7837fb85d5d915fea2bcf52 # Parent 8bcbea777be94d312d9bf9d1a2ff0ff3a2b6fcec# Parent 62e75f9a08ab63d042201aa737e65c56b2a0ca7c Merged and adapted changes from the trailing-data branch. diff -r 8bcbea777be9 -r 5e69d28e5fb0 results.py --- a/results.py Tue May 21 19:20:32 2024 +0200 +++ b/results.py Fri May 24 00:20:23 2024 +0200 @@ -3,7 +3,7 @@ """ Result abstractions. -Copyright (C) 2016, 2017, 2023 Paul Boddie +Copyright (C) 2016, 2017, 2023, 2024 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -69,6 +69,20 @@ def has_kind(self, kinds): return False + # Support for formulating expressions for direct testing. + + def yields_integer(self): + return False + + def apply_test(self): + + "Return the result in a form suitable for direct testing." + + if self.yields_integer(): + return "__INTEGER(%s)" % self + else: + return "__BOOL(%s)" % self + class AccessRef(Result): """ diff -r 8bcbea777be9 -r 5e69d28e5fb0 translator.py --- a/translator.py Tue May 21 19:20:32 2024 +0200 +++ b/translator.py Fri May 24 00:20:23 2024 +0200 @@ -1317,21 +1317,24 @@ if stores_accessor: self.record_temp("__tmp_values") + # NOTE: Special case for optimisation. + + yields_integer = target and objpath == "native.int.is_int" + # Employ result targets only in functions. + result_target = None + if self.in_function: if self.result_target_name: result_target = self.result_target_name self.result_target_name = None - else: + + # Reserve a temporary result target only if it will be used. + + elif not literal_instantiation and not yields_integer: result_target = "__tmp_results[%d]" % self.result_target - - # Reserve a temporary result target only if it will be used. - - if not literal_instantiation: - self.next_temp("__tmp_results") - else: - result_target = None + self.next_temp("__tmp_results") # Arguments are presented in a temporary frame array with any context # always being the first argument. Where it would be unused, it may be @@ -1466,9 +1469,17 @@ # the number of values. The result target and context are excluded. if literal_instantiation: - argstr = "%d, %s" % (len(args) - reserved_args, ", ".join(args[reserved_args:])) + final_args = args[reserved_args:] + argstr = "%d, %s" % (len(final_args), ", ".join(final_args)) else: - argstr = ", ".join(args) + # NOTE: Special case for optimisation. + + if yields_integer: + final_args = args[reserved_args:] + else: + final_args = args + + argstr = ", ".join(final_args) kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0" kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0" @@ -1542,7 +1553,11 @@ if instantiation: return InstantiationResult(instantiation, stages) else: - return InvocationResult(result_target, stages) + # Provide the parameter details for possible optimisation when + # translating the result. + + return InvocationResult(result_target, stages, + yields_integer and final_args or None) # With unknown targets, the generic invocation function is applied to # the callable and argument collections. @@ -2353,7 +2368,7 @@ if temps: self.remove_temps(temps) else: - self.writeline("%s (__BOOL(%s))" % (statement, test_ref)) + self.writeline("%s (%s)" % (statement, test_ref.apply_test())) self.writeline("{") self.indent += 1 diff -r 8bcbea777be9 -r 5e69d28e5fb0 transresults.py --- a/transresults.py Tue May 21 19:20:32 2024 +0200 +++ b/transresults.py Fri May 24 00:20:23 2024 +0200 @@ -3,7 +3,7 @@ """ Translation result abstractions. -Copyright (C) 2016, 2017, 2018, 2021, 2023 Paul Boddie +Copyright (C) 2016-2018, 2021, 2023, 2024 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -295,15 +295,23 @@ "A translation result for an invocation." - def __init__(self, result_target, instructions): + def __init__(self, result_target, instructions, args=None): InstructionSequence.__init__(self, instructions) self.result_target = result_target + self.args = args + + def yields_integer(self): + return self.args and True or False def __str__(self): - return encode_instructions(self.instructions) + if self.yields_integer(): + return ", ".join(self.args) + else: + return encode_instructions(self.instructions) def __repr__(self): - return "InvocationResult(%r, %r)" % (self.result_target, self.instructions) + return "InvocationResult(%r, %r, %r)" % (self.result_target, + self.instructions, self.args) class InstantiationResult(InvocationResult, TrInstanceRef): @@ -349,14 +357,7 @@ "A logical expression result." - def _convert(self, expr): - - "Return 'expr' converted to a testable value." - - if isinstance(expr, LogicalResult): - return expr.apply_test() - else: - return "__BOOL(%s)" % expr + pass class NegationResult(LogicalResult): @@ -369,8 +370,7 @@ "Return the result in a form suitable for direct testing." - expr = self._convert(self.expr) - return "(!%s)" % expr + return "(!%s)" % self.expr.apply_test() def discards_temporary(self, test=True): @@ -381,9 +381,12 @@ return None + def yields_integer(self): + return self.expr.yields_integer() + def __str__(self): return "(%s ? %s : %s)" % ( - self._convert(self.expr), + self.expr.apply_test(), PredefinedConstantRef("False"), PredefinedConstantRef("True")) @@ -414,7 +417,7 @@ results = [] for expr in self.exprs: - results.append(self._convert(expr)) + results.append(expr.apply_test()) if self.conjunction: return "(%s)" % " && ".join(results) @@ -440,6 +443,12 @@ return temps + def yields_integer(self): + for expr in self.exprs: + if not expr.yields_integer(): + return False + return True + def __str__(self): """