From da6c56a001a83f85a0184d635166638b476bce17 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Fri, 15 Mar 2019 12:27:55 +0000 Subject: [PATCH 1/4] Use extend_class in declaration of dictionary. --- vm/src/obj/objdict.rs | 45 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 3b37a801b..fa136d555 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -371,34 +371,19 @@ fn dict_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn init(context: &PyContext) { - let dict_type = &context.dict_type; - context.set_attr(&dict_type, "__len__", context.new_rustfunc(dict_len)); - context.set_attr( - &dict_type, - "__contains__", - context.new_rustfunc(dict_contains), - ); - context.set_attr( - &dict_type, - "__delitem__", - context.new_rustfunc(dict_delitem), - ); - context.set_attr( - &dict_type, - "__getitem__", - context.new_rustfunc(dict_getitem), - ); - context.set_attr(&dict_type, "__iter__", context.new_rustfunc(dict_iter)); - context.set_attr(&dict_type, "__new__", context.new_rustfunc(dict_new)); - context.set_attr(&dict_type, "__repr__", context.new_rustfunc(dict_repr)); - context.set_attr( - &dict_type, - "__setitem__", - context.new_rustfunc(dict_setitem), - ); - context.set_attr(&dict_type, "clear", context.new_rustfunc(dict_clear)); - context.set_attr(&dict_type, "values", context.new_rustfunc(dict_values)); - context.set_attr(&dict_type, "items", context.new_rustfunc(dict_items)); - context.set_attr(&dict_type, "keys", context.new_rustfunc(dict_iter)); - context.set_attr(&dict_type, "get", context.new_rustfunc(dict_get)); + extend_class!(context, &context.dict_type, { + "__len__" => context.new_rustfunc(dict_len), + "__contains__" => context.new_rustfunc(dict_contains), + "__delitem__" => context.new_rustfunc(dict_delitem), + "__getitem__" => context.new_rustfunc(dict_getitem), + "__iter__" => context.new_rustfunc(dict_iter), + "__new__" => context.new_rustfunc(dict_new), + "__repr__" => context.new_rustfunc(dict_repr), + "__setitem__" => context.new_rustfunc(dict_setitem), + "clear" => context.new_rustfunc(dict_clear), + "values" => context.new_rustfunc(dict_values), + "items" => context.new_rustfunc(dict_items), + "keys" => context.new_rustfunc(dict_iter), + "get" => context.new_rustfunc(dict_get), + }); } From a718a5a72303b7b42f9d8caeceffda264cc6269d Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Fri, 15 Mar 2019 13:21:35 +0000 Subject: [PATCH 2/4] Refactor dict methods to new style declarations. --- vm/src/obj/objdict.rs | 292 ++++++++++++++++-------------------------- 1 file changed, 111 insertions(+), 181 deletions(-) diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index fa136d555..63131fef9 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -4,8 +4,8 @@ use std::fmt; use std::ops::{Deref, DerefMut}; use crate::pyobject::{ - PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, - PyValue, TypeProtocol, + OptionalArg, PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObjectRef, PyRef, + PyResult, PyValue, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -133,7 +133,6 @@ pub fn attributes_to_py_dict(vm: &mut VirtualMachine, attributes: PyAttributes) } // Python dict methods: - fn dict_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -174,216 +173,147 @@ fn dict_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(dict) } -fn dict_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict_obj, Some(vm.ctx.dict_type()))]); - let elements = get_elements(dict_obj); - Ok(vm.ctx.new_int(elements.len())) -} +impl PyDictRef { + fn len(self, _vm: &mut VirtualMachine) -> usize { + self.entries.borrow().len() + } -fn dict_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict_obj, Some(vm.ctx.dict_type()))]); + fn repr(self, vm: &mut VirtualMachine) -> PyResult { + let s = if let Some(_guard) = ReprGuard::enter(self.as_object()) { + let elements = get_key_value_pairs(self.as_object()); + let mut str_parts = vec![]; + for (key, value) in elements { + let key_repr = vm.to_repr(&key)?; + let value_repr = vm.to_repr(&value)?; + let key_str = objstr::get_value(&key_repr); + let value_str = objstr::get_value(&value_repr); + str_parts.push(format!("{}: {}", key_str, value_str)); + } - let s = if let Some(_guard) = ReprGuard::enter(dict_obj) { - let elements = get_key_value_pairs(dict_obj); - let mut str_parts = vec![]; - for (key, value) in elements { - let key_repr = vm.to_repr(&key)?; - let value_repr = vm.to_repr(&value)?; - let key_str = objstr::get_value(&key_repr); - let value_str = objstr::get_value(&value_repr); - str_parts.push(format!("{}: {}", key_str, value_str)); - } + format!("{{{}}}", str_parts.join(", ")) + } else { + "{...}".to_string() + }; + Ok(vm.new_str(s)) + } - format!("{{{}}}", str_parts.join(", ")) - } else { - "{...}".to_string() - }; - Ok(vm.new_str(s)) -} + fn contains(self, needle: PyObjectRef, _vm: &mut VirtualMachine) -> bool { + let needle = objstr::get_value(&needle); + self.entries.borrow().contains_key(&needle) + } -pub fn dict_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (dict, Some(vm.ctx.dict_type())), - (needle, Some(vm.ctx.str_type())) - ] - ); - - let needle = objstr::get_value(&needle); - for element in get_elements(dict).iter() { - if &needle == element.0 { - return Ok(vm.new_bool(true)); + fn delitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult<()> { + let needle = objstr::get_value(&needle); + // Delete the item: + let mut elements = self.entries.borrow_mut(); + match elements.remove(&needle) { + Some(_) => Ok(()), + None => Err(vm.new_value_error(format!("Key not found: {}", needle))), } } - Ok(vm.new_bool(false)) -} - -fn dict_delitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (dict, Some(vm.ctx.dict_type())), - (needle, Some(vm.ctx.str_type())) - ] - ); - - // What we are looking for: - let needle = objstr::get_value(&needle); - - // Delete the item: - let mut elements = get_mut_elements(dict); - match elements.remove(&needle) { - Some(_) => Ok(vm.get_none()), - None => Err(vm.new_value_error(format!("Key not found: {}", needle))), + fn clear(self, _vm: &mut VirtualMachine) { + self.entries.borrow_mut().clear() } -} -fn dict_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]); - get_mut_elements(dict).clear(); - Ok(vm.get_none()) -} + /// When iterating over a dictionary, we iterate over the keys of it. + fn iter(self, vm: &mut VirtualMachine) -> PyIteratorValue { + let keys = self + .entries + .borrow() + .values() + .map(|(k, _v)| k.clone()) + .collect(); + let key_list = vm.ctx.new_list(keys); -/// When iterating over a dictionary, we iterate over the keys of it. -fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]); - - let keys = get_elements(dict) - .values() - .map(|(k, _v)| k.clone()) - .collect(); - let key_list = vm.ctx.new_list(keys); - - let iter_obj = PyObject::new( PyIteratorValue { position: Cell::new(0), iterated_obj: key_list, - }, - vm.ctx.iter_type(), - ); + } + } - Ok(iter_obj) -} + fn values(self, vm: &mut VirtualMachine) -> PyIteratorValue { + let values = self + .entries + .borrow() + .values() + .map(|(_k, v)| v.clone()) + .collect(); + let values_list = vm.ctx.new_list(values); -fn dict_values(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]); - - let values = get_elements(dict) - .values() - .map(|(_k, v)| v.clone()) - .collect(); - let values_list = vm.ctx.new_list(values); - - let iter_obj = PyObject::new( PyIteratorValue { position: Cell::new(0), iterated_obj: values_list, - }, - vm.ctx.iter_type(), - ); + } + } - Ok(iter_obj) -} + fn items(self, vm: &mut VirtualMachine) -> PyIteratorValue { + let items = self + .entries + .borrow() + .values() + .map(|(k, v)| vm.ctx.new_tuple(vec![k.clone(), v.clone()])) + .collect(); + let items_list = vm.ctx.new_list(items); -fn dict_items(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]); - - let items = get_elements(dict) - .values() - .map(|(k, v)| vm.ctx.new_tuple(vec![k.clone(), v.clone()])) - .collect(); - let items_list = vm.ctx.new_list(items); - - let iter_obj = PyObject::new( PyIteratorValue { position: Cell::new(0), iterated_obj: items_list, - }, - vm.ctx.iter_type(), - ); - - Ok(iter_obj) -} - -fn dict_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (dict, Some(vm.ctx.dict_type())), - (needle, Some(vm.ctx.str_type())), - (value, None) - ] - ); - - set_item(dict, vm, needle, value); - - Ok(vm.get_none()) -} - -fn dict_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (dict, Some(vm.ctx.dict_type())), - (needle, Some(vm.ctx.str_type())) - ] - ); - - // What we are looking for: - let needle = objstr::get_value(&needle); - - let elements = get_elements(dict); - if elements.contains_key(&needle) { - Ok(elements[&needle].1.clone()) - } else { - Err(vm.new_value_error(format!("Key not found: {}", needle))) + } } -} -fn dict_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (dict, Some(vm.ctx.dict_type())), - (key, Some(vm.ctx.str_type())) - ], - optional = [(default, None)] - ); + fn setitem(self, needle: PyObjectRef, value: PyObjectRef, _vm: &mut VirtualMachine) { + let mut elements = self.entries.borrow_mut(); + set_item_in_content(&mut elements, &needle, &value) + } - // What we are looking for: - let key = objstr::get_value(&key); + fn getitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + // What we are looking for: + let needle = objstr::get_value(&needle); - let elements = get_elements(dict); - if elements.contains_key(&key) { - Ok(elements[&key].1.clone()) - } else if let Some(value) = default { - Ok(value.clone()) - } else { - Ok(vm.get_none()) + let elements = self.entries.borrow(); + if elements.contains_key(&needle) { + Ok(elements[&needle].1.clone()) + } else { + Err(vm.new_value_error(format!("Key not found: {}", needle))) + } + } + + fn get( + self, + key: PyObjectRef, + default: OptionalArg, + vm: &mut VirtualMachine, + ) -> PyObjectRef { + // What we are looking for: + let key = objstr::get_value(&key); + + let elements = self.entries.borrow(); + if elements.contains_key(&key) { + elements[&key].1.clone() + } else { + match default { + OptionalArg::Present(value) => value, + OptionalArg::Missing => vm.ctx.none(), + } + } } } pub fn init(context: &PyContext) { extend_class!(context, &context.dict_type, { - "__len__" => context.new_rustfunc(dict_len), - "__contains__" => context.new_rustfunc(dict_contains), - "__delitem__" => context.new_rustfunc(dict_delitem), - "__getitem__" => context.new_rustfunc(dict_getitem), - "__iter__" => context.new_rustfunc(dict_iter), + "__len__" => context.new_rustfunc(PyDictRef::len), + "__contains__" => context.new_rustfunc(PyDictRef::contains), + "__delitem__" => context.new_rustfunc(PyDictRef::delitem), + "__getitem__" => context.new_rustfunc(PyDictRef::getitem), + "__iter__" => context.new_rustfunc(PyDictRef::iter), "__new__" => context.new_rustfunc(dict_new), - "__repr__" => context.new_rustfunc(dict_repr), - "__setitem__" => context.new_rustfunc(dict_setitem), - "clear" => context.new_rustfunc(dict_clear), - "values" => context.new_rustfunc(dict_values), - "items" => context.new_rustfunc(dict_items), - "keys" => context.new_rustfunc(dict_iter), - "get" => context.new_rustfunc(dict_get), + "__repr__" => context.new_rustfunc(PyDictRef::repr), + "__setitem__" => context.new_rustfunc(PyDictRef::setitem), + "clear" => context.new_rustfunc(PyDictRef::clear), + "values" => context.new_rustfunc(PyDictRef::values), + "items" => context.new_rustfunc(PyDictRef::items), + "keys" => context.new_rustfunc(PyDictRef::iter), + "get" => context.new_rustfunc(PyDictRef::get), }); } From 2f5c3ef1dfabdb9970f358914038ca178c0b43b7 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Fri, 15 Mar 2019 14:01:36 +0000 Subject: [PATCH 3/4] Use PyStringRef to check type of dictionary keys. --- vm/src/obj/objdict.rs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 63131fef9..17b1674c0 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -10,7 +10,7 @@ use crate::pyobject::{ use crate::vm::{ReprGuard, VirtualMachine}; use super::objiter; -use super::objstr; +use super::objstr::{self, PyStringRef}; use super::objtype; pub type DictContentType = HashMap; @@ -197,18 +197,17 @@ impl PyDictRef { Ok(vm.new_str(s)) } - fn contains(self, needle: PyObjectRef, _vm: &mut VirtualMachine) -> bool { - let needle = objstr::get_value(&needle); - self.entries.borrow().contains_key(&needle) + fn contains(self, key: PyStringRef, _vm: &mut VirtualMachine) -> bool { + self.entries.borrow().contains_key(&key.value) } - fn delitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult<()> { - let needle = objstr::get_value(&needle); + fn delitem(self, key: PyStringRef, vm: &mut VirtualMachine) -> PyResult<()> { + let ref key = key.value; // Delete the item: let mut elements = self.entries.borrow_mut(); - match elements.remove(&needle) { + match elements.remove(key) { Some(_) => Ok(()), - None => Err(vm.new_value_error(format!("Key not found: {}", needle))), + None => Err(vm.new_value_error(format!("Key not found: {}", key))), } } @@ -267,30 +266,30 @@ impl PyDictRef { set_item_in_content(&mut elements, &needle, &value) } - fn getitem(self, needle: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { - // What we are looking for: - let needle = objstr::get_value(&needle); + fn getitem(self, key: PyStringRef, vm: &mut VirtualMachine) -> PyResult { + let ref key = key.value; + // What we are looking for: let elements = self.entries.borrow(); - if elements.contains_key(&needle) { - Ok(elements[&needle].1.clone()) + if elements.contains_key(key) { + Ok(elements[key].1.clone()) } else { - Err(vm.new_value_error(format!("Key not found: {}", needle))) + Err(vm.new_value_error(format!("Key not found: {}", key))) } } fn get( self, - key: PyObjectRef, + key: PyStringRef, default: OptionalArg, vm: &mut VirtualMachine, ) -> PyObjectRef { // What we are looking for: - let key = objstr::get_value(&key); + let ref key = key.value; let elements = self.entries.borrow(); - if elements.contains_key(&key) { - elements[&key].1.clone() + if elements.contains_key(key) { + elements[key].1.clone() } else { match default { OptionalArg::Present(value) => value, From 9eeeeeae48b3b083c99846ef1c35953cbaeb4419 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Fri, 15 Mar 2019 16:53:30 +0000 Subject: [PATCH 4/4] Change return type of vm.to_repr and vm.to_str to PyStringRef. --- vm/src/builtins.rs | 10 ++++------ vm/src/exceptions.rs | 9 ++++----- vm/src/frame.rs | 6 +++--- vm/src/obj/objdict.rs | 4 +--- vm/src/obj/objlist.rs | 7 +++---- vm/src/obj/objobject.rs | 20 ++++++++------------ vm/src/obj/objset.rs | 5 ++--- vm/src/obj/objstr.rs | 2 +- vm/src/obj/objtuple.rs | 3 +-- vm/src/vm.rs | 16 +++++++++------- wasm/lib/src/browser_module.rs | 6 +++--- 11 files changed, 39 insertions(+), 49 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 86f6e8472..d3084e57a 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -13,7 +13,7 @@ use crate::obj::objbool; use crate::obj::objdict; use crate::obj::objint; use crate::obj::objiter; -use crate::obj::objstr; +use crate::obj::objstr::{self, PyStringRef}; use crate::obj::objtype; use crate::frame::Scope; @@ -625,8 +625,7 @@ pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else { write!(stdout_lock, " ").unwrap(); } - let v = vm.to_str(&a)?; - let s = objstr::borrow_value(&v); + let ref s = vm.to_str(&a)?.value; write!(stdout_lock, "{}", s).unwrap(); } @@ -643,9 +642,8 @@ pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.get_none()) } -fn builtin_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(obj, None)]); - vm.to_repr(obj) +fn builtin_repr(obj: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + vm.to_repr(&obj) } fn builtin_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 94853d5d0..0f3553535 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -1,5 +1,4 @@ use crate::obj::objsequence; -use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, @@ -30,19 +29,19 @@ pub fn print_exception(vm: &mut VirtualMachine, exc: &PyObjectRef) { if objtype::isinstance(&element, &vm.ctx.tuple_type()) { let element = objsequence::get_elements(&element); let filename = if let Ok(x) = vm.to_str(&element[0]) { - objstr::get_value(&x) + x.value.clone() } else { "".to_string() }; let lineno = if let Ok(x) = vm.to_str(&element[1]) { - objstr::get_value(&x) + x.value.clone() } else { "".to_string() }; let obj_name = if let Ok(x) = vm.to_str(&element[2]) { - objstr::get_value(&x) + x.value.clone() } else { "".to_string() }; @@ -58,7 +57,7 @@ pub fn print_exception(vm: &mut VirtualMachine, exc: &PyObjectRef) { } match vm.to_str(exc) { - Ok(txt) => println!("{}", objstr::get_value(&txt)), + Ok(txt) => println!("{}", txt.value), Err(err) => println!("Error during error {:?}", err), } } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index d1cadb001..3fedd8d3c 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -693,7 +693,7 @@ impl Frame { let repr = vm.to_repr(&expr)?; // TODO: implement sys.displayhook if let Some(print) = vm.ctx.get_attr(&vm.builtins, "print") { - vm.invoke(print, vec![repr])?; + vm.invoke(print, vec![repr.into_object()])?; } } Ok(None) @@ -764,8 +764,8 @@ impl Frame { bytecode::Instruction::FormatValue { conversion, spec } => { use ast::ConversionFlag::*; let value = match conversion { - Some(Str) => vm.to_str(&self.pop_value())?, - Some(Repr) => vm.to_repr(&self.pop_value())?, + Some(Str) => vm.to_str(&self.pop_value())?.into_object(), + Some(Repr) => vm.to_repr(&self.pop_value())?.into_object(), Some(Ascii) => self.pop_value(), // TODO None => self.pop_value(), }; diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 17b1674c0..5503ceb56 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -185,9 +185,7 @@ impl PyDictRef { for (key, value) in elements { let key_repr = vm.to_repr(&key)?; let value_repr = vm.to_repr(&value)?; - let key_str = objstr::get_value(&key_repr); - let value_str = objstr::get_value(&value_repr); - str_parts.push(format!("{}: {}", key_str, value_str)); + str_parts.push(format!("{}: {}", key_repr.value, value_repr.value)); } format!("{{{}}}", str_parts.join(", ")) diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index f0baedb1b..8bf8337c5 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -6,7 +6,6 @@ use super::objsequence::{ 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::pyobject::{ IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, @@ -151,7 +150,7 @@ impl PyListRef { 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)); + str_parts.push(s.value.clone()); } format!("[{}]", str_parts.join(", ")) } else { @@ -204,7 +203,7 @@ impl PyListRef { return Ok(index); } } - let needle_str = objstr::get_value(&vm.to_str(&needle).unwrap()); + let ref needle_str = vm.to_str(&needle)?.value; Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) } @@ -241,7 +240,7 @@ impl PyListRef { self.elements.borrow_mut().remove(index); Ok(()) } else { - let needle_str = objstr::get_value(&vm.to_str(&needle)?); + let ref needle_str = vm.to_str(&needle)?.value; Err(vm.new_value_error(format!("'{}' is not in list", needle_str))) } } diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 2423f5e93..43166ceb1 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -1,5 +1,5 @@ use super::objlist::PyList; -use super::objstr; +use super::objstr::{self, PyStringRef}; use super::objtype; use crate::obj::objproperty::PropertyBuilder; use crate::pyobject::{ @@ -134,17 +134,13 @@ pub fn object_dir(obj: PyObjectRef, vm: &mut VirtualMachine) -> PyList { PyList::from(attributes) } -fn object_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [ - (obj, Some(vm.ctx.object())), - (format_spec, Some(vm.ctx.str_type())) - ] - ); - if objstr::get_value(format_spec).is_empty() { - vm.to_str(obj) +fn object_format( + obj: PyObjectRef, + format_spec: PyStringRef, + vm: &mut VirtualMachine, +) -> PyResult { + if format_spec.value.is_empty() { + vm.to_str(&obj) } else { Err(vm.new_type_error("unsupported format string passed to object.__format__".to_string())) } diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index f33208915..721712ad4 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -10,7 +10,6 @@ use std::hash::{Hash, Hasher}; use super::objbool; use super::objint; use super::objiter; -use super::objstr; use super::objtype; use crate::pyobject::{ PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, @@ -211,7 +210,7 @@ fn set_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let mut str_parts = vec![]; for elem in elements.values() { let part = vm.to_repr(elem)?; - str_parts.push(objstr::get_value(&part)); + str_parts.push(part.value.clone()); } format!("{{{}}}", str_parts.join(", ")) @@ -582,7 +581,7 @@ fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let mut str_parts = vec![]; for elem in elements.values() { let part = vm.to_repr(elem)?; - str_parts.push(objstr::get_value(&part)); + str_parts.push(part.value.clone()); } format!("frozenset({{{}}})", str_parts.join(", ")) diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 0a969b686..8345137f0 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -794,7 +794,7 @@ fn str_new( vm: &mut VirtualMachine, ) -> PyResult { let string = match object { - OptionalArg::Present(ref input) => vm.to_str(input)?, + OptionalArg::Present(ref input) => vm.to_str(input)?.into_object(), OptionalArg::Missing => vm.new_str("".to_string()), }; if string.typ().is(&cls) { diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 1702c2237..75aca6186 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -13,7 +13,6 @@ use super::objint; use super::objsequence::{ get_elements, get_item, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul, }; -use super::objstr; use super::objtype; #[derive(Default)] @@ -152,7 +151,7 @@ impl PyTupleRef { 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)); + str_parts.push(s.value.clone()); } if str_parts.len() == 1 { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 45b5d7d3d..9eaf1fc3e 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -23,12 +23,12 @@ use crate::obj::objgenerator; use crate::obj::objiter; use crate::obj::objlist::PyList; use crate::obj::objsequence; -use crate::obj::objstr; +use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTuple; use crate::obj::objtype; use crate::pyobject::{ AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, - TypeProtocol, + TryFromObject, TypeProtocol, }; use crate::stdlib; use crate::sysmodule; @@ -228,17 +228,19 @@ impl VirtualMachine { } // Container of the virtual machine state: - pub fn to_str(&mut self, obj: &PyObjectRef) -> PyResult { - self.call_method(&obj, "__str__", vec![]) + pub fn to_str(&mut self, obj: &PyObjectRef) -> PyResult { + let str = self.call_method(&obj, "__str__", vec![])?; + TryFromObject::try_from_object(self, str) } pub fn to_pystr(&mut self, obj: &PyObjectRef) -> Result { let py_str_obj = self.to_str(obj)?; - Ok(objstr::get_value(&py_str_obj)) + Ok(py_str_obj.value.clone()) } - pub fn to_repr(&mut self, obj: &PyObjectRef) -> PyResult { - self.call_method(obj, "__repr__", vec![]) + pub fn to_repr(&mut self, obj: &PyObjectRef) -> PyResult { + let repr = self.call_method(obj, "__repr__", vec![])?; + TryFromObject::try_from_object(self, repr) } pub fn import(&mut self, module: &str) -> PyResult { diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index 11ea35ea2..ed8da51fb 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -70,9 +70,9 @@ fn browser_fetch(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if let Some(headers) = headers { let h = request.headers(); for (key, value) in rustpython_vm::obj::objdict::get_key_value_pairs(&headers) { - let key = objstr::get_value(&vm.to_str(&key)?); - let value = objstr::get_value(&vm.to_str(&value)?); - h.set(&key, &value) + let ref key = vm.to_str(&key)?.value; + let ref value = vm.to_str(&value)?.value; + h.set(key, value) .map_err(|err| convert::js_py_typeerror(vm, err))?; } }