Add bool coercion support.

This commit is contained in:
whitequark 2015-07-22 19:09:14 +03:00
parent de181e0cb9
commit bf60978c7b
5 changed files with 57 additions and 9 deletions

View File

@ -284,8 +284,33 @@ class ARTIQIRGenerator(algorithm.Visitor):
finally:
self.current_assign = None
def coerce_to_bool(self, insn, block=None):
if builtins.is_bool(insn.type):
return insn
elif builtins.is_int(insn.type):
return self.append(ir.Compare(ast.NotEq(loc=None), insn, ir.Constant(0, insn.type)),
block=block)
elif builtins.is_float(insn.type):
return self.append(ir.Compare(ast.NotEq(loc=None), insn, ir.Constant(0, insn.type)),
block=block)
elif builtins.is_iterable(insn.type):
length = self.iterable_len(insn)
return self.append(ir.Compare(ast.NotEq(loc=None), length, ir.Constant(0, length.type)),
block=block)
else:
note = diagnostic.Diagnostic("note",
"this expression has type {type}",
{"type": types.TypePrinter().name(insn.type)},
insn.loc)
diag = diagnostic.Diagnostic("warning",
"this expression, which is always truthful, is coerced to bool", {},
insn.loc, notes=[note])
self.engine.process(diag)
return ir.Constant(True, builtins.TBool())
def visit_If(self, node):
cond = self.visit(node.test)
cond = self.coerce_to_bool(cond)
head = self.current_block
if_true = self.add_block()
@ -838,17 +863,19 @@ class ARTIQIRGenerator(algorithm.Visitor):
zip(blocks, [(h,t) for (v,h,t) in blocks[1:]] + [(tail, tail)]):
phi.add_incoming(value, value_tail)
if next_value_head != tail:
cond = self.coerce_to_bool(value, block=value_tail)
if isinstance(node.op, ast.And):
value_tail.append(ir.BranchIf(value, next_value_head, tail))
value_tail.append(ir.BranchIf(cond, next_value_head, tail))
else:
value_tail.append(ir.BranchIf(value, tail, next_value_head))
value_tail.append(ir.BranchIf(cond, tail, next_value_head))
else:
value_tail.append(ir.Branch(tail))
return phi
def visit_UnaryOpT(self, node):
if isinstance(node.op, ast.Not):
return self.append(ir.Select(self.visit(node.operand),
cond = self.coerce_to_bool(self.visit(node.operand))
return self.append(ir.Select(cond,
ir.Constant(False, builtins.TBool()),
ir.Constant(True, builtins.TBool())))
elif isinstance(node.op, ast.USub):
@ -1116,9 +1143,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
return ir.Constant(False, builtins.TBool())
elif len(node.args) == 1 and len(node.keywords) == 0:
arg = self.visit(node.args[0])
return self.append(ir.Select(arg,
ir.Constant(True, builtins.TBool()),
ir.Constant(False, builtins.TBool())))
return self.coerce_to_bool(arg)
else:
assert False
elif types.is_builtin(typ, "int"):

View File

@ -295,7 +295,7 @@ class LLVMIRGenerator:
if builtins.get_int_width(typ) > builtins.get_int_width(value_typ):
return self.llbuilder.sext(self.map(insn.value()), self.llty_of_type(typ),
name=insn.name)
else: # builtins.get_int_width(typ) < builtins.get_int_width(value_typ):
else: # builtins.get_int_width(typ) <= builtins.get_int_width(value_typ):
return self.llbuilder.trunc(self.map(insn.value()), self.llty_of_type(typ),
name=insn.name)
else:

View File

@ -0,0 +1,5 @@
# RUN: %python -m artiq.compiler.testbench.module +diag %s >%t
# RUN: OutputCheck %s --file-to-check=%t
# CHECK-L: ${LINE:+1}: warning: this expression, which is always truthful, is coerced to bool
bool(IndexError())

View File

@ -1,7 +1,5 @@
# RUN: %python -m artiq.compiler.testbench.jit %s
assert (not True) == False
assert (not False) == True
assert -(-1) == 1
assert -(-1.0) == 1.0
assert +1 == 1

View File

@ -0,0 +1,20 @@
# RUN: %python -m artiq.compiler.testbench.jit %s
assert (not 0) == True
assert (not 1) == False
assert (0 and 0) is 0
assert (1 and 0) is 0
assert (0 and 1) is 0
assert (1 and 2) is 2
assert (0 or 0) is 0
assert (1 or 0) is 1
assert (0 or 1) is 1
assert (1 or 2) is 1
assert bool(False) is False and bool(False) is False
assert bool(0) is False and bool(1) is True
assert bool(0.0) is False and bool(1.0) is True
x = []; assert bool(x) is False; x = [1]; assert bool(x) is True
assert bool(range(0)) is False and bool(range(1)) is True