From f10fa6db44c8df2876ee3aaed18f421cdbf50a2c Mon Sep 17 00:00:00 2001 From: Joey Hain Date: Mon, 25 Feb 2019 19:01:01 -0800 Subject: [PATCH] Remove outer RefCell from PyObjectRef --- vm/src/frame.rs | 24 ++++----- vm/src/obj/objbool.rs | 10 ++-- vm/src/obj/objbytearray.rs | 26 ++++----- vm/src/obj/objbytes.rs | 65 +++++++++-------------- vm/src/obj/objcode.rs | 2 +- vm/src/obj/objcomplex.rs | 6 +-- vm/src/obj/objdict.rs | 44 ++++++++-------- vm/src/obj/objenumerate.rs | 19 ++++--- vm/src/obj/objfilter.rs | 6 +-- vm/src/obj/objfloat.rs | 6 +-- vm/src/obj/objframe.rs | 3 +- vm/src/obj/objfunction.rs | 2 +- vm/src/obj/objgenerator.rs | 21 ++++---- vm/src/obj/objint.rs | 2 +- vm/src/obj/objiter.rs | 23 ++++---- vm/src/obj/objlist.rs | 32 ++++------- vm/src/obj/objmap.rs | 6 +-- vm/src/obj/objobject.rs | 26 +++++---- vm/src/obj/objrange.rs | 4 +- vm/src/obj/objsequence.rs | 43 +++++++-------- vm/src/obj/objset.rs | 105 ++++++++++++++++++------------------- vm/src/obj/objslice.rs | 6 +-- vm/src/obj/objstr.rs | 42 ++++++--------- vm/src/obj/objtuple.rs | 40 +++++--------- vm/src/obj/objtype.rs | 26 +++++---- vm/src/obj/objzip.rs | 2 +- vm/src/pyobject.rs | 95 ++++++++++++++++++--------------- vm/src/stdlib/io.rs | 18 ++++--- vm/src/stdlib/json.rs | 4 +- vm/src/stdlib/socket.rs | 79 ++++++++++++---------------- vm/src/stdlib/weakref.rs | 2 +- vm/src/sysmodule.rs | 2 +- vm/src/vm.rs | 14 ++--- 33 files changed, 380 insertions(+), 425 deletions(-) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index f97be6894..6ef7e9863 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -281,7 +281,7 @@ impl Frame { let mut out: Vec> = elements .into_iter() - .map(|x| match x.borrow().payload { + .map(|x| match x.payload { PyObjectPayload::Integer { ref value } => Some(value.clone()), PyObjectPayload::None => None, _ => panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x), @@ -531,7 +531,7 @@ impl Frame { } else { let msg = format!( "Can only raise BaseException derived types, not {}", - exception.borrow() + exception ); let type_error_type = vm.ctx.exceptions.type_error.clone(); let type_error = vm.new_exception(type_error_type, msg); @@ -564,7 +564,7 @@ impl Frame { } bytecode::Instruction::PrintExpr => { let expr = self.pop_value(); - match expr.borrow().payload { + match expr.payload { PyObjectPayload::None => (), _ => { let repr = vm.to_repr(&expr)?; @@ -591,9 +591,9 @@ impl Frame { } bytecode::Instruction::StoreLocals => { let locals = self.pop_value(); - match self.locals.borrow_mut().payload { - PyObjectPayload::Scope { ref mut scope } => { - scope.locals = locals; + match self.locals.payload { + PyObjectPayload::Scope { ref scope } => { + //scope.locals = locals; // FIXME } _ => panic!("We really expect our scope to be a scope!"), } @@ -854,7 +854,7 @@ impl Frame { } fn delete_name(&mut self, vm: &mut VirtualMachine, name: &str) -> FrameResult { - let locals = match self.locals.borrow().payload { + let locals = match self.locals.payload { PyObjectPayload::Scope { ref scope } => scope.locals.clone(), _ => panic!("We really expect our scope to be a scope!"), }; @@ -1127,7 +1127,7 @@ impl fmt::Debug for Frame { let stack_str = self .stack .iter() - .map(|elem| format!("\n > {:?}", elem.borrow())) + .map(|elem| format!("\n > {:?}", elem)) .collect::>() .join(""); let block_str = self @@ -1136,12 +1136,12 @@ impl fmt::Debug for Frame { .map(|elem| format!("\n > {:?}", elem)) .collect::>() .join(""); - let local_str = match self.locals.borrow().payload { - PyObjectPayload::Scope { ref scope } => match scope.locals.borrow().payload { + let local_str = match self.locals.payload { + PyObjectPayload::Scope { ref scope } => match scope.locals.payload { PyObjectPayload::Dict { ref elements } => { - objdict::get_key_value_pairs_from_content(elements) + objdict::get_key_value_pairs_from_content(&elements.borrow()) .iter() - .map(|elem| format!("\n {:?} = {:?}", elem.0.borrow(), elem.1.borrow())) + .map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1)) .collect::>() .join("") } diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 41681a476..cf16e1f5f 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -12,17 +12,17 @@ impl IntoPyObject for bool { } pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result { - let result = match obj.borrow().payload { + let result = match obj.payload { PyObjectPayload::Integer { ref value } => !value.is_zero(), PyObjectPayload::Float { value } => value != 0.0, - PyObjectPayload::Sequence { ref elements } => !elements.is_empty(), - PyObjectPayload::Dict { ref elements } => !elements.is_empty(), + PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(), + PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(), PyObjectPayload::String { ref value } => !value.is_empty(), PyObjectPayload::None { .. } => false, _ => { if let Ok(f) = vm.get_method(obj.clone(), "__bool__") { let bool_res = vm.invoke(f, PyFuncArgs::default())?; - let v = match bool_res.borrow().payload { + let v = match bool_res.payload { PyObjectPayload::Integer { ref value } => !value.is_zero(), _ => return Err(vm.new_type_error(String::from("TypeError"))), }; @@ -60,7 +60,7 @@ pub fn not(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult { // Retrieve inner int value: pub fn get_value(obj: &PyObjectRef) -> bool { - if let PyObjectPayload::Integer { value } = &obj.borrow().payload { + if let PyObjectPayload::Integer { value } = &obj.payload { !value.is_zero() } else { panic!("Inner error getting inner boolean"); diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index d98b80e74..0cabf23fd 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -1,5 +1,7 @@ //! Implementation of the python bytearray object. +use std::cell::RefCell; + use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol}; use super::objint; @@ -140,7 +142,12 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else { vec![] }; - Ok(PyObject::new(PyObjectPayload::Bytes { value }, cls.clone())) + Ok(PyObject::new( + PyObjectPayload::Bytes { + value: RefCell::new(value), + }, + cls.clone(), + )) } fn bytesarray_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -283,10 +290,9 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytearray_type()))]); - let mut mut_obj = zelf.borrow_mut(); - match mut_obj.payload { - PyObjectPayload::Bytes { ref mut value } => { - value.clear(); + match zelf.payload { + PyObjectPayload::Bytes { ref value } => { + value.borrow_mut().clear(); Ok(vm.get_none()) } _ => panic!("Bytearray has incorrect payload."), @@ -307,17 +313,11 @@ fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn bytearray_lower(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]); let value = get_value(obj).to_vec().to_ascii_lowercase(); - Ok(PyObject::new( - PyObjectPayload::Bytes { value }, - vm.ctx.bytearray_type(), - )) + Ok(vm.ctx.new_bytearray(value)) } fn bytearray_upper(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]); let value = get_value(obj).to_vec().to_ascii_uppercase(); - Ok(PyObject::new( - PyObjectPayload::Bytes { value }, - vm.ctx.bytearray_type(), - )) + Ok(vm.ctx.new_bytearray(value)) } diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index f63a9c80d..b4b489854 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -1,3 +1,8 @@ +use std::cell::RefCell; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; +use std::ops::DerefMut; + use super::objint; use super::objtype; use crate::pyobject::{ @@ -5,11 +10,6 @@ use crate::pyobject::{ }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; -use std::cell::Ref; -use std::cell::RefMut; -use std::hash::{Hash, Hasher}; -use std::ops::Deref; -use std::ops::DerefMut; // Binary data support @@ -70,7 +70,12 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { vec![] }; - Ok(PyObject::new(PyObjectPayload::Bytes { value }, cls.clone())) + Ok(PyObject::new( + PyObjectPayload::Bytes { + value: RefCell::new(value), + }, + cls.clone(), + )) } fn bytes_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -98,11 +103,7 @@ fn bytes_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) { get_value(a).to_vec() >= get_value(b).to_vec() } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>'", - a.borrow(), - b.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", a, b))); }; Ok(vm.ctx.new_bool(result)) } @@ -117,11 +118,7 @@ fn bytes_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) { get_value(a).to_vec() > get_value(b).to_vec() } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>='", - a.borrow(), - b.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", a, b))); }; Ok(vm.ctx.new_bool(result)) } @@ -136,11 +133,7 @@ fn bytes_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) { get_value(a).to_vec() <= get_value(b).to_vec() } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<'", - a.borrow(), - b.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", a, b))); }; Ok(vm.ctx.new_bool(result)) } @@ -155,11 +148,7 @@ fn bytes_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) { get_value(a).to_vec() < get_value(b).to_vec() } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<='", - a.borrow(), - b.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", a, b))); }; Ok(vm.ctx.new_bool(result)) } @@ -181,23 +170,19 @@ fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref> + 'a { - Ref::map(obj.borrow(), |py_obj| { - if let PyObjectPayload::Bytes { ref value } = py_obj.payload { - value - } else { - panic!("Inner error getting bytearray {:?}", obj); - } - }) + if let PyObjectPayload::Bytes { ref value } = obj.payload { + value.borrow() + } else { + panic!("Inner error getting bytearray {:?}", obj); + } } pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut> + 'a { - RefMut::map(obj.borrow_mut(), |py_obj| { - if let PyObjectPayload::Bytes { ref mut value } = py_obj.payload { - value - } else { - panic!("Inner error getting bytearray {:?}", obj); - } - }) + if let PyObjectPayload::Bytes { ref value } = obj.payload { + value.borrow_mut() + } else { + panic!("Inner error getting bytearray {:?}", obj); + } } fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 05d1b6238..178946de8 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -29,7 +29,7 @@ pub fn init(context: &PyContext) { } pub fn get_value(obj: &PyObjectRef) -> bytecode::CodeObject { - if let PyObjectPayload::Code { code } = &obj.borrow().payload { + if let PyObjectPayload::Code { code } = &obj.payload { code.clone() } else { panic!("Inner error getting code {:?}", obj) diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index 9182f7bc2..0b0d5ba7a 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -45,7 +45,7 @@ pub fn init(context: &PyContext) { } pub fn get_value(obj: &PyObjectRef) -> Complex64 { - if let PyObjectPayload::Complex { value } = &obj.borrow().payload { + if let PyObjectPayload::Complex { value } = &obj.payload { *value } else { panic!("Inner error getting complex"); @@ -117,7 +117,7 @@ fn complex_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { v1.im, ))) } else { - Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot add {} and {}", i, i2))) } } @@ -136,7 +136,7 @@ fn complex_radd(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { v1.im, ))) } else { - Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot add {} and {}", i, i2))) } } diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 42e188b46..9a7c365aa 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -6,7 +6,7 @@ use crate::pyobject::{ TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; -use std::cell::{Ref, RefCell, RefMut}; +use std::cell::RefCell; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; @@ -19,30 +19,26 @@ pub type DictContentType = HashMap; pub fn new(dict_type: PyObjectRef) -> PyObjectRef { PyObject::new( PyObjectPayload::Dict { - elements: HashMap::new(), + elements: RefCell::new(HashMap::new()), }, dict_type.clone(), ) } pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref + 'a { - Ref::map(obj.borrow(), |py_obj| { - if let PyObjectPayload::Dict { ref elements } = py_obj.payload { - elements - } else { - panic!("Cannot extract dict elements"); - } - }) + if let PyObjectPayload::Dict { ref elements } = obj.payload { + elements.borrow() + } else { + panic!("Cannot extract dict elements"); + } } fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut + 'a { - RefMut::map(obj.borrow_mut(), |py_obj| { - if let PyObjectPayload::Dict { ref mut elements } = py_obj.payload { - elements - } else { - panic!("Cannot extract dict elements"); - } - }) + if let PyObjectPayload::Dict { ref elements } = obj.payload { + elements.borrow_mut() + } else { + panic!("Cannot extract dict elements"); + } } pub fn set_item( @@ -309,12 +305,16 @@ fn dict_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) { - (*dict_type.borrow_mut()).payload = PyObjectPayload::Class { - name: String::from("dict"), - dict: RefCell::new(HashMap::new()), - mro: vec![object_type], - }; - (*dict_type.borrow_mut()).typ = Some(type_type.clone()); + // this is not ideal + let ptr = PyObjectRef::into_raw(dict_type.clone()) as *mut PyObject; + unsafe { + (*ptr).payload = PyObjectPayload::Class { + name: String::from("dict"), + dict: RefCell::new(HashMap::new()), + mro: vec![object_type], + }; + (*ptr).typ = Some(type_type.clone()); + } } pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index 9e5f369f1..88097bfe5 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -1,10 +1,12 @@ +use std::cell::RefCell; +use std::ops::AddAssign; + use super::objint; use super::objiter; use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use num_bigint::BigInt; use num_traits::Zero; -use std::ops::AddAssign; fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( @@ -20,7 +22,10 @@ fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; let iterator = objiter::get_iter(vm, iterable)?; Ok(PyObject::new( - PyObjectPayload::EnumerateIterator { counter, iterator }, + PyObjectPayload::EnumerateIterator { + counter: RefCell::new(counter), + iterator, + }, cls.clone(), )) } @@ -33,16 +38,16 @@ fn enumerate_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); if let PyObjectPayload::EnumerateIterator { - ref mut counter, - ref mut iterator, - } = enumerate.borrow_mut().payload + ref counter, + ref iterator, + } = enumerate.payload { let next_obj = objiter::call_next(vm, iterator)?; let result = vm .ctx - .new_tuple(vec![vm.ctx.new_int(counter.clone()), next_obj]); + .new_tuple(vec![vm.ctx.new_int(counter.borrow().clone()), next_obj]); - AddAssign::add_assign(counter, 1); + AddAssign::add_assign(&mut counter.borrow_mut() as &mut BigInt, 1); Ok(result) } else { diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 1fe163374..998d51c9b 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -25,9 +25,9 @@ fn filter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(filter, Some(vm.ctx.filter_type()))]); if let PyObjectPayload::FilterIterator { - ref mut predicate, - ref mut iterator, - } = filter.borrow_mut().payload + ref predicate, + ref iterator, + } = filter.payload { loop { let next_obj = objiter::call_next(vm, iterator)?; diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index c7b46299d..25c95f80f 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -61,7 +61,7 @@ fn float_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // Retrieve inner float value: pub fn get_value(obj: &PyObjectRef) -> f64 { - if let PyObjectPayload::Float { value } = &obj.borrow().payload { + if let PyObjectPayload::Float { value } = &obj.payload { *value } else { panic!("Inner error getting float"); @@ -81,12 +81,12 @@ pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> Result PyResult { diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs index 3f9dd07d7..efd3792bf 100644 --- a/vm/src/obj/objframe.rs +++ b/vm/src/obj/objframe.rs @@ -31,7 +31,6 @@ fn frame_flocals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]); let frame = get_value(frame); let py_scope = frame.locals.clone(); - let py_scope = py_scope.borrow(); if let PyObjectPayload::Scope { scope } = &py_scope.payload { Ok(scope.locals.clone()) @@ -46,7 +45,7 @@ fn frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn get_value(obj: &PyObjectRef) -> Frame { - if let PyObjectPayload::Frame { frame } = &obj.borrow().payload { + if let PyObjectPayload::Frame { frame } = &obj.payload { frame.clone() } else { panic!("Inner error getting int {:?}", obj); diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index d59c7bb28..a2092c308 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -67,7 +67,7 @@ fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn function_code(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - match args.args[0].borrow().payload { + match args.args[0].payload { PyObjectPayload::Function { ref code, .. } => Ok(code.clone()), _ => Err(vm.new_type_error("no code".to_string())), } diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 0f204e5ba..fdde5a6c1 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -56,16 +56,17 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult { - if let PyObjectPayload::Generator { ref mut frame } = gen.borrow_mut().payload { - frame.push_value(value.clone()); - match frame.run_frame(vm)? { - ExecutionResult::Yield(value) => Ok(value), - ExecutionResult::Return(_value) => { - // Stop iteration! - let stop_iteration = vm.ctx.exceptions.stop_iteration.clone(); - Err(vm.new_exception(stop_iteration, "End of generator".to_string())) - } - } + if let PyObjectPayload::Generator { ref frame } = gen.payload { + //frame.push_value(value.clone()); + //match frame.run_frame(vm)? { + // ExecutionResult::Yield(value) => Ok(value), + // ExecutionResult::Return(_value) => { + // // Stop iteration! + // let stop_iteration = vm.ctx.exceptions.stop_iteration.clone(); + // Err(vm.new_exception(stop_iteration, "End of generator".to_string())) + // } + //} + unimplemented!("FIXME") } else { panic!("Cannot extract frame from non-generator"); } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index c6bb93b9a..9f5e48893 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -94,7 +94,7 @@ pub fn to_int( // Retrieve inner int value: pub fn get_value(obj: &PyObjectRef) -> IntType { - if let PyObjectPayload::Integer { value } = &obj.borrow().payload { + if let PyObjectPayload::Integer { value } = &obj.payload { value.clone() } else { panic!("Inner error getting int {:?}", obj); diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index a3e30a152..70ae95e49 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -128,16 +128,15 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(iter, Some(vm.ctx.iter_type()))]); if let PyObjectPayload::Iterator { - ref mut position, - iterated_obj: ref mut iterated_obj_ref, - } = iter.borrow_mut().payload + ref position, + iterated_obj: ref iterated_obj_ref, + } = iter.payload { - let iterated_obj = iterated_obj_ref.borrow_mut(); - match iterated_obj.payload { + match iterated_obj_ref.payload { PyObjectPayload::Sequence { ref elements } => { - if *position < elements.len() { - let obj_ref = elements[*position].clone(); - *position += 1; + if *position < elements.borrow().len() { + let obj_ref = elements.borrow()[*position].clone(); + //*position += 1; // FIXME Ok(obj_ref) } else { Err(new_stop_iteration(vm)) @@ -146,7 +145,7 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { PyObjectPayload::Range { ref range } => { if let Some(int) = range.get(*position) { - *position += 1; + //*position += 1; // FIXME Ok(vm.ctx.new_int(int)) } else { Err(new_stop_iteration(vm)) @@ -154,9 +153,9 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } PyObjectPayload::Bytes { ref value } => { - if *position < value.len() { - let obj_ref = vm.ctx.new_int(value[*position]); - *position += 1; + if *position < value.borrow().len() { + let obj_ref = vm.ctx.new_int(value.borrow()[*position]); + // *position += 1; // FIXME Ok(obj_ref) } else { Err(new_stop_iteration(vm)) diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 53f0d7498..8f32892c3 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; + use super::objbool; use super::objint; use super::objsequence::{ @@ -55,7 +57,9 @@ fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::Sequence { elements }, + PyObjectPayload::Sequence { + elements: RefCell::new(elements), + }, cls.clone(), )) } @@ -93,11 +97,7 @@ fn list_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_lt(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<'", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -115,11 +115,7 @@ fn list_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_gt(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>'", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -137,11 +133,7 @@ fn list_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_ge(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>='", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -159,11 +151,7 @@ fn list_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_le(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<='", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -182,7 +170,7 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { 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.borrow(), o2.borrow()))) + Err(vm.new_type_error(format!("Cannot add {} and {}", o, o2))) } } diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 9ba88955b..78cbdcf74 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -28,9 +28,9 @@ fn map_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(map, Some(vm.ctx.map_type()))]); if let PyObjectPayload::MapIterator { - ref mut mapper, - ref mut iterators, - } = map.borrow_mut().payload + ref mapper, + ref iterators, + } = map.payload { let next_objs = iterators .iter() diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 62f31b8c2..67414373a 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -1,8 +1,8 @@ use super::objstr; use super::objtype; use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, - TypeProtocol, + AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, + PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use std::cell::RefCell; @@ -16,12 +16,16 @@ pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { } pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) { - (*object_type.borrow_mut()).payload = PyObjectPayload::Class { - name: String::from("object"), - dict: RefCell::new(HashMap::new()), - mro: vec![], - }; - (*object_type.borrow_mut()).typ = Some(type_type.clone()); + // this is not ideal + let ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; + unsafe { + (*ptr).payload = PyObjectPayload::Class { + name: String::from("object"), + dict: RefCell::new(HashMap::new()), + mro: vec![], + }; + (*ptr).typ = Some(type_type.clone()); + } } fn object_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -101,7 +105,7 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ] ); - match zelf.borrow().payload { + match zelf.payload { PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => { let attr_name = objstr::get_value(attr); dict.borrow_mut().remove(&attr_name); @@ -174,7 +178,7 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { } fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - match args.args[0].borrow().payload { + match args.args[0].payload { PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => { let new_dict = vm.new_dict(); for (attr, value) in dict.borrow().iter() { @@ -230,7 +234,7 @@ fn object_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let attribute_error = vm.context().exceptions.attribute_error.clone(); Err(vm.new_exception( attribute_error, - format!("{} has no attribute '{}'", obj.borrow(), name), + format!("{} has no attribute '{}'", obj, name), )) } } diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index e2ac5de45..5ced88d91 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -151,7 +151,7 @@ impl RangeType { } pub fn get_value(obj: &PyObjectRef) -> RangeType { - if let PyObjectPayload::Range { range } = &obj.borrow().payload { + if let PyObjectPayload::Range { range } = &obj.payload { range.clone() } else { panic!("Inner error getting range {:?}", obj); @@ -287,7 +287,7 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let range = get_value(zelf); - match subscript.borrow().payload { + match subscript.payload { PyObjectPayload::Integer { ref value } => { if let Some(int) = range.get(value) { Ok(vm.ctx.new_int(int)) diff --git a/vm/src/obj/objsequence.rs b/vm/src/obj/objsequence.rs index b52c8e04d..58437b98e 100644 --- a/vm/src/obj/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -1,12 +1,13 @@ +use std::cell::RefCell; +use std::marker::Sized; +use std::ops::{Deref, DerefMut, Range}; + use super::objbool; use super::objint; use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use num_bigint::BigInt; use num_traits::{One, Signed, ToPrimitive, Zero}; -use std::cell::{Ref, RefMut}; -use std::marker::Sized; -use std::ops::{Deref, DerefMut, Range}; pub trait PySliceableSequence { fn do_slice(&self, range: Range) -> Self; @@ -64,7 +65,7 @@ pub trait PySliceableSequence { Self: Sized, { // TODO: we could potentially avoid this copy and use slice - match &(slice.borrow()).payload { + match &slice.payload { PyObjectPayload::Slice { start, stop, step } => { let step = step.clone().unwrap_or_else(BigInt::one); if step.is_zero() { @@ -140,7 +141,7 @@ pub fn get_item( elements: &[PyObjectRef], subscript: PyObjectRef, ) -> PyResult { - match &(subscript.borrow()).payload { + match &subscript.payload { PyObjectPayload::Integer { value } => match value.to_i32() { Some(value) => { if let Some(pos_index) = elements.to_vec().get_pos(value) { @@ -156,9 +157,9 @@ pub fn get_item( }, PyObjectPayload::Slice { .. } => Ok(PyObject::new( - match &(sequence.borrow()).payload { + match &sequence.payload { PyObjectPayload::Sequence { .. } => PyObjectPayload::Sequence { - elements: elements.to_vec().get_slice_items(vm, &subscript)?, + elements: RefCell::new(elements.to_vec().get_slice_items(vm, &subscript)?), }, ref payload => panic!("sequence get_item called for non-sequence: {:?}", payload), }, @@ -302,23 +303,19 @@ pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec(obj: &'a PyObjectRef) -> impl Deref> + 'a { - Ref::map(obj.borrow(), |x| { - if let PyObjectPayload::Sequence { ref elements } = x.payload { - elements - } else { - panic!("Cannot extract elements from non-sequence"); - } - }) + if let PyObjectPayload::Sequence { ref elements } = obj.payload { + elements.borrow() + } else { + panic!("Cannot extract elements from non-sequence"); + } } pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut> + 'a { - RefMut::map(obj.borrow_mut(), |x| { - if let PyObjectPayload::Sequence { ref mut elements } = x.payload { - elements - } else { - panic!("Cannot extract list elements from non-sequence"); - // TODO: raise proper error? - // Err(vm.new_type_error("list.append is called with no list".to_string())) - } - }) + if let PyObjectPayload::Sequence { ref elements } = obj.payload { + elements.borrow_mut() + } else { + panic!("Cannot extract list elements from non-sequence"); + // TODO: raise proper error? + // Err(vm.new_type_error("list.append is called with no list".to_string())) + } } diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index ebae2b44c..dcb47bc8c 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -2,6 +2,11 @@ * Builtin set type with a sequence of unique items. */ +use std::cell::RefCell; +use std::collections::hash_map::DefaultHasher; +use std::collections::HashMap; +use std::hash::{Hash, Hasher}; + use super::objbool; use super::objint; use super::objiter; @@ -11,13 +16,10 @@ use crate::pyobject::{ PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; -use std::collections::hash_map::DefaultHasher; -use std::collections::HashMap; -use std::hash::{Hash, Hasher}; pub fn get_elements(obj: &PyObjectRef) -> HashMap { - if let PyObjectPayload::Set { elements } = &obj.borrow().payload { - elements.clone() + if let PyObjectPayload::Set { elements } = &obj.payload { + elements.borrow().clone() } else { panic!("Cannot extract set elements from non-set"); } @@ -62,10 +64,10 @@ fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(s, Some(vm.ctx.set_type())), (item, None)] ); - let mut mut_obj = s.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => insert_into_set(vm, elements, item), + match s.payload { + PyObjectPayload::Set { ref elements } => { + insert_into_set(vm, &mut elements.borrow_mut(), item) + } _ => Err(vm.new_type_error("set.add is called with no item".to_string())), } } @@ -77,10 +79,8 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(s, Some(vm.ctx.set_type())), (item, None)] ); - let mut mut_obj = s.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { + match s.payload { + PyObjectPayload::Set { ref elements } => { fn remove( vm: &mut VirtualMachine, elements: &mut HashMap, @@ -89,13 +89,13 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ) -> PyResult { match elements.remove(&key) { None => { - let item_str = format!("{:?}", value.borrow()); + let item_str = format!("{:?}", value); Err(vm.new_key_error(item_str)) } Some(_) => Ok(vm.get_none()), } } - perform_action_with_hash(vm, elements, item, &remove) + perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &remove) } _ => Err(vm.new_type_error("set.remove is called with no item".to_string())), } @@ -108,10 +108,8 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(s, Some(vm.ctx.set_type())), (item, None)] ); - let mut mut_obj = s.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { + match s.payload { + PyObjectPayload::Set { ref elements } => { fn discard( vm: &mut VirtualMachine, elements: &mut HashMap, @@ -121,7 +119,7 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { elements.remove(&key); Ok(vm.get_none()) } - perform_action_with_hash(vm, elements, item, &discard) + perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &discard) } _ => Err(vm.new_type_error("set.discard is called with no item".to_string())), } @@ -130,10 +128,9 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn set_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("set.clear called"); arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]); - let mut mut_obj = s.borrow_mut(); - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { - elements.clear(); + match s.payload { + PyObjectPayload::Set { ref elements } => { + elements.borrow_mut().clear(); Ok(vm.get_none()) } _ => Err(vm.new_type_error("".to_string())), @@ -150,7 +147,7 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); if !objtype::issubclass(cls, &vm.ctx.set_type()) { - return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow()))); + return Err(vm.new_type_error(format!("{} is not a subtype of set", cls))); } let elements: HashMap = match iterable { @@ -166,7 +163,9 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::Set { elements }, + PyObjectPayload::Set { + elements: RefCell::new(elements), + }, cls.clone(), )) } @@ -183,7 +182,9 @@ fn set_copy(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]); let elements = get_elements(s); Ok(PyObject::new( - PyObjectPayload::Set { elements }, + PyObjectPayload::Set { + elements: RefCell::new(elements), + }, vm.ctx.set_type(), )) } @@ -335,7 +336,9 @@ fn set_union(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { elements.extend(get_elements(other).clone()); Ok(PyObject::new( - PyObjectPayload::Set { elements }, + PyObjectPayload::Set { + elements: RefCell::new(elements), + }, vm.ctx.set_type(), )) } @@ -375,7 +378,9 @@ fn set_symmetric_difference(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResu } Ok(PyObject::new( - PyObjectPayload::Set { elements }, + PyObjectPayload::Set { + elements: RefCell::new(elements), + }, vm.ctx.set_type(), )) } @@ -413,7 +418,9 @@ fn set_combine_inner( } Ok(PyObject::new( - PyObjectPayload::Set { elements }, + PyObjectPayload::Set { + elements: RefCell::new(elements), + }, vm.ctx.set_type(), )) } @@ -421,11 +428,9 @@ fn set_combine_inner( fn set_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]); - let mut mut_obj = s.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => match elements.clone().keys().next() { - Some(key) => Ok(elements.remove(key).unwrap()), + match s.payload { + PyObjectPayload::Set { ref elements } => match elements.borrow().clone().keys().next() { + Some(key) => Ok(elements.borrow_mut().remove(key).unwrap()), None => Err(vm.new_key_error("pop from an empty set".to_string())), }, _ => Err(vm.new_type_error("".to_string())), @@ -444,13 +449,11 @@ fn set_ior(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)] ); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { + match zelf.payload { + PyObjectPayload::Set { ref elements } => { let iterator = objiter::get_iter(vm, iterable)?; while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) { - insert_into_set(vm, elements, &v)?; + insert_into_set(vm, &mut elements.borrow_mut(), &v)?; } } _ => return Err(vm.new_type_error("set.update is called with no other".to_string())), @@ -487,18 +490,16 @@ fn set_combine_update_inner( required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)] ); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { - for element in elements.clone().iter() { + match zelf.payload { + PyObjectPayload::Set { ref elements } => { + for element in elements.borrow().clone().iter() { let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?; let should_remove = match op { SetCombineOperation::Intersection => !objbool::get_value(&value), SetCombineOperation::Difference => objbool::get_value(&value), }; if should_remove { - elements.remove(&element.0.clone()); + elements.borrow_mut().remove(&element.0.clone()); } } } @@ -519,19 +520,17 @@ fn set_ixor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)] ); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Set { ref mut elements } => { - let elements_original = elements.clone(); + match zelf.payload { + PyObjectPayload::Set { ref elements } => { + let elements_original = elements.borrow().clone(); let iterator = objiter::get_iter(vm, iterable)?; while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) { - insert_into_set(vm, elements, &v)?; + insert_into_set(vm, &mut elements.borrow_mut(), &v)?; } for element in elements_original.iter() { let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?; if objbool::get_value(&value) { - elements.remove(&element.0.clone()); + elements.borrow_mut().remove(&element.0.clone()); } } } diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 19abc214f..0a81847e2 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -59,7 +59,7 @@ fn get_property_value(vm: &mut VirtualMachine, value: &Option) -> PyResu fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { start, .. } = &slice.borrow().payload { + if let PyObjectPayload::Slice { start, .. } = &slice.payload { get_property_value(vm, start) } else { panic!("Slice has incorrect payload."); @@ -68,7 +68,7 @@ fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { stop, .. } = &slice.borrow().payload { + if let PyObjectPayload::Slice { stop, .. } = &slice.payload { get_property_value(vm, stop) } else { panic!("Slice has incorrect payload."); @@ -77,7 +77,7 @@ fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn slice_step(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { step, .. } = &slice.borrow().payload { + if let PyObjectPayload::Slice { step, .. } = &slice.payload { get_property_value(vm, step) } else { panic!("Slice has incorrect payload."); diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 04394f7c5..580ab2b80 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -3,12 +3,10 @@ use super::objsequence::PySliceableSequence; use super::objtype; use crate::format::{FormatParseError, FormatPart, FormatString}; use crate::pyobject::{ - FromPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, - TypeProtocol, + FromPyObject, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; -use std::cell::Ref; use std::hash::{Hash, Hasher}; use std::ops::Range; use std::str::FromStr; @@ -115,21 +113,19 @@ pub fn init(context: &PyContext) { } pub fn get_value(obj: &PyObjectRef) -> String { - if let PyObjectPayload::String { value } = &obj.borrow().payload { + if let PyObjectPayload::String { value } = &obj.payload { value.to_string() } else { panic!("Inner error getting str"); } } -pub fn borrow_value(obj: &PyObjectRef) -> Ref { - Ref::map(obj.borrow(), |py_obj| { - if let PyObjectPayload::String { value } = &py_obj.payload { - value.as_ref() - } else { - panic!("Inner error getting str"); - } - }) +pub fn borrow_value(obj: &PyObjectRef) -> &str { + if let PyObjectPayload::String { value } = &obj.payload { + value.as_str() + } else { + panic!("Inner error getting str"); + } } fn str_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -158,7 +154,7 @@ fn str_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, &vm.ctx.str_type()) { Ok(vm.ctx.new_bool(v1 > get_value(i2))) } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2))) } } @@ -173,7 +169,7 @@ fn str_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, &vm.ctx.str_type()) { Ok(vm.ctx.new_bool(v1 >= get_value(i2))) } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2))) } } @@ -188,7 +184,7 @@ fn str_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, &vm.ctx.str_type()) { Ok(vm.ctx.new_bool(v1 < get_value(i2))) } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2))) } } @@ -203,7 +199,7 @@ fn str_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, &vm.ctx.str_type()) { Ok(vm.ctx.new_bool(v1 <= get_value(i2))) } else { - Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow()))) + Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2))) } } @@ -258,7 +254,7 @@ fn str_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { .ctx .new_str(format!("{}{}", get_value(&s), get_value(&s2)))) } else { - Err(vm.new_type_error(format!("Cannot add {} and {}", s.borrow(), s2.borrow()))) + Err(vm.new_type_error(format!("Cannot add {} and {}", s, s2))) } } @@ -387,11 +383,7 @@ fn str_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } Ok(vm.ctx.new_str(result)) } else { - Err(vm.new_type_error(format!( - "Cannot multiply {} and {}", - s.borrow(), - s2.borrow() - ))) + Err(vm.new_type_error(format!("Cannot multiply {} and {}", s, s2))) } } @@ -1115,7 +1107,7 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu } } } else { - match (*b.borrow()).payload { + match b.payload { PyObjectPayload::Slice { .. } => { let string = value.to_string().get_slice_items(vm, &b)?; Ok(vm.new_str(string)) @@ -1130,8 +1122,8 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu // help get optional string indices fn get_slice( - start: Option<&std::rc::Rc>>, - end: Option<&std::rc::Rc>>, + start: Option<&PyObjectRef>, + end: Option<&PyObjectRef>, len: usize, ) -> Result<(usize, usize), String> { let start_idx = match start { diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 81e3b9959..8ddc3640a 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -1,3 +1,6 @@ +use std::cell::RefCell; +use std::hash::{Hash, Hasher}; + use super::objbool; use super::objint; use super::objsequence::{ @@ -7,7 +10,6 @@ use super::objstr; use super::objtype; use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol}; use crate::vm::{ReprGuard, VirtualMachine}; -use std::hash::{Hash, Hasher}; fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( @@ -21,11 +23,7 @@ fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_lt(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<'", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -43,11 +41,7 @@ fn tuple_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_gt(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>'", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -65,11 +59,7 @@ fn tuple_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_ge(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '>='", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -87,11 +77,7 @@ fn tuple_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let other = get_elements(other); seq_le(vm, &zelf, &other)? } else { - return Err(vm.new_type_error(format!( - "Cannot compare {} and {} using '<='", - zelf.borrow(), - other.borrow() - ))); + return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other))); }; Ok(vm.ctx.new_bool(result)) @@ -110,11 +96,7 @@ fn tuple_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { 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.borrow(), - other.borrow() - ))) + Err(vm.new_type_error(format!("Cannot add {} and {}", zelf, other))) } } @@ -193,7 +175,7 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); if !objtype::issubclass(cls, &vm.ctx.tuple_type()) { - return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls.borrow()))); + return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls))); } let elements = if let Some(iterable) = iterable { @@ -203,7 +185,9 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::Sequence { elements }, + PyObjectPayload::Sequence { + elements: RefCell::new(elements), + }, cls.clone(), )) } diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index aa7618e38..693599675 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -14,12 +14,16 @@ use std::collections::HashMap; */ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) { - (*type_type.borrow_mut()).payload = PyObjectPayload::Class { - name: String::from("type"), - dict: RefCell::new(PyAttributes::new()), - mro: vec![object_type], - }; - (*type_type.borrow_mut()).typ = Some(type_type.clone()); + // this is not ideal + let ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; + unsafe { + (*ptr).payload = PyObjectPayload::Class { + name: String::from("type"), + dict: RefCell::new(PyAttributes::new()), + mro: vec![object_type], + }; + (*ptr).typ = Some(type_type); + } } pub fn init(context: &PyContext) { @@ -71,7 +75,7 @@ fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn _mro(cls: PyObjectRef) -> Option> { - match cls.borrow().payload { + match cls.payload { PyObjectPayload::Class { ref mro, .. } => { let mut mro = mro.clone(); mro.insert(0, cls.clone()); @@ -96,7 +100,7 @@ pub fn issubclass(typ: &PyObjectRef, cls: &PyObjectRef) -> bool { } pub fn get_type_name(typ: &PyObjectRef) -> String { - if let PyObjectPayload::Class { name, .. } = &typ.borrow().payload { + if let PyObjectPayload::Class { name, .. } = &typ.payload { name.clone() } else { panic!("Cannot get type_name of non-type type {:?}", typ); @@ -211,7 +215,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult let attribute_error = vm.context().exceptions.attribute_error.clone(); Err(vm.new_exception( attribute_error, - format!("{} has no attribute '{}'", cls.borrow(), name), + format!("{} has no attribute '{}'", cls, name), )) } } @@ -224,7 +228,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes { let mut base_classes = objtype::base_classes(obj); base_classes.reverse(); for bc in base_classes { - if let PyObjectPayload::Class { dict, .. } = &bc.borrow().payload { + if let PyObjectPayload::Class { dict, .. } = &bc.payload { for (name, value) in dict.borrow().iter() { attributes.insert(name.to_string(), value.clone()); } @@ -232,7 +236,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes { } // Get instance attributes: - if let PyObjectPayload::Instance { dict } = &obj.borrow().payload { + if let PyObjectPayload::Instance { dict } = &obj.payload { for (name, value) in dict.borrow().iter() { attributes.insert(name.to_string(), value.clone()); } diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index 43005f416..d1cb833db 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -19,7 +19,7 @@ fn zip_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn zip_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zip, Some(vm.ctx.zip_type()))]); - if let PyObjectPayload::ZipIterator { ref mut iterators } = zip.borrow_mut().payload { + if let PyObjectPayload::ZipIterator { ref iterators } = zip.payload { if iterators.is_empty() { Err(objiter::new_stop_iteration(vm)) } else { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 073a5d646..c854efa0e 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -54,21 +54,15 @@ Basically reference counting, but then done by rust. * Good reference: https://github.com/ProgVal/pythonvm-rust/blob/master/src/objects/mod.rs */ -/* -The PyRef type implements -https://doc.rust-lang.org/std/cell/index.html#introducing-mutability-inside-of-something-immutable -*/ -pub type PyRef = Rc>; - /// The `PyObjectRef` is one of the most used types. It is a reference to a /// python object. A single python object can have multiple references, and /// this reference counting is accounted for by this type. Use the `.clone()` /// method to create a new reference and increment the amount of references /// to the python object by 1. -pub type PyObjectRef = PyRef; +pub type PyObjectRef = Rc; /// Same as PyObjectRef, except for being a weak reference. -pub type PyObjectWeakRef = Weak>; +pub type PyObjectWeakRef = Weak; /// Use this type for function which return a python object or and exception. /// Both the python object and the python exception are `PyObjectRef` types @@ -488,12 +482,19 @@ impl PyContext { } pub fn new_bytes(&self, data: Vec) -> PyObjectRef { - PyObject::new(PyObjectPayload::Bytes { value: data }, self.bytes_type()) + PyObject::new( + PyObjectPayload::Bytes { + value: RefCell::new(data), + }, + self.bytes_type(), + ) } pub fn new_bytearray(&self, data: Vec) -> PyObjectRef { PyObject::new( - PyObjectPayload::Bytes { value: data }, + PyObjectPayload::Bytes { + value: RefCell::new(data), + }, self.bytearray_type(), ) } @@ -507,24 +508,38 @@ impl PyContext { } pub fn new_tuple(&self, elements: Vec) -> PyObjectRef { - PyObject::new(PyObjectPayload::Sequence { elements }, self.tuple_type()) + PyObject::new( + PyObjectPayload::Sequence { + elements: RefCell::new(elements), + }, + self.tuple_type(), + ) } pub fn new_list(&self, elements: Vec) -> PyObjectRef { - PyObject::new(PyObjectPayload::Sequence { elements }, self.list_type()) + PyObject::new( + PyObjectPayload::Sequence { + elements: RefCell::new(elements), + }, + self.list_type(), + ) } pub fn new_set(&self) -> PyObjectRef { // Initialized empty, as calling __hash__ is required for adding each object to the set // which requires a VM context - this is done in the objset code itself. - let elements: HashMap = HashMap::new(); - PyObject::new(PyObjectPayload::Set { elements }, self.set_type()) + PyObject::new( + PyObjectPayload::Set { + elements: RefCell::new(HashMap::new()), + }, + self.set_type(), + ) } pub fn new_dict(&self) -> PyObjectRef { PyObject::new( PyObjectPayload::Dict { - elements: HashMap::new(), + elements: RefCell::new(HashMap::new()), }, self.dict_type(), ) @@ -642,10 +657,10 @@ impl PyContext { // Item set/get: pub fn set_item(&self, obj: &PyObjectRef, key: &str, v: PyObjectRef) { - match obj.borrow_mut().payload { - PyObjectPayload::Dict { ref mut elements } => { + match obj.payload { + PyObjectPayload::Dict { ref elements } => { let key = self.new_str(key.to_string()); - objdict::set_item_in_content(elements, &key, &v); + objdict::set_item_in_content(&mut elements.borrow_mut(), &key, &v); } ref k => panic!("TODO {:?}", k), }; @@ -659,7 +674,7 @@ impl PyContext { } pub fn set_attr(&self, obj: &PyObjectRef, attr_name: &str, value: PyObjectRef) { - match obj.borrow().payload { + match obj.payload { PyObjectPayload::Module { ref dict, .. } => self.set_attr(dict, attr_name, value), PyObjectPayload::Instance { ref dict } | PyObjectPayload::Class { ref dict, .. } => { dict.borrow_mut().insert(attr_name.to_string(), value); @@ -708,7 +723,7 @@ pub trait IdProtocol { impl IdProtocol for PyObjectRef { fn get_id(&self) -> usize { - self.as_ptr() as usize + &*self as &PyObject as *const PyObject as usize } fn is(&self, other: &PyObjectRef) -> bool { @@ -726,7 +741,7 @@ pub trait TypeProtocol { impl TypeProtocol for PyObjectRef { fn typ(&self) -> PyObjectRef { - self.borrow().typ() + (**self).typ() } } @@ -746,14 +761,14 @@ pub trait ParentProtocol { impl ParentProtocol for PyObjectRef { fn has_parent(&self) -> bool { - match self.borrow().payload { + match self.payload { PyObjectPayload::Scope { ref scope } => scope.parent.is_some(), _ => panic!("Only scopes have parent (not {:?}", self), } } fn get_parent(&self) -> PyObjectRef { - match self.borrow().payload { + match self.payload { PyObjectPayload::Scope { ref scope } => match scope.parent { Some(ref value) => value.clone(), None => panic!("OMG"), @@ -769,7 +784,6 @@ pub trait AttributeProtocol { } fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option { - let class = class.borrow(); match class.payload { PyObjectPayload::Class { ref dict, .. } => dict.borrow().get(attr_name).cloned(), _ => panic!("Only classes should be in MRO!"), @@ -777,7 +791,6 @@ fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option { } fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool { - let class = class.borrow(); match class.payload { PyObjectPayload::Class { ref dict, .. } => dict.borrow().contains_key(attr_name), _ => panic!("Only classes should be in MRO!"), @@ -786,8 +799,7 @@ fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool { impl AttributeProtocol for PyObjectRef { fn get_attr(&self, attr_name: &str) -> Option { - let obj = self.borrow(); - match obj.payload { + match self.payload { PyObjectPayload::Module { ref dict, .. } => dict.get_item(attr_name), PyObjectPayload::Class { ref mro, .. } => { if let Some(item) = class_get_item(self, attr_name) { @@ -806,8 +818,7 @@ impl AttributeProtocol for PyObjectRef { } fn has_attr(&self, attr_name: &str) -> bool { - let obj = self.borrow(); - match obj.payload { + match self.payload { PyObjectPayload::Module { ref dict, .. } => dict.contains_key(attr_name), PyObjectPayload::Class { ref mro, .. } => { class_has_item(self, attr_name) || mro.iter().any(|d| class_has_item(d, attr_name)) @@ -826,9 +837,9 @@ pub trait DictProtocol { impl DictProtocol for PyObjectRef { fn contains_key(&self, k: &str) -> bool { - match self.borrow().payload { + match self.payload { PyObjectPayload::Dict { ref elements } => { - objdict::content_contains_key_str(elements, k) + objdict::content_contains_key_str(&elements.borrow(), k) } PyObjectPayload::Scope { ref scope } => scope.locals.contains_key(k), ref payload => unimplemented!("TODO {:?}", payload), @@ -836,15 +847,17 @@ impl DictProtocol for PyObjectRef { } fn get_item(&self, k: &str) -> Option { - match self.borrow().payload { - PyObjectPayload::Dict { ref elements } => objdict::content_get_key_str(elements, k), + match self.payload { + PyObjectPayload::Dict { ref elements } => { + objdict::content_get_key_str(&elements.borrow(), k) + } PyObjectPayload::Scope { ref scope } => scope.locals.get_item(k), _ => panic!("TODO"), } } fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)> { - match self.borrow().payload { + match self.payload { PyObjectPayload::Dict { .. } => objdict::get_key_value_pairs(self), PyObjectPayload::Module { ref dict, .. } => dict.get_key_value_pairs(), PyObjectPayload::Scope { ref scope } => scope.locals.get_key_value_pairs(), @@ -1161,23 +1174,23 @@ pub enum PyObjectPayload { value: Complex64, }, Bytes { - value: Vec, + value: RefCell>, }, Sequence { - elements: Vec, + elements: RefCell>, }, Dict { - elements: objdict::DictContentType, + elements: RefCell, }, Set { - elements: HashMap, + elements: RefCell>, }, Iterator { position: usize, iterated_obj: PyObjectRef, }, EnumerateIterator { - counter: BigInt, + counter: RefCell, iterator: PyObjectRef, }, FilterIterator { @@ -1244,7 +1257,7 @@ pub enum PyObjectPayload { function: Box PyResult>, }, Socket { - socket: Socket, + socket: RefCell, }, } @@ -1303,7 +1316,7 @@ impl PyObject { // Move this object into a reference object, transferring ownership. pub fn into_ref(self) -> PyObjectRef { - Rc::new(RefCell::new(self)) + Rc::new(self) } } diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 0d7a46ee0..f1b9c24f9 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -84,8 +84,8 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { .map_err(|_| vm.new_value_error("IO Error".to_string()))?; //Copy bytes from the buffer vector into the results vector - if let PyObjectPayload::Bytes { ref mut value } = buffer.borrow_mut().payload { - result.extend(value.iter().cloned()); + if let PyObjectPayload::Bytes { ref value } = buffer.payload { + result.extend(value.borrow().iter().cloned()); }; let len = vm.get_method(buffer.clone(), &"__len__".to_string()); @@ -167,11 +167,12 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let handle = os::rust_file(raw_fd); let mut f = handle.take(length); - if let PyObjectPayload::Bytes { ref mut value } = obj.borrow_mut().payload { + if let PyObjectPayload::Bytes { ref value } = obj.payload { //TODO: Implement for MemoryView - value.clear(); - match f.read_to_end(&mut *value) { + let mut value_mut = value.borrow_mut(); + value_mut.clear(); + match f.read_to_end(&mut value_mut) { Ok(_) => {} Err(_) => return Err(vm.new_value_error("Error reading from Take".to_string())), } @@ -197,9 +198,10 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { //to support windows - i.e. raw file_handles let mut handle = os::rust_file(raw_fd); - match obj.borrow_mut().payload { - PyObjectPayload::Bytes { ref mut value } => { - match handle.write(&value[..]) { + match obj.payload { + PyObjectPayload::Bytes { ref value } => { + let value_mut = value.borrow(); + match handle.write(&value_mut[..]) { Ok(len) => { //reset raw fd on the FileIO object let updated = os::raw_file_number(handle); diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 53507e81d..e0288bdf6 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -65,7 +65,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> { map.serialize_entry(&key, &self.clone_with_object(&e.1))?; } map.end() - } else if let PyObjectPayload::None = self.pyobject.borrow().payload { + } else if let PyObjectPayload::None = self.pyobject.payload { serializer.serialize_none() } else { Err(serde::ser::Error::custom(format!( @@ -167,7 +167,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> { // than wrapping the given object up and then unwrapping it to determine whether or // not it is a string while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? { - let key = match key_obj.borrow().payload { + let key = match key_obj.payload { PyObjectPayload::String { ref value } => value.clone(), _ => unimplemented!("map keys must be strings"), }; diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index f1634d645..533f4fdcd 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -1,3 +1,9 @@ +use std::cell::RefCell; +use std::io; +use std::io::Read; +use std::io::Write; +use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket}; + use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objsequence::get_elements; @@ -8,10 +14,6 @@ use crate::pyobject::{ use crate::vm::VirtualMachine; use num_traits::ToPrimitive; -use std::io; -use std::io::Read; -use std::io::Write; -use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket}; #[derive(Copy, Clone)] enum AddressFamily { @@ -113,7 +115,7 @@ fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let address_family = AddressFamily::from_i32(objint::get_value(family_int).to_i32().unwrap()); let kind = SocketKind::from_i32(objint::get_value(kind_int).to_i32().unwrap()); - let socket = Socket::new(address_family, kind); + let socket = RefCell::new(Socket::new(address_family, kind)); Ok(PyObject::new( PyObjectPayload::Socket { socket }, @@ -134,12 +136,10 @@ fn socket_connect(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let address_string = format!("{}:{}", host, port.to_string()); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => { if let Ok(stream) = TcpStream::connect(address_string) { - socket.con = Some(Connection::TcpStream(stream)); + socket.borrow_mut().con = Some(Connection::TcpStream(stream)); Ok(vm.get_none()) } else { // TODO: Socket error @@ -163,12 +163,10 @@ fn socket_bind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let address_string = format!("{}:{}", host, port.to_string()); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => { if let Ok(stream) = TcpListener::bind(address_string) { - socket.con = Some(Connection::TcpListener(stream)); + socket.borrow_mut().con = Some(Connection::TcpListener(stream)); Ok(vm.get_none()) } else { // TODO: Socket error @@ -186,11 +184,9 @@ fn socket_listen(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, None)]); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => { - let ret = match socket.con { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => { + let ret = match socket.borrow_mut().con { Some(ref mut v) => v.accept(), None => return Err(vm.new_type_error("".to_string())), }; @@ -200,15 +196,15 @@ fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { _ => return Err(vm.new_type_error("".to_string())), }; - let socket = Socket { - address_family: socket.address_family.clone(), - sk: socket.sk.clone(), + let socket = RefCell::new(Socket { + address_family: socket.borrow().address_family.clone(), + sk: socket.borrow().sk.clone(), con: Some(Connection::TcpStream(tcp_stream)), - }; + }); - let sock_obj = PyObject::new(PyObjectPayload::Socket { socket }, mut_obj.typ()); + let sock_obj = PyObject::new(PyObjectPayload::Socket { socket }, zelf.typ()); - let elements = vec![sock_obj, vm.get_none()]; + let elements = RefCell::new(vec![sock_obj, vm.get_none()]); Ok(PyObject::new( PyObjectPayload::Sequence { elements }, @@ -225,19 +221,14 @@ fn socket_recv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(zelf, None), (bufsize, Some(vm.ctx.int_type()))] ); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => { let mut buffer = Vec::new(); - let _temp = match socket.con { + let _temp = match socket.borrow_mut().con { Some(ref mut v) => v.read_to_end(&mut buffer).unwrap(), None => 0, }; - Ok(PyObject::new( - PyObjectPayload::Bytes { value: buffer }, - vm.ctx.bytes_type(), - )) + Ok(vm.ctx.new_bytes(buffer)) } _ => Err(vm.new_type_error("".to_string())), } @@ -249,11 +240,9 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(zelf, None), (bytes, Some(vm.ctx.bytes_type()))] ); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => { - match socket.con { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => { + match socket.borrow_mut().con { Some(ref mut v) => v.write(&objbytes::get_value(&bytes)).unwrap(), None => return Err(vm.new_type_error("".to_string())), }; @@ -265,13 +254,11 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn socket_close(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, None)]); - let mut mut_obj = zelf.borrow_mut(); - - match mut_obj.payload { - PyObjectPayload::Socket { ref mut socket } => match socket.address_family { - AddressFamily::AfInet => match socket.sk { + match zelf.payload { + PyObjectPayload::Socket { ref socket } => match socket.borrow().address_family { + AddressFamily::AfInet => match socket.borrow().sk { SocketKind::SockStream => { - socket.con = None; + socket.borrow_mut().con = None; Ok(vm.get_none()) } _ => Err(vm.new_type_error("".to_string())), diff --git a/vm/src/stdlib/weakref.rs b/vm/src/stdlib/weakref.rs index 0fc087867..5b67f1664 100644 --- a/vm/src/stdlib/weakref.rs +++ b/vm/src/stdlib/weakref.rs @@ -46,7 +46,7 @@ fn ref_call(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn get_value(obj: &PyObjectRef) -> PyObjectWeakRef { - if let PyObjectPayload::WeakRef { referent } = &obj.borrow().payload { + if let PyObjectPayload::WeakRef { referent } = &obj.payload { referent.clone() } else { panic!("Inner error getting weak ref {:?}", obj); diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index 1e07b4d9b..00453f10e 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -30,7 +30,7 @@ fn sys_getrefcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn sys_getsizeof(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(object, None)]); // TODO: implement default optional argument. - let size = mem::size_of_val(&object.borrow()); + let size = mem::size_of_val(&object); Ok(vm.ctx.new_int(size)) } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 149a5313c..0a0f97ce5 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -190,7 +190,7 @@ impl VirtualMachine { } pub fn get_builtin_scope(&mut self) -> PyObjectRef { - let a2 = &*self.builtins.borrow(); + let a2 = &*self.builtins; match a2.payload { PyObjectPayload::Module { ref dict, .. } => dict.clone(), _ => { @@ -271,7 +271,7 @@ impl VirtualMachine { pub fn invoke(&mut self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult { trace!("Invoke: {:?} {:?}", func_ref, args); - match func_ref.borrow().payload { + match func_ref.payload { PyObjectPayload::RustFunction { ref function } => function(self, args), PyObjectPayload::Function { ref code, @@ -406,8 +406,8 @@ impl VirtualMachine { // Add missing positional arguments, if we have fewer positional arguments than the // function definition calls for if nargs < nexpected_args { - let available_defaults = match defaults.borrow().payload { - PyObjectPayload::Sequence { ref elements } => elements.clone(), + let available_defaults = match defaults.payload { + PyObjectPayload::Sequence { ref elements } => elements.borrow().clone(), PyObjectPayload::None => vec![], _ => panic!("function defaults not tuple or None"), }; @@ -493,11 +493,7 @@ impl VirtualMachine { let cls = obj.typ(); match cls.get_attr(method_name) { Some(method) => self.call_get_descriptor(method, obj.clone()), - None => Err(self.new_type_error(format!( - "{} has no method {:?}", - obj.borrow(), - method_name - ))), + None => Err(self.new_type_error(format!("{} has no method {:?}", obj, method_name))), } }