Skip to content

Use NotImplemented in binary operations #433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions tests/snippets/builtin_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@

assert complex(1, -1) == complex(1, -1)
assert complex(1, 0) == 1
assert not complex(1, 1) == 1
assert 1 == complex(1, 0)
assert complex(1, 1) != 1
assert 1 != complex(1, 1)
assert complex(1, 0) == 1.0
assert not complex(1, 1) == 1.0
assert not complex(1, 0) == 1.5
assert 1.0 == complex(1, 0)
assert complex(1, 1) != 1.0
assert 1.0 != complex(1, 1)
assert complex(1, 0) != 1.5
assert not 1.0 != complex(1, 0)
assert bool(complex(1, 0))
assert not complex(1, 2) == complex(1, 1)
# Currently broken - see issue #419
# assert complex(1, 2) != 'foo'
assert complex(1, 2) != complex(1, 1)
assert complex(1, 2) != 'foo'
assert complex(1, 2).__eq__('foo') == NotImplemented

# __neg__
Expand Down
11 changes: 11 additions & 0 deletions tests/snippets/object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class MyObject:
pass

assert not MyObject() == MyObject()
assert MyObject() != MyObject()
myobj = MyObject()
assert myobj == myobj
assert not myobj != myobj

assert MyObject().__eq__(MyObject()) == NotImplemented
assert MyObject().__ne__(MyObject()) == NotImplemented
4 changes: 2 additions & 2 deletions vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -988,8 +988,8 @@ impl Frame {
let b = self.pop_value();
let a = self.pop_value();
let value = match *op {
bytecode::ComparisonOperator::Equal => vm._eq(&a, b)?,
bytecode::ComparisonOperator::NotEqual => vm._ne(&a, b)?,
bytecode::ComparisonOperator::Equal => vm._eq(a, b)?,
bytecode::ComparisonOperator::NotEqual => vm._ne(a, b)?,
bytecode::ComparisonOperator::Less => vm._lt(&a, b)?,
bytecode::ComparisonOperator::LessOrEqual => vm._le(&a, b)?,
bytecode::ComparisonOperator::Greater => vm._gt(&a, b)?,
Expand Down
22 changes: 7 additions & 15 deletions vm/src/obj/objfloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn float_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
false
}
} else {
false
return Ok(vm.ctx.not_implemented());
};
Ok(vm.ctx.new_bool(result))
}
Expand Down Expand Up @@ -181,7 +181,7 @@ fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(v1 + objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -198,11 +198,7 @@ fn float_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let r2 = float_mod(vm, args.clone())?;
Ok(vm.ctx.new_tuple(vec![r1, r2]))
} else {
Err(vm.new_type_error(format!(
"Cannot divmod power {} and {}",
i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -221,11 +217,7 @@ fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.to_f64()
.ok_or_else(|| vm.new_overflow_error("int too large to convert to float".to_string()))?
} else {
return Err(vm.new_type_error(format!(
"Cannot floordiv {} and {}",
i.borrow(),
i2.borrow()
)));
return Ok(vm.ctx.not_implemented());
};

if v2 != 0.0 {
Expand All @@ -249,7 +241,7 @@ fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(v1 - objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -268,7 +260,7 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.to_f64()
.ok_or_else(|| vm.new_overflow_error("int too large to convert to float".to_string()))?
} else {
return Err(vm.new_type_error(format!("Cannot mod {} and {}", i.borrow(), i2.borrow())));
return Ok(vm.ctx.not_implemented());
};

if v2 != 0.0 {
Expand Down Expand Up @@ -300,7 +292,7 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let result = v1.powf(objint::get_value(i2).to_f64().unwrap());
Ok(vm.ctx.new_float(result))
} else {
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand Down
44 changes: 12 additions & 32 deletions vm/src/obj/objint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ fn int_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
false
}
} else {
false
return Ok(vm.ctx.not_implemented());
};
Ok(vm.ctx.new_bool(result))
}
Expand Down Expand Up @@ -303,11 +303,7 @@ fn int_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Err(vm.new_zero_division_error("integer floordiv by zero".to_string()))
}
} else {
Err(vm.new_type_error(format!(
"Cannot floordiv {} and {}",
i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand Down Expand Up @@ -358,11 +354,7 @@ fn int_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(i.to_f64().unwrap() - objfloat::get_value(i2)))
} else {
Err(vm.new_not_implemented_error(format!(
"Cannot substract {} and {}",
_i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -379,11 +371,7 @@ fn int_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(get_value(i).to_f64().unwrap() * objfloat::get_value(i2)))
} else {
Err(vm.new_type_error(format!(
"Cannot multiply {} and {}",
i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -405,7 +393,7 @@ fn int_truediv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
} else if objtype::isinstance(i2, &vm.ctx.float_type()) {
objfloat::get_value(i2)
} else {
return Err(vm.new_type_error(format!("Cannot divide {} and {}", i.borrow(), i2.borrow())));
return Ok(vm.ctx.not_implemented());
};

if v2 == 0.0 {
Expand All @@ -431,7 +419,7 @@ fn int_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Err(vm.new_zero_division_error("integer modulo by zero".to_string()))
}
} else {
Err(vm.new_type_error(format!("Cannot modulo {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand Down Expand Up @@ -460,11 +448,7 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = objfloat::get_value(i2);
Ok(vm.ctx.new_float((v1.to_f64().unwrap()).powf(v2)))
} else {
Err(vm.new_type_error(format!(
"Cannot raise power {} and {}",
i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -489,11 +473,7 @@ fn int_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Err(vm.new_zero_division_error("integer divmod by zero".to_string()))
}
} else {
Err(vm.new_type_error(format!(
"Cannot divmod power {} and {}",
i.borrow(),
i2.borrow()
)))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -508,7 +488,7 @@ fn int_xor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 ^ v2))
} else {
Err(vm.new_type_error(format!("Cannot xor {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -525,7 +505,7 @@ fn int_rxor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

Ok(vm.ctx.new_int(left_val ^ right_val))
} else {
Err(vm.new_type_error(format!("Cannot rxor {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -540,7 +520,7 @@ fn int_or(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 | v2))
} else {
Err(vm.new_type_error(format!("Cannot or {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand All @@ -555,7 +535,7 @@ fn int_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 & v2))
} else {
Err(vm.new_type_error(format!("Cannot and {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
}
}

Expand Down
2 changes: 1 addition & 1 deletion vm/src/obj/objlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ fn list_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(zelf);
let mut count: usize = 0;
for element in elements.iter() {
let is_eq = vm._eq(element, value.clone())?;
let is_eq = vm._eq(element.clone(), value.clone())?;
if objbool::boolval(vm, is_eq)? {
count += 1;
}
Expand Down
11 changes: 5 additions & 6 deletions vm/src/obj/objobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use super::super::pyobject::{
TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objbool;
use super::objstr;
use super::objtype;
use std::cell::RefCell;
Expand All @@ -29,19 +28,19 @@ fn object_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, Some(vm.ctx.object())), (other, None)]
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);
Ok(vm.ctx.new_bool(zelf.is(other)))
Ok(vm.ctx.not_implemented())
}

fn object_ne(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, Some(vm.ctx.object())), (other, None)]
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);
let eq = vm.call_method(zelf, "__eq__", vec![other.clone()])?;
objbool::not(vm, &eq)

Ok(vm.ctx.not_implemented())
}

fn object_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Expand Down
2 changes: 1 addition & 1 deletion vm/src/obj/objset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ pub fn set_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
required = [(set, Some(vm.ctx.set_type())), (needle, None)]
);
for element in get_elements(set).iter() {
match vm.call_method(needle, "__eq__", vec![element.1.clone()]) {
match vm._eq(needle.clone(), element.1.clone()) {
Ok(value) => {
if objbool::get_value(&value) {
return Ok(vm.new_bool(true));
Expand Down
2 changes: 1 addition & 1 deletion vm/src/obj/objtuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ fn tuple_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(zelf);
let mut count: usize = 0;
for element in elements.iter() {
let is_eq = vm._eq(element, value.clone())?;
let is_eq = vm._eq(element.clone(), value.clone())?;
if objbool::boolval(vm, is_eq)? {
count += 1;
}
Expand Down
Loading