diff --git a/vm/src/compile.rs b/vm/src/compile.rs index 21ce3a99fa..08045eb535 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -8,7 +8,7 @@ use crate::bytecode::{self, CallType, CodeObject, Instruction}; use crate::error::CompileError; use crate::obj::objcode; -use crate::pyobject::{PyObject, PyObjectPayload, PyObjectRef}; +use crate::pyobject::{PyObject, PyObjectRef}; use num_complex::Complex64; use rustpython_parser::{ast, parser}; @@ -49,12 +49,7 @@ pub fn compile( let code = compiler.pop_code_object(); trace!("Compilation completed: {:?}", code); - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objcode::PyCode::new(code)), - }, - code_type, - )) + Ok(PyObject::new(objcode::PyCode::new(code), code_type)) } pub enum Mode { diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 0d87886370..48d3d6229c 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -22,8 +22,8 @@ use crate::obj::objslice::PySlice; use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ - DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TryFromObject, TypeProtocol, + DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -181,7 +181,7 @@ pub struct Frame { pub lasti: RefCell, // index of last instruction ran } -impl PyObjectPayload2 for Frame { +impl PyValue for Frame { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.frame_type() } @@ -407,12 +407,7 @@ impl Frame { let stop = out[1].take(); let step = if out.len() == 3 { out[2].take() } else { None }; - let obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySlice { start, stop, step }), - }, - vm.ctx.slice_type(), - ); + let obj = PyObject::new(PySlice { start, stop, step }, vm.ctx.slice_type()); self.push_value(obj); Ok(None) } @@ -706,11 +701,7 @@ impl Frame { } bytecode::Instruction::LoadBuildClass => { let rustfunc = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyBuiltinFunction::new(Box::new( - builtins::builtin_build_class_, - ))), - }, + PyBuiltinFunction::new(Box::new(builtins::builtin_build_class_)), vm.ctx.type_type(), ); self.push_value(rustfunc); diff --git a/vm/src/function.rs b/vm/src/function.rs deleted file mode 100644 index c978be7085..0000000000 --- a/vm/src/function.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::fmt; -use std::marker::PhantomData; -use std::ops::Deref; - -use crate::obj::objtype; -use crate::obj::objtype::PyClassRef; -use crate::pyobject::{ - IntoPyObject, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TryFromObject, TypeProtocol, -}; -use crate::vm::VirtualMachine; - -// TODO: Move PyFuncArgs, FromArgs, etc. here - -// TODO: `PyRef` probably actually belongs in the pyobject module. - -/// A reference to the payload of a built-in object. -/// -/// Note that a `PyRef` can only deref to a shared / immutable reference. -/// It is the payload type's responsibility to handle (possibly concurrent) -/// mutability with locks or concurrent data structures if required. -/// -/// A `PyRef` can be directly returned from a built-in function to handle -/// situations (such as when implementing in-place methods such as `__iadd__`) -/// where a reference to the same object must be returned. -#[derive(Clone)] -pub struct PyRef { - // invariant: this obj must always have payload of type T - obj: PyObjectRef, - _payload: PhantomData, -} - -impl PyRef -where - T: PyObjectPayload2, -{ - pub fn new(ctx: &PyContext, payload: T) -> Self { - PyRef { - obj: PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(payload), - }, - T::required_type(ctx), - ), - _payload: PhantomData, - } - } - - pub fn new_with_type(vm: &mut VirtualMachine, payload: T, cls: PyClassRef) -> PyResult { - let required_type = T::required_type(&vm.ctx); - if objtype::issubclass(&cls.obj, &required_type) { - Ok(PyRef { - obj: PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(payload), - }, - cls.obj, - ), - _payload: PhantomData, - }) - } else { - let subtype = vm.to_pystr(&cls.obj)?; - let basetype = vm.to_pystr(&required_type)?; - Err(vm.new_type_error(format!("{} is not a subtype of {}", subtype, basetype))) - } - } - - pub fn as_object(&self) -> &PyObjectRef { - &self.obj - } - pub fn into_object(self) -> PyObjectRef { - self.obj - } -} - -impl Deref for PyRef -where - T: PyObjectPayload2, -{ - type Target = T; - - fn deref(&self) -> &T { - self.obj.payload().expect("unexpected payload for type") - } -} - -impl TryFromObject for PyRef -where - T: PyObjectPayload2, -{ - fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult { - if objtype::isinstance(&obj, &T::required_type(&vm.ctx)) { - Ok(PyRef { - obj, - _payload: PhantomData, - }) - } else { - let expected_type = vm.to_pystr(&T::required_type(&vm.ctx))?; - let actual_type = vm.to_pystr(&obj.typ())?; - Err(vm.new_type_error(format!( - "Expected type {}, not {}", - expected_type, actual_type, - ))) - } - } -} - -impl IntoPyObject for PyRef { - fn into_pyobject(self, _ctx: &PyContext) -> PyResult { - Ok(self.obj) - } -} - -impl fmt::Display for PyRef { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.obj.fmt(f) - } -} diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 78696f9f3f..b32b91cb7d 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -41,7 +41,6 @@ pub mod eval; mod exceptions; pub mod format; pub mod frame; -pub mod function; pub mod import; pub mod obj; pub mod pyobject; diff --git a/vm/src/obj/objbuiltinfunc.rs b/vm/src/obj/objbuiltinfunc.rs index 8e3b2c3422..94a8bc59ba 100644 --- a/vm/src/obj/objbuiltinfunc.rs +++ b/vm/src/obj/objbuiltinfunc.rs @@ -1,13 +1,13 @@ use std::fmt; -use crate::pyobject::{PyContext, PyNativeFunc, PyObjectPayload2, PyObjectRef}; +use crate::pyobject::{PyContext, PyNativeFunc, PyObjectRef, PyValue}; pub struct PyBuiltinFunction { // TODO: shouldn't be public pub value: PyNativeFunc, } -impl PyObjectPayload2 for PyBuiltinFunction { +impl PyValue for PyBuiltinFunction { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.builtin_function_or_method_type() } diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index 77b1c14ebc..d737efaaea 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -5,8 +5,7 @@ use std::fmt::Write; use std::ops::{Deref, DerefMut}; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use super::objint; @@ -29,7 +28,7 @@ impl PyByteArray { } } -impl PyObjectPayload2 for PyByteArray { +impl PyValue for PyByteArray { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.bytearray_type() } @@ -173,12 +172,7 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else { vec![] }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyByteArray::new(value)), - }, - cls.clone(), - )) + Ok(PyObject::new(PyByteArray::new(value), cls.clone())) } fn bytesarray_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 2aa0006ddf..c78e919bbc 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -5,8 +5,7 @@ use std::ops::Deref; use super::objint; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; @@ -30,7 +29,7 @@ impl Deref for PyBytes { } } -impl PyObjectPayload2 for PyBytes { +impl PyValue for PyBytes { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.bytes_type() } @@ -95,12 +94,7 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { vec![] }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyBytes::new(value)), - }, - cls.clone(), - )) + Ok(PyObject::new(PyBytes::new(value), cls.clone())) } fn bytes_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -209,11 +203,9 @@ fn bytes_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytes_type()))]); let iter_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: obj.clone(), - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: obj.clone(), }, vm.ctx.iter_type(), ); diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index ccd2114aed..36aaf4eab8 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -4,7 +4,7 @@ use crate::bytecode; use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use std::fmt; @@ -25,7 +25,7 @@ impl fmt::Debug for PyCode { } } -impl PyObjectPayload2 for PyCode { +impl PyValue for PyCode { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.code_type() } diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index 66205559c9..75cd455f82 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -2,8 +2,7 @@ use super::objfloat; use super::objint; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_complex::Complex64; @@ -14,7 +13,7 @@ pub struct PyComplex { value: Complex64, } -impl PyObjectPayload2 for PyComplex { +impl PyValue for PyComplex { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.complex_type() } @@ -90,12 +89,7 @@ fn complex_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let value = Complex64::new(real, imag); - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyComplex { value }), - }, - cls.clone(), - )) + Ok(PyObject::new(PyComplex { value }, cls.clone())) } fn complex_real(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index fe27b5b28f..c5cc3ec992 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -1,17 +1,17 @@ -use crate::function::PyRef; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; -use super::objiter; -use super::objstr; -use super::objtype; use crate::pyobject::{ - PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, + PyValue, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; +use super::objiter; +use super::objstr; +use super::objtype; + pub type DictContentType = HashMap; #[derive(Default, Debug)] @@ -21,7 +21,7 @@ pub struct PyDict { } pub type PyDictRef = PyRef; -impl PyObjectPayload2 for PyDict { +impl PyValue for PyDict { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.dict_type() } @@ -251,11 +251,9 @@ fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let key_list = vm.ctx.new_list(keys); let iter_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: key_list, - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: key_list, }, vm.ctx.iter_type(), ); @@ -273,11 +271,9 @@ fn dict_values(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let values_list = vm.ctx.new_list(values); let iter_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: values_list, - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: values_list, }, vm.ctx.iter_type(), ); @@ -295,11 +291,9 @@ fn dict_items(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let items_list = vm.ctx.new_list(items); let iter_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: items_list, - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: items_list, }, vm.ctx.iter_type(), ); @@ -348,12 +342,10 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: // this is not ideal let ptr = PyObjectRef::into_raw(dict_type.clone()) as *mut PyObject; unsafe { - (*ptr).payload = PyObjectPayload::AnyRustValue { - value: Box::new(objtype::PyClass { - name: String::from("dict"), - mro: vec![object_type], - }), - }; + (*ptr).payload = Box::new(objtype::PyClass { + name: String::from("dict"), + mro: vec![object_type], + }); (*ptr).dict = Some(RefCell::new(HashMap::new())); (*ptr).typ = Some(type_type.clone()); } diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index aa573ad6f0..b37f610628 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -4,8 +4,7 @@ use std::ops::AddAssign; use super::objint; use super::objiter; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::BigInt; @@ -17,7 +16,7 @@ pub struct PyEnumerate { iterator: PyObjectRef, } -impl PyObjectPayload2 for PyEnumerate { +impl PyValue for PyEnumerate { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.enumerate_type() } @@ -37,11 +36,9 @@ fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; let iterator = objiter::get_iter(vm, iterable)?; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyEnumerate { - counter: RefCell::new(counter), - iterator, - }), + PyEnumerate { + counter: RefCell::new(counter), + iterator, }, cls.clone(), )) diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 94703be575..94cd15bb83 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -1,6 +1,5 @@ use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, - PyResult, TypeProtocol, + IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance @@ -13,7 +12,7 @@ pub struct PyFilter { iterator: PyObjectRef, } -impl PyObjectPayload2 for PyFilter { +impl PyValue for PyFilter { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.filter_type() } @@ -27,11 +26,9 @@ fn filter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); let iterator = objiter::get_iter(vm, iterable)?; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyFilter { - predicate: function.clone(), - iterator, - }), + PyFilter { + predicate: function.clone(), + iterator, }, cls.clone(), )) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index f544adcc36..ae16b625aa 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -2,10 +2,8 @@ use super::objbytes; use super::objint; use super::objstr; use super::objtype; -use crate::function::PyRef; use crate::pyobject::{ - IntoPyObject, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + IntoPyObject, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::ToBigInt; @@ -17,7 +15,7 @@ pub struct PyFloat { value: f64, } -impl PyObjectPayload2 for PyFloat { +impl PyValue for PyFloat { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.float_type() } @@ -190,12 +188,7 @@ impl PyFloatRef { let type_name = objtype::get_type_name(&arg.typ()); return Err(vm.new_type_error(format!("can't convert {} to float", type_name))); }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyFloat { value }), - }, - cls.clone(), - )) + Ok(PyObject::new(PyFloat { value }, cls.clone())) } fn mod_(self, other: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 2f278ca076..ec2a460737 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,6 +1,6 @@ use crate::frame::Scope; use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult, + AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -23,7 +23,7 @@ impl PyFunction { } } -impl PyObjectPayload2 for PyFunction { +impl PyValue for PyFunction { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.function_type() } @@ -42,7 +42,7 @@ impl PyMethod { } } -impl PyObjectPayload2 for PyMethod { +impl PyValue for PyMethod { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.bound_method_type() } diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 1babd5c9dc..8e2434c384 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -4,8 +4,7 @@ use crate::frame::{ExecutionResult, Frame}; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -14,7 +13,7 @@ pub struct PyGenerator { frame: PyObjectRef, } -impl PyObjectPayload2 for PyGenerator { +impl PyValue for PyGenerator { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.generator_type() } @@ -41,9 +40,7 @@ pub fn init(context: &PyContext) { pub fn new_generator(vm: &mut VirtualMachine, frame: PyObjectRef) -> PyResult { Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyGenerator { frame }), - }, + PyGenerator { frame }, vm.ctx.generator_type.clone(), )) } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 8e5f3f59c6..a7bc9e2b29 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -5,10 +5,9 @@ use num_integer::Integer; use num_traits::{Pow, Signed, ToPrimitive, Zero}; use crate::format::FormatSpec; -use crate::function::PyRef; use crate::pyobject::{ - FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TryFromObject, TypeProtocol, + FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyRef, PyResult, + PyValue, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -32,7 +31,7 @@ impl PyInt { } } -impl PyObjectPayload2 for PyInt { +impl PyValue for PyInt { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.int_type() } @@ -106,12 +105,7 @@ fn int_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Some(val) => to_int(vm, val, base)?, None => Zero::zero(), }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyInt::new(val)), - }, - cls.clone(), - )) + Ok(PyObject::new(PyInt::new(val), cls.clone())) } // Casting function: diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 8ad69bff31..8bf7dce249 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -8,10 +8,9 @@ use super::objsequence::{ }; use super::objstr; use super::objtype; -use crate::function::PyRef; use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, + PyResult, PyValue, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; use num_traits::ToPrimitive; @@ -30,7 +29,7 @@ impl From> for PyList { } } -impl PyObjectPayload2 for PyList { +impl PyValue for PyList { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.list_type() } @@ -112,11 +111,9 @@ impl PyListRef { fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: self.into_object(), - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: self.into_object(), }, vm.ctx.iter_type(), ) @@ -305,12 +302,7 @@ fn list_new( vec![] }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyList::from(elements)), - }, - cls.into_object(), - )) + Ok(PyObject::new(PyList::from(elements), cls.into_object())) } fn quicksort( diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 4cbb8d3ee9..c183da0df8 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -1,6 +1,5 @@ use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -12,7 +11,7 @@ pub struct PyMap { iterators: Vec, } -impl PyObjectPayload2 for PyMap { +impl PyValue for PyMap { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.map_type() } @@ -31,11 +30,9 @@ fn map_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { .map(|iterable| objiter::get_iter(vm, iterable)) .collect::, _>>()?; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyMap { - mapper: function.clone(), - iterators, - }), + PyMap { + mapper: function.clone(), + iterators, }, cls.clone(), )) diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 988abbed9c..0170ee435c 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -1,6 +1,5 @@ use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -9,7 +8,7 @@ pub struct PyMemoryView { obj: PyObjectRef, } -impl PyObjectPayload2 for PyMemoryView { +impl PyValue for PyMemoryView { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.memoryview_type() } @@ -19,10 +18,8 @@ pub fn new_memory_view(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(cls, None), (bytes_object, None)]); vm.ctx.set_attr(&cls, "obj", bytes_object.clone()); Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyMemoryView { - obj: bytes_object.clone(), - }), + PyMemoryView { + obj: bytes_object.clone(), }, cls.clone(), )) diff --git a/vm/src/obj/objmodule.rs b/vm/src/obj/objmodule.rs index 4f7a641b99..297ee6dc00 100644 --- a/vm/src/obj/objmodule.rs +++ b/vm/src/obj/objmodule.rs @@ -1,5 +1,4 @@ -use crate::function::PyRef; -use crate::pyobject::{DictProtocol, PyContext, PyObjectPayload2, PyObjectRef, PyResult}; +use crate::pyobject::{DictProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; #[derive(Clone, Debug)] @@ -9,7 +8,7 @@ pub struct PyModule { } pub type PyModuleRef = PyRef; -impl PyObjectPayload2 for PyModule { +impl PyValue for PyModule { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.module_type() } diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index 80980f5283..6e3bca6804 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -1,6 +1,5 @@ -use crate::function::PyRef; use crate::pyobject::{ - IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -8,7 +7,7 @@ use crate::vm::VirtualMachine; pub struct PyNone; pub type PyNoneRef = PyRef; -impl PyObjectPayload2 for PyNone { +impl PyValue for PyNone { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.none().typ() } diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 0d9d21f1ea..7a560399c5 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -1,10 +1,9 @@ use super::objstr; use super::objtype; -use crate::function::PyRef; use crate::obj::objproperty::PropertyBuilder; use crate::pyobject::{ AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, - PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyObjectRef, PyRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use std::cell::RefCell; @@ -12,6 +11,7 @@ use std::collections::HashMap; #[derive(Clone, Debug)] pub struct PyInstance; + pub type PyInstanceRef = PyRef; pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { @@ -25,12 +25,10 @@ pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_typ // this is not ideal let ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; unsafe { - (*ptr).payload = PyObjectPayload::AnyRustValue { - value: Box::new(objtype::PyClass { - name: String::from("object"), - mro: vec![], - }), - }; + (*ptr).payload = Box::new(objtype::PyClass { + name: String::from("object"), + mro: vec![], + }); (*ptr).dict = Some(RefCell::new(HashMap::new())); (*ptr).typ = Some(type_type.clone()); } diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index b94692177e..59117244d2 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -2,15 +2,14 @@ */ -use crate::function::PyRef; +use std::marker::PhantomData; + use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::IntoPyNativeFunc; use crate::pyobject::{ - OptionalArg, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + IntoPyNativeFunc, OptionalArg, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, }; use crate::VirtualMachine; -use std::marker::PhantomData; /// Read-only property, doesn't have __set__ or __delete__ #[derive(Debug)] @@ -18,7 +17,7 @@ pub struct PyReadOnlyProperty { getter: PyObjectRef, } -impl PyObjectPayload2 for PyReadOnlyProperty { +impl PyValue for PyReadOnlyProperty { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.readonly_property_type() } @@ -40,7 +39,7 @@ pub struct PyProperty { deleter: Option, } -impl PyObjectPayload2 for PyProperty { +impl PyValue for PyProperty { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.property_type() } @@ -138,12 +137,7 @@ impl<'a, T> PropertyBuilder<'a, T> { deleter: None, }; - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(payload), - }, - self.ctx.property_type(), - ) + PyObject::new(payload, self.ctx.property_type()) } else { let payload = PyReadOnlyProperty { getter: self.getter.expect( @@ -151,12 +145,7 @@ impl<'a, T> PropertyBuilder<'a, T> { ), }; - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(payload), - }, - self.ctx.readonly_property_type(), - ) + PyObject::new(payload, self.ctx.readonly_property_type()) } } } diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index f249a1f486..1e0eee53f6 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -6,8 +6,7 @@ use num_integer::Integer; use num_traits::{One, Signed, ToPrimitive, Zero}; use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -24,7 +23,7 @@ pub struct PyRange { pub step: BigInt, } -impl PyObjectPayload2 for PyRange { +impl PyValue for PyRange { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.range_type() } @@ -228,12 +227,7 @@ fn range_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if step.is_zero() { Err(vm.new_value_error("range with 0 step size".to_string())) } else { - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyRange { start, end, step }), - }, - cls.clone(), - )) + Ok(PyObject::new(PyRange { start, end, step }, cls.clone())) } } @@ -241,11 +235,9 @@ fn range_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(range, Some(vm.ctx.range_type()))]); Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: range.clone(), - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: range.clone(), }, vm.ctx.iter_type(), )) @@ -257,16 +249,9 @@ fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let range = get_value(zelf).reversed(); Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(range), - }, - vm.ctx.range_type(), - ), - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: PyObject::new(range, vm.ctx.range_type()), }, vm.ctx.iter_type(), )) @@ -330,12 +315,10 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyRange { - start: new_start, - end: new_end, - step: new_step, - }), + PyRange { + start: new_start, + end: new_end, + step: new_step, }, vm.ctx.range_type(), )) diff --git a/vm/src/obj/objsequence.rs b/vm/src/obj/objsequence.rs index 5d7ddaf329..120868d452 100644 --- a/vm/src/obj/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -5,7 +5,7 @@ use std::ops::{Deref, DerefMut, Range}; use num_bigint::BigInt; use num_traits::{One, Signed, ToPrimitive, Zero}; -use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{IdProtocol, PyObject, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use super::objbool; @@ -163,29 +163,25 @@ pub fn get_item( } if subscript.payload::().is_some() { - let payload = if sequence.payload::().is_some() { - PyObjectPayload::AnyRustValue { - value: Box::new(PyList::from( - elements.to_vec().get_slice_items(vm, &subscript)?, - )), - } + if sequence.payload::().is_some() { + Ok(PyObject::new( + PyList::from(elements.to_vec().get_slice_items(vm, &subscript)?), + sequence.typ(), + )) } else if sequence.payload::().is_some() { - PyObjectPayload::AnyRustValue { - value: Box::new(PyTuple::from( - elements.to_vec().get_slice_items(vm, &subscript)?, - )), - } + Ok(PyObject::new( + PyTuple::from(elements.to_vec().get_slice_items(vm, &subscript)?), + sequence.typ(), + )) } else { panic!("sequence get_item called for non-sequence") - }; - - return Ok(PyObject::new(payload, sequence.typ())); + } + } else { + Err(vm.new_type_error(format!( + "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", + sequence, subscript + ))) } - - Err(vm.new_type_error(format!( - "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", - sequence, subscript - ))) } pub fn seq_equal( diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index 76eca5ec2a..bb8483a0e2 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -13,8 +13,7 @@ use super::objiter; use super::objstr; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -23,7 +22,7 @@ pub struct PySet { elements: RefCell>, } -impl PyObjectPayload2 for PySet { +impl PyValue for PySet { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.set_type() } @@ -169,10 +168,8 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { }; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySet { - elements: RefCell::new(elements), - }), + PySet { + elements: RefCell::new(elements), }, cls.clone(), )) @@ -190,10 +187,8 @@ 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::AnyRustValue { - value: Box::new(PySet { - elements: RefCell::new(elements), - }), + PySet { + elements: RefCell::new(elements), }, vm.ctx.set_type(), )) @@ -346,10 +341,8 @@ fn set_union(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { elements.extend(get_elements(other).clone()); Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySet { - elements: RefCell::new(elements), - }), + PySet { + elements: RefCell::new(elements), }, vm.ctx.set_type(), )) @@ -390,10 +383,8 @@ fn set_symmetric_difference(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResu } Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySet { - elements: RefCell::new(elements), - }), + PySet { + elements: RefCell::new(elements), }, vm.ctx.set_type(), )) @@ -432,10 +423,8 @@ fn set_combine_inner( } Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySet { - elements: RefCell::new(elements), - }), + PySet { + elements: RefCell::new(elements), }, vm.ctx.set_type(), )) @@ -566,11 +555,9 @@ fn set_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let items = get_elements(zelf).values().cloned().collect(); let set_list = vm.ctx.new_list(items); let iter_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: set_list, - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: set_list, }, vm.ctx.iter_type(), ); diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 45b92b5af6..5ab3c7a332 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -1,7 +1,6 @@ use super::objint; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::BigInt; @@ -14,7 +13,7 @@ pub struct PySlice { pub step: Option, } -impl PyObjectPayload2 for PySlice { +impl PyValue for PySlice { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.slice_type() } @@ -55,12 +54,10 @@ fn slice_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } }?; Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySlice { - start: start.map(|x| objint::get_value(x)), - stop: stop.map(|x| objint::get_value(x)), - step: step.map(|x| objint::get_value(x)), - }), + PySlice { + start: start.map(|x| objint::get_value(x)), + stop: stop.map(|x| objint::get_value(x)), + step: step.map(|x| objint::get_value(x)), }, cls.clone(), )) diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 09ef07576d..a0e2e110d7 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -6,10 +6,9 @@ use num_traits::ToPrimitive; use unicode_segmentation::UnicodeSegmentation; use crate::format::{FormatParseError, FormatPart, FormatString}; -use crate::function::PyRef; use crate::pyobject::{ - IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectPayload2, PyObjectRef, - PyResult, TypeProtocol, + IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectRef, PyRef, PyResult, + PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -597,7 +596,7 @@ impl PyStringRef { } } -impl PyObjectPayload2 for PyString { +impl PyValue for PyString { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.str_type() } diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index e583055c30..2c692469fc 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -1,10 +1,9 @@ use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; -use crate::function::PyRef; use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyIteratorValue, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, + IdProtocol, OptionalArg, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, + PyValue, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -31,7 +30,7 @@ impl From> for PyTuple { } } -impl PyObjectPayload2 for PyTuple { +impl PyValue for PyTuple { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.tuple_type() } @@ -127,11 +126,9 @@ impl PyTupleRef { fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyIteratorValue { - position: Cell::new(0), - iterated_obj: self.into_object(), - }), + PyIteratorValue { + position: Cell::new(0), + iterated_obj: self.into_object(), }, vm.ctx.iter_type(), ) @@ -216,12 +213,7 @@ fn tuple_new( vec![] }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyTuple::from(elements)), - }, - cls.into_object(), - )) + Ok(PyObject::new(PyTuple::from(elements), cls.into_object())) } #[rustfmt::skip] // to avoid line splitting diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index be4591dfcd..3b893f321e 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -1,22 +1,24 @@ -use super::objdict; -use super::objstr; -use crate::function::PyRef; +use std::cell::RefCell; +use std::collections::HashMap; + use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectRef, + PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; -use std::cell::RefCell; -use std::collections::HashMap; + +use super::objdict; +use super::objstr; #[derive(Clone, Debug)] pub struct PyClass { pub name: String, pub mro: Vec, } + pub type PyClassRef = PyRef; -impl PyObjectPayload2 for PyClass { +impl PyValue for PyClass { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.type_type() } @@ -30,12 +32,10 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: // this is not ideal let ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; unsafe { - (*ptr).payload = PyObjectPayload::AnyRustValue { - value: Box::new(PyClass { - name: String::from("type"), - mro: vec![object_type], - }), - }; + (*ptr).payload = Box::new(PyClass { + name: String::from("type"), + mro: vec![object_type], + }); (*ptr).dict = Some(RefCell::new(PyAttributes::new())); (*ptr).typ = Some(type_type); } @@ -318,12 +318,10 @@ pub fn new( let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect(); let mro = linearise_mro(mros).unwrap(); Ok(PyObject { - payload: PyObjectPayload::AnyRustValue { - value: Box::new(PyClass { - name: String::from(name), - mro, - }), - }, + payload: Box::new(PyClass { + name: String::from(name), + mro, + }), dict: Some(RefCell::new(dict)), typ: Some(typ), } diff --git a/vm/src/obj/objweakref.rs b/vm/src/obj/objweakref.rs index 8a4651de73..d2e2d08dc4 100644 --- a/vm/src/obj/objweakref.rs +++ b/vm/src/obj/objweakref.rs @@ -1,7 +1,6 @@ -use crate::function::PyRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::PyObjectPayload2; -use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult}; +use crate::pyobject::PyValue; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyRef, PyResult}; use crate::vm::VirtualMachine; use std::rc::{Rc, Weak}; @@ -23,7 +22,7 @@ impl PyWeak { } } -impl PyObjectPayload2 for PyWeak { +impl PyValue for PyWeak { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.weakref_type() } diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index 70cded6b20..8831564a8f 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -1,6 +1,5 @@ use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -11,7 +10,7 @@ pub struct PyZip { iterators: Vec, } -impl PyObjectPayload2 for PyZip { +impl PyValue for PyZip { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.zip_type() } @@ -25,12 +24,7 @@ fn zip_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { .iter() .map(|iterable| objiter::get_iter(vm, iterable)) .collect::, _>>()?; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyZip { iterators }), - }, - cls.clone(), - )) + Ok(PyObject::new(PyZip { iterators }, cls.clone())) } fn zip_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 23c269324a..55ea50a390 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,8 +1,10 @@ +use std::any::Any; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::fmt; use std::iter; -use std::ops::RangeInclusive; +use std::marker::PhantomData; +use std::ops::{Deref, RangeInclusive}; use std::rc::Rc; use num_bigint::BigInt; @@ -42,7 +44,7 @@ use crate::obj::objslice; use crate::obj::objstr; use crate::obj::objsuper; use crate::obj::objtuple::{self, PyTuple}; -use crate::obj::objtype::{self, PyClass}; +use crate::obj::objtype::{self, PyClass, PyClassRef}; use crate::obj::objweakref; use crate::obj::objzip; use crate::vm::VirtualMachine; @@ -159,6 +161,24 @@ pub fn create_type( objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap() } +#[derive(Debug)] +pub struct PyNotImplemented; + +impl PyValue for PyNotImplemented { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.not_implemented().typ() + } +} + +#[derive(Debug)] +pub struct PyEllipsis; + +impl PyValue for PyEllipsis { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.ellipsis_type.clone() + } +} + // Basic objects: impl PyContext { pub fn new() -> Self { @@ -212,38 +232,19 @@ impl PyContext { let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type, &dict_type); let none = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objnone::PyNone), - }, + objnone::PyNone, create_type("NoneType", &type_type, &object_type, &dict_type), ); - let ellipsis = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(()), - }, - ellipsis_type.clone(), - ); + let ellipsis = PyObject::new(PyEllipsis, ellipsis_type.clone()); let not_implemented = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(()), - }, + PyNotImplemented, create_type("NotImplementedType", &type_type, &object_type, &dict_type), ); - let true_value = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyInt::new(BigInt::one())), - }, - bool_type.clone(), - ); - let false_value = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyInt::new(BigInt::zero())), - }, - bool_type.clone(), - ); + let true_value = PyObject::new(PyInt::new(BigInt::one()), bool_type.clone()); + let false_value = PyObject::new(PyInt::new(BigInt::zero()), bool_type.clone()); let context = PyContext { bool_type, memoryview_type, @@ -481,57 +482,27 @@ impl PyContext { } pub fn new_int(&self, i: T) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyInt::new(i)), - }, - self.int_type(), - ) + PyObject::new(PyInt::new(i), self.int_type()) } pub fn new_float(&self, value: f64) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyFloat::from(value)), - }, - self.float_type(), - ) + PyObject::new(PyFloat::from(value), self.float_type()) } pub fn new_complex(&self, value: Complex64) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyComplex::from(value)), - }, - self.complex_type(), - ) + PyObject::new(PyComplex::from(value), self.complex_type()) } pub fn new_str(&self, s: String) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objstr::PyString { value: s }), - }, - self.str_type(), - ) + PyObject::new(objstr::PyString { value: s }, self.str_type()) } pub fn new_bytes(&self, data: Vec) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objbytes::PyBytes::new(data)), - }, - self.bytes_type(), - ) + PyObject::new(objbytes::PyBytes::new(data), self.bytes_type()) } pub fn new_bytearray(&self, data: Vec) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objbytearray::PyByteArray::new(data)), - }, - self.bytearray_type(), - ) + PyObject::new(objbytearray::PyByteArray::new(data), self.bytearray_type()) } pub fn new_bool(&self, b: bool) -> PyObjectRef { @@ -543,41 +514,21 @@ impl PyContext { } pub fn new_tuple(&self, elements: Vec) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyTuple::from(elements)), - }, - self.tuple_type(), - ) + PyObject::new(PyTuple::from(elements), self.tuple_type()) } pub fn new_list(&self, elements: Vec) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyList::from(elements)), - }, - self.list_type(), - ) + PyObject::new(PyList::from(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. - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PySet::default()), - }, - self.set_type(), - ) + PyObject::new(PySet::default(), self.set_type()) } pub fn new_dict(&self) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyDict::default()), - }, - self.dict_type(), - ) + PyObject::new(PyDict::default(), self.dict_type()) } pub fn new_class(&self, name: &str, base: PyObjectRef) -> PyObjectRef { @@ -590,11 +541,9 @@ impl PyContext { pub fn new_module(&self, name: &str, dict: PyObjectRef) -> PyObjectRef { PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyModule { - name: name.to_string(), - dict, - }), + PyModule { + name: name.to_string(), + dict, }, self.module_type.clone(), ) @@ -605,20 +554,13 @@ impl PyContext { F: IntoPyNativeFunc, { PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyBuiltinFunction::new(f.into_func())), - }, + PyBuiltinFunction::new(f.into_func()), self.builtin_function_or_method_type(), ) } pub fn new_frame(&self, code: PyObjectRef, scope: Scope) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(Frame::new(code, scope)), - }, - self.frame_type(), - ) + PyObject::new(Frame::new(code, scope), self.frame_type()) } pub fn new_property(&self, f: F) -> PyObjectRef @@ -629,12 +571,7 @@ impl PyContext { } pub fn new_code_object(&self, code: bytecode::CodeObject) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(objcode::PyCode::new(code)), - }, - self.code_type(), - ) + PyObject::new(objcode::PyCode::new(code), self.code_type()) } pub fn new_function( @@ -644,20 +581,13 @@ impl PyContext { defaults: PyObjectRef, ) -> PyObjectRef { PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyFunction::new(code_obj, scope, defaults)), - }, + PyFunction::new(code_obj, scope, defaults), self.function_type(), ) } pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyMethod::new(object, function)), - }, - self.bound_method_type(), - ) + PyObject::new(PyMethod::new(object, function), self.bound_method_type()) } pub fn new_instance(&self, class: PyObjectRef, dict: Option) -> PyObjectRef { @@ -667,11 +597,9 @@ impl PyContext { PyAttributes::new() }; PyObject { - payload: PyObjectPayload::AnyRustValue { - value: Box::new(objobject::PyInstance), - }, typ: Some(class), dict: Some(RefCell::new(dict)), + payload: Box::new(objobject::PyInstance), } .into_ref() } @@ -734,11 +662,110 @@ impl Default for PyContext { /// This is an actual python object. It consists of a `typ` which is the /// python class, and carries some rust payload optionally. This rust /// payload can be a rust float or rust int in case of float and int objects. -#[derive(Default)] pub struct PyObject { - pub payload: PyObjectPayload, pub typ: Option, pub dict: Option>, // __dict__ member + pub payload: Box, +} + +impl Default for PyObject { + fn default() -> Self { + PyObject { + typ: None, + dict: None, + payload: Box::new(()), + } + } +} + +/// A reference to a Python object. +/// +/// Note that a `PyRef` can only deref to a shared / immutable reference. +/// It is the payload type's responsibility to handle (possibly concurrent) +/// mutability with locks or concurrent data structures if required. +/// +/// A `PyRef` can be directly returned from a built-in function to handle +/// situations (such as when implementing in-place methods such as `__iadd__`) +/// where a reference to the same object must be returned. +#[derive(Clone)] +pub struct PyRef { + // invariant: this obj must always have payload of type T + obj: PyObjectRef, + _payload: PhantomData, +} + +impl PyRef { + pub fn new(ctx: &PyContext, payload: T) -> Self { + PyRef { + obj: PyObject::new(payload, T::required_type(ctx)), + _payload: PhantomData, + } + } + + pub fn new_with_type(vm: &mut VirtualMachine, payload: T, cls: PyClassRef) -> PyResult { + let required_type = T::required_type(&vm.ctx); + if objtype::issubclass(&cls.obj, &required_type) { + Ok(PyRef { + obj: PyObject::new(payload, cls.obj), + _payload: PhantomData, + }) + } else { + let subtype = vm.to_pystr(&cls.obj)?; + let basetype = vm.to_pystr(&required_type)?; + Err(vm.new_type_error(format!("{} is not a subtype of {}", subtype, basetype))) + } + } + + pub fn as_object(&self) -> &PyObjectRef { + &self.obj + } + pub fn into_object(self) -> PyObjectRef { + self.obj + } +} + +impl Deref for PyRef +where + T: PyValue, +{ + type Target = T; + + fn deref(&self) -> &T { + self.obj.payload().expect("unexpected payload for type") + } +} + +impl TryFromObject for PyRef +where + T: PyValue, +{ + fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult { + if objtype::isinstance(&obj, &T::required_type(&vm.ctx)) { + Ok(PyRef { + obj, + _payload: PhantomData, + }) + } else { + let expected_type = vm.to_pystr(&T::required_type(&vm.ctx))?; + let actual_type = vm.to_pystr(&obj.typ())?; + Err(vm.new_type_error(format!( + "Expected type {}, not {}", + expected_type, actual_type, + ))) + } + } +} + +impl IntoPyObject for PyRef { + fn into_pyobject(self, _ctx: &PyContext) -> PyResult { + Ok(self.obj) + } +} + +impl fmt::Display for PyRef { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.obj.fmt(f) + } } pub trait IdProtocol { @@ -1345,15 +1372,10 @@ where // explicitly implementing `IntoPyObject`. impl IntoPyObject for T where - T: PyObjectPayload2 + Sized, + T: PyValue + Sized, { fn into_pyobject(self, ctx: &PyContext) -> PyResult { - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(self), - }, - T::required_type(ctx), - )) + Ok(PyObject::new(self, T::required_type(ctx))) } } @@ -1483,22 +1505,6 @@ into_py_native_func_tuple!((a, A), (b, B), (c, C)); into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D)); into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E)); -/// Rather than determining the type of a python object, this enum is more -/// a holder for the rust payload of a python object. It is more a carrier -/// of rust data for a particular python object. Determine the python type -/// by using for example the `.typ()` method on a python object. -pub enum PyObjectPayload { - AnyRustValue { value: Box }, -} - -impl Default for PyObjectPayload { - fn default() -> Self { - PyObjectPayload::AnyRustValue { - value: Box::new(()), - } - } -} - // TODO: This is a workaround and shouldn't exist. // Each iterable type should have its own distinct iterator type. #[derive(Debug)] @@ -1507,26 +1513,18 @@ pub struct PyIteratorValue { pub iterated_obj: PyObjectRef, } -impl PyObjectPayload2 for PyIteratorValue { +impl PyValue for PyIteratorValue { fn required_type(ctx: &PyContext) -> PyObjectRef { ctx.iter_type() } } -impl fmt::Debug for PyObjectPayload { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - PyObjectPayload::AnyRustValue { value } => value.fmt(f), - } - } -} - impl PyObject { - pub fn new(payload: PyObjectPayload, typ: PyObjectRef) -> PyObjectRef { + pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { - payload, typ: Some(typ), dict: Some(RefCell::new(PyAttributes::new())), + payload: Box::new(payload), } .into_ref() } @@ -1536,15 +1534,14 @@ impl PyObject { Rc::new(self) } - pub fn payload(&self) -> Option<&T> { - let PyObjectPayload::AnyRustValue { ref value } = self.payload; - value.downcast_ref() + pub fn payload(&self) -> Option<&T> { + self.payload.downcast_ref() } } // The intention is for this to replace `PyObjectPayload` once everything is // converted to use `PyObjectPayload::AnyRustvalue`. -pub trait PyObjectPayload2: std::any::Any + fmt::Debug { +pub trait PyValue: Any + fmt::Debug { fn required_type(ctx: &PyContext) -> PyObjectRef; } diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index 0828a13d14..d9e1a2e761 100644 --- a/vm/src/stdlib/re.rs +++ b/vm/src/stdlib/re.rs @@ -12,10 +12,17 @@ use std::path::PathBuf; use crate::obj::objstr; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::VirtualMachine; +impl PyValue for Regex { + fn required_type(_ctx: &PyContext) -> PyObjectRef { + // TODO + unimplemented!() + } +} + /// Create the python `re` module with all its members. pub fn mk_module(ctx: &PyContext) -> PyObjectRef { let match_type = py_class!(ctx, "Match", ctx.object(), { @@ -97,11 +104,19 @@ fn make_regex(vm: &mut VirtualMachine, pattern: &PyObjectRef) -> PyResult } /// Inner data for a match object. +#[derive(Debug)] struct PyMatch { start: usize, end: usize, } +impl PyValue for PyMatch { + fn required_type(_ctx: &PyContext) -> PyObjectRef { + // TODO + unimplemented!() + } +} + /// Take a found regular expression and convert it to proper match object. fn create_match(vm: &mut VirtualMachine, match_value: &Match) -> PyResult { // Return match object: @@ -118,12 +133,7 @@ fn create_match(vm: &mut VirtualMachine, match_value: &Match) -> PyResult { end: match_value.end(), }; - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(match_value), - }, - match_class.clone(), - )) + Ok(PyObject::new(match_value, match_class.clone())) } /// Compile a regular expression into a Pattern object. @@ -141,12 +151,7 @@ fn re_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let module = import::import_module(vm, PathBuf::default(), "re").unwrap(); let pattern_class = vm.ctx.get_attr(&module, "Pattern").unwrap(); - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(regex), - }, - pattern_class.clone(), - )) + Ok(PyObject::new(regex, pattern_class.clone())) } fn pattern_match(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -192,8 +197,7 @@ fn match_end(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { /// Retrieve inner rust regex from python object: fn get_regex<'a>(obj: &'a PyObjectRef) -> &'a Regex { // TODO: Regex shouldn't be stored in payload directly, create newtype wrapper - let PyObjectPayload::AnyRustValue { ref value } = obj.payload; - if let Some(regex) = value.downcast_ref::() { + if let Some(regex) = obj.payload.downcast_ref::() { return regex; } panic!("Inner error getting regex {:?}", obj); @@ -201,8 +205,7 @@ fn get_regex<'a>(obj: &'a PyObjectRef) -> &'a Regex { /// Retrieve inner rust match from python object: fn get_match<'a>(obj: &'a PyObjectRef) -> &'a PyMatch { - let PyObjectPayload::AnyRustValue { ref value } = obj.payload; - if let Some(value) = value.downcast_ref::() { + if let Some(value) = obj.payload.downcast_ref::() { return value; } panic!("Inner error getting match {:?}", obj); diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index d6e6283af9..df8bd33243 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -3,20 +3,20 @@ use std::io; use std::io::Read; use std::io::Write; use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; -use std::ops::DerefMut; +use std::ops::Deref; use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objsequence::get_elements; use crate::obj::objstr; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] enum AddressFamily { Unix = 1, Inet = 2, @@ -34,7 +34,7 @@ impl AddressFamily { } } -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] enum SocketKind { Stream = 1, Dgram = 2, @@ -50,6 +50,7 @@ impl SocketKind { } } +#[derive(Debug)] enum Connection { TcpListener(TcpListener), TcpStream(TcpStream), @@ -110,10 +111,18 @@ impl Write for Connection { } } +#[derive(Debug)] pub struct Socket { address_family: AddressFamily, socket_kind: SocketKind, - con: Option, + con: RefCell>, +} + +impl PyValue for Socket { + fn required_type(_ctx: &PyContext) -> PyObjectRef { + // TODO + unimplemented!() + } } impl Socket { @@ -121,17 +130,13 @@ impl Socket { Socket { address_family, socket_kind, - con: None, + con: RefCell::new(None), } } } -fn get_socket<'a>(obj: &'a PyObjectRef) -> impl DerefMut + 'a { - let PyObjectPayload::AnyRustValue { ref value } = obj.payload; - if let Some(socket) = value.downcast_ref::>() { - return socket.borrow_mut(); - } - panic!("Inner error getting socket {:?}", obj); +fn get_socket<'a>(obj: &'a PyObjectRef) -> impl Deref + 'a { + obj.payload::().unwrap() } fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -149,12 +154,8 @@ fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { AddressFamily::from_i32(vm, objint::get_value(family_int).to_i32().unwrap())?; let kind = SocketKind::from_i32(vm, objint::get_value(kind_int).to_i32().unwrap())?; - let socket = RefCell::new(Socket::new(address_family, kind)); - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(socket), - }, + Socket::new(address_family, kind), cls.clone(), )) } @@ -168,18 +169,21 @@ fn socket_connect(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let address_string = get_address_string(vm, address)?; - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); match socket.socket_kind { SocketKind::Stream => match TcpStream::connect(address_string) { Ok(stream) => { - socket.con = Some(Connection::TcpStream(stream)); + socket + .con + .borrow_mut() + .replace(Connection::TcpStream(stream)); Ok(vm.get_none()) } Err(s) => Err(vm.new_os_error(s.to_string())), }, SocketKind::Dgram => { - if let Some(Connection::UdpSocket(con)) = &socket.con { + if let Some(Connection::UdpSocket(con)) = socket.con.borrow().as_ref() { match con.connect(address_string) { Ok(_) => Ok(vm.get_none()), Err(s) => Err(vm.new_os_error(s.to_string())), @@ -200,19 +204,25 @@ fn socket_bind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let address_string = get_address_string(vm, address)?; - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); match socket.socket_kind { SocketKind::Stream => match TcpListener::bind(address_string) { Ok(stream) => { - socket.con = Some(Connection::TcpListener(stream)); + socket + .con + .borrow_mut() + .replace(Connection::TcpListener(stream)); Ok(vm.get_none()) } Err(s) => Err(vm.new_os_error(s.to_string())), }, SocketKind::Dgram => match UdpSocket::bind(address_string) { Ok(dgram) => { - socket.con = Some(Connection::UdpSocket(dgram)); + socket + .con + .borrow_mut() + .replace(Connection::UdpSocket(dgram)); Ok(vm.get_none()) } Err(s) => Err(vm.new_os_error(s.to_string())), @@ -256,10 +266,10 @@ 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 socket = get_socket(zelf); + let socket = get_socket(zelf); - let ret = match socket.con { - Some(ref mut v) => v.accept(), + let ret = match socket.con.borrow_mut().as_mut() { + Some(v) => v.accept(), None => return Err(vm.new_type_error("".to_string())), }; @@ -268,18 +278,13 @@ fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Err(s) => return Err(vm.new_os_error(s.to_string())), }; - let socket = RefCell::new(Socket { + let socket = Socket { address_family: socket.address_family, socket_kind: socket.socket_kind, - con: Some(Connection::TcpStream(tcp_stream)), - }); + con: RefCell::new(Some(Connection::TcpStream(tcp_stream))), + }; - let sock_obj = PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(socket), - }, - zelf.typ(), - ); + let sock_obj = PyObject::new(socket, zelf.typ()); let addr_tuple = get_addr_tuple(vm, addr)?; @@ -292,11 +297,11 @@ fn socket_recv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(zelf, None), (bufsize, Some(vm.ctx.int_type()))] ); - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); let mut buffer = vec![0u8; objint::get_value(bufsize).to_usize().unwrap()]; - match socket.con { - Some(ref mut v) => match v.read_exact(&mut buffer) { + match socket.con.borrow_mut().as_mut() { + Some(v) => match v.read_exact(&mut buffer) { Ok(_) => (), Err(s) => return Err(vm.new_os_error(s.to_string())), }, @@ -312,11 +317,11 @@ fn socket_recvfrom(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(zelf, None), (bufsize, Some(vm.ctx.int_type()))] ); - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); let mut buffer = vec![0u8; objint::get_value(bufsize).to_usize().unwrap()]; - let ret = match socket.con { - Some(ref mut v) => v.recv_from(&mut buffer), + let ret = match socket.con.borrow().as_ref() { + Some(v) => v.recv_from(&mut buffer), None => return Err(vm.new_type_error("".to_string())), }; @@ -336,10 +341,10 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(zelf, None), (bytes, Some(vm.ctx.bytes_type()))] ); - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); - match socket.con { - Some(ref mut v) => match v.write(&objbytes::get_value(&bytes)) { + match socket.con.borrow_mut().as_mut() { + Some(v) => match v.write(&objbytes::get_value(&bytes)) { Ok(_) => (), Err(s) => return Err(vm.new_os_error(s.to_string())), }, @@ -360,30 +365,29 @@ fn socket_sendto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); let address_string = get_address_string(vm, address)?; - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); match socket.socket_kind { SocketKind::Dgram => { - match socket.con { - Some(ref mut v) => match v.send_to(&objbytes::get_value(&bytes), address_string) { + if let Some(v) = socket.con.borrow().as_ref() { + return match v.send_to(&objbytes::get_value(&bytes), address_string) { Ok(_) => Ok(vm.get_none()), Err(s) => Err(vm.new_os_error(s.to_string())), - }, - None => { - // Doing implicit bind - match UdpSocket::bind("0.0.0.0:0") { - Ok(dgram) => { - match dgram.send_to(&objbytes::get_value(&bytes), address_string) { - Ok(_) => { - socket.con = Some(Connection::UdpSocket(dgram)); - Ok(vm.get_none()) - } - Err(s) => Err(vm.new_os_error(s.to_string())), - } - } - Err(s) => Err(vm.new_os_error(s.to_string())), + }; + } + // Doing implicit bind + match UdpSocket::bind("0.0.0.0:0") { + Ok(dgram) => match dgram.send_to(&objbytes::get_value(&bytes), address_string) { + Ok(_) => { + socket + .con + .borrow_mut() + .replace(Connection::UdpSocket(dgram)); + Ok(vm.get_none()) } - } + Err(s) => Err(vm.new_os_error(s.to_string())), + }, + Err(s) => Err(vm.new_os_error(s.to_string())), } } _ => Err(vm.new_not_implemented_error("".to_string())), @@ -393,17 +397,17 @@ fn socket_sendto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn socket_close(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, None)]); - let mut socket = get_socket(zelf); - socket.con = None; + let socket = get_socket(zelf); + socket.con.borrow_mut().take(); Ok(vm.get_none()) } fn socket_getsockname(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(zelf, None)]); - let mut socket = get_socket(zelf); + let socket = get_socket(zelf); - let addr = match socket.con { - Some(ref mut v) => v.local_addr(), + let addr = match socket.con.borrow().as_ref() { + Some(v) => v.local_addr(), None => return Err(vm.new_type_error("".to_string())), }; diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index d8014ae520..f6362be0ea 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -4,7 +4,7 @@ use js_sys::Promise; use num_traits::cast::ToPrimitive; use rustpython_vm::obj::{objint, objstr}; use rustpython_vm::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use rustpython_vm::{import::import, VirtualMachine}; use std::path::PathBuf; @@ -151,26 +151,27 @@ fn browser_cancel_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> Ok(vm.get_none()) } +#[derive(Debug)] pub struct PyPromise { value: Promise, } +impl PyValue for PyPromise { + fn required_type(_ctx: &PyContext) -> PyObjectRef { + // TODO + unimplemented!() + } +} + impl PyPromise { pub fn new_obj(promise_type: PyObjectRef, value: Promise) -> PyObjectRef { - PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyPromise { value }), - }, - promise_type, - ) + PyObject::new(PyPromise { value }, promise_type) } } pub fn get_promise_value(obj: &PyObjectRef) -> Promise { - if let PyObjectPayload::AnyRustValue { value } = &obj.payload { - if let Some(promise) = value.downcast_ref::() { - return promise.value.clone(); - } + if let Some(promise) = obj.payload.downcast_ref::() { + return promise.value.clone(); } panic!("Inner error getting promise") }