Lichen

Changeset

629:c45334be1ad6
2017-02-27 Paul Boddie raw files shortlog changelog graph Introduced a logical result that simplifies negation expressions when they are used directly by "if" statements.
translator.py (file)
     1.1 --- a/translator.py	Mon Feb 27 15:49:05 2017 +0100
     1.2 +++ b/translator.py	Mon Feb 27 15:50:30 2017 +0100
     1.3 @@ -303,6 +303,25 @@
     1.4      def __repr__(self):
     1.5          return "BooleanResult(%r)" % self.s
     1.6  
     1.7 +class LogicalResult(TranslationResult):
     1.8 +
     1.9 +    "A logical expression result."
    1.10 +
    1.11 +    def __init__(self, expr):
    1.12 +        self.expr = expr
    1.13 +
    1.14 +    def apply_test(self, negate=False):
    1.15 +        return "(%s__BOOL(%s))" % (negate and "" or "!", self.expr)
    1.16 +
    1.17 +    def __str__(self):
    1.18 +        return "(__BOOL(%s) ? %s : %s)" % (
    1.19 +            self.expr,
    1.20 +            PredefinedConstantRef("False"),
    1.21 +            PredefinedConstantRef("True"))
    1.22 +
    1.23 +    def __repr__(self):
    1.24 +        return "LogicalResult(%r)" % self.expr
    1.25 +
    1.26  def make_expression(expr):
    1.27  
    1.28      "Make a new expression from the existing 'expr'."
    1.29 @@ -1635,9 +1654,7 @@
    1.30  
    1.31          "Process the given operator node 'n'."
    1.32  
    1.33 -        return make_expression("(__BOOL(%s) ? %s : %s)" %
    1.34 -            (self.process_structure_node(n.expr), PredefinedConstantRef("False"),
    1.35 -            PredefinedConstantRef("True")))
    1.36 +        return LogicalResult(self.process_structure_node(n.expr))
    1.37  
    1.38      def process_raise_node(self, n):
    1.39  
    1.40 @@ -1847,17 +1864,13 @@
    1.41  
    1.42          if not (isinstance(test, PredefinedConstantRef) and test.value):
    1.43  
    1.44 -            # NOTE: This needs to evaluate whether the operand is true or false
    1.45 -            # NOTE: according to Python rules.
    1.46 -
    1.47 -            self.writeline("if (!__BOOL(%s))" % test)
    1.48 -            self.writeline("{")
    1.49 -            self.indent += 1
    1.50 +            # Emit a negated test of the continuation condition.
    1.51 +
    1.52 +            self.start_if(True, test, True)
    1.53              if n.else_:
    1.54                  self.process_structure_node(n.else_)
    1.55              self.writestmt("break;")
    1.56 -            self.indent -= 1
    1.57 -            self.writeline("}")
    1.58 +            self.end_if()
    1.59  
    1.60          in_conditional = self.in_conditional
    1.61          self.in_conditional = True
    1.62 @@ -2050,8 +2063,16 @@
    1.63          for i, parameter in enumerate(parameters):
    1.64              self.writeline("__attr * const %s = &__args[%d];" % (encode_path(parameter), i+1))
    1.65  
    1.66 -    def start_if(self, first, test_ref):
    1.67 -        self.writestmt("%sif (__BOOL(%s))" % (not first and "else " or "", test_ref))
    1.68 +    def start_if(self, first, test_ref, negate=False):
    1.69 +        statement = "%sif" % (not first and "else " or "")
    1.70 +
    1.71 +        # Consume logical results directly.
    1.72 +
    1.73 +        if isinstance(test_ref, LogicalResult):
    1.74 +            self.writeline("%s %s" % (statement, test_ref.apply_test(negate)))
    1.75 +        else:
    1.76 +            self.writeline("%s (%s__BOOL(%s))" % (statement, negate and "!" or "", test_ref))
    1.77 +
    1.78          self.writeline("{")
    1.79          self.indent += 1
    1.80