From 10531191bb32b8d24ff439102c26c0279cb4194b Mon Sep 17 00:00:00 2001 From: Adrian Wielgosik Date: Fri, 8 Mar 2019 19:42:38 +0100 Subject: [PATCH] Convert most tuple/list methods to new args style --- vm/src/frame.rs | 19 +- vm/src/function.rs | 7 + vm/src/obj/objfloat.rs | 4 +- vm/src/obj/objlist.rs | 689 ++++++++++++++------------------------ vm/src/obj/objsequence.rs | 6 +- vm/src/obj/objtuple.rs | 428 ++++++++++------------- 6 files changed, 444 insertions(+), 709 deletions(-) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 4fd7ae687b..4bbf523419 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -21,7 +21,7 @@ use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ DictProtocol, IdProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, - TypeProtocol, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -138,14 +138,7 @@ impl Frame { vm.ctx.new_int(lineno.get_row()), vm.ctx.new_str(run_obj_name.clone()), ]); - objlist::list_append( - vm, - PyFuncArgs { - args: vec![traceback, pos], - kwargs: vec![], - }, - ) - .unwrap(); + objlist::PyListRef::try_from_object(vm, traceback)?.append(pos, vm); // exception.__trace match self.unwind_exception(vm, exception) { None => {} @@ -312,13 +305,7 @@ impl Frame { bytecode::Instruction::ListAppend { i } => { let list_obj = self.nth_value(*i); let item = self.pop_value(); - objlist::list_append( - vm, - PyFuncArgs { - args: vec![list_obj.clone(), item], - kwargs: vec![], - }, - )?; + objlist::PyListRef::try_from_object(vm, list_obj)?.append(item, vm); Ok(None) } bytecode::Instruction::SetAdd { i } => { diff --git a/vm/src/function.rs b/vm/src/function.rs index 993167ffc9..5cffd8c987 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -44,6 +44,13 @@ where _payload: PhantomData, } } + + pub fn as_object(&self) -> &PyObjectRef { + &self.obj + } + pub fn into_object(self) -> PyObjectRef { + self.obj + } } impl Deref for PyRef diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 64c26973e9..f544adcc36 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -152,7 +152,7 @@ impl PyFloatRef { } } - fn new_str(cls: PyObjectRef, arg: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + fn new_float(cls: PyObjectRef, arg: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { let value = if objtype::isinstance(&arg, &vm.ctx.float_type()) { get_value(&arg) } else if objtype::isinstance(&arg, &vm.ctx.int_type()) { @@ -373,7 +373,7 @@ pub fn init(context: &PyContext) { context.set_attr(&float_type, "__radd__", context.new_rustfunc(PyFloatRef::add)); context.set_attr(&float_type, "__divmod__", context.new_rustfunc(PyFloatRef::divmod)); context.set_attr(&float_type, "__floordiv__", context.new_rustfunc(PyFloatRef::floordiv)); - context.set_attr(&float_type, "__new__", context.new_rustfunc(PyFloatRef::new_str)); + context.set_attr(&float_type, "__new__", context.new_rustfunc(PyFloatRef::new_float)); context.set_attr(&float_type, "__mod__", context.new_rustfunc(PyFloatRef::mod_)); context.set_attr(&float_type, "__neg__", context.new_rustfunc(PyFloatRef::neg)); context.set_attr(&float_type, "__pow__", context.new_rustfunc(PyFloatRef::pow)); diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 0a2ece3651..d71c13976f 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -3,14 +3,15 @@ use std::cell::{Cell, RefCell}; use super::objbool; use super::objint; use super::objsequence::{ - get_elements, get_elements_cell, get_item, get_mut_elements, seq_equal, seq_ge, seq_gt, seq_le, - seq_lt, seq_mul, PySliceableSequence, + get_elements, get_elements_cell, get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, + PySliceableSequence, }; use super::objstr; use super::objtype; +use crate::function::PyRef; use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, - PyResult, TypeProtocol, + IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; use num_traits::ToPrimitive; @@ -35,323 +36,279 @@ impl PyObjectPayload2 for PyList { } } -// set_item: -fn set_item( - vm: &mut VirtualMachine, - l: &mut Vec, - idx: PyObjectRef, - obj: PyObjectRef, -) -> PyResult { - if objtype::isinstance(&idx, &vm.ctx.int_type()) { - let value = objint::get_value(&idx).to_i32().unwrap(); - if let Some(pos_index) = l.get_pos(value) { - l[pos_index] = obj; - Ok(vm.get_none()) - } else { - Err(vm.new_index_error("list index out of range".to_string())) - } - } else { - panic!( - "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", - l, idx - ) - } -} +pub type PyListRef = PyRef; -fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(cls, None)], - optional = [(iterable, None)] - ); +impl PyListRef { + pub fn append(self, x: PyObjectRef, _vm: &mut VirtualMachine) { + self.elements.borrow_mut().push(x); + } - if !objtype::issubclass(cls, &vm.ctx.list_type()) { - return Err(vm.new_type_error(format!("{:?} is not a subtype of list", cls))); + fn extend(self, x: PyObjectRef, vm: &mut VirtualMachine) -> PyResult<()> { + let mut new_elements = vm.extract_elements(&x)?; + self.elements.borrow_mut().append(&mut new_elements); + Ok(()) } - let elements = if let Some(iterable) = iterable { - vm.extract_elements(iterable)? - } else { - vec![] - }; + fn insert(self, position: isize, element: PyObjectRef, _vm: &mut VirtualMachine) { + let mut vec = self.elements.borrow_mut(); + let vec_len = vec.len().to_isize().unwrap(); + // This unbounded position can be < 0 or > vec.len() + let unbounded_position = if position < 0 { + vec_len + position + } else { + position + }; + // Bound it by [0, vec.len()] + let position = unbounded_position.max(0).min(vec_len).to_usize().unwrap(); + vec.insert(position, element.clone()); + } - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyList::from(elements)), - }, - cls.clone(), - )) -} + fn add(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let e1 = self.elements.borrow(); + let e2 = get_elements(&other); + let elements = e1.iter().chain(e2.iter()).cloned().collect(); + Ok(vm.ctx.new_list(elements)) + } else { + Err(vm.new_type_error(format!("Cannot add {} and {}", self.as_object(), other))) + } + } -fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); + fn iadd(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + self.elements + .borrow_mut() + .extend_from_slice(&get_elements(&other)); + Ok(self.into_object()) + } else { + Ok(vm.ctx.not_implemented()) + } + } - if zelf.is(&other) { - return Ok(vm.ctx.new_bool(true)); + fn clear(self, _vm: &mut VirtualMachine) { + self.elements.borrow_mut().clear(); } - let result = if objtype::isinstance(other, &vm.ctx.list_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_equal(vm, &zelf, &other)? - } else { - false - }; - Ok(vm.ctx.new_bool(result)) -} + fn copy(self, vm: &mut VirtualMachine) -> PyObjectRef { + vm.ctx.new_list(self.elements.borrow().clone()) + } -fn list_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.list_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_lt(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other))); - }; + fn len(self, _vm: &mut VirtualMachine) -> usize { + self.elements.borrow().len() + } - Ok(vm.ctx.new_bool(result)) -} + fn reverse(self, _vm: &mut VirtualMachine) { + self.elements.borrow_mut().reverse(); + } -fn list_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.list_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_gt(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other))); - }; + fn getitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + get_item( + vm, + self.as_object(), + &self.elements.borrow(), + needle.clone(), + ) + } - Ok(vm.ctx.new_bool(result)) -} + fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { + PyObject::new( + PyObjectPayload::Iterator { + position: Cell::new(0), + iterated_obj: self.into_object(), + }, + vm.ctx.iter_type(), + ) + } -fn list_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.list_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_ge(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other))); - }; + fn setitem(self, key: PyObjectRef, value: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + let mut elements = self.elements.borrow_mut(); - Ok(vm.ctx.new_bool(result)) -} + if objtype::isinstance(&key, &vm.ctx.int_type()) { + let idx = objint::get_value(&key).to_i32().unwrap(); + if let Some(pos_index) = elements.get_pos(idx) { + elements[pos_index] = value; + Ok(vm.get_none()) + } else { + Err(vm.new_index_error("list index out of range".to_string())) + } + } else { + panic!( + "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", + elements, key + ) + } + } -fn list_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.list_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_le(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other))); - }; + fn repr(self, vm: &mut VirtualMachine) -> PyResult { + let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) { + let mut str_parts = vec![]; + for elem in self.elements.borrow().iter() { + let s = vm.to_repr(elem)?; + str_parts.push(objstr::get_value(&s)); + } + format!("[{}]", str_parts.join(", ")) + } else { + "[...]".to_string() + }; + Ok(s) + } - Ok(vm.ctx.new_bool(result)) -} + fn mul(self, counter: isize, vm: &mut VirtualMachine) -> PyObjectRef { + let new_elements = seq_mul(&self.elements.borrow(), counter); + vm.ctx.new_list(new_elements) + } -fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(o, Some(vm.ctx.list_type())), (o2, None)] - ); - - if objtype::isinstance(o2, &vm.ctx.list_type()) { - let e1 = get_elements(o); - let e2 = get_elements(o2); - let elements = e1.iter().chain(e2.iter()).cloned().collect(); - Ok(vm.ctx.new_list(elements)) - } else { - Err(vm.new_type_error(format!("Cannot add {} and {}", o, o2))) + fn count(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + let mut count: usize = 0; + for element in self.elements.borrow().iter() { + if needle.is(&element) { + count += 1; + } else { + let py_equal = vm._eq(element.clone(), needle.clone())?; + if objbool::boolval(vm, py_equal)? { + count += 1; + } + } + } + Ok(count) } -} -fn list_iadd(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (other, None)] - ); + fn contains(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + for element in self.elements.borrow().iter() { + if needle.is(&element) { + return Ok(true); + } + let py_equal = vm._eq(element.clone(), needle.clone())?; + if objbool::boolval(vm, py_equal)? { + return Ok(true); + } + } - if objtype::isinstance(other, &vm.ctx.list_type()) { - get_mut_elements(zelf).extend_from_slice(&get_elements(other)); - Ok(zelf.clone()) - } else { - Ok(vm.ctx.not_implemented()) + Ok(false) } -} -fn list_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(o, Some(vm.ctx.list_type()))]); + fn index(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + for (index, element) in self.elements.borrow().iter().enumerate() { + if needle.is(&element) { + return Ok(index); + } + let py_equal = vm._eq(needle.clone(), element.clone())?; + if objbool::boolval(vm, py_equal)? { + return Ok(index); + } + } + let needle_str = objstr::get_value(&vm.to_str(&needle).unwrap()); + Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) + } - let s = if let Some(_guard) = ReprGuard::enter(o) { - let elements = get_elements(o); - let mut str_parts = vec![]; - for elem in elements.iter() { - let s = vm.to_repr(elem)?; - str_parts.push(objstr::get_value(&s)); + fn pop(self, vm: &mut VirtualMachine) -> PyResult { + let mut elements = self.elements.borrow_mut(); + if let Some(result) = elements.pop() { + Ok(result) + } else { + Err(vm.new_index_error("pop from empty list".to_string())) } - format!("[{}]", str_parts.join(", ")) - } else { - "[...]".to_string() - }; + } - Ok(vm.new_str(s)) -} + fn remove(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult<()> { + let mut ri: Option = None; + for (index, element) in self.elements.borrow().iter().enumerate() { + if needle.is(&element) { + ri = Some(index); + break; + } + let py_equal = vm._eq(needle.clone(), element.clone())?; + if objbool::get_value(&py_equal) { + ri = Some(index); + break; + } + } -pub fn list_append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.append called with: {:?}", args); - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (x, None)] - ); - let mut elements = get_mut_elements(list); - elements.push(x.clone()); - Ok(vm.get_none()) -} + if let Some(index) = ri { + self.elements.borrow_mut().remove(index); + Ok(()) + } else { + let needle_str = objstr::get_value(&vm.to_str(&needle)?); + Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) + } + } -fn list_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.clear called with: {:?}", args); - arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]); - let mut elements = get_mut_elements(list); - elements.clear(); - Ok(vm.get_none()) -} + fn eq(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if self.as_object().is(&other) { + return Ok(true); + } -fn list_copy(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, Some(vm.ctx.list_type()))]); - let elements = get_elements(zelf); - Ok(vm.ctx.new_list(elements.clone())) -} + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_equal(vm, &zelf, &other)?) + } else { + Ok(false) + } + } -fn list_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.list_type())), (value, None)] - ); - let elements = get_elements(zelf); - let mut count: usize = 0; - for element in elements.iter() { - if value.is(&element) { - count += 1; + fn lt(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_lt(vm, &zelf, &other)?) } else { - let is_eq = vm._eq(element.clone(), value.clone())?; - if objbool::boolval(vm, is_eq)? { - count += 1; - } + Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", self, other))) } } - Ok(vm.context().new_int(count)) -} -pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (x, None)] - ); - let mut new_elements = vm.extract_elements(x)?; - let mut elements = get_mut_elements(list); - elements.append(&mut new_elements); - Ok(vm.get_none()) -} + fn gt(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_gt(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", self, other))) + } + } -fn list_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.index called with: {:?}", args); - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (needle, None)] - ); - for (index, element) in get_elements(list).iter().enumerate() { - if needle.is(&element) { - return Ok(vm.context().new_int(index)); + fn ge(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_ge(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", self, other))) } - let py_equal = vm._eq(needle.clone(), element.clone())?; - if objbool::get_value(&py_equal) { - return Ok(vm.context().new_int(index)); + } + + fn le(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.list_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_le(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", self, other))) } } - let needle_str = objstr::get_value(&vm.to_str(needle).unwrap()); - Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) } -fn list_insert(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.insert called with: {:?}", args); - arg_check!( - vm, - args, - required = [ - (list, Some(vm.ctx.list_type())), - (insert_position, Some(vm.ctx.int_type())), - (element, None) - ] - ); - let int_position = match objint::get_value(insert_position).to_isize() { - Some(i) => i, - None => { - return Err( - vm.new_overflow_error("Python int too large to convert to Rust isize".to_string()) - ); - } - }; - let mut vec = get_mut_elements(list); - let vec_len = vec.len().to_isize().unwrap(); - // This unbounded position can be < 0 or > vec.len() - let unbounded_position = if int_position < 0 { - vec_len + int_position +fn list_new( + cls: PyRef, + iterable: OptionalArg, + vm: &mut VirtualMachine, +) -> PyResult { + if !objtype::issubclass(cls.as_object(), &vm.ctx.list_type()) { + return Err(vm.new_type_error(format!("{} is not a subtype of list", cls))); + } + + let elements = if let OptionalArg::Present(iterable) = iterable { + vm.extract_elements(&iterable)? } else { - int_position + vec![] }; - // Bound it by [0, vec.len()] - let position = unbounded_position.max(0).min(vec_len).to_usize().unwrap(); - vec.insert(position, element.clone()); - Ok(vm.get_none()) -} - -fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.len called with: {:?}", args); - arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]); - let elements = get_elements(list); - Ok(vm.context().new_int(elements.len())) -} -fn list_reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.reverse called with: {:?}", args); - arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]); - let mut elements = get_mut_elements(list); - elements.reverse(); - Ok(vm.get_none()) + Ok(PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(PyList::from(elements)), + }, + cls.into_object(), + )) } fn quicksort( @@ -443,121 +400,7 @@ fn list_sort(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.get_none()) } -fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.contains called with: {:?}", args); - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (needle, None)] - ); - for element in get_elements(list).iter() { - if needle.is(&element) { - return Ok(vm.new_bool(true)); - } - match vm._eq(needle.clone(), element.clone()) { - Ok(value) => { - if objbool::get_value(&value) { - return Ok(vm.new_bool(true)); - } - } - Err(_) => return Err(vm.new_type_error("".to_string())), - } - } - - Ok(vm.new_bool(false)) -} - -fn list_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("list.getitem called with: {:?}", args); - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (needle, None)] - ); - get_item(vm, list, &get_elements(list), needle.clone()) -} - -fn list_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]); - - let iter_obj = PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: list.clone(), - }, - vm.ctx.iter_type(), - ); - - // We are all good here: - Ok(iter_obj) -} - -fn list_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (key, None), (value, None)] - ); - let mut elements = get_mut_elements(list); - set_item(vm, &mut elements, key.clone(), value.clone()) -} - -fn list_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (list, Some(vm.ctx.list_type())), - (product, Some(vm.ctx.int_type())) - ] - ); - - let new_elements = seq_mul(&get_elements(list), product); - - Ok(vm.ctx.new_list(new_elements)) -} - -fn list_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, Some(vm.ctx.list_type()))]); - - let mut elements = get_mut_elements(zelf); - if let Some(result) = elements.pop() { - Ok(result) - } else { - Err(vm.new_index_error("pop from empty list".to_string())) - } -} - -fn list_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(list, Some(vm.ctx.list_type())), (needle, None)] - ); - - let mut ri: Option = None; - for (index, element) in get_elements(list).iter().enumerate() { - if needle.is(&element) { - ri = Some(index); - break; - } - let py_equal = vm._eq(needle.clone(), element.clone())?; - if objbool::get_value(&py_equal) { - ri = Some(index); - break; - } - } - - if let Some(index) = ri { - let mut elements = get_mut_elements(list); - elements.remove(index); - Ok(vm.get_none()) - } else { - let needle_str = objstr::get_value(&vm.to_str(needle)?); - Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) - } -} - +#[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { let list_type = &context.list_type; @@ -565,43 +408,31 @@ pub fn init(context: &PyContext) { If no argument is given, the constructor creates a new empty list.\n\ The argument must be an iterable if specified."; - context.set_attr(&list_type, "__add__", context.new_rustfunc(list_add)); - context.set_attr(&list_type, "__iadd__", context.new_rustfunc(list_iadd)); - context.set_attr( - &list_type, - "__contains__", - context.new_rustfunc(list_contains), - ); - context.set_attr(&list_type, "__eq__", context.new_rustfunc(list_eq)); - context.set_attr(&list_type, "__lt__", context.new_rustfunc(list_lt)); - context.set_attr(&list_type, "__gt__", context.new_rustfunc(list_gt)); - context.set_attr(&list_type, "__le__", context.new_rustfunc(list_le)); - context.set_attr(&list_type, "__ge__", context.new_rustfunc(list_ge)); - context.set_attr( - &list_type, - "__getitem__", - context.new_rustfunc(list_getitem), - ); - context.set_attr(&list_type, "__iter__", context.new_rustfunc(list_iter)); - context.set_attr( - &list_type, - "__setitem__", - context.new_rustfunc(list_setitem), - ); - context.set_attr(&list_type, "__mul__", context.new_rustfunc(list_mul)); - context.set_attr(&list_type, "__len__", context.new_rustfunc(list_len)); + context.set_attr(&list_type, "__add__", context.new_rustfunc(PyListRef::add)); + context.set_attr(&list_type, "__iadd__", context.new_rustfunc(PyListRef::iadd)); + context.set_attr(&list_type, "__contains__", context.new_rustfunc(PyListRef::contains)); + context.set_attr(&list_type, "__eq__", context.new_rustfunc(PyListRef::eq)); + context.set_attr(&list_type, "__lt__", context.new_rustfunc(PyListRef::lt)); + context.set_attr(&list_type, "__gt__", context.new_rustfunc(PyListRef::gt)); + context.set_attr(&list_type, "__le__", context.new_rustfunc(PyListRef::le)); + context.set_attr(&list_type, "__ge__", context.new_rustfunc(PyListRef::ge)); + context.set_attr(&list_type, "__getitem__", context.new_rustfunc(PyListRef::getitem)); + context.set_attr(&list_type, "__iter__", context.new_rustfunc(PyListRef::iter)); + context.set_attr(&list_type, "__setitem__", context.new_rustfunc(PyListRef::setitem)); + context.set_attr(&list_type, "__mul__", context.new_rustfunc(PyListRef::mul)); + context.set_attr(&list_type, "__len__", context.new_rustfunc(PyListRef::len)); context.set_attr(&list_type, "__new__", context.new_rustfunc(list_new)); - context.set_attr(&list_type, "__repr__", context.new_rustfunc(list_repr)); + context.set_attr(&list_type, "__repr__", context.new_rustfunc(PyListRef::repr)); context.set_attr(&list_type, "__doc__", context.new_str(list_doc.to_string())); - context.set_attr(&list_type, "append", context.new_rustfunc(list_append)); - context.set_attr(&list_type, "clear", context.new_rustfunc(list_clear)); - context.set_attr(&list_type, "copy", context.new_rustfunc(list_copy)); - context.set_attr(&list_type, "count", context.new_rustfunc(list_count)); - context.set_attr(&list_type, "extend", context.new_rustfunc(list_extend)); - context.set_attr(&list_type, "index", context.new_rustfunc(list_index)); - context.set_attr(&list_type, "insert", context.new_rustfunc(list_insert)); - context.set_attr(&list_type, "reverse", context.new_rustfunc(list_reverse)); + context.set_attr(&list_type, "append", context.new_rustfunc(PyListRef::append)); + context.set_attr(&list_type, "clear", context.new_rustfunc(PyListRef::clear)); + context.set_attr(&list_type, "copy", context.new_rustfunc(PyListRef::copy)); + context.set_attr(&list_type, "count", context.new_rustfunc(PyListRef::count)); + context.set_attr(&list_type, "extend", context.new_rustfunc(PyListRef::extend)); + context.set_attr(&list_type, "index", context.new_rustfunc(PyListRef::index)); + context.set_attr(&list_type, "insert", context.new_rustfunc(PyListRef::insert)); + context.set_attr(&list_type, "reverse", context.new_rustfunc(PyListRef::reverse)); context.set_attr(&list_type, "sort", context.new_rustfunc(list_sort)); - context.set_attr(&list_type, "pop", context.new_rustfunc(list_pop)); - context.set_attr(&list_type, "remove", context.new_rustfunc(list_remove)); + context.set_attr(&list_type, "pop", context.new_rustfunc(PyListRef::pop)); + context.set_attr(&list_type, "remove", context.new_rustfunc(PyListRef::remove)); } diff --git a/vm/src/obj/objsequence.rs b/vm/src/obj/objsequence.rs index f18f23e4d8..ad68206210 100644 --- a/vm/src/obj/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -9,7 +9,7 @@ use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResu use crate::vm::VirtualMachine; use super::objbool; -use super::objint::{self, PyInt}; +use super::objint::PyInt; use super::objlist::PyList; use super::objtuple::PyTuple; @@ -304,9 +304,7 @@ pub fn seq_le( Ok(seq_lt(vm, zelf, other)? || seq_equal(vm, zelf, other)?) } -pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec { - let counter = objint::get_value(&product).to_isize().unwrap(); - +pub fn seq_mul(elements: &[PyObjectRef], counter: isize) -> Vec { let current_len = elements.len(); let new_len = counter.max(0) as usize * current_len; let mut new_elements = Vec::with_capacity(new_len); diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index a9f140b53c..e2e80d8c81 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -1,9 +1,10 @@ use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; +use crate::function::PyRef; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + IdProtocol, OptionalArg, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, + PyResult, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -36,175 +37,179 @@ impl PyObjectPayload2 for PyTuple { } } -fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); +pub type PyTupleRef = PyRef; - let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_lt(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other))); - }; - - Ok(vm.ctx.new_bool(result)) -} - -fn tuple_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_gt(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other))); - }; - - Ok(vm.ctx.new_bool(result)) -} - -fn tuple_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); - - let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_ge(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other))); - }; +impl PyTupleRef { + fn lt(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_lt(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", self, other))) + } + } - Ok(vm.ctx.new_bool(result)) -} + fn gt(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_gt(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", self, other))) + } + } -fn tuple_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); + fn ge(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_ge(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", self, other))) + } + } - let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_le(vm, &zelf, &other)? - } else { - return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other))); - }; + fn le(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let zelf = self.elements.borrow(); + let other = get_elements(&other); + Ok(seq_le(vm, &zelf, &other)?) + } else { + Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", self, other))) + } + } - Ok(vm.ctx.new_bool(result)) -} + fn add(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let e1 = self.elements.borrow(); + let e2 = get_elements(&other); + let elements = e1.iter().chain(e2.iter()).cloned().collect(); + Ok(vm.ctx.new_tuple(elements)) + } else { + Err(vm.new_type_error(format!("Cannot add {} and {}", self, other))) + } + } -fn tuple_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); + fn count(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + let mut count: usize = 0; + for element in self.elements.borrow().iter() { + if element.is(&needle) { + count += 1; + } else { + let is_eq = vm._eq(element.clone(), needle.clone())?; + if objbool::boolval(vm, is_eq)? { + count += 1; + } + } + } + Ok(count) + } - if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let e1 = get_elements(zelf); - let e2 = get_elements(other); - let elements = e1.iter().chain(e2.iter()).cloned().collect(); - Ok(vm.ctx.new_tuple(elements)) - } else { - Err(vm.new_type_error(format!("Cannot add {} and {}", zelf, other))) + fn eq(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + if objtype::isinstance(&other, &vm.ctx.tuple_type()) { + let zelf = &self.elements.borrow(); + let other = get_elements(&other); + seq_equal(vm, &zelf, &other) + } else { + Ok(false) + } } -} -fn tuple_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (value, None)] - ); - let elements = get_elements(zelf); - let mut count: usize = 0; - for element in elements.iter() { - let is_eq = vm._eq(element.clone(), value.clone())?; - if objbool::boolval(vm, is_eq)? { - count += 1; + fn hash(self, vm: &mut VirtualMachine) -> PyResult { + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + for element in self.elements.borrow().iter() { + let element_hash = objint::get_value(&vm.call_method(element, "__hash__", vec![])?); + element_hash.hash(&mut hasher); } + Ok(hasher.finish()) } - Ok(vm.context().new_int(count)) -} -fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.tuple_type())), (other, None)] - ); + fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { + PyObject::new( + PyObjectPayload::Iterator { + position: Cell::new(0), + iterated_obj: self.into_object(), + }, + vm.ctx.iter_type(), + ) + } - let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) { - let zelf = get_elements(zelf); - let other = get_elements(other); - seq_equal(vm, &zelf, &other)? - } else { - false - }; - Ok(vm.ctx.new_bool(result)) -} + fn len(self, _vm: &mut VirtualMachine) -> usize { + self.elements.borrow().len() + } + + fn repr(self, vm: &mut VirtualMachine) -> PyResult { + let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) { + let mut str_parts = vec![]; + for elem in self.elements.borrow().iter() { + let s = vm.to_repr(elem)?; + str_parts.push(objstr::get_value(&s)); + } -fn tuple_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]); - let elements = get_elements(zelf); - let mut hasher = std::collections::hash_map::DefaultHasher::new(); - for element in elements.iter() { - let element_hash = objint::get_value(&vm.call_method(element, "__hash__", vec![])?); - element_hash.hash(&mut hasher); + if str_parts.len() == 1 { + format!("({},)", str_parts[0]) + } else { + format!("({})", str_parts.join(", ")) + } + } else { + "(...)".to_string() + }; + Ok(s) } - let hash = hasher.finish(); - Ok(vm.ctx.new_int(hash)) -} -fn tuple_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(tuple, Some(vm.ctx.tuple_type()))]); + fn mul(self, counter: isize, vm: &mut VirtualMachine) -> PyObjectRef { + let new_elements = seq_mul(&self.elements.borrow(), counter); + vm.ctx.new_tuple(new_elements) + } - let iter_obj = PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: tuple.clone(), - }, - vm.ctx.iter_type(), - ); + fn getitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + get_item( + vm, + self.as_object(), + &self.elements.borrow(), + needle.clone(), + ) + } - Ok(iter_obj) -} + fn index(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + for (index, element) in self.elements.borrow().iter().enumerate() { + if element.is(&needle) { + return Ok(index); + } + let is_eq = vm._eq(needle.clone(), element.clone())?; + if objbool::boolval(vm, is_eq)? { + return Ok(index); + } + } + Err(vm.new_value_error("tuple.index(x): x not in tuple".to_string())) + } -fn tuple_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]); - let elements = get_elements(zelf); - Ok(vm.context().new_int(elements.len())) + fn contains(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + for element in self.elements.borrow().iter() { + if element.is(&needle) { + return Ok(true); + } + let is_eq = vm._eq(needle.clone(), element.clone())?; + if objbool::boolval(vm, is_eq)? { + return Ok(true); + } + } + Ok(false) + } } -fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(cls, None)], - optional = [(iterable, None)] - ); - - if !objtype::issubclass(cls, &vm.ctx.tuple_type()) { +fn tuple_new( + cls: PyRef, + iterable: OptionalArg, + vm: &mut VirtualMachine, +) -> PyResult { + if !objtype::issubclass(cls.as_object(), &vm.ctx.tuple_type()) { return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls))); } - let elements = if let Some(iterable) = iterable { - vm.extract_elements(iterable)? + let elements = if let OptionalArg::Present(iterable) = iterable { + vm.extract_elements(&iterable)? } else { vec![] }; @@ -213,125 +218,32 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { PyObjectPayload::AnyRustValue { value: Box::new(PyTuple::from(elements)), }, - cls.clone(), + cls.into_object(), )) } -fn tuple_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(zelf, Some(vm.ctx.tuple_type()))]); - - let s = if let Some(_guard) = ReprGuard::enter(zelf) { - let elements = get_elements(zelf); - - let mut str_parts = vec![]; - for elem in elements.iter() { - let s = vm.to_repr(elem)?; - str_parts.push(objstr::get_value(&s)); - } - - if str_parts.len() == 1 { - format!("({},)", str_parts[0]) - } else { - format!("({})", str_parts.join(", ")) - } - } else { - "(...)".to_string() - }; - Ok(vm.new_str(s)) -} - -fn tuple_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (zelf, Some(vm.ctx.tuple_type())), - (product, Some(vm.ctx.int_type())) - ] - ); - - let new_elements = seq_mul(&get_elements(zelf), product); - - Ok(vm.ctx.new_tuple(new_elements)) -} - -fn tuple_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(tuple, Some(vm.ctx.tuple_type())), (needle, None)] - ); - get_item(vm, tuple, &get_elements(&tuple), needle.clone()) -} - -pub fn tuple_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(tuple, Some(vm.ctx.tuple_type())), (needle, None)] - ); - for (index, element) in get_elements(tuple).iter().enumerate() { - let py_equal = vm._eq(needle.clone(), element.clone())?; - if objbool::get_value(&py_equal) { - return Ok(vm.context().new_int(index)); - } - } - Err(vm.new_value_error("tuple.index(x): x not in tuple".to_string())) -} - -pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(tuple, Some(vm.ctx.tuple_type())), (needle, None)] - ); - for element in get_elements(tuple).iter() { - match vm._eq(needle.clone(), element.clone()) { - Ok(value) => { - if objbool::get_value(&value) { - return Ok(vm.new_bool(true)); - } - } - Err(_) => return Err(vm.new_type_error("".to_string())), - } - } - - Ok(vm.new_bool(false)) -} - +#[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { let tuple_type = &context.tuple_type; let tuple_doc = "tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items If the argument is a tuple, the return value is the same object."; - context.set_attr(&tuple_type, "__add__", context.new_rustfunc(tuple_add)); - context.set_attr(&tuple_type, "__eq__", context.new_rustfunc(tuple_eq)); - context.set_attr( - &tuple_type, - "__contains__", - context.new_rustfunc(tuple_contains), - ); - context.set_attr( - &tuple_type, - "__getitem__", - context.new_rustfunc(tuple_getitem), - ); - context.set_attr(&tuple_type, "__hash__", context.new_rustfunc(tuple_hash)); - context.set_attr(&tuple_type, "__iter__", context.new_rustfunc(tuple_iter)); - context.set_attr(&tuple_type, "__len__", context.new_rustfunc(tuple_len)); + context.set_attr(&tuple_type, "__add__", context.new_rustfunc(PyTupleRef::add)); + context.set_attr(&tuple_type, "__eq__", context.new_rustfunc(PyTupleRef::eq)); + context.set_attr(&tuple_type,"__contains__",context.new_rustfunc(PyTupleRef::contains)); + context.set_attr(&tuple_type,"__getitem__",context.new_rustfunc(PyTupleRef::getitem)); + context.set_attr(&tuple_type, "__hash__", context.new_rustfunc(PyTupleRef::hash)); + context.set_attr(&tuple_type, "__iter__", context.new_rustfunc(PyTupleRef::iter)); + context.set_attr(&tuple_type, "__len__", context.new_rustfunc(PyTupleRef::len)); context.set_attr(&tuple_type, "__new__", context.new_rustfunc(tuple_new)); - context.set_attr(&tuple_type, "__mul__", context.new_rustfunc(tuple_mul)); - context.set_attr(&tuple_type, "__repr__", context.new_rustfunc(tuple_repr)); - context.set_attr(&tuple_type, "count", context.new_rustfunc(tuple_count)); - context.set_attr(&tuple_type, "__lt__", context.new_rustfunc(tuple_lt)); - context.set_attr(&tuple_type, "__le__", context.new_rustfunc(tuple_le)); - context.set_attr(&tuple_type, "__gt__", context.new_rustfunc(tuple_gt)); - context.set_attr(&tuple_type, "__ge__", context.new_rustfunc(tuple_ge)); - context.set_attr( - &tuple_type, - "__doc__", - context.new_str(tuple_doc.to_string()), - ); - context.set_attr(&tuple_type, "index", context.new_rustfunc(tuple_index)); + context.set_attr(&tuple_type, "__mul__", context.new_rustfunc(PyTupleRef::mul)); + context.set_attr(&tuple_type, "__repr__", context.new_rustfunc(PyTupleRef::repr)); + context.set_attr(&tuple_type, "count", context.new_rustfunc(PyTupleRef::count)); + context.set_attr(&tuple_type, "__lt__", context.new_rustfunc(PyTupleRef::lt)); + context.set_attr(&tuple_type, "__le__", context.new_rustfunc(PyTupleRef::le)); + context.set_attr(&tuple_type, "__gt__", context.new_rustfunc(PyTupleRef::gt)); + context.set_attr(&tuple_type, "__ge__", context.new_rustfunc(PyTupleRef::ge)); + context.set_attr(&tuple_type,"__doc__",context.new_str(tuple_doc.to_string())); + context.set_attr(&tuple_type, "index", context.new_rustfunc(PyTupleRef::index)); }