From 45bc8c8f7a983d3dad5371b7823e34fc676bf2de Mon Sep 17 00:00:00 2001 From: Joey Hain Date: Sun, 10 Mar 2019 12:17:50 -0700 Subject: [PATCH] Move PyRef to pyobject module --- vm/src/function.rs | 118 -------------------------------------- vm/src/lib.rs | 1 - vm/src/obj/objdict.rs | 12 ++-- vm/src/obj/objfloat.rs | 5 +- vm/src/obj/objint.rs | 3 +- vm/src/obj/objlist.rs | 3 +- vm/src/obj/objmodule.rs | 3 +- vm/src/obj/objnone.rs | 4 +- vm/src/obj/objobject.rs | 4 +- vm/src/obj/objproperty.rs | 8 +-- vm/src/obj/objstr.rs | 3 +- vm/src/obj/objtuple.rs | 3 +- vm/src/obj/objtype.rs | 18 +++--- vm/src/obj/objweakref.rs | 3 +- vm/src/pyobject.rs | 108 +++++++++++++++++++++++++++++++++- 15 files changed, 138 insertions(+), 158 deletions(-) delete mode 100644 vm/src/function.rs diff --git a/vm/src/function.rs b/vm/src/function.rs deleted file mode 100644 index c978be708..000000000 --- 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 78696f9f3..b32b91cb7 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/objdict.rs b/vm/src/obj/objdict.rs index fe27b5b28..84391cdd8 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -1,16 +1,16 @@ -use crate::function::PyRef; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; +use crate::pyobject::{ + PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyRef, PyResult, TypeProtocol, +}; +use crate::vm::{ReprGuard, VirtualMachine}; + use super::objiter; use super::objstr; use super::objtype; -use crate::pyobject::{ - PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, -}; -use crate::vm::{ReprGuard, VirtualMachine}; pub type DictContentType = HashMap; diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index f544adcc3..6f1790d68 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -2,10 +2,9 @@ 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, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyRef, + PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::ToBigInt; diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 8e5f3f59c..5b751faa0 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, + PyObjectPayload2, PyObjectRef, PyRef, PyResult, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index 8ad69bff3..ecabb009a 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, + PyObjectPayload2, PyObjectRef, PyRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; use num_traits::ToPrimitive; diff --git a/vm/src/obj/objmodule.rs b/vm/src/obj/objmodule.rs index 4f7a641b9..92f55566d 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, PyObjectPayload2, PyObjectRef, PyRef, PyResult}; use crate::vm::VirtualMachine; #[derive(Clone, Debug)] diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index 80980f528..6cde6ef06 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -1,6 +1,6 @@ -use crate::function::PyRef; use crate::pyobject::{ - IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 0d9d21f1e..54fcd1b6e 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, + PyObjectPayload, 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 { diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index b94692177..9aaea31cd 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -2,15 +2,15 @@ */ -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, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyRef, PyResult, }; use crate::VirtualMachine; -use std::marker::PhantomData; /// Read-only property, doesn't have __set__ or __delete__ #[derive(Debug)] diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 09ef07576..d9c39e337 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, + PyRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index e583055c3..95c1b12f9 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, + PyObjectPayload2, PyObjectRef, PyRef, PyResult, }; use crate::vm::{ReprGuard, VirtualMachine}; diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index be4591dfc..44bb9bc62 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -1,19 +1,21 @@ -use super::objdict; -use super::objstr; -use crate::function::PyRef; -use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, -}; -use crate::vm::VirtualMachine; use std::cell::RefCell; use std::collections::HashMap; +use crate::pyobject::{ + AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyRef, PyResult, TypeProtocol, +}; +use crate::vm::VirtualMachine; + +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 { diff --git a/vm/src/obj/objweakref.rs b/vm/src/obj/objweakref.rs index 8a4651de7..45cb4108a 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::{PyContext, PyObject, PyObjectRef, PyRef, PyResult}; use crate::vm::VirtualMachine; use std::rc::{Rc, Weak}; diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 23c269324..c7c99723c 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -2,7 +2,8 @@ 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 +43,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; @@ -741,6 +742,109 @@ pub struct PyObject { pub dict: Option>, // __dict__ member } +/// 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 +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) + } +} + pub trait IdProtocol { fn get_id(&self) -> usize; fn is(&self, other: &PyObjectRef) -> bool;