Skip to content

Commit ee2b2a8

Browse files
Merge pull request RustPython#909 from sapir/add-bool-methods
Add bool methods
2 parents a36fb77 + 45d7c38 commit ee2b2a8

3 files changed

Lines changed: 102 additions & 8 deletions

File tree

tests/snippets/bools.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,29 @@ def __bool__(self):
5151
assert int(True) == 1
5252
assert True.conjugate() == 1
5353
assert isinstance(True.conjugate(), int)
54+
55+
# Boolean operations on pairs of Bools should return Bools, not ints
56+
assert (False | True) is True
57+
assert (False & True) is False
58+
assert (False ^ True) is True
59+
# But only if both are Bools
60+
assert (False | 1) is not True
61+
assert (0 | True) is not True
62+
assert (False & 1) is not False
63+
assert (0 & True) is not False
64+
assert (False ^ 1) is not True
65+
assert (0 ^ True) is not True
66+
67+
# Check that the same works with __XXX__ methods
68+
assert False.__or__(0) is not False
69+
assert False.__or__(False) is False
70+
assert False.__ror__(0) is not False
71+
assert False.__ror__(False) is False
72+
assert False.__and__(0) is not False
73+
assert False.__and__(False) is False
74+
assert False.__rand__(0) is not False
75+
assert False.__rand__(False) is False
76+
assert False.__xor__(0) is not False
77+
assert False.__xor__(False) is False
78+
assert False.__rxor__(0) is not False
79+
assert False.__rxor__(False) is False

vm/src/obj/objbool.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ The class bool is a subclass of the class int, and cannot be subclassed.";
4242
extend_class!(context, bool_type, {
4343
"__new__" => context.new_rustfunc(bool_new),
4444
"__repr__" => context.new_rustfunc(bool_repr),
45+
"__or__" => context.new_rustfunc(bool_or),
46+
"__ror__" => context.new_rustfunc(bool_ror),
47+
"__and__" => context.new_rustfunc(bool_and),
48+
"__rand__" => context.new_rustfunc(bool_rand),
49+
"__xor__" => context.new_rustfunc(bool_xor),
50+
"__rxor__" => context.new_rustfunc(bool_rxor),
4551
"__doc__" => context.new_str(bool_doc.to_string())
4652
});
4753
}
@@ -71,6 +77,72 @@ fn bool_repr(vm: &VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObj
7177
Ok(vm.new_str(s))
7278
}
7379

80+
fn do_bool_or(vm: &VirtualMachine, lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult {
81+
if objtype::isinstance(lhs, &vm.ctx.bool_type())
82+
&& objtype::isinstance(rhs, &vm.ctx.bool_type())
83+
{
84+
let lhs = get_value(lhs);
85+
let rhs = get_value(rhs);
86+
(lhs || rhs).into_pyobject(vm)
87+
} else {
88+
Ok(lhs.payload::<PyInt>().unwrap().or(rhs.clone(), vm))
89+
}
90+
}
91+
92+
fn bool_or(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
93+
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
94+
do_bool_or(vm, lhs, rhs)
95+
}
96+
97+
fn bool_ror(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
98+
arg_check!(vm, args, required = [(rhs, None), (lhs, None)]);
99+
do_bool_or(vm, lhs, rhs)
100+
}
101+
102+
fn do_bool_and(vm: &VirtualMachine, lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult {
103+
if objtype::isinstance(lhs, &vm.ctx.bool_type())
104+
&& objtype::isinstance(rhs, &vm.ctx.bool_type())
105+
{
106+
let lhs = get_value(lhs);
107+
let rhs = get_value(rhs);
108+
(lhs && rhs).into_pyobject(vm)
109+
} else {
110+
Ok(lhs.payload::<PyInt>().unwrap().and(rhs.clone(), vm))
111+
}
112+
}
113+
114+
fn bool_and(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
115+
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
116+
do_bool_and(vm, lhs, rhs)
117+
}
118+
119+
fn bool_rand(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
120+
arg_check!(vm, args, required = [(rhs, None), (lhs, None)]);
121+
do_bool_and(vm, lhs, rhs)
122+
}
123+
124+
fn do_bool_xor(vm: &VirtualMachine, lhs: &PyObjectRef, rhs: &PyObjectRef) -> PyResult {
125+
if objtype::isinstance(lhs, &vm.ctx.bool_type())
126+
&& objtype::isinstance(rhs, &vm.ctx.bool_type())
127+
{
128+
let lhs = get_value(lhs);
129+
let rhs = get_value(rhs);
130+
(lhs ^ rhs).into_pyobject(vm)
131+
} else {
132+
Ok(lhs.payload::<PyInt>().unwrap().xor(rhs.clone(), vm))
133+
}
134+
}
135+
136+
fn bool_xor(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
137+
arg_check!(vm, args, required = [(lhs, None), (rhs, None)]);
138+
do_bool_xor(vm, lhs, rhs)
139+
}
140+
141+
fn bool_rxor(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
142+
arg_check!(vm, args, required = [(rhs, None), (lhs, None)]);
143+
do_bool_xor(vm, lhs, rhs)
144+
}
145+
74146
fn bool_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
75147
arg_check!(
76148
vm,

vm/src/obj/objint.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl PyInt {
309309
}
310310

311311
#[pymethod(name = "__xor__")]
312-
fn xor(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
312+
pub fn xor(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
313313
if objtype::isinstance(&other, &vm.ctx.int_type()) {
314314
vm.ctx.new_int((&self.value) ^ get_value(&other))
315315
} else {
@@ -319,15 +319,11 @@ impl PyInt {
319319

320320
#[pymethod(name = "__rxor__")]
321321
fn rxor(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
322-
if objtype::isinstance(&other, &vm.ctx.int_type()) {
323-
vm.ctx.new_int(get_value(&other) ^ (&self.value))
324-
} else {
325-
vm.ctx.not_implemented()
326-
}
322+
self.xor(other, vm)
327323
}
328324

329325
#[pymethod(name = "__or__")]
330-
fn or(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
326+
pub fn or(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
331327
if objtype::isinstance(&other, &vm.ctx.int_type()) {
332328
vm.ctx.new_int((&self.value) | get_value(&other))
333329
} else {
@@ -336,7 +332,7 @@ impl PyInt {
336332
}
337333

338334
#[pymethod(name = "__and__")]
339-
fn and(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
335+
pub fn and(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
340336
if objtype::isinstance(&other, &vm.ctx.int_type()) {
341337
let v2 = get_value(&other);
342338
vm.ctx.new_int((&self.value) & v2)

0 commit comments

Comments
 (0)