Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
under 100 errors
Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
  • Loading branch information
arihant2math committed Jan 23, 2025
commit f79c3200e533ebc643edfac13972855971ddbf99
51 changes: 23 additions & 28 deletions vm/src/stdlib/ctypes/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,9 @@ pub fn make_array_with_length(
let outer_type = cls.get_attr("_type_").ok_or_else(|| {
vm.new_attribute_error("class must define a '_type_' attribute".to_string())
})?;
let length = length as usize;
let _type_ = vm
// TODO: original was get_attribute
.get_attribute_opt(outer_type.clone(), "_type_")
let _type_ = outer_type.get_attr("_type_", vm)
.map_err(|_| vm.new_type_error("_type_ must have storage info".to_string()))?;
let itemsize = get_size(_type_.unwrap().downcast::<PyStr>().unwrap().to_string().as_str());
let itemsize = get_size(_type_.downcast::<PyStr>().unwrap().to_string().as_str());
let capacity = length
.checked_mul(itemsize)
.ok_or_else(|| vm.new_overflow_error("array too large".to_string()))?;
Expand Down Expand Up @@ -116,7 +113,7 @@ fn set_array_value(
return Err(vm.new_type_error("not a ctype instance".to_string()));
}

let obj_cls = obj.clone().class();
let obj_cls = obj.clone().class().clone();

// TODO: ensure fast_issubclass is the right thing to use
if !obj_cls.fast_issubclass(PyCData::static_type()) {
Expand Down Expand Up @@ -192,11 +189,10 @@ fn array_slice_getitem<'a>(
size: usize,
vm: &'a VirtualMachine,
) -> PyResult {
let length = vm
.get_attribute_opt(zelf.clone(), "_length_")
.map(|c_l| usize::try_from_object(vm, c_l.unwrap()))??;
let length = zelf.get_attr("_length_", &vm)
.map(|c_l| usize::try_from_object(vm, c_l))??;

let tp = vm.get_attribute_opt(zelf, "_type_")?.unwrap().downcast::<PyStr>().unwrap().to_string();
let tp = zelf.get_attr("_type_", vm)?.downcast::<PyStr>().unwrap().to_string();
let _type_ = tp.as_str();
let (step, start, stop) = array_get_slice_params(slice, &Some(vm.ctx.new_int(length).to_pyobject(&vm)), vm)?;

Expand Down Expand Up @@ -241,7 +237,7 @@ fn array_slice_setitem(
(stop - start - 1) / step + 1
};

if slice_length != vm.obj_len(&obj)? as isize {
if slice_length != obj.length(vm)? as isize {
return Err(vm.new_value_error("Can only assign sequence of same size".to_string()));
}

Expand Down Expand Up @@ -349,37 +345,37 @@ impl PyCDataMethods for PyCArrayMeta {
let mut value = value;
let cls = zelf.class().clone();

if value.is_instance(&cls.into(), vm)? {
if value.is_instance(cls.as_object(), vm)? {
return Ok(value);
}

let length = vm
.get_attribute(zelf.as_object().clone(), "_length_")
let length = zelf.as_object().get_attr("_length_", &vm)
.map(|c_l| usize::try_from_object(vm, c_l))??;

let value_len = vm.obj_len(&value)?;
let value_len = value.length(vm)?;

if let Ok(tp) = vm.get_attribute_opt(zelf.as_object().clone(), "_type_") {
let _type = tp.unwrap().downcast::<PyCSimple>().unwrap();
if let Ok(tp) = zelf.as_object().get_attr("_type_", vm) {
let _type = tp.downcast::<PyCSimple>().unwrap();

if _type._type_.as_str() == "c" {
if vm.isinstance(&value, &vm.ctx.types.bytes_type).is_ok() {
// TODO: replace with match statement
if value.is_instance(vm.ctx.types.bytes_type.as_ref(), vm).is_ok() {
if value_len > length {
return Err(vm.new_value_error("Invalid length".to_string()));
}
value = make_array_with_length(cls.clone(), length, vm)?.as_object().clone();
} else if vm.isinstance(&value, &cls).is_err() {
value = make_array_with_length(&cls, length, vm)?.as_object().clone();
} else if value.is_instance(&cls, vm).is_err() {
return Err(
vm.new_type_error(format!("expected bytes, {} found", value.class().name()))
);
}
} else if _type._type_.as_str() == "u" {
if vm.isinstance(&value, &vm.ctx.types.str_type).is_ok() {
if value.is_instance(vm.ctx.types.str_type.as_ref(), vm).is_ok() {
if value_len > length {
return Err(vm.new_value_error("Invalid length".to_string()));
}
value = make_array_with_length(cls.clone(), length, vm)?.as_object().clone();
} else if vm.isinstance(&value, &cls).is_err() {
} else if value.is_instance(cls.as_ref(), vm).is_err() {
return Err(vm.new_type_error(format!(
"expected unicode string, {} found",
value.class().name()
Expand All @@ -388,7 +384,7 @@ impl PyCDataMethods for PyCArrayMeta {
}
}

if value.is_instance(&vm.ctx.types.tuple_type, &vm).is_ok() {
if value.is_instance(vm.ctx.types.tuple_type.as_ref(), &vm).is_ok() {
if value_len > length {
return Err(vm.new_runtime_error("Invalid length".to_string()));
}
Expand All @@ -403,12 +399,11 @@ impl PyCDataMethods for PyCArrayMeta {
impl PyCArrayMeta {
#[pyslot]
fn slot_new(cls: PyTypeRef, vm: &VirtualMachine) -> PyResult {
let length_obj = vm
.get_attribute_opt(cls.as_object().to_owned(), "_length_")
let length_obj = cls.as_object().get_attr("_length_", &vm)
.map_err(|_| {
vm.new_attribute_error("class must define a '_length_' attribute".to_string())
})?;
let length_int = length_obj.unwrap().downcast_exact::<PyInt>(vm).map_err(|_| {
let length_int = length_obj.downcast_exact::<PyInt>(vm).map_err(|_| {
vm.new_type_error("The '_length_' attribute must be an integer".to_string())
})?;
let length: usize = if length_int.as_bigint().is_negative() {
Expand All @@ -430,7 +425,7 @@ impl PyCArray {
#[pymethod(magic)]
pub fn init(zelf: PyRef<Self>, value: OptionalArg, vm: &VirtualMachine) -> PyResult<()> {
value.map_or(Ok(()), |value| {
let value_length = vm.obj_len(&value)?;
let value_length = value.length(vm)?;

if value_length < zelf._length_ {
let value_vec: Vec<PyObjectRef> = vm.extract_elements(&value)?;
Expand All @@ -445,7 +440,7 @@ impl PyCArray {
stop: vm.new_pyobj(zelf._length_),
step: None,
}
.into_ref(vm),
.into_ref(&vm.ctx),
);

Self::setitem(zelf, py_slice, value, vm)
Expand Down
47 changes: 31 additions & 16 deletions vm/src/stdlib/ctypes/basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ use crate::function::Either;
use crate::builtins::PyTypeRef;
use crate::protocol::PyBuffer;
use crossbeam_utils::atomic::AtomicCell;
use crate::class::StaticType;
use crate::convert::IntoObject;
use crate::object::MaybeTraverse;
use crate::types::AsBuffer;

pub fn get_size(ty: &str) -> usize {
Expand All @@ -39,8 +42,8 @@ pub fn get_size(ty: &str) -> usize {
}

fn at_address(cls: &PyTypeRef, buf: usize, vm: &VirtualMachine) -> PyResult<RawBuffer> {
match vm.get_attribute_opt(cls.as_object().to_owned(), "__abstract__") {
Ok(attr) => match bool::try_from_object(vm, attr.unwrap()) {
match cls.as_object().get_attr("__abstract__", &vm)? {
Ok(attr) => match bool::try_from_object(vm, attr) {
Ok(false) => {
let len = vm
.get_attribute(cls.as_object().to_owned(), "_length_")
Expand Down Expand Up @@ -77,11 +80,11 @@ fn buffer_copy(
vm: &VirtualMachine,
copy: bool,
) -> PyResult<PyCData> {
match vm.get_attribute(cls.as_object().to_owned(), "__abstract__") {
match cls.as_object().to_owned().get_attr("__abstract__", vm) {
Ok(attr) => {
match bool::try_from_object(vm, attr) {
Ok(b) if !b => {
let buffer = PyBuffer::try_from_object(vm, &obj)?;
let buffer = PyBuffer::try_from_object(vm, obj)?;
let opts = buffer.get_options().clone();

// TODO: Fix the way the size of stored
Expand Down Expand Up @@ -147,13 +150,13 @@ where
let cls = zelf.as_object().clone_class();
if vm.isinstance(&value, &cls)? {
Ok(value)
} else if let Ok(parameter) = vm.get_attribute(value.clone(), "_as_parameter_") {
} else if let Ok(parameter) = value.get_attr("_as_parameter_", vm) {
T::from_param(zelf, parameter, vm)
} else {
Err(vm.new_attribute_error(format!(
"expected {} instance instead of {}",
cls.name,
value.class().name
value.class().name()
)))
}
}
Expand Down Expand Up @@ -231,12 +234,12 @@ pub trait PyCDataMethods: PyPayload {
name: PyStrRef,
vm: &VirtualMachine,
) -> PyResult<PyCData> {
if let Ok(h) = vm.get_attribute(cls.as_object().to_owned(), "_handle") {
if let Ok(h) = cls.as_object().to_owned().get_attr("_handle", vm) {
// This is something to be "CPython" like
let raw_ptr = if let Ok(h_int) = h.downcast_exact::<PyInt>(vm) {
dlsym(h_int, name, vm)
} else {
Err(vm.new_type_error(format!("_handle must be an int not {}", dll.class().name)))
Err(vm.new_type_error(format!("_handle must be an int not {}", dll.class().name())))
}?;

let sym_ptr = usize::try_from_object(vm, raw_ptr)?;
Expand Down Expand Up @@ -274,7 +277,7 @@ pub fn generic_get_buffer<T>(zelf: &Py<T>, vm: &VirtualMachine) -> PyResult<PyBu
where
for<'a> T: PyPayload + fmt::Debug + BorrowValue<'a> + BorrowValueMut<'a>,
{
if let Ok(buffer) = vm.get_attribute(zelf.as_object().clone(), "_buffer") {
if let Ok(buffer) = zelf.as_object().clone().get_attr("_buffer", vm) {
if let Ok(_buffer) = buffer.downcast_exact::<RawBuffer>(vm) {
Ok(Box::new(PyCBuffer::<T> {
data: zelf.clone(),
Expand Down Expand Up @@ -333,6 +336,18 @@ impl fmt::Debug for RawBuffer {
}
}

impl MaybeTraverse for RawBuffer {
fn try_traverse(&self, _traverse_fn: &mut TraverseFn) {
todo!()
}
}

impl PyPayload for RawBuffer {
fn class(_ctx: &Context) -> &'static Py<PyType> {
todo!()
}
}

unsafe impl Send for RawBuffer {}
unsafe impl Sync for RawBuffer {}

Expand Down Expand Up @@ -382,10 +397,10 @@ pub fn sizeof_func(tp: Either<PyTypeRef, PyObjectRef>, vm: &VirtualMachine) -> P
match tp {
Either::A(type_) if type_.issubclass(PyCSimple::static_type()) => {
let zelf = new_simple_type(Either::B(&type_), vm)?;
PyCDataFunctions::size_of_instances(zelf.into_ref(vm), vm)
PyCDataFunctions::size_of_instances(zelf.into_ref(&vm.ctx), vm)
}
Either::B(obj) if obj.has_class_attr("size_of_instances") => {
let size_of_method = vm.get_attribute(obj, "size_of_instances").unwrap();
let size_of_method = obj.get_attr("size_of_instances", vm)?;
let size_of_return = vm.invoke(&size_of_method, ())?;
Ok(usize::try_from_object(vm, size_of_return)?)
}
Expand All @@ -396,12 +411,12 @@ pub fn sizeof_func(tp: Either<PyTypeRef, PyObjectRef>, vm: &VirtualMachine) -> P
// FIXME: this function is too hacky, work a better way of doing it
pub fn alignment(tp: Either<PyTypeRef, PyObjectRef>, vm: &VirtualMachine) -> PyResult<usize> {
match tp {
Either::A(type_) if type_.issubclass(PyCSimple::static_type()) => {
Either::A(type_) if type_.fast_issubclass(PyCSimple::static_type()) => {
let zelf = new_simple_type(Either::B(&type_), vm)?;
PyCDataFunctions::alignment_of_instances(zelf.into_ref(vm), vm)
PyCDataFunctions::alignment_of_instances(zelf.into_ref(&vm.ctx), vm)
}
Either::B(obj) if obj.has_class_attr("alignment_of_instances") => {
let alignment_of_m = vm.get_attribute(obj, "alignment_of_instances")?;
let alignment_of_m = obj.get_attr("alignment_of_instances", vm)?;
let alignment_of_r = vm.invoke(&alignment_of_m, ())?;
usize::try_from_object(vm, alignment_of_m)
}
Expand All @@ -411,7 +426,7 @@ pub fn alignment(tp: Either<PyTypeRef, PyObjectRef>, vm: &VirtualMachine) -> PyR

pub fn byref(tp: PyObjectRef, vm: &VirtualMachine) -> PyResult {
//TODO: Return a Pointer when Pointer implementation is ready
let class = tp.clone_class();
let class = tp.clone().class();

if class.issubclass(PyCData::static_type()) {
if let Some(ref_to) = vm.get_method(tp, "ref_to") {
Expand All @@ -426,7 +441,7 @@ pub fn byref(tp: PyObjectRef, vm: &VirtualMachine) -> PyResult {
}

pub fn addressof(tp: PyObjectRef, vm: &VirtualMachine) -> PyResult {
let class = tp.clone_class();
let class = tp.clone().class();

if class.issubclass(PyCData::static_type()) {
if let Some(address_of) = vm.get_method(tp, "address_of") {
Expand Down
24 changes: 12 additions & 12 deletions vm/src/stdlib/ctypes/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::builtins::{PyInt, PyType, PyTypeRef};
use crate::common::lock::PyRwLock;

use crate::function::FuncArgs;
use crate::{Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine};

use crate::{AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine};
use crate::class::StaticType;
use crate::stdlib::ctypes::basics::PyCData;
use crate::stdlib::ctypes::primitive::PyCSimple;

Expand Down Expand Up @@ -156,7 +156,7 @@ impl Function {
}

pub fn set_ret(&mut self, ret: &str) {
(*self.return_type.as_mut()) = if ret == "P" {
*self.return_type.as_mut() = if ret == "P" {
Type::void()
} else {
str_to_type(ret)
Expand Down Expand Up @@ -287,11 +287,11 @@ impl PyCFuncPtr {
match inner_obj.isinstance(PyCSimple::static_type(), &vm) {
// FIXME: checks related to _type_ are temporary
// it needs to check for from_param method, instead
Ok(_) => vm.get_attribute(inner_obj.clone(), "_type_"),
Ok(_) => inner_obj.get_attr("_type_", vm),
_ => Err(vm.new_type_error(format!(
"item {} in _argtypes_ must be subclass of _SimpleType, but type {} found",
idx,
inner_obj.class().name
inner_obj.class().name()
))),
}
})
Expand All @@ -317,7 +317,7 @@ impl PyCFuncPtr {
fn set_restype(&self, restype: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
match vm.isinstance(&restype, PyCSimple::static_type()) {
// TODO: checks related to _type_ are temporary
Ok(_) => match vm.get_attribute(restype.clone(), "_type_") {
Ok(_) => match restype.get_attr("_type_", vm) {
Ok(_type_) => {
// TODO: restype must be a type, a callable, or None
self._restype_.store(restype.clone());
Expand All @@ -331,7 +331,7 @@ impl PyCFuncPtr {

Err(_) => Err(vm.new_type_error(format!(
"value is not an instance of _CData, type {} found",
restype.class().name
restype.class().name()
))),
}
}
Expand All @@ -344,7 +344,7 @@ impl PyCFuncPtr {
arg: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
match vm.get_attribute(cls.as_object().to_owned(), "_argtypes_") {
match cls.as_object().to_owned().get_attr("_argtypes_", vm) {
Ok(_) => Self::from_dll(cls, func_name, arg, vm),
Err(_) => Err(vm.new_type_error(
"cannot construct instance of this class: no argtypes slot".to_string(),
Expand All @@ -364,7 +364,7 @@ impl PyCFuncPtr {
arg: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
if let Ok(h) = vm.get_attribute(arg.clone(), "_handle") {
if let Ok(h) = arg.get_attr("_handle", vm) {
if let Ok(handle) = h.downcast::<PyInt>() {
let handle_obj = handle.clone().into_object();
let ptr_fn = dlsym(handle, func_name.clone(), vm)?;
Expand All @@ -383,7 +383,7 @@ impl PyCFuncPtr {
}
.into_ref_with_type(vm, cls)
} else {
Err(vm.new_type_error(format!("_handle must be an int not {}", arg.class().name)))
Err(vm.new_type_error(format!("_handle must be an int not {}", arg.class().name())))
}
} else {
Err(vm.new_attribute_error(
Expand Down Expand Up @@ -424,12 +424,12 @@ impl Callable for PyCFuncPtr {
.issubclass(&obj.clone_class(), PyCSimple::static_type())
.is_ok()
{
Ok(vm.get_attribute(obj.clone(), "value")?)
Ok(obj.get_attr("value", vm)?)
} else {
Err(vm.new_type_error(format!(
"positional argument {} must be subclass of _SimpleType, but type {} found",
idx,
obj.class().name
obj.class().name()
)))
}
})
Expand Down
4 changes: 2 additions & 2 deletions vm/src/stdlib/ctypes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ mod _ctypes {
#[pyfunction]
pub(crate) fn POINTER(tp: PyTypeRef, vm: &VirtualMachine) -> PyResult {
pointer::POINTER(tp);
Ok(vm.get_none())
Ok(vm.ctx.none())
}

#[pyfunction]
pub(crate) fn pointer(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
pointer::pointer_fn(obj);
Ok(vm.get_none())
Ok(vm.ctx.none())
}

#[pyfunction]
Expand Down
Loading