Object protocol

This commit is contained in:
Jeong YunWon
2021-10-15 04:01:06 +09:00
parent 0ad892b9a4
commit 79e951b630
5 changed files with 154 additions and 13 deletions

View File

@@ -38,11 +38,11 @@ impl TryFromBorrowedObject for PyBytesInner {
#[derive(FromArgs)]
pub struct ByteInnerNewOptions {
#[pyarg(any, optional)]
source: OptionalArg<PyObjectRef>,
pub source: OptionalArg<PyObjectRef>,
#[pyarg(any, optional)]
encoding: OptionalArg<PyStrRef>,
pub encoding: OptionalArg<PyStrRef>,
#[pyarg(any, optional)]
errors: OptionalArg<PyStrRef>,
pub errors: OptionalArg<PyStrRef>,
}
impl ByteInnerNewOptions {

View File

@@ -129,16 +129,6 @@ impl TryFromObject for PyIter<PyObjectRef> {
}
}
impl PyObjectRef {
/// Takes an object and returns an iterator for it.
/// This is typically a new iterator but if the argument is an iterator, this
/// returns itself.
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
// PyObject_GetIter
PyIter::try_from_object(vm, self)
}
}
pub enum PyIterReturn<T = PyObjectRef> {
Return(T),
StopIteration(Option<PyObjectRef>),

View File

@@ -1,6 +1,7 @@
mod buffer;
mod iter;
mod mapping;
mod object;
pub use buffer::{BufferInternal, BufferOptions, BufferResizeGuard, PyBuffer};
pub use iter::{PyIter, PyIterIter, PyIterReturn};

148
vm/src/protocol/object.rs Normal file
View File

@@ -0,0 +1,148 @@
//! Object Protocol
//! https://docs.python.org/3/c-api/object.html
use crate::{
builtins::{pystr::IntoPyStrRef, PyBytes, PyInt, PyStrRef},
bytesinner::ByteInnerNewOptions,
common::{hash::PyHash, str::to_ascii},
function::OptionalArg,
protocol::PyIter,
pyref_type_error,
types::{Constructor, PyComparisonOp},
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
};
// RustPython doesn't need these items
// PyObject *Py_NotImplemented
// Py_RETURN_NOTIMPLEMENTED
impl PyObjectRef {
// int PyObject_Print(PyObject *o, FILE *fp, int flags)
pub fn has_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<bool> {
self.get_attr(attr_name, vm).map(|o| vm.is_none(&o))
}
pub fn get_attr(self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
vm.get_attribute(self, attr_name)
}
// PyObject *PyObject_GenericGetAttr(PyObject *o, PyObject *name)
pub fn set_attr(
&self,
attr_name: impl IntoPyStrRef,
attr_value: impl Into<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<()> {
vm.set_attr(self, attr_name, attr_value)
}
// int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
pub fn del_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult<()> {
vm.del_attr(self, attr_name)
}
// PyObject *PyObject_GenericGetDict(PyObject *o, void *context)
// int PyObject_GenericSetDict(PyObject *o, PyObject *value, void *context)
pub fn rich_compare(self, other: Self, opid: PyComparisonOp, vm: &VirtualMachine) -> PyResult {
vm.obj_cmp(self, other, opid)
}
pub fn rich_compare_bool(
&self,
other: &Self,
opid: PyComparisonOp,
vm: &VirtualMachine,
) -> PyResult<bool> {
vm.bool_cmp(self, other, opid)
}
pub fn repr(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
vm.to_repr(self)
}
pub fn ascii(&self, vm: &VirtualMachine) -> PyResult<ascii::AsciiString> {
let repr = vm.to_repr(self)?;
let ascii = to_ascii(repr.as_str());
Ok(ascii)
}
pub fn str(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> {
vm.to_str(self)
}
pub fn bytes(self, vm: &VirtualMachine) -> PyResult {
let bytes_type = &vm.ctx.types.bytes_type;
match self.downcast_exact::<PyInt>(vm) {
Ok(int) => Err(pyref_type_error(vm, bytes_type, int.as_object())),
Err(obj) => PyBytes::py_new(
bytes_type.clone(),
ByteInnerNewOptions {
source: OptionalArg::Present(obj),
encoding: OptionalArg::Missing,
errors: OptionalArg::Missing,
},
vm,
),
}
}
pub fn is_subclass(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
vm.issubclass(self, cls)
}
pub fn is_instance(&self, cls: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
vm.isinstance(self, cls)
}
pub fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> {
vm._hash(self)
}
// const hash_not_implemented: fn(&PyObjectRef, &VirtualMachine) ->PyResult<PyHash> = crate::types::Unhashable::slot_hash;
pub fn is_true(self, vm: &VirtualMachine) -> PyResult<bool> {
self.try_to_bool(vm)
}
pub fn not(self, vm: &VirtualMachine) -> PyResult<bool> {
self.is_true(vm).map(|x| !x)
}
// type protocol
// PyObject *PyObject_Type(PyObject *o)
// int PyObject_TypeCheck(PyObject *o, PyTypeObject *type)
pub fn length(&self, vm: &VirtualMachine) -> PyResult<usize> {
vm.obj_len(self)
}
pub fn length_hint(
self,
defaultvalue: Option<usize>,
vm: &VirtualMachine,
) -> PyResult<Option<usize>> {
Ok(vm.length_hint(self)?.or(defaultvalue))
}
// item protocol
// PyObject *PyObject_GetItem(PyObject *o, PyObject *key)
// int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
// int PyObject_DelItem(PyObject *o, PyObject *key)
// PyObject *PyObject_Dir(PyObject *o)
/// Takes an object and returns an iterator for it.
/// This is typically a new iterator but if the argument is an iterator, this
/// returns itself.
pub fn get_iter(self, vm: &VirtualMachine) -> PyResult<PyIter> {
// PyObject_GetIter
PyIter::try_from_object(vm, self)
}
// PyObject *PyObject_GetAIter(PyObject *o)
}

View File

@@ -502,6 +502,8 @@ where
fn slot_hash(zelf: &PyObjectRef, vm: &VirtualMachine) -> PyResult<PyHash> {
Err(vm.new_type_error(format!("unhashable type: '{}'", zelf.class().name())))
}
#[cold]
fn hash(_zelf: &PyRef<Self>, _vm: &VirtualMachine) -> PyResult<PyHash> {
unreachable!("slot_hash is implemented for unhashable types");
}