Implement MemberDescrObject setter

This commit is contained in:
Moreal authored and Jeong YunWon committed 2022-09-18 06:49:37 +09:00
1 parent 768a8e5148
commit e7b39bdc8a
5 files changed
+79 -8

No files matched your search

+1 -1
View File
@@ -694,7 +694,7 @@ where
quote_spanned! { ident.span() =>
class.set_str_attr(
#py_name,
ctx.new_member(#py_name, Self::#ident, class),
ctx.new_member(#py_name, Self::#ident, None, class),
ctx,
);
}
+53
View File
@@ -1,6 +1,7 @@
use super::{PyStr, PyType, PyTypeRef};
use crate::{
class::PyClassImpl,
function::PySetterValue,
types::{Constructor, GetDescriptor, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
@@ -18,15 +19,23 @@ pub enum MemberKind {
ObjectEx = 16,
}
pub type MemberSetterFunc = Option<fn(&VirtualMachine, PyObjectRef, PySetterValue) -> PyResult<()>>;
pub enum MemberGetter {
Getter(fn(&VirtualMachine, PyObjectRef) -> PyResult),
Offset(usize),
}
pub enum MemberSetter {
Setter(MemberSetterFunc),
Offset(usize),
}
pub struct MemberDef {
pub name: String,
pub kind: MemberKind,
pub getter: MemberGetter,
pub setter: MemberSetter,
pub doc: Option<String>,
}
@@ -37,6 +46,21 @@ impl MemberDef {
MemberGetter::Offset(offset) => get_slot_from_object(obj, offset, self, vm),
}
}
fn set(
&self,
obj: PyObjectRef,
value: PySetterValue<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
match self.setter {
MemberSetter::Setter(setter) => match setter {
Some(setter) => (setter)(vm, obj, value),
None => Err(vm.new_attribute_error("readonly attribute".to_string())),
},
MemberSetter::Offset(offset) => set_slot_at_object(obj, offset, self, value, vm),
}
}
}
impl std::fmt::Debug for MemberDef {
@@ -103,6 +127,17 @@ impl MemberDescrObject {
qualname.to_owned()
})
}
#[pyslot]
fn descr_set(
zelf: PyObjectRef,
obj: PyObjectRef,
value: PySetterValue<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
let zelf = Self::_zelf(zelf, vm)?;
zelf.member.set(obj, value, vm)
}
}
// PyMember_GetOne
@@ -124,6 +159,24 @@ fn get_slot_from_object(
Ok(slot)
}
// PyMember_SetOne
fn set_slot_at_object(
obj: PyObjectRef,
offset: usize,
member: &MemberDef,
value: PySetterValue,
_vm: &VirtualMachine,
) -> PyResult<()> {
match member.kind {
MemberKind::ObjectEx => match value {
PySetterValue::Assign(v) => obj.set_slot(offset, Some(v)),
PySetterValue::Delete => obj.set_slot(offset, None),
},
}
Ok(())
}
impl Unconstructible for MemberDescrObject {}
impl GetDescriptor for MemberDescrObject {
+6 -1
View File
@@ -4,7 +4,11 @@ use super::{
};
use crate::{
builtins::PyBaseExceptionRef,
builtins::{descriptor::MemberGetter, function::PyCellRef, tuple::PyTupleTyped},
builtins::{
descriptor::{MemberGetter, MemberSetter},
function::PyCellRef,
tuple::PyTupleTyped,
},
class::{PyClassImpl, StaticType},
convert::ToPyObject,
function::{FuncArgs, KwArgs, OptionalArg, PySetterValue},
@@ -689,6 +693,7 @@ impl PyType {
name: member.to_string(),
kind: MemberKind::ObjectEx,
getter: MemberGetter::Offset(offset),
setter: MemberSetter::Offset(offset),
doc: None,
};
let member_descriptor: PyRef<MemberDescrObject> = vm.new_pyref(MemberDescrObject {
+13 -5
View File
@@ -25,6 +25,7 @@ use crate::{
builtins::{PyDictRef, PyTypeRef},
vm::VirtualMachine,
};
use itertools::Itertools;
use std::{
any::TypeId,
borrow::Borrow,
@@ -115,7 +116,7 @@ struct PyInner<T> {
weak_list: WeakRefList,
payload: T,
slots: Vec<Option<PyObjectRef>>,
slots: Box<[PyRwLock<Option<PyObjectRef>>]>,
}
impl<T: fmt::Debug> fmt::Debug for PyInner<T> {
@@ -436,7 +437,10 @@ impl<T: PyObjectPayload> PyInner<T> {
dict: dict.map(InstanceDict::new),
weak_list: WeakRefList::new(),
payload,
slots: vec![None; member_count],
slots: std::iter::repeat_with(|| PyRwLock::new(None))
.take(member_count)
.collect_vec()
.into_boxed_slice(),
})
}
}
@@ -799,7 +803,11 @@ impl PyObject {
}
pub(crate) fn get_slot(&self, offset: usize) -> Option<PyObjectRef> {
self.0.slots[offset].clone()
self.0.slots[offset].read().clone()
}
pub(crate) fn set_slot(&self, offset: usize, value: Option<PyObjectRef>) {
*self.0.slots[offset].write() = value;
}
}
@@ -1131,7 +1139,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
dict: None,
weak_list: WeakRefList::new(),
payload: type_payload,
slots: Vec::new(),
slots: Box::new([]),
},
Uninit { typ }
)));
@@ -1143,7 +1151,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
dict: None,
weak_list: WeakRefList::new(),
payload: object_payload,
slots: Vec::new(),
slots: Box::new([]),
},
Uninit { typ },
)));
+6 -1
View File
@@ -3,7 +3,10 @@ use crate::{
builtinfunc::{PyBuiltinFunction, PyBuiltinMethod, PyNativeFuncDef},
bytes,
code::{self, PyCode},
descriptor::{DescrObject, MemberDef, MemberDescrObject, MemberGetter, MemberKind},
descriptor::{
DescrObject, MemberDef, MemberDescrObject, MemberGetter, MemberKind, MemberSetter,
MemberSetterFunc,
},
getset::PyGetSet,
object, pystr,
type_::PyAttributes,
@@ -458,12 +461,14 @@ impl Context {
&self,
name: &str,
getter: fn(&VirtualMachine, PyObjectRef) -> PyResult,
setter: MemberSetterFunc,
class: &'static Py<PyType>,
) -> PyRef<MemberDescrObject> {
let member_def = MemberDef {
name: name.to_owned(),
kind: MemberKind::ObjectEx,
getter: MemberGetter::Getter(getter),
setter: MemberSetter::Setter(setter),
doc: None,
};
let member_descriptor = MemberDescrObject {