forked from M-Labs/artiq
Add bool coercion support.
This commit is contained in:
parent
de181e0cb9
commit
bf60978c7b
|
@ -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"):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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())
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue