# HG changeset patch # User Paul Boddie # Date 1488218801 -3600 # Node ID f6495d78bda5a3f04830dd46b66d5c8a8c7931c3 # Parent c45334be1ad6e81d52866b43d5bb64f2fe725b11 Introduced results for other logical operations, refining common behaviour. diff -r c45334be1ad6 -r f6495d78bda5 tests/logical_simple.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/logical_simple.py Mon Feb 27 19:06:41 2017 +0100 @@ -0,0 +1,28 @@ +a = 1 +b = 2 +c = a and b +print c # 2 + +d = a or b +print d # 1 + +e = not a +print e # False + +if a and b: + print "a and b" # a and b + +if not (a and b): + print "not (a and b)" # + +if not not (a and b): + print "not not (a and b)" # not not (a and b) + +if a or b: + print "a or b" # a or b + +if not (a or b): + print "not (a or b)" # + +if not not (a or b): + print "not not (a or b)" # not not (a or b) diff -r c45334be1ad6 -r f6495d78bda5 translator.py --- a/translator.py Mon Feb 27 15:50:30 2017 +0100 +++ b/translator.py Mon Feb 27 19:06:41 2017 +0100 @@ -307,20 +307,90 @@ "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 + +class NegationResult(LogicalResult): + + "A negation expression result." + def __init__(self, expr): self.expr = expr - def apply_test(self, negate=False): - return "(%s__BOOL(%s))" % (negate and "" or "!", self.expr) + def apply_test(self): + + "Return the result in a form suitable for direct testing." + + expr = self._convert(self.expr) + return "(!(%s))" % expr def __str__(self): - return "(__BOOL(%s) ? %s : %s)" % ( - self.expr, + return "(%s ? %s : %s)" % ( + self._convert(self.expr), PredefinedConstantRef("False"), PredefinedConstantRef("True")) def __repr__(self): - return "LogicalResult(%r)" % self.expr + return "NegationResult(%r)" % self.expr + +class LogicalOperationResult(LogicalResult): + + "A logical operation result." + + def __init__(self, exprs, conjunction): + self.exprs = exprs + self.conjunction = conjunction + + def apply_test(self): + + """ + Return the result in a form suitable for direct testing. + + Convert ... to ... + + and + ((__BOOL()) && (__BOOL())) + + or + ((__BOOL()) || (__BOOL())) + """ + + results = [] + for expr in self.exprs: + results.append(self._convert(expr)) + + if self.conjunction: + return "(%s)" % " && ".join(results) + else: + return "(%s)" % " || ".join(results) + + def __str__(self): + + """ + Convert ... to ... + + and + (__tmp_result = , !__BOOL(__tmp_result)) ? __tmp_result : + + or + (__tmp_result = , __BOOL(__tmp_result)) ? __tmp_result : + """ + + results = [] + for expr in self.exprs[:-1]: + results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, self.conjunction and "!" or "")) + results.append(str(self.exprs[-1])) + + return "(%s)" % "".join(results) + + def __repr__(self): + return "LogicalOperationResult(%r, %r)" % (self.exprs, self.conjunction) def make_expression(expr): @@ -1541,35 +1611,17 @@ def process_logical_node(self, n): - """ - Process the given operator node 'n'. - - Convert ... to ... - - and - (__tmp_result = , !__BOOL(__tmp_result)) ? __tmp_result : - - or - (__tmp_result = , __BOOL(__tmp_result)) ? __tmp_result : - """ + "Process the given operator node 'n'." self.record_temp("__tmp_result") - if isinstance(n, compiler.ast.And): - op = "!" - else: - op = "" - + conjunction = isinstance(n, compiler.ast.And) results = [] - for node in n.nodes[:-1]: - expr = self.process_structure_node(node) - results.append("(__tmp_result = %s, %s__BOOL(__tmp_result)) ? __tmp_result : " % (expr, op)) - - expr = self.process_structure_node(n.nodes[-1]) - results.append(str(expr)) - - return make_expression("(%s)" % "".join(results)) + for node in n.nodes: + results.append(self.process_structure_node(node)) + + return LogicalOperationResult(results, conjunction) def process_name_node(self, n, expr=None): @@ -1654,7 +1706,7 @@ "Process the given operator node 'n'." - return LogicalResult(self.process_structure_node(n.expr)) + return NegationResult(self.process_structure_node(n.expr)) def process_raise_node(self, n): @@ -1866,7 +1918,7 @@ # Emit a negated test of the continuation condition. - self.start_if(True, test, True) + self.start_if(True, NegationResult(test)) if n.else_: self.process_structure_node(n.else_) self.writestmt("break;") @@ -2063,15 +2115,15 @@ for i, parameter in enumerate(parameters): self.writeline("__attr * const %s = &__args[%d];" % (encode_path(parameter), i+1)) - def start_if(self, first, test_ref, negate=False): + def start_if(self, first, test_ref): statement = "%sif" % (not first and "else " or "") # Consume logical results directly. if isinstance(test_ref, LogicalResult): - self.writeline("%s %s" % (statement, test_ref.apply_test(negate))) + self.writeline("%s %s" % (statement, test_ref.apply_test())) else: - self.writeline("%s (%s__BOOL(%s))" % (statement, negate and "!" or "", test_ref)) + self.writeline("%s (__BOOL(%s))" % (statement, test_ref)) self.writeline("{") self.indent += 1