Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 4 additions & 0 deletions tests/snippets/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ class MyObject:

assert MyObject().__eq__(MyObject()) == NotImplemented
assert MyObject().__ne__(MyObject()) == NotImplemented
assert MyObject().__lt__(MyObject()) == NotImplemented
assert MyObject().__le__(MyObject()) == NotImplemented
assert MyObject().__gt__(MyObject()) == NotImplemented
assert MyObject().__ge__(MyObject()) == NotImplemented
4 changes: 2 additions & 2 deletions vm/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ fn builtin_max(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
} else {
y.clone()
};
let order = vm.call_method(&x_key, "__gt__", vec![y_key.clone()])?;
let order = vm._gt(x_key.clone(), y_key.clone())?;

if !objbool::get_value(&order) {
x = y.clone();
Expand Down Expand Up @@ -471,7 +471,7 @@ fn builtin_min(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
} else {
y.clone()
};
let order = vm.call_method(&x_key, "__gt__", vec![y_key.clone()])?;
let order = vm._gt(x_key.clone(), y_key.clone())?;

if objbool::get_value(&order) {
x = y.clone();
Expand Down
8 changes: 4 additions & 4 deletions vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -990,10 +990,10 @@ impl Frame {
let value = match *op {
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)?,
bytecode::ComparisonOperator::GreaterOrEqual => vm._ge(&a, b)?,
bytecode::ComparisonOperator::Less => vm._lt(a, b)?,
bytecode::ComparisonOperator::LessOrEqual => vm._le(a, b)?,
bytecode::ComparisonOperator::Greater => vm._gt(a, b)?,
bytecode::ComparisonOperator::GreaterOrEqual => vm._ge(a, b)?,
bytecode::ComparisonOperator::Is => vm.ctx.new_bool(self._is(a, b)),
bytecode::ComparisonOperator::IsNot => self._is_not(vm, a, b)?,
bytecode::ComparisonOperator::In => self._in(vm, a, b)?,
Expand Down
2 changes: 1 addition & 1 deletion vm/src/obj/objfloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn float_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_bool(v1 < objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow())))
Ok(vm.ctx.not_implemented())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think float_{gt,ge,le} need this change as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks

}
}

Expand Down
44 changes: 44 additions & 0 deletions vm/src/obj/objobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,46 @@ fn object_ne(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.ctx.not_implemented())
}

fn object_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);

Ok(vm.ctx.not_implemented())
}

fn object_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);

Ok(vm.ctx.not_implemented())
}

fn object_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);

Ok(vm.ctx.not_implemented())
}

fn object_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(_zelf, Some(vm.ctx.object())), (_other, None)]
);

Ok(vm.ctx.not_implemented())
}

fn object_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(_zelf, Some(vm.ctx.object()))]);

Expand Down Expand Up @@ -91,6 +131,10 @@ pub fn init(context: &PyContext) {
context.set_attr(&object, "__init__", context.new_rustfunc(object_init));
context.set_attr(&object, "__eq__", context.new_rustfunc(object_eq));
context.set_attr(&object, "__ne__", context.new_rustfunc(object_ne));
context.set_attr(&object, "__lt__", context.new_rustfunc(object_lt));
context.set_attr(&object, "__le__", context.new_rustfunc(object_le));
context.set_attr(&object, "__gt__", context.new_rustfunc(object_gt));
context.set_attr(&object, "__ge__", context.new_rustfunc(object_ge));
context.set_attr(&object, "__delattr__", context.new_rustfunc(object_delattr));
context.set_attr(
&object,
Expand Down
24 changes: 16 additions & 8 deletions vm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,20 +620,28 @@ impl VirtualMachine {
})
}

pub fn _lt(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_method(a, "__lt__", vec![b])
pub fn _lt(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_or_unsupported(a, b, "__lt__", "__gt__", |vm, a, b| {
Copy link
Copy Markdown
Contributor

@windelbouwman windelbouwman Feb 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opposite of < is >=, right? I would expect __lt__ to fail over to __ge__.

Copy link
Copy Markdown
Contributor

@OddCoincidence OddCoincidence Feb 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because call_or_unsupported flips the operands. If you think about it, a > b and b < a are equivalent. a > b and b <= a are not.

Also from the python docs:

lt() and gt() are each other’s reflection, le() and ge() are each other’s reflection

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, you are right! Sorry for that!

Err(vm.new_unsupported_operand_error(a, b, "<"))
})
}

pub fn _le(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_method(a, "__le__", vec![b])
pub fn _le(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_or_unsupported(a, b, "__le__", "__ge__", |vm, a, b| {
Err(vm.new_unsupported_operand_error(a, b, "<="))
})
}

pub fn _gt(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_method(a, "__gt__", vec![b])
pub fn _gt(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_or_unsupported(a, b, "__gt__", "__lt__", |vm, a, b| {
Err(vm.new_unsupported_operand_error(a, b, ">"))
})
}

pub fn _ge(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_method(a, "__ge__", vec![b])
pub fn _ge(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
self.call_or_unsupported(a, b, "__ge__", "__le__", |vm, a, b| {
Err(vm.new_unsupported_operand_error(a, b, ">="))
})
}
}

Expand Down