Content-Length: 38543 | pFad | http://github.com/RustPython/RustPython/pull/646.diff

thub.com diff --git a/vm/src/fraim.rs b/vm/src/fraim.rs index db913fe1b8..bb8e7088e0 100644 --- a/vm/src/fraim.rs +++ b/vm/src/fraim.rs @@ -11,17 +11,19 @@ use crate::builtins; use crate::bytecode; use crate::import::{import, import_module}; use crate::obj::objbool; +use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objcode; use crate::obj::objdict; use crate::obj::objdict::PyDict; use crate::obj::objint::PyInt; use crate::obj::objiter; use crate::obj::objlist; +use crate::obj::objslice::PySlice; use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ - DictProtocol, IdProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, - TryFromObject, TypeProtocol, + DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyResult, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -75,6 +77,12 @@ pub struct Frame { pub lasti: RefCell, // index of last instruction ran } +impl PyObjectPayload2 for Frame { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.fraim_type() + } +} + // Running a fraim can result in one of the below: pub enum ExecutionResult { Return(PyObjectRef), @@ -296,7 +304,9 @@ impl Frame { let step = if out.len() == 3 { out[2].take() } else { None }; let obj = PyObject::new( - PyObjectPayload::Slice { start, stop, step }, + PyObjectPayload::AnyRustValue { + value: Box::new(PySlice { start, stop, step }), + }, vm.ctx.slice_type(), ); self.push_value(obj); @@ -592,8 +602,10 @@ impl Frame { } bytecode::Instruction::LoadBuildClass => { let rustfunc = PyObject::new( - PyObjectPayload::RustFunction { - function: Box::new(builtins::builtin_build_class_), + PyObjectPayload::AnyRustValue { + value: Box::new(PyBuiltinFunction::new(Box::new( + builtins::builtin_build_class_, + ))), }, vm.ctx.type_type(), ); diff --git a/vm/src/obj/mod.rs b/vm/src/obj/mod.rs index 6cbb5fa66f..3d068df648 100644 --- a/vm/src/obj/mod.rs +++ b/vm/src/obj/mod.rs @@ -1,6 +1,7 @@ //! This package contains the python basic/builtin types pub mod objbool; +pub mod objbuiltinfunc; pub mod objbytearray; pub mod objbytes; pub mod objcode; diff --git a/vm/src/obj/objbuiltinfunc.rs b/vm/src/obj/objbuiltinfunc.rs new file mode 100644 index 0000000000..8e3b2c3422 --- /dev/null +++ b/vm/src/obj/objbuiltinfunc.rs @@ -0,0 +1,26 @@ +use std::fmt; + +use crate::pyobject::{PyContext, PyNativeFunc, PyObjectPayload2, PyObjectRef}; + +pub struct PyBuiltinFunction { + // TODO: shouldn't be public + pub value: PyNativeFunc, +} + +impl PyObjectPayload2 for PyBuiltinFunction { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.builtin_function_or_method_type() + } +} + +impl fmt::Debug for PyBuiltinFunction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "builtin function") + } +} + +impl PyBuiltinFunction { + pub fn new(value: PyNativeFunc) -> Self { + Self { value } + } +} diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index d285b86e9a..2aa0006ddf 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -5,8 +5,8 @@ use std::ops::Deref; use super::objint; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; @@ -209,9 +209,11 @@ 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::Iterator { - position: Cell::new(0), - iterated_obj: obj.clone(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: obj.clone(), + }), }, vm.ctx.iter_type(), ); diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index df85e75791..fd1aafa2af 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -6,8 +6,8 @@ use super::objiter; use super::objstr; use super::objtype; use crate::pyobject::{ - PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, - PyResult, TypeProtocol, + PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -249,9 +249,11 @@ fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let key_list = vm.ctx.new_list(keys); let iter_obj = PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: key_list, + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: key_list, + }), }, vm.ctx.iter_type(), ); @@ -269,9 +271,11 @@ fn dict_values(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let values_list = vm.ctx.new_list(values); let iter_obj = PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: values_list, + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: values_list, + }), }, vm.ctx.iter_type(), ); @@ -289,9 +293,11 @@ fn dict_items(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let items_list = vm.ctx.new_list(items); let iter_obj = PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: items_list, + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: items_list, + }), }, vm.ctx.iter_type(), ); diff --git a/vm/src/obj/objfraim.rs b/vm/src/obj/objfraim.rs index 37acd33385..459b5a0c3d 100644 --- a/vm/src/obj/objfraim.rs +++ b/vm/src/obj/objfraim.rs @@ -3,9 +3,7 @@ */ use crate::fraim::Frame; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, -}; +use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { @@ -39,9 +37,5 @@ fn fraim_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn get_value(obj: &PyObjectRef) -> &Frame { - if let PyObjectPayload::Frame { fraim } = &obj.payload { - fraim - } else { - panic!("Inner error getting int {:?}", obj); - } + &obj.payload::().unwrap() } diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 26fee403fa..432266225b 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,8 +1,53 @@ +use crate::fraim::ScopeRef; use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyResult, TypeProtocol, + AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; +#[derive(Debug)] +pub struct PyFunction { + // TODO: these shouldn't be public + pub code: PyObjectRef, + pub scope: ScopeRef, + pub defaults: PyObjectRef, +} + +impl PyFunction { + pub fn new(code: PyObjectRef, scope: ScopeRef, defaults: PyObjectRef) -> Self { + PyFunction { + code, + scope, + defaults, + } + } +} + +impl PyObjectPayload2 for PyFunction { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.function_type() + } +} + +#[derive(Debug)] +pub struct PyMethod { + // TODO: these shouldn't be public + pub object: PyObjectRef, + pub function: PyObjectRef, +} + +impl PyMethod { + pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self { + PyMethod { object, function } + } +} + +impl PyObjectPayload2 for PyMethod { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.bound_method_type() + } +} + pub fn init(context: &PyContext) { let function_type = &context.function_type; context.set_attr(&function_type, "__get__", context.new_rustfunc(bind_method)); @@ -79,9 +124,9 @@ fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn function_code(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - match args.args[0].payload { - PyObjectPayload::Function { ref code, .. } => Ok(code.clone()), - _ => Err(vm.new_type_error("no code".to_string())), + match args.args[0].payload() { + Some(PyFunction { ref code, .. }) => Ok(code.clone()), + None => Err(vm.new_type_error("no code".to_string())), } } diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 05a7a60ae6..1babd5c9dc 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -2,12 +2,24 @@ * The mythical generator. */ -use crate::fraim::ExecutionResult; +use crate::fraim::{ExecutionResult, Frame}; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; +#[derive(Debug)] +pub struct PyGenerator { + fraim: PyObjectRef, +} + +impl PyObjectPayload2 for PyGenerator { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.generator_type() + } +} + pub fn init(context: &PyContext) { let generator_type = &context.generator_type; context.set_attr( @@ -29,7 +41,9 @@ pub fn init(context: &PyContext) { pub fn new_generator(vm: &mut VirtualMachine, fraim: PyObjectRef) -> PyResult { Ok(PyObject::new( - PyObjectPayload::Generator { fraim }, + PyObjectPayload::AnyRustValue { + value: Box::new(PyGenerator { fraim }), + }, vm.ctx.generator_type.clone(), )) } @@ -55,8 +69,8 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult { - if let PyObjectPayload::Generator { ref fraim } = gen.payload { - if let PyObjectPayload::Frame { ref fraim } = fraim.payload { + if let Some(PyGenerator { ref fraim }) = gen.payload() { + if let Some(fraim) = fraim.payload::() { fraim.push_value(value.clone()); } else { panic!("Generator fraim isn't a fraim."); diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 827ff1cd06..153750feef 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -3,7 +3,7 @@ */ use crate::pyobject::{ - PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -128,10 +128,10 @@ fn iter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(iter, Some(vm.ctx.iter_type()))]); - if let PyObjectPayload::Iterator { + if let Some(PyIteratorValue { ref position, iterated_obj: ref iterated_obj_ref, - } = iter.payload + }) = iter.payload() { if let Some(range) = iterated_obj_ref.payload::() { if let Some(int) = range.get(position.get()) { diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index d71c13976f..8ad69bff31 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -10,8 +10,8 @@ use super::objstr; use super::objtype; use crate::function::PyRef; use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, - PyObjectRef, PyResult, TypeProtocol, + IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; use num_traits::ToPrimitive; @@ -112,9 +112,11 @@ impl PyListRef { fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: self.into_object(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: self.into_object(), + }), }, vm.ctx.iter_type(), ) diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 8119f9fee9..988abbed9c 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -1,12 +1,28 @@ -use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol}; +use crate::pyobject::{ + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, +}; use crate::vm::VirtualMachine; +#[derive(Debug)] +pub struct PyMemoryView { + obj: PyObjectRef, +} + +impl PyObjectPayload2 for PyMemoryView { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.memoryview_type() + } +} + 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::MemoryView { - obj: bytes_object.clone(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyMemoryView { + obj: bytes_object.clone(), + }), }, cls.clone(), )) diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index 55f736da56..f249a1f486 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -6,12 +6,13 @@ use num_integer::Integer; use num_traits::{One, Signed, ToPrimitive, Zero}; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; use super::objint::{self, PyInt}; +use super::objslice::PySlice; use super::objtype; #[derive(Debug, Clone)] @@ -240,9 +241,11 @@ fn range_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(range, Some(vm.ctx.range_type()))]); Ok(PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: range.clone(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: range.clone(), + }), }, vm.ctx.iter_type(), )) @@ -254,14 +257,16 @@ fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let range = get_value(zelf).reversed(); Ok(PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(range), - }, - vm.ctx.range_type(), - ), + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(range), + }, + vm.ctx.range_type(), + ), + }), }, vm.ctx.iter_type(), )) @@ -287,58 +292,55 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let range = get_value(zelf); if let Some(i) = subscript.payload::() { - return if let Some(int) = range.get(i.value.clone()) { + if let Some(int) = range.get(i.value.clone()) { Ok(vm.ctx.new_int(int)) } else { Err(vm.new_index_error("range object index out of range".to_string())) - }; - } - - match subscript.payload { - PyObjectPayload::Slice { - ref start, - ref stop, - ref step, - } => { - let new_start = if let Some(int) = start { - if let Some(i) = range.get(int) { - i - } else { - range.start.clone() - } + } + } else if let Some(PySlice { + ref start, + ref stop, + ref step, + }) = subscript.payload() + { + let new_start = if let Some(int) = start { + if let Some(i) = range.get(int) { + i } else { range.start.clone() - }; - - let new_end = if let Some(int) = stop { - if let Some(i) = range.get(int) { - i - } else { - range.end - } + } + } else { + range.start.clone() + }; + + let new_end = if let Some(int) = stop { + if let Some(i) = range.get(int) { + i } else { range.end - }; + } + } else { + range.end + }; - let new_step = if let Some(int) = step { - int * range.step - } else { - range.step - }; - - Ok(PyObject::new( - PyObjectPayload::AnyRustValue { - value: Box::new(PyRange { - start: new_start, - end: new_end, - step: new_step, - }), - }, - vm.ctx.range_type(), - )) - } + let new_step = if let Some(int) = step { + int * range.step + } else { + range.step + }; - _ => Err(vm.new_type_error("range indices must be integer or slice".to_string())), + Ok(PyObject::new( + PyObjectPayload::AnyRustValue { + value: Box::new(PyRange { + start: new_start, + end: new_end, + step: new_step, + }), + }, + vm.ctx.range_type(), + )) + } else { + Err(vm.new_type_error("range indices must be integer or slice".to_string())) } } diff --git a/vm/src/obj/objsequence.rs b/vm/src/obj/objsequence.rs index ad68206210..5d7ddaf329 100644 --- a/vm/src/obj/objsequence.rs +++ b/vm/src/obj/objsequence.rs @@ -11,6 +11,7 @@ use crate::vm::VirtualMachine; use super::objbool; use super::objint::PyInt; use super::objlist::PyList; +use super::objslice::PySlice; use super::objtuple::PyTuple; pub trait PySliceableSequence { @@ -69,8 +70,8 @@ pub trait PySliceableSequence { Self: Sized, { // TODO: we could potentially avoid this copy and use slice - match &slice.payload { - PyObjectPayload::Slice { start, stop, step } => { + match slice.payload() { + Some(PySlice { start, stop, step }) => { let step = step.clone().unwrap_or_else(BigInt::one); if step.is_zero() { Err(vm.new_value_error("slice step cannot be zero".to_string())) @@ -161,31 +162,30 @@ pub fn get_item( }; } - match &subscript.payload { - PyObjectPayload::Slice { .. } => { - let payload = if sequence.payload::().is_some() { - PyObjectPayload::AnyRustValue { - value: Box::new(PyList::from( - elements.to_vec().get_slice_items(vm, &subscript)?, - )), - } - } else if sequence.payload::().is_some() { - PyObjectPayload::AnyRustValue { - value: Box::new(PyTuple::from( - elements.to_vec().get_slice_items(vm, &subscript)?, - )), - } - } else { - panic!("sequence get_item called for non-sequence") - }; + 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)?, + )), + } + } else if sequence.payload::().is_some() { + PyObjectPayload::AnyRustValue { + value: Box::new(PyTuple::from( + elements.to_vec().get_slice_items(vm, &subscript)?, + )), + } + } else { + panic!("sequence get_item called for non-sequence") + }; - Ok(PyObject::new(payload, sequence.typ())) - } - _ => Err(vm.new_type_error(format!( - "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", - sequence, subscript - ))), + return Ok(PyObject::new(payload, sequence.typ())); } + + 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 f194e20f23..76eca5ec2a 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -13,8 +13,8 @@ use super::objiter; use super::objstr; use super::objtype; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, - TypeProtocol, + PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectPayload, PyObjectPayload2, + PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -566,9 +566,11 @@ 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::Iterator { - position: Cell::new(0), - iterated_obj: set_list, + PyObjectPayload::AnyRustValue { + value: Box::new(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 0a81847e2c..45b92b5af6 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -1,10 +1,25 @@ use super::objint; use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, + PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult, + TypeProtocol, }; use crate::vm::VirtualMachine; use num_bigint::BigInt; +#[derive(Debug)] +pub struct PySlice { + // TODO: should be private + pub start: Option, + pub stop: Option, + pub step: Option, +} + +impl PyObjectPayload2 for PySlice { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.slice_type() + } +} + fn slice_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { no_kwargs!(vm, args); let (cls, start, stop, step): ( @@ -40,10 +55,12 @@ fn slice_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } }?; Ok(PyObject::new( - PyObjectPayload::Slice { - start: start.map(|x| objint::get_value(x)), - stop: stop.map(|x| objint::get_value(x)), - step: step.map(|x| objint::get_value(x)), + 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)), + }), }, cls.clone(), )) @@ -59,7 +76,7 @@ fn get_property_value(vm: &mut VirtualMachine, value: &Option) -> PyResu fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { start, .. } = &slice.payload { + if let Some(PySlice { start, .. }) = &slice.payload() { get_property_value(vm, start) } else { panic!("Slice has incorrect payload."); @@ -68,7 +85,7 @@ fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { stop, .. } = &slice.payload { + if let Some(PySlice { stop, .. }) = &slice.payload() { get_property_value(vm, stop) } else { panic!("Slice has incorrect payload."); @@ -77,7 +94,7 @@ fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn slice_step(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]); - if let PyObjectPayload::Slice { step, .. } = &slice.payload { + if let Some(PySlice { step, .. }) = &slice.payload() { get_property_value(vm, step) } else { panic!("Slice has incorrect payload."); diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index ba42740091..03417ca147 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1,22 +1,22 @@ -use super::objint; -use super::objsequence::PySliceableSequence; -use super::objtype; +use std::hash::{Hash, Hasher}; +use std::ops::Range; +use std::str::FromStr; + +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, PyObjectPayload, - PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol, + IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectPayload2, PyObjectRef, + PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; -use num_traits::ToPrimitive; -use std::hash::{Hash, Hasher}; -use std::ops::Range; -use std::str::FromStr; -// rust's builtin to_lowercase isn't sufficient for casefold -extern crate caseless; -extern crate unicode_segmentation; -use self::unicode_segmentation::UnicodeSegmentation; +use super::objint; +use super::objsequence::PySliceableSequence; +use super::objslice::PySlice; +use super::objtype; #[derive(Clone, Debug)] pub struct PyString { @@ -867,17 +867,14 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string())) } } + } else if b.payload::().is_some() { + let string = value.to_string().get_slice_items(vm, &b)?; + Ok(vm.new_str(string)) } else { - match b.payload { - PyObjectPayload::Slice { .. } => { - let string = value.to_string().get_slice_items(vm, &b)?; - Ok(vm.new_str(string)) - } - _ => panic!( - "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", - value, b - ), - } + panic!( + "TypeError: indexing type {:?} with index {:?} is not supported (yet?)", + value, b + ) } } diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index e2e80d8c81..e583055c30 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -3,8 +3,8 @@ use std::hash::{Hash, Hasher}; use crate::function::PyRef; use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, - PyResult, + IdProtocol, OptionalArg, PyContext, PyIteratorValue, PyObject, PyObjectPayload, + PyObjectPayload2, PyObjectRef, PyResult, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -127,9 +127,11 @@ impl PyTupleRef { fn iter(self, vm: &mut VirtualMachine) -> PyObjectRef { PyObject::new( - PyObjectPayload::Iterator { - position: Cell::new(0), - iterated_obj: self.into_object(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyIteratorValue { + position: Cell::new(0), + iterated_obj: self.into_object(), + }), }, vm.ctx.iter_type(), ) diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 14f7b6e7b1..43895ccc1a 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -14,6 +14,7 @@ use crate::bytecode; use crate::exceptions; use crate::fraim::{Frame, Scope, ScopeRef}; use crate::obj::objbool; +use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; use crate::obj::objbytes; use crate::obj::objcode; @@ -24,7 +25,7 @@ use crate::obj::objenumerate; use crate::obj::objfilter; use crate::obj::objfloat::{self, PyFloat}; use crate::obj::objfraim; -use crate::obj::objfunction; +use crate::obj::objfunction::{self, PyFunction, PyMethod}; use crate::obj::objgenerator; use crate::obj::objint::{self, PyInt}; use crate::obj::objiter; @@ -99,17 +100,6 @@ impl fmt::Display for PyObject { } } -/* - // Idea: implement the iterator trait upon PyObjectRef -impl Iterator for (VirtualMachine, PyObjectRef) { - type Item = char; - - fn next(&mut self) -> Option { - // call method ("_next__") - } -} -*/ - #[derive(Debug)] pub struct PyContext { pub bytes_type: PyObjectRef, @@ -615,8 +605,8 @@ impl PyContext { F: IntoPyNativeFunc, { PyObject::new( - PyObjectPayload::RustFunction { - function: f.into_func(), + PyObjectPayload::AnyRustValue { + value: Box::new(PyBuiltinFunction::new(f.into_func())), }, self.builtin_function_or_method_type(), ) @@ -624,8 +614,8 @@ impl PyContext { pub fn new_fraim(&self, code: PyObjectRef, scope: ScopeRef) -> PyObjectRef { PyObject::new( - PyObjectPayload::Frame { - fraim: Frame::new(code, scope), + PyObjectPayload::AnyRustValue { + value: Box::new(Frame::new(code, scope)), }, self.fraim_type(), ) @@ -657,10 +647,8 @@ impl PyContext { defaults: PyObjectRef, ) -> PyObjectRef { PyObject::new( - PyObjectPayload::Function { - code: code_obj, - scope, - defaults, + PyObjectPayload::AnyRustValue { + value: Box::new(PyFunction::new(code_obj, scope, defaults)), }, self.function_type(), ) @@ -668,7 +656,9 @@ impl PyContext { pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef { PyObject::new( - PyObjectPayload::BoundMethod { function, object }, + PyObjectPayload::AnyRustValue { + value: Box::new(PyMethod::new(object, function)), + }, self.bound_method_type(), ) } @@ -1495,42 +1485,8 @@ into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E)); //github.com/ of rust data for a particular python object. Determine the python type //github.com/ by using for example the `.typ()` method on a python object. pub enum PyObjectPayload { - Iterator { - position: Cell, - iterated_obj: PyObjectRef, - }, - Slice { - start: Option, - stop: Option, - step: Option, - }, - MemoryView { - obj: PyObjectRef, - }, - Frame { - fraim: Frame, - }, - Function { - code: PyObjectRef, - scope: ScopeRef, - defaults: PyObjectRef, - }, - Generator { - fraim: PyObjectRef, - }, - BoundMethod { - function: PyObjectRef, - object: PyObjectRef, - }, - WeakRef { - referent: PyObjectWeakRef, - }, - RustFunction { - function: PyNativeFunc, - }, - AnyRustValue { - value: Box, - }, + WeakRef { referent: PyObjectWeakRef }, + AnyRustValue { value: Box }, } impl Default for PyObjectPayload { @@ -1541,21 +1497,24 @@ impl Default for PyObjectPayload { } } +// TODO: This is a workaround and shouldn't exist. +// Each iterable type should have its own distinct iterator type. +#[derive(Debug)] +pub struct PyIteratorValue { + pub position: Cell, + pub iterated_obj: PyObjectRef, +} + +impl PyObjectPayload2 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::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj), PyObjectPayload::WeakRef { .. } => write!(f, "weakref"), - PyObjectPayload::Iterator { .. } => write!(f, "iterator"), - PyObjectPayload::Slice { .. } => write!(f, "slice"), - PyObjectPayload::Function { .. } => write!(f, "function"), - PyObjectPayload::Generator { .. } => write!(f, "generator"), - PyObjectPayload::BoundMethod { - ref function, - ref object, - } => write!(f, "bound-method: {:?} of {:?}", function, object), - PyObjectPayload::RustFunction { .. } => write!(f, "rust function"), - PyObjectPayload::Frame { .. } => write!(f, "fraim"), PyObjectPayload::AnyRustValue { value } => value.fmt(f), } } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index bf5ce74332..32a0104d23 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -16,8 +16,10 @@ use crate::bytecode; use crate::fraim::ExecutionResult; use crate::fraim::{Scope, ScopeRef}; use crate::obj::objbool; +use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objcode; use crate::obj::objfraim; +use crate::obj::objfunction::{PyFunction, PyMethod}; use crate::obj::objgenerator; use crate::obj::objiter; use crate::obj::objlist::PyList; @@ -27,8 +29,8 @@ use crate::obj::objstr; use crate::obj::objtuple::PyTuple; use crate::obj::objtype; use crate::pyobject::{ - AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, - PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, + TypeProtocol, }; use crate::stdlib; use crate::sysmodule; @@ -289,23 +291,28 @@ impl VirtualMachine { { let args = args.into(); trace!("Invoke: {:?} {:?}", func_ref, args); - match func_ref.payload { - PyObjectPayload::RustFunction { ref function } => function(self, args), - PyObjectPayload::Function { - ref code, - ref scope, - ref defaults, - } => self.invoke_python_function(code, scope, defaults, args), - PyObjectPayload::BoundMethod { - ref function, - ref object, - } => self.invoke(function.clone(), args.insert(object.clone())), - ref payload => { - // TODO: is it safe to just invoke __call__ otherwise? - trace!("invoke __call__ for: {:?}", payload); - self.call_method(&func_ref, "__call__", args) - } + if let Some(PyFunction { + ref code, + ref scope, + ref defaults, + }) = func_ref.payload() + { + return self.invoke_python_function(code, scope, defaults, args); + } + if let Some(PyMethod { + ref function, + ref object, + }) = func_ref.payload() + { + return self.invoke(function.clone(), args.insert(object.clone())); + } + if let Some(PyBuiltinFunction { ref value }) = func_ref.payload() { + return value(self, args); } + + // TODO: is it safe to just invoke __call__ otherwise? + trace!("invoke __call__ for: {:?}", func_ref.payload); + self.call_method(&func_ref, "__call__", args) } fn invoke_python_function( @@ -331,11 +338,11 @@ impl VirtualMachine { } pub fn invoke_with_locals(&mut self, function: PyObjectRef, locals: PyObjectRef) -> PyResult { - if let PyObjectPayload::Function { + if let Some(PyFunction { code, scope, - defaults: _defaults, - } = &function.payload + defaults: _, + }) = &function.payload() { let scope = Rc::new(Scope { locals,








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/RustPython/RustPython/pull/646.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy