mirror of https://github.com/m-labs/artiq.git
Add bool coercion support.
This commit is contained in:
parent
de181e0cb9
commit
bf60978c7b
|
@ -284,8 +284,33 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
finally:
|
finally:
|
||||||
self.current_assign = None
|
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):
|
def visit_If(self, node):
|
||||||
cond = self.visit(node.test)
|
cond = self.visit(node.test)
|
||||||
|
cond = self.coerce_to_bool(cond)
|
||||||
head = self.current_block
|
head = self.current_block
|
||||||
|
|
||||||
if_true = self.add_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)]):
|
zip(blocks, [(h,t) for (v,h,t) in blocks[1:]] + [(tail, tail)]):
|
||||||
phi.add_incoming(value, value_tail)
|
phi.add_incoming(value, value_tail)
|
||||||
if next_value_head != tail:
|
if next_value_head != tail:
|
||||||
|
cond = self.coerce_to_bool(value, block=value_tail)
|
||||||
if isinstance(node.op, ast.And):
|
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:
|
else:
|
||||||
value_tail.append(ir.BranchIf(value, tail, next_value_head))
|
value_tail.append(ir.BranchIf(cond, tail, next_value_head))
|
||||||
else:
|
else:
|
||||||
value_tail.append(ir.Branch(tail))
|
value_tail.append(ir.Branch(tail))
|
||||||
return phi
|
return phi
|
||||||
|
|
||||||
def visit_UnaryOpT(self, node):
|
def visit_UnaryOpT(self, node):
|
||||||
if isinstance(node.op, ast.Not):
|
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(False, builtins.TBool()),
|
||||||
ir.Constant(True, builtins.TBool())))
|
ir.Constant(True, builtins.TBool())))
|
||||||
elif isinstance(node.op, ast.USub):
|
elif isinstance(node.op, ast.USub):
|
||||||
|
@ -1116,9 +1143,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
return ir.Constant(False, builtins.TBool())
|
return ir.Constant(False, builtins.TBool())
|
||||||
elif len(node.args) == 1 and len(node.keywords) == 0:
|
elif len(node.args) == 1 and len(node.keywords) == 0:
|
||||||
arg = self.visit(node.args[0])
|
arg = self.visit(node.args[0])
|
||||||
return self.append(ir.Select(arg,
|
return self.coerce_to_bool(arg)
|
||||||
ir.Constant(True, builtins.TBool()),
|
|
||||||
ir.Constant(False, builtins.TBool())))
|
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
elif types.is_builtin(typ, "int"):
|
elif types.is_builtin(typ, "int"):
|
||||||
|
|
|
@ -295,7 +295,7 @@ class LLVMIRGenerator:
|
||||||
if builtins.get_int_width(typ) > builtins.get_int_width(value_typ):
|
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),
|
return self.llbuilder.sext(self.map(insn.value()), self.llty_of_type(typ),
|
||||||
name=insn.name)
|
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),
|
return self.llbuilder.trunc(self.map(insn.value()), self.llty_of_type(typ),
|
||||||
name=insn.name)
|
name=insn.name)
|
||||||
else:
|
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
|
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||||
|
|
||||||
assert (not True) == False
|
|
||||||
assert (not False) == True
|
|
||||||
assert -(-1) == 1
|
assert -(-1) == 1
|
||||||
assert -(-1.0) == 1.0
|
assert -(-1.0) == 1.0
|
||||||
assert +1 == 1
|
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