Implement bool.__or__, __and__ and __xor__

This commit is contained in:
Y. Sapir committed 2019-05-03 01:54:18 +03:00
1 parent 26306b528f
commit ea347dfdec
3 files changed
+54 -3

No files matched your search

+12
View File
@@ -51,3 +51,15 @@ assert True > 0
assert int(True) == 1
assert True.conjugate() == 1
assert isinstance(True.conjugate(), int)
# Boolean operations on pairs of Bools should return Bools, not ints
assert (False | True) is True
assert (False & True) is False
assert (False ^ True) is True
# But only if both are Bools
assert (False | 1) is not True
assert (0 | True) is not True
assert (False & 1) is not False
assert (0 & True) is not False
assert (False ^ 1) is not True
assert (0 ^ True) is not True
+39
View File
@@ -42,6 +42,9 @@ The class bool is a subclass of the class int, and cannot be subclassed.";
extend_class!(context, bool_type, {
"__new__" => context.new_rustfunc(bool_new),
"__repr__" => context.new_rustfunc(bool_repr),
"__or__" => context.new_rustfunc(bool_or),
"__and__" => context.new_rustfunc(bool_and),
"__xor__" => context.new_rustfunc(bool_xor),
"__doc__" => context.new_str(bool_doc.to_string())
});
}
@@ -71,6 +74,42 @@ fn bool_repr(vm: &VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObj
Ok(vm.new_str(s))
}
fn bool_or(vm: &VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObjectRef> {
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
if objtype::isinstance(lhs, &vm.ctx.bool_type()) && objtype::isinstance(rhs, &vm.ctx.bool_type()) {
let lhs = get_value(lhs);
let rhs = get_value(rhs);
(lhs || rhs).into_pyobject(vm)
} else {
Ok(lhs.payload::<PyInt>().unwrap().or(rhs.clone(), vm))
}
}
fn bool_and(vm: &VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObjectRef> {
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
if objtype::isinstance(lhs, &vm.ctx.bool_type()) && objtype::isinstance(rhs, &vm.ctx.bool_type()) {
let lhs = get_value(lhs);
let rhs = get_value(rhs);
(lhs && rhs).into_pyobject(vm)
} else {
Ok(lhs.payload::<PyInt>().unwrap().and(rhs.clone(), vm))
}
}
fn bool_xor(vm: &VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObjectRef> {
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
if objtype::isinstance(lhs, &vm.ctx.bool_type()) && objtype::isinstance(rhs, &vm.ctx.bool_type()) {
let lhs = get_value(lhs);
let rhs = get_value(rhs);
(lhs ^ rhs).into_pyobject(vm)
} else {
Ok(lhs.payload::<PyInt>().unwrap().xor(rhs.clone(), vm))
}
}
fn bool_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
+3 -3
View File
@@ -286,7 +286,7 @@ impl PyInt {
}
#[pymethod(name = "__xor__")]
fn xor(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
pub fn xor(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
if objtype::isinstance(&other, &vm.ctx.int_type()) {
vm.ctx.new_int((&self.value) ^ get_value(&other))
} else {
@@ -300,7 +300,7 @@ impl PyInt {
}
#[pymethod(name = "__or__")]
fn or(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
pub fn or(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
if objtype::isinstance(&other, &vm.ctx.int_type()) {
vm.ctx.new_int((&self.value) | get_value(&other))
} else {
@@ -309,7 +309,7 @@ impl PyInt {
}
#[pymethod(name = "__and__")]
fn and(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
pub fn and(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
if objtype::isinstance(&other, &vm.ctx.int_type()) {
let v2 = get_value(&other);
vm.ctx.new_int((&self.value) & v2)