From dd56d1d5a215e3828a397e3723745fc504d9bc33 Mon Sep 17 00:00:00 2001 From: Joey Hain Date: Fri, 8 Mar 2019 18:52:11 -0800 Subject: [PATCH 1/6] function --- vm/src/obj/objfunction.rs | 34 ++++++++++++++++++++++++++++++---- vm/src/pyobject.rs | 14 +++----------- vm/src/vm.rs | 20 ++++++++++++-------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 26fee403fa4..46e59663d1e 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,8 +1,34 @@ +use crate::frame::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() + } +} + pub fn init(context: &PyContext) { let function_type = &context.function_type; context.set_attr(&function_type, "__get__", context.new_rustfunc(bind_method)); @@ -79,9 +105,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/pyobject.rs b/vm/src/pyobject.rs index 14f7b6e7b16..e5c3f4e5c43 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -24,7 +24,7 @@ use crate::obj::objenumerate; use crate::obj::objfilter; use crate::obj::objfloat::{self, PyFloat}; use crate::obj::objframe; -use crate::obj::objfunction; +use crate::obj::objfunction::{self, PyFunction}; use crate::obj::objgenerator; use crate::obj::objint::{self, PyInt}; use crate::obj::objiter; @@ -657,10 +657,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(), ) @@ -1510,11 +1508,6 @@ pub enum PyObjectPayload { Frame { frame: Frame, }, - Function { - code: PyObjectRef, - scope: ScopeRef, - defaults: PyObjectRef, - }, Generator { frame: PyObjectRef, }, @@ -1548,7 +1541,6 @@ impl fmt::Debug for PyObjectPayload { 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, diff --git a/vm/src/vm.rs b/vm/src/vm.rs index bf5ce74332c..63f252bc08f 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -18,6 +18,7 @@ use crate::frame::{Scope, ScopeRef}; use crate::obj::objbool; use crate::obj::objcode; use crate::obj::objframe; +use crate::obj::objfunction::PyFunction; use crate::obj::objgenerator; use crate::obj::objiter; use crate::obj::objlist::PyList; @@ -289,13 +290,16 @@ impl VirtualMachine { { let args = args.into(); trace!("Invoke: {:?} {:?}", func_ref, args); + if let Some(PyFunction { + ref code, + ref scope, + ref defaults, + }) = func_ref.payload() + { + return self.invoke_python_function(code, scope, defaults, 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, @@ -331,11 +335,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, From 5a74121c76a02e146bf5d6daf28f1f6dbe7752f3 Mon Sep 17 00:00:00 2001 From: Joey Hain Date: Fri, 8 Mar 2019 19:11:01 -0800 Subject: [PATCH 2/6] method --- vm/src/obj/objfunction.rs | 19 +++++++++++++++++++ vm/src/pyobject.rs | 14 ++++---------- vm/src/vm.rs | 13 ++++++++----- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 46e59663d1e..432266225b2 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -29,6 +29,25 @@ impl PyObjectPayload2 for PyFunction { } } +#[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)); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index e5c3f4e5c43..cd7712c4527 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -24,7 +24,7 @@ use crate::obj::objenumerate; use crate::obj::objfilter; use crate::obj::objfloat::{self, PyFloat}; use crate::obj::objframe; -use crate::obj::objfunction::{self, PyFunction}; +use crate::obj::objfunction::{self, PyFunction, PyMethod}; use crate::obj::objgenerator; use crate::obj::objint::{self, PyInt}; use crate::obj::objiter; @@ -666,7 +666,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(), ) } @@ -1511,10 +1513,6 @@ pub enum PyObjectPayload { Generator { frame: PyObjectRef, }, - BoundMethod { - function: PyObjectRef, - object: PyObjectRef, - }, WeakRef { referent: PyObjectWeakRef, }, @@ -1542,10 +1540,6 @@ impl fmt::Debug for PyObjectPayload { PyObjectPayload::Iterator { .. } => write!(f, "iterator"), PyObjectPayload::Slice { .. } => write!(f, "slice"), 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, "frame"), PyObjectPayload::AnyRustValue { value } => value.fmt(f), diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 63f252bc08f..72af935dbf1 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -18,7 +18,7 @@ use crate::frame::{Scope, ScopeRef}; use crate::obj::objbool; use crate::obj::objcode; use crate::obj::objframe; -use crate::obj::objfunction::PyFunction; +use crate::obj::objfunction::{PyFunction, PyMethod}; use crate::obj::objgenerator; use crate::obj::objiter; use crate::obj::objlist::PyList; @@ -298,12 +298,15 @@ impl VirtualMachine { { 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())); + } match func_ref.payload { PyObjectPayload::RustFunction { ref function } => function(self, 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); From c1180fc564011dda46b095f7c643deeafc822ee6 Mon Sep 17 00:00:00 2001 From: Joey Date: Sat, 9 Mar 2019 08:45:46 -0800 Subject: [PATCH 3/6] builtin_function_or_method --- vm/src/frame.rs | 7 +++++-- vm/src/obj/mod.rs | 1 + vm/src/obj/objbuiltinfunc.rs | 26 ++++++++++++++++++++++++++ vm/src/pyobject.rs | 9 +++------ vm/src/vm.rs | 18 +++++++++--------- 5 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 vm/src/obj/objbuiltinfunc.rs diff --git a/vm/src/frame.rs b/vm/src/frame.rs index db913fe1b86..8e91194a057 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -11,6 +11,7 @@ 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; @@ -592,8 +593,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 6cbb5fa66f5..3d068df6480 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 00000000000..8e3b2c3422e --- /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/pyobject.rs b/vm/src/pyobject.rs index cd7712c4527..740e27ace3e 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -14,6 +14,7 @@ use crate::bytecode; use crate::exceptions; use crate::frame::{Frame, Scope, ScopeRef}; use crate::obj::objbool; +use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; use crate::obj::objbytes; use crate::obj::objcode; @@ -615,8 +616,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(), ) @@ -1516,9 +1517,6 @@ pub enum PyObjectPayload { WeakRef { referent: PyObjectWeakRef, }, - RustFunction { - function: PyNativeFunc, - }, AnyRustValue { value: Box, }, @@ -1540,7 +1538,6 @@ impl fmt::Debug for PyObjectPayload { PyObjectPayload::Iterator { .. } => write!(f, "iterator"), PyObjectPayload::Slice { .. } => write!(f, "slice"), PyObjectPayload::Generator { .. } => write!(f, "generator"), - PyObjectPayload::RustFunction { .. } => write!(f, "rust function"), PyObjectPayload::Frame { .. } => write!(f, "frame"), PyObjectPayload::AnyRustValue { value } => value.fmt(f), } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 72af935dbf1..32a0104d23e 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -16,6 +16,7 @@ use crate::bytecode; use crate::frame::ExecutionResult; use crate::frame::{Scope, ScopeRef}; use crate::obj::objbool; +use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objcode; use crate::obj::objframe; use crate::obj::objfunction::{PyFunction, PyMethod}; @@ -28,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; @@ -305,14 +306,13 @@ impl VirtualMachine { { return self.invoke(function.clone(), args.insert(object.clone())); } - match func_ref.payload { - PyObjectPayload::RustFunction { ref function } => function(self, args), - 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(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( From 53e4591911947bd63530ffaa5947ebc3f7269b12 Mon Sep 17 00:00:00 2001 From: Joey Date: Sat, 9 Mar 2019 09:21:21 -0800 Subject: [PATCH 4/6] frame --- vm/src/frame.rs | 10 ++++++++-- vm/src/obj/objframe.rs | 10 ++-------- vm/src/obj/objgenerator.rs | 4 ++-- vm/src/pyobject.rs | 8 ++------ 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 8e91194a057..391ab6fe3d4 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -21,8 +21,8 @@ use crate::obj::objlist; 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; @@ -76,6 +76,12 @@ pub struct Frame { pub lasti: RefCell, // index of last instruction ran } +impl PyObjectPayload2 for Frame { + fn required_type(ctx: &PyContext) -> PyObjectRef { + ctx.frame_type() + } +} + // Running a frame can result in one of the below: pub enum ExecutionResult { Return(PyObjectRef), diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs index 37acd33385f..459b5a0c3d9 100644 --- a/vm/src/obj/objframe.rs +++ b/vm/src/obj/objframe.rs @@ -3,9 +3,7 @@ */ use crate::frame::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 frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn get_value(obj: &PyObjectRef) -> &Frame { - if let PyObjectPayload::Frame { frame } = &obj.payload { - frame - } else { - panic!("Inner error getting int {:?}", obj); - } + &obj.payload::().unwrap() } diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 05a7a60ae67..9192b07aae5 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -2,7 +2,7 @@ * The mythical generator. */ -use crate::frame::ExecutionResult; +use crate::frame::{ExecutionResult, Frame}; use crate::pyobject::{ PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol, }; @@ -56,7 +56,7 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult { if let PyObjectPayload::Generator { ref frame } = gen.payload { - if let PyObjectPayload::Frame { ref frame } = frame.payload { + if let Some(frame) = frame.payload::() { frame.push_value(value.clone()); } else { panic!("Generator frame isn't a frame."); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 740e27ace3e..c1dadb92d2e 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -625,8 +625,8 @@ impl PyContext { pub fn new_frame(&self, code: PyObjectRef, scope: ScopeRef) -> PyObjectRef { PyObject::new( - PyObjectPayload::Frame { - frame: Frame::new(code, scope), + PyObjectPayload::AnyRustValue { + value: Box::new(Frame::new(code, scope)), }, self.frame_type(), ) @@ -1508,9 +1508,6 @@ pub enum PyObjectPayload { MemoryView { obj: PyObjectRef, }, - Frame { - frame: Frame, - }, Generator { frame: PyObjectRef, }, @@ -1538,7 +1535,6 @@ impl fmt::Debug for PyObjectPayload { PyObjectPayload::Iterator { .. } => write!(f, "iterator"), PyObjectPayload::Slice { .. } => write!(f, "slice"), PyObjectPayload::Generator { .. } => write!(f, "generator"), - PyObjectPayload::Frame { .. } => write!(f, "frame"), PyObjectPayload::AnyRustValue { value } => value.fmt(f), } } From 6eea40799be84c0624cec7ba3fe073bad6aae65c Mon Sep 17 00:00:00 2001 From: Joey Date: Sat, 9 Mar 2019 09:27:58 -0800 Subject: [PATCH 5/6] generator --- vm/src/obj/objgenerator.rs | 20 +++++++++++++++++--- vm/src/pyobject.rs | 4 ---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 9192b07aae5..1babd5c9dc6 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -4,10 +4,22 @@ use crate::frame::{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 { + frame: 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, frame: PyObjectRef) -> PyResult { Ok(PyObject::new( - PyObjectPayload::Generator { frame }, + PyObjectPayload::AnyRustValue { + value: Box::new(PyGenerator { frame }), + }, vm.ctx.generator_type.clone(), )) } @@ -55,7 +69,7 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult { - if let PyObjectPayload::Generator { ref frame } = gen.payload { + if let Some(PyGenerator { ref frame }) = gen.payload() { if let Some(frame) = frame.payload::() { frame.push_value(value.clone()); } else { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index c1dadb92d2e..c9c7ed02ac2 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1508,9 +1508,6 @@ pub enum PyObjectPayload { MemoryView { obj: PyObjectRef, }, - Generator { - frame: PyObjectRef, - }, WeakRef { referent: PyObjectWeakRef, }, @@ -1534,7 +1531,6 @@ impl fmt::Debug for PyObjectPayload { PyObjectPayload::WeakRef { .. } => write!(f, "weakref"), PyObjectPayload::Iterator { .. } => write!(f, "iterator"), PyObjectPayload::Slice { .. } => write!(f, "slice"), - PyObjectPayload::Generator { .. } => write!(f, "generator"), PyObjectPayload::AnyRustValue { value } => value.fmt(f), } } From 157d18d7a155dfaa740426a68f43b0face68c203 Mon Sep 17 00:00:00 2001 From: Joey Date: Sat, 9 Mar 2019 10:15:18 -0800 Subject: [PATCH 6/6] Convert iterator --- vm/src/obj/objbytes.rs | 12 +++++++----- vm/src/obj/objdict.rs | 28 +++++++++++++++++----------- vm/src/obj/objiter.rs | 6 +++--- vm/src/obj/objlist.rs | 12 +++++++----- vm/src/obj/objrange.rs | 30 +++++++++++++++++------------- vm/src/obj/objset.rs | 12 +++++++----- vm/src/obj/objtuple.rs | 12 +++++++----- vm/src/pyobject.rs | 30 ++++++++++++++---------------- 8 files changed, 79 insertions(+), 63 deletions(-) diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index d285b86e9a0..2aa0006ddf8 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 df85e757914..fd1aafa2af8 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/objiter.rs b/vm/src/obj/objiter.rs index 827ff1cd062..153750feefe 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 d71c13976f0..8ad69bff312 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/objrange.rs b/vm/src/obj/objrange.rs index 55f736da564..b526cbbb5d1 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -6,8 +6,8 @@ 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; @@ -240,9 +240,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 +256,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(), )) diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index f194e20f23d..76eca5ec2a4 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/objtuple.rs b/vm/src/obj/objtuple.rs index e2e80d8c815..e583055c302 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 c9c7ed02ac2..ab2d1160167 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -100,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, @@ -1496,10 +1485,6 @@ into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E)); /// of rust data for a particular python object. Determine the python type /// 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, @@ -1524,12 +1509,25 @@ 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::AnyRustValue { value } => value.fmt(f), }