forked from M-Labs/artiq
compiler: Map host numpy.bool_ values to TBool
Since we don't implement any integer-like operations for TBool (addition, bitwise not, etc.), TBool is currently neither strictly equivalent to builtin bool nor numpy.bool_, but through very obvious compiler errors (operation not supported) rather than silently different runtime behaviour. Just mapping both to TBool thus is a huge improvement over the current behaviour (where numpy.False_ is a true-like object). In the future, we could still implement more operations for TBool, presumably following numpy.bool_ rather than the builtin type, just like builtin integers get translated to the numpy-like TInt{32,64}. GitHub: Fixes #1275.
This commit is contained in:
parent
b8cd163978
commit
1f40f3ce15
|
@ -162,10 +162,11 @@ class ASTSynthesizer:
|
||||||
typ = builtins.TNone()
|
typ = builtins.TNone()
|
||||||
return asttyped.NameConstantT(value=value, type=typ,
|
return asttyped.NameConstantT(value=value, type=typ,
|
||||||
loc=self._add(repr(value)))
|
loc=self._add(repr(value)))
|
||||||
elif value is True or value is False:
|
elif isinstance(value, (bool, numpy.bool_)):
|
||||||
typ = builtins.TBool()
|
typ = builtins.TBool()
|
||||||
return asttyped.NameConstantT(value=value, type=typ,
|
coerced = bool(value)
|
||||||
loc=self._add(repr(value)))
|
return asttyped.NameConstantT(value=coerced, type=typ,
|
||||||
|
loc=self._add(repr(coerced)))
|
||||||
elif value is numpy.float:
|
elif value is numpy.float:
|
||||||
typ = builtins.fn_float()
|
typ = builtins.fn_float()
|
||||||
return asttyped.NameConstantT(value=None, type=typ,
|
return asttyped.NameConstantT(value=None, type=typ,
|
||||||
|
|
|
@ -1558,7 +1558,8 @@ class LLVMIRGenerator:
|
||||||
return ll.Constant.literal_struct([])
|
return ll.Constant.literal_struct([])
|
||||||
elif builtins.is_bool(typ):
|
elif builtins.is_bool(typ):
|
||||||
assert value in (True, False), fail_msg
|
assert value in (True, False), fail_msg
|
||||||
return ll.Constant(llty, value)
|
# Explicitly cast to bool to handle numpy.bool_.
|
||||||
|
return ll.Constant(llty, bool(value))
|
||||||
elif builtins.is_int(typ):
|
elif builtins.is_int(typ):
|
||||||
assert isinstance(value, (int, numpy.int32, numpy.int64)), fail_msg
|
assert isinstance(value, (int, numpy.int32, numpy.int64)), fail_msg
|
||||||
return ll.Constant(llty, int(value))
|
return ll.Constant(llty, int(value))
|
||||||
|
|
|
@ -36,6 +36,12 @@ class RoundtripTest(ExperimentCase):
|
||||||
self.assertRoundtrip(True)
|
self.assertRoundtrip(True)
|
||||||
self.assertRoundtrip(False)
|
self.assertRoundtrip(False)
|
||||||
|
|
||||||
|
def test_numpy_bool(self):
|
||||||
|
# These won't return as numpy.bool_, but the bare-Python results should still
|
||||||
|
# compare equal.
|
||||||
|
self.assertRoundtrip(numpy.True_)
|
||||||
|
self.assertRoundtrip(numpy.False_)
|
||||||
|
|
||||||
def test_int(self):
|
def test_int(self):
|
||||||
self.assertRoundtrip(numpy.int32(42))
|
self.assertRoundtrip(numpy.int32(42))
|
||||||
self.assertRoundtrip(numpy.int64(42))
|
self.assertRoundtrip(numpy.int64(42))
|
||||||
|
@ -492,3 +498,23 @@ class AssertTest(ExperimentCase):
|
||||||
check_fail(lambda: exp.check(False), "AssertionError")
|
check_fail(lambda: exp.check(False), "AssertionError")
|
||||||
exp.check_msg(True)
|
exp.check_msg(True)
|
||||||
check_fail(lambda: exp.check_msg(False), "foo")
|
check_fail(lambda: exp.check_msg(False), "foo")
|
||||||
|
|
||||||
|
|
||||||
|
class _NumpyBool(EnvExperiment):
|
||||||
|
def build(self):
|
||||||
|
self.setattr_device("core")
|
||||||
|
self.np_true = numpy.True_
|
||||||
|
self.np_false = numpy.False_
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def run(self):
|
||||||
|
assert self.np_true
|
||||||
|
assert self.np_true == True
|
||||||
|
assert not self.np_false
|
||||||
|
assert self.np_false == False
|
||||||
|
|
||||||
|
|
||||||
|
class NumpyBoolTest(ExperimentCase):
|
||||||
|
def test_numpy_bool(self):
|
||||||
|
"""Test NumPy bools decay to ARTIQ compiler builtin bools as expected"""
|
||||||
|
self.create(_NumpyBool).run()
|
||||||
|
|
Loading…
Reference in New Issue