2.1 --- a/translator.py Mon Feb 27 15:50:30 2017 +0100
2.2 +++ b/translator.py Mon Feb 27 19:06:41 2017 +0100
2.3 @@ -307,20 +307,90 @@
2.4
2.5 "A logical expression result."
2.6
2.7 + def _convert(self, expr):
2.8 +
2.9 + "Return 'expr' converted to a testable value."
2.10 +
2.11 + if isinstance(expr, LogicalResult):
2.12 + return expr.apply_test()
2.13 + else:
2.14 + return "__BOOL(%s)" % expr
2.15 +
2.16 +class NegationResult(LogicalResult):
2.17 +
2.18 + "A negation expression result."
2.19 +
2.20 def __init__(self, expr):
2.21 self.expr = expr
2.22
2.23 - def apply_test(self, negate=False):
2.24 - return "(%s__BOOL(%s))" % (negate and "" or "!", self.expr)
2.25 + def apply_test(self):
2.26 +
2.27 + "Return the result in a form suitable for direct testing."
2.28 +
2.29 + expr = self._convert(self.expr)
2.30 + return "(!(%s))" % expr
2.31
2.32 def __str__(self):
2.33 - return "(__BOOL(%s) ? %s : %s)" % (
2.34 - self.expr,
2.35 + return "(%s ? %s : %s)" % (
2.36 + self._convert(self.expr),
2.37 PredefinedConstantRef("False"),
2.38 PredefinedConstantRef("True"))
2.39
2.40 def __repr__(self):
2.41 - return "LogicalResult(%r)" % self.expr
2.42 + return "NegationResult(%r)" % self.expr
2.43 +
2.44 +class LogicalOperationResult(LogicalResult):
2.45 +
2.46 + "A logical operation result."
2.47 +
2.48 + def __init__(self, exprs, conjunction):
2.49 + self.exprs = exprs
2.50 + self.conjunction = conjunction
2.51 +
2.52 + def apply_test(self):
2.53 +
2.54 + """
2.55 + Return the result in a form suitable for direct testing.
2.56 +
2.57 + Convert ... to ...
2.58 +
2.59 + <a> and <b>
2.60 + ((__BOOL(<a>)) && (__BOOL(<b>)))
2.61 +
2.62 + <a> or <b>
2.63 + ((__BOOL(<a>)) || (__BOOL(<b>)))
2.64 + """
2.65 +
2.66 + results = []
2.67 + for expr in self.exprs:
2.68 + results.append(self._convert(expr))
2.69 +
2.70 + if self.conjunction:
2.71 + return "(%s)" % " && ".join(results)
2.72 + else:
2.73 + return "(%s)" % " || ".join(results)
2.74 +
2.75 + def __str__(self):
2.76 +
2.77 + """
2.78 + Convert ... to ...
2.79 +
2.80 + <a> and <b>
2.81 + (__tmp_result = <a>, !__BOOL(__tmp_result)) ? __tmp_result : <b>
2.82 +
2.83 + <a> or <b>
2.84 + (__tmp_result = <a>, __BOOL(__tmp_result)) ? __tmp_result : <b>
2.85 + """
2.86 +
2.87 + results = []
2.88 + for expr in self.exprs[:-1]:
2.89 + results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, self.conjunction and "!" or ""))
2.90 + results.append(str(self.exprs[-1]))
2.91 +
2.92 + return "(%s)" % "".join(results)
2.93 +
2.94 + def __repr__(self):
2.95 + return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction)
2.96
2.97 def make_expression(expr):
2.98
2.99 @@ -1541,35 +1611,17 @@
2.100
2.101 def process_logical_node(self, n):
2.102
2.103 - """
2.104 - Process the given operator node 'n'.
2.105 -
2.106 - Convert ... to ...
2.107 -
2.108 - <a> and <b>
2.109 - (__tmp_result = <a>, !__BOOL(__tmp_result)) ? __tmp_result : <b>
2.110 -
2.111 - <a> or <b>
2.112 - (__tmp_result = <a>, __BOOL(__tmp_result)) ? __tmp_result : <b>
2.113 - """
2.114 + "Process the given operator node 'n'."
2.115
2.116 self.record_temp("__tmp_result")
2.117
2.118 - if isinstance(n, compiler.ast.And):
2.119 - op = "!"
2.120 - else:
2.121 - op = ""
2.122 -
2.123 + conjunction = isinstance(n, compiler.ast.And)
2.124 results = []
2.125
2.126 - for node in n.nodes[:-1]:
2.127 - expr = self.process_structure_node(node)
2.128 - results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, op))
2.129 -
2.130 - expr = self.process_structure_node(n.nodes[-1])
2.131 - results.append(str(expr))
2.132 -
2.133 - return make_expression("(%s)" % "".join(results))
2.134 + for node in n.nodes:
2.135 + results.append(self.process_structure_node(node))
2.136 +
2.137 + return LogicalOperationResult(results, conjunction)
2.138
2.139 def process_name_node(self, n, expr=None):
2.140
2.141 @@ -1654,7 +1706,7 @@
2.142
2.143 "Process the given operator node 'n'."
2.144
2.145 - return LogicalResult(self.process_structure_node(n.expr))
2.146 + return NegationResult(self.process_structure_node(n.expr))
2.147
2.148 def process_raise_node(self, n):
2.149
2.150 @@ -1866,7 +1918,7 @@
2.151
2.152 # Emit a negated test of the continuation condition.
2.153
2.154 - self.start_if(True, test, True)
2.155 + self.start_if(True, NegationResult(test))
2.156 if n.else_:
2.157 self.process_structure_node(n.else_)
2.158 self.writestmt("break;")
2.159 @@ -2063,15 +2115,15 @@
2.160 for i, parameter in enumerate(parameters):
2.161 self.writeline("__attr * const %s = &__args[%d];" % (encode_path(parameter), i+1))
2.162
2.163 - def start_if(self, first, test_ref, negate=False):
2.164 + def start_if(self, first, test_ref):
2.165 statement = "%sif" % (not first and "else " or "")
2.166
2.167 # Consume logical results directly.
2.168
2.169 if isinstance(test_ref, LogicalResult):
2.170 - self.writeline("%s %s" % (statement, test_ref.apply_test(negate)))
2.171 + self.writeline("%s %s" % (statement, test_ref.apply_test()))
2.172 else:
2.173 - self.writeline("%s (%s__BOOL(%s))" % (statement, negate and "!" or "", test_ref))
2.174 + self.writeline("%s (__BOOL(%s))" % (statement, test_ref))
2.175
2.176 self.writeline("{")
2.177 self.indent += 1