1.1 --- a/translator.py Mon Feb 27 15:50:30 2017 +0100
1.2 +++ b/translator.py Mon Feb 27 19:06:41 2017 +0100
1.3 @@ -307,20 +307,90 @@
1.4
1.5 "A logical expression result."
1.6
1.7 + def _convert(self, expr):
1.8 +
1.9 + "Return 'expr' converted to a testable value."
1.10 +
1.11 + if isinstance(expr, LogicalResult):
1.12 + return expr.apply_test()
1.13 + else:
1.14 + return "__BOOL(%s)" % expr
1.15 +
1.16 +class NegationResult(LogicalResult):
1.17 +
1.18 + "A negation expression result."
1.19 +
1.20 def __init__(self, expr):
1.21 self.expr = expr
1.22
1.23 - def apply_test(self, negate=False):
1.24 - return "(%s__BOOL(%s))" % (negate and "" or "!", self.expr)
1.25 + def apply_test(self):
1.26 +
1.27 + "Return the result in a form suitable for direct testing."
1.28 +
1.29 + expr = self._convert(self.expr)
1.30 + return "(!(%s))" % expr
1.31
1.32 def __str__(self):
1.33 - return "(__BOOL(%s) ? %s : %s)" % (
1.34 - self.expr,
1.35 + return "(%s ? %s : %s)" % (
1.36 + self._convert(self.expr),
1.37 PredefinedConstantRef("False"),
1.38 PredefinedConstantRef("True"))
1.39
1.40 def __repr__(self):
1.41 - return "LogicalResult(%r)" % self.expr
1.42 + return "NegationResult(%r)" % self.expr
1.43 +
1.44 +class LogicalOperationResult(LogicalResult):
1.45 +
1.46 + "A logical operation result."
1.47 +
1.48 + def __init__(self, exprs, conjunction):
1.49 + self.exprs = exprs
1.50 + self.conjunction = conjunction
1.51 +
1.52 + def apply_test(self):
1.53 +
1.54 + """
1.55 + Return the result in a form suitable for direct testing.
1.56 +
1.57 + Convert ... to ...
1.58 +
1.59 + <a> and <b>
1.60 + ((__BOOL(<a>)) && (__BOOL(<b>)))
1.61 +
1.62 + <a> or <b>
1.63 + ((__BOOL(<a>)) || (__BOOL(<b>)))
1.64 + """
1.65 +
1.66 + results = []
1.67 + for expr in self.exprs:
1.68 + results.append(self._convert(expr))
1.69 +
1.70 + if self.conjunction:
1.71 + return "(%s)" % " && ".join(results)
1.72 + else:
1.73 + return "(%s)" % " || ".join(results)
1.74 +
1.75 + def __str__(self):
1.76 +
1.77 + """
1.78 + Convert ... to ...
1.79 +
1.80 + <a> and <b>
1.81 + (__tmp_result = <a>, !__BOOL(__tmp_result)) ? __tmp_result : <b>
1.82 +
1.83 + <a> or <b>
1.84 + (__tmp_result = <a>, __BOOL(__tmp_result)) ? __tmp_result : <b>
1.85 + """
1.86 +
1.87 + results = []
1.88 + for expr in self.exprs[:-1]:
1.89 + results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, self.conjunction and "!" or ""))
1.90 + results.append(str(self.exprs[-1]))
1.91 +
1.92 + return "(%s)" % "".join(results)
1.93 +
1.94 + def __repr__(self):
1.95 + return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction)
1.96
1.97 def make_expression(expr):
1.98
1.99 @@ -1541,35 +1611,17 @@
1.100
1.101 def process_logical_node(self, n):
1.102
1.103 - """
1.104 - Process the given operator node 'n'.
1.105 -
1.106 - Convert ... to ...
1.107 -
1.108 - <a> and <b>
1.109 - (__tmp_result = <a>, !__BOOL(__tmp_result)) ? __tmp_result : <b>
1.110 -
1.111 - <a> or <b>
1.112 - (__tmp_result = <a>, __BOOL(__tmp_result)) ? __tmp_result : <b>
1.113 - """
1.114 + "Process the given operator node 'n'."
1.115
1.116 self.record_temp("__tmp_result")
1.117
1.118 - if isinstance(n, compiler.ast.And):
1.119 - op = "!"
1.120 - else:
1.121 - op = ""
1.122 -
1.123 + conjunction = isinstance(n, compiler.ast.And)
1.124 results = []
1.125
1.126 - for node in n.nodes[:-1]:
1.127 - expr = self.process_structure_node(node)
1.128 - results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, op))
1.129 -
1.130 - expr = self.process_structure_node(n.nodes[-1])
1.131 - results.append(str(expr))
1.132 -
1.133 - return make_expression("(%s)" % "".join(results))
1.134 + for node in n.nodes:
1.135 + results.append(self.process_structure_node(node))
1.136 +
1.137 + return LogicalOperationResult(results, conjunction)
1.138
1.139 def process_name_node(self, n, expr=None):
1.140
1.141 @@ -1654,7 +1706,7 @@
1.142
1.143 "Process the given operator node 'n'."
1.144
1.145 - return LogicalResult(self.process_structure_node(n.expr))
1.146 + return NegationResult(self.process_structure_node(n.expr))
1.147
1.148 def process_raise_node(self, n):
1.149
1.150 @@ -1866,7 +1918,7 @@
1.151
1.152 # Emit a negated test of the continuation condition.
1.153
1.154 - self.start_if(True, test, True)
1.155 + self.start_if(True, NegationResult(test))
1.156 if n.else_:
1.157 self.process_structure_node(n.else_)
1.158 self.writestmt("break;")
1.159 @@ -2063,15 +2115,15 @@
1.160 for i, parameter in enumerate(parameters):
1.161 self.writeline("__attr * const %s = &__args[%d];" % (encode_path(parameter), i+1))
1.162
1.163 - def start_if(self, first, test_ref, negate=False):
1.164 + def start_if(self, first, test_ref):
1.165 statement = "%sif" % (not first and "else " or "")
1.166
1.167 # Consume logical results directly.
1.168
1.169 if isinstance(test_ref, LogicalResult):
1.170 - self.writeline("%s %s" % (statement, test_ref.apply_test(negate)))
1.171 + self.writeline("%s %s" % (statement, test_ref.apply_test()))
1.172 else:
1.173 - self.writeline("%s (%s__BOOL(%s))" % (statement, negate and "!" or "", test_ref))
1.174 + self.writeline("%s (__BOOL(%s))" % (statement, test_ref))
1.175
1.176 self.writeline("{")
1.177 self.indent += 1