diff --git a/Cargo.lock b/Cargo.lock index 262c5eb68..0da0a83d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1670,6 +1670,7 @@ dependencies = [ name = "rustpython-derive" version = "0.1.2" dependencies = [ + "indexmap", "maplit", "once_cell", "proc-macro2", @@ -1818,6 +1819,7 @@ version = "0.1.2" dependencies = [ "js-sys", "parking_lot", + "rustpython-common", "rustpython-compiler", "rustpython-parser", "rustpython-vm", diff --git a/common/src/lib.rs b/common/src/lib.rs index 5bbee0a85..34c011634 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -5,4 +5,5 @@ pub mod float_ops; pub mod hash; pub mod lock; pub mod rc; +pub mod static_cell; pub mod str; diff --git a/common/src/static_cell.rs b/common/src/static_cell.rs new file mode 100644 index 000000000..8e86e9aca --- /dev/null +++ b/common/src/static_cell.rs @@ -0,0 +1,76 @@ +#[cfg(not(feature = "threading"))] +mod non_threading { + use crate::lock::OnceCell; + pub type StaticCell = std::thread::LocalKey>; + + #[macro_export] + macro_rules! static_cells { + // process multiple declarations + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => ( + std::thread_local! { + $(#[$attr])* $vis static $name: $crate::lock::OnceCell<&'static $t> = $crate::lock::OnceCell::new(); + } + ); + } +} +#[cfg(not(feature = "threading"))] +pub use non_threading::*; + +#[cfg(feature = "threading")] +mod threading { + use crate::lock::OnceCell; + + pub struct StaticKey { + inner: T, + } + + impl StaticKey { + pub const fn new(inner: T) -> Self { + Self { inner } + } + + pub fn with(&self, f: F) -> R + where + F: FnOnce(&T) -> R, + { + f(&self.inner) + } + } + + pub type StaticCell = StaticKey>; + + #[macro_export] + macro_rules! static_cells { + // process multiple declarations + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => ( + $(#[$attr])* $vis static $name: $crate::static_cell::StaticKey<$crate::lock::OnceCell<&'static $t>> = $crate::static_cell::StaticKey::new($crate::lock::OnceCell::new()); + ); + } +} +#[cfg(feature = "threading")] +pub use threading::*; + +pub fn get(cell: &'static StaticCell) -> Option<&'static T> { + cell.with(|cell| cell.get().copied()) +} + +pub fn init_expect(cell: &'static StaticCell, value: T, msg: &'static str) -> &'static T { + cell.with(|cell| { + let static_ref = Box::leak(Box::new(value)) as &_; + cell.set(static_ref) + .unwrap_or_else(|_| panic!("double initializing '{}'", msg)); + static_ref + }) +} + +pub fn get_or_init(cell: &'static StaticCell, f: F) -> &'static T +where + F: FnOnce() -> T, +{ + cell.with(|cell| { + *cell.get_or_init(|| { + let value = f(); + Box::leak(Box::new(value)) + }) + }) +} diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 61c019918..69167ee21 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -20,3 +20,4 @@ rustpython-bytecode = { path = "../bytecode", version = "0.1.1" } maplit = "1.0" once_cell = "1.3.1" textwrap = "0.12.1" +indexmap = "^1" diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index 882c8b779..99fe8c88f 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -133,6 +133,7 @@ fn generate_class_def( ident: &Ident, name: &str, module_name: Option<&str>, + base: Option, attrs: &[Attribute], ) -> std::result::Result { let doc = if let Some(doc) = attrs.doc() { @@ -159,11 +160,27 @@ fn generate_class_def( false } }); + if base.is_some() && is_pystruct { + return Err(syn::Error::new_spanned( + ident, + "PyStructSequence cannot have `base` class attr", + ) + .into()); + } + let base = base.map(|name| Ident::new(&name, ident.span())); let base_class = if is_pystruct { quote! { - fn base_class(ctx: &::rustpython_vm::pyobject::PyContext) -> ::rustpython_vm::builtins::PyTypeRef { - ctx.types.tuple_type.clone() + fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef { + use rustpython_vm::pyobject::StaticType; + rustpython_vm::builtins::PyTuple::static_type() + } + } + } else if let Some(base) = base { + quote! { + fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef { + use rustpython_vm::pyobject::StaticType; + #base::static_type() } } } else { @@ -176,6 +193,17 @@ fn generate_class_def( const MODULE_NAME: Option<&'static str> = #module_name; const TP_NAME: &'static str = #module_class_name; const DOC: Option<&'static str> = #doc; + } + + impl ::rustpython_vm::pyobject::StaticType for #ident { + fn static_cell() -> &'static ::rustpython_common::static_cell::StaticCell<::rustpython_vm::builtins::PyTypeRef> { + use ::rustpython_common::static_cells; + static_cells! { + static CELL: ::rustpython_vm::builtins::PyTypeRef; + } + &CELL + } + #base_class } }; @@ -191,7 +219,8 @@ pub(crate) fn impl_pyclass( let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?; let class_name = class_meta.class_name()?; let module_name = class_meta.module()?; - let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), &attrs)?; + let base = class_meta.base()?; + let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), base, &attrs)?; let ret = quote! { #item diff --git a/derive/src/util.rs b/derive/src/util.rs index 735f48481..756478f20 100644 --- a/derive/src/util.rs +++ b/derive/src/util.rs @@ -1,3 +1,4 @@ +use indexmap::map::IndexMap; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use std::collections::HashMap; @@ -18,7 +19,7 @@ pub(crate) const ALL_ALLOWED_NAMES: &[&str] = &[ ]; #[derive(Default)] -pub(crate) struct ItemNursery(HashMap<(String, Vec), TokenStream>); +pub(crate) struct ItemNursery(IndexMap<(String, Vec), TokenStream>); impl ItemNursery { pub fn add_item( @@ -27,10 +28,10 @@ impl ItemNursery { cfgs: Vec, tokens: TokenStream, ) -> Result<()> { - if let Some(existing) = self.0.insert((name, cfgs), tokens) { + if let Some(existing) = self.0.insert((name.clone(), cfgs), tokens) { Err(syn::Error::new_spanned( existing, - "Duplicated #[py*] attribute found", + format!("Duplicated #[py*] attribute found for '{}'", name), )) } else { Ok(()) @@ -232,7 +233,7 @@ impl ItemMeta for SimpleItemMeta { pub(crate) struct ClassItemMeta(ItemMetaInner); impl ItemMeta for ClassItemMeta { - const ALLOWED_NAMES: &'static [&'static str] = &["module", "name"]; + const ALLOWED_NAMES: &'static [&'static str] = &["module", "name", "base"]; fn from_inner(inner: ItemMetaInner) -> Self { Self(inner) @@ -267,6 +268,10 @@ impl ClassItemMeta { Ok(value) } + pub fn base(&self) -> Result> { + self.inner()._optional_str("base") + } + pub fn module(&self) -> Result> { const KEY: &str = "module"; let inner = self.inner(); diff --git a/vm/src/builtins/asyncgenerator.rs b/vm/src/builtins/asyncgenerator.rs index fdd4658ac..02717c52b 100644 --- a/vm/src/builtins/asyncgenerator.rs +++ b/vm/src/builtins/asyncgenerator.rs @@ -20,8 +20,8 @@ pub struct PyAsyncGen { type PyAsyncGenRef = PyRef; impl PyValue for PyAsyncGen { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.async_generator.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.async_generator } } @@ -118,8 +118,8 @@ impl PyAsyncGen { #[derive(Debug)] pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef); impl PyValue for PyAsyncGenWrappedValue { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.async_generator_wrapped_value.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.async_generator_wrapped_value } } @@ -167,8 +167,8 @@ pub(crate) struct PyAsyncGenASend { } impl PyValue for PyAsyncGenASend { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.async_generator_asend.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.async_generator_asend } } @@ -263,8 +263,8 @@ pub(crate) struct PyAsyncGenAThrow { } impl PyValue for PyAsyncGenAThrow { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.async_generator_athrow.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.async_generator_athrow } } diff --git a/vm/src/builtins/builtinfunc.rs b/vm/src/builtins/builtinfunc.rs index c70f0773a..985e644b6 100644 --- a/vm/src/builtins/builtinfunc.rs +++ b/vm/src/builtins/builtinfunc.rs @@ -63,8 +63,8 @@ pub struct PyBuiltinFunction { } impl PyValue for PyBuiltinFunction { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.builtin_function_or_method_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.builtin_function_or_method_type } } @@ -139,8 +139,8 @@ pub struct PyBuiltinMethod { } impl PyValue for PyBuiltinMethod { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.method_descriptor_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.method_descriptor_type } } diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index 7d284349d..2e156e5a4 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -83,8 +83,8 @@ impl From> for PyByteArray { } impl PyValue for PyByteArray { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.bytearray_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.bytearray_type } } @@ -562,7 +562,7 @@ impl PyByteArray { fn reduce(zelf: PyRef, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef) { let bytes = PyBytes::from(zelf.borrow_value().elements.clone()).into_pyobject(vm); ( - Self::class(vm), + Self::class(vm).clone(), PyTupleRef::with_elements(vec![bytes], &vm.ctx), ) } @@ -650,8 +650,8 @@ pub struct PyByteArrayIterator { } impl PyValue for PyByteArrayIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.bytearray_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.bytearray_iterator_type } } diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 96b73440f..108885ba6 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -89,8 +89,8 @@ impl Deref for PyBytes { } impl PyValue for PyBytes { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.bytes_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.bytes_type } } @@ -537,8 +537,8 @@ pub struct PyBytesIterator { } impl PyValue for PyBytesIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.bytes_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.bytes_iterator_type } } diff --git a/vm/src/builtins/classmethod.rs b/vm/src/builtins/classmethod.rs index d166487e7..d84dc5f5a 100644 --- a/vm/src/builtins/classmethod.rs +++ b/vm/src/builtins/classmethod.rs @@ -38,8 +38,8 @@ impl From for PyClassMethod { } impl PyValue for PyClassMethod { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.classmethod_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.classmethod_type } } diff --git a/vm/src/builtins/code.rs b/vm/src/builtins/code.rs index 173c87513..28cf628f2 100644 --- a/vm/src/builtins/code.rs +++ b/vm/src/builtins/code.rs @@ -37,11 +37,14 @@ impl fmt::Debug for PyCode { } impl PyValue for PyCode { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.code_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.code_type } } +#[pyimpl(with(PyRef))] +impl PyCode {} + #[pyimpl] impl PyCodeRef { #[pyslot] diff --git a/vm/src/builtins/complex.rs b/vm/src/builtins/complex.rs index 6dcf86906..d299fcf64 100644 --- a/vm/src/builtins/complex.rs +++ b/vm/src/builtins/complex.rs @@ -22,8 +22,8 @@ pub struct PyComplex { } impl PyValue for PyComplex { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.complex_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.complex_type } } diff --git a/vm/src/builtins/coroutine.rs b/vm/src/builtins/coroutine.rs index 3562855f0..d7157b63c 100644 --- a/vm/src/builtins/coroutine.rs +++ b/vm/src/builtins/coroutine.rs @@ -16,8 +16,8 @@ pub struct PyCoroutine { } impl PyValue for PyCoroutine { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.coroutine_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.coroutine_type } } @@ -102,8 +102,8 @@ pub struct PyCoroutineWrapper { } impl PyValue for PyCoroutineWrapper { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.coroutine_wrapper_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.coroutine_wrapper_type } } diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index 1694e5664..fd0968c6c 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -43,8 +43,8 @@ impl fmt::Debug for PyDict { } impl PyValue for PyDict { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.dict_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.dict_type } } @@ -645,8 +645,8 @@ macro_rules! dict_iterator { } impl PyValue for $name { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.$class.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.$class } } @@ -698,8 +698,8 @@ macro_rules! dict_iterator { } impl PyValue for $iter_name { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.$iter_class.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.$iter_class } } @@ -754,8 +754,8 @@ macro_rules! dict_iterator { } impl PyValue for $reverse_iter_name { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.$reverse_iter_class.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.$reverse_iter_class } } }; diff --git a/vm/src/builtins/enumerate.rs b/vm/src/builtins/enumerate.rs index dc7858a4c..c11342c05 100644 --- a/vm/src/builtins/enumerate.rs +++ b/vm/src/builtins/enumerate.rs @@ -19,8 +19,8 @@ pub struct PyEnumerate { } impl PyValue for PyEnumerate { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.enumerate_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.enumerate_type } } diff --git a/vm/src/builtins/filter.rs b/vm/src/builtins/filter.rs index 02a99426f..067d41b8d 100644 --- a/vm/src/builtins/filter.rs +++ b/vm/src/builtins/filter.rs @@ -16,8 +16,8 @@ pub struct PyFilter { } impl PyValue for PyFilter { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.filter_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.filter_type } } diff --git a/vm/src/builtins/float.rs b/vm/src/builtins/float.rs index 8e4518681..88e0d268b 100644 --- a/vm/src/builtins/float.rs +++ b/vm/src/builtins/float.rs @@ -33,8 +33,8 @@ impl PyFloat { } impl PyValue for PyFloat { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.float_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.float_type } } diff --git a/vm/src/builtins/frame.rs b/vm/src/builtins/frame.rs index 410772b44..947dd673a 100644 --- a/vm/src/builtins/frame.rs +++ b/vm/src/builtins/frame.rs @@ -5,14 +5,17 @@ use super::code::PyCodeRef; use super::dict::PyDictRef; use super::pystr::PyStrRef; -use crate::frame::FrameRef; -use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult}; +use crate::frame::{Frame, FrameRef}; +use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { FrameRef::extend_class(context, &context.types.frame_type); } +#[pyimpl(with(PyRef))] +impl Frame {} + #[pyimpl] impl FrameRef { #[pyslot] diff --git a/vm/src/builtins/function.rs b/vm/src/builtins/function.rs index 34afc0723..9771c6cec 100644 --- a/vm/src/builtins/function.rs +++ b/vm/src/builtins/function.rs @@ -264,8 +264,8 @@ impl PyFunction { } impl PyValue for PyFunction { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.function_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.function_type } } @@ -397,8 +397,8 @@ impl PyBoundMethod { } impl PyValue for PyBoundMethod { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.bound_method_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.bound_method_type } } diff --git a/vm/src/builtins/generator.rs b/vm/src/builtins/generator.rs index 4c1aaf627..b8213b006 100644 --- a/vm/src/builtins/generator.rs +++ b/vm/src/builtins/generator.rs @@ -17,8 +17,8 @@ pub struct PyGenerator { } impl PyValue for PyGenerator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.generator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.generator_type } } diff --git a/vm/src/builtins/getset.rs b/vm/src/builtins/getset.rs index d43973c19..48204f613 100644 --- a/vm/src/builtins/getset.rs +++ b/vm/src/builtins/getset.rs @@ -173,8 +173,8 @@ impl std::fmt::Debug for PyGetSet { } impl PyValue for PyGetSet { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.getset_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.getset_type } } diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 45e84ca8d..19c668ad5 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -71,8 +71,8 @@ where } impl PyValue for PyInt { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.int_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.int_type } fn into_object(self, vm: &VirtualMachine) -> PyObjectRef { diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index 535ca540c..492aee776 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -19,8 +19,8 @@ pub struct PySequenceIterator { } impl PyValue for PySequenceIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.iter_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.iter_type } } @@ -88,8 +88,8 @@ pub struct PyCallableIterator { } impl PyValue for PyCallableIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.callable_iterator.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.callable_iterator } } diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 1afe8018e..8849ae270 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -53,8 +53,8 @@ impl FromIterator for PyList { } impl PyValue for PyList { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.list_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.list_type } } @@ -459,8 +459,8 @@ pub struct PyListIterator { } impl PyValue for PyListIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.list_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.list_iterator_type } } @@ -498,8 +498,8 @@ pub struct PyListReverseIterator { } impl PyValue for PyListReverseIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.list_reverseiterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.list_reverseiterator_type } } diff --git a/vm/src/builtins/map.rs b/vm/src/builtins/map.rs index 05fed79c5..ae21dc8c5 100644 --- a/vm/src/builtins/map.rs +++ b/vm/src/builtins/map.rs @@ -16,8 +16,8 @@ pub struct PyMap { } impl PyValue for PyMap { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.map_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.map_type } } diff --git a/vm/src/builtins/mappingproxy.rs b/vm/src/builtins/mappingproxy.rs index 7c5668f8b..21ce7c776 100644 --- a/vm/src/builtins/mappingproxy.rs +++ b/vm/src/builtins/mappingproxy.rs @@ -22,8 +22,8 @@ enum MappingProxyInner { } impl PyValue for PyMappingProxy { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.mappingproxy_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.mappingproxy_type } } diff --git a/vm/src/builtins/memory.rs b/vm/src/builtins/memory.rs index 7022d9469..9dded35a7 100644 --- a/vm/src/builtins/memory.rs +++ b/vm/src/builtins/memory.rs @@ -766,8 +766,8 @@ impl Hashable for PyMemoryView { } impl PyValue for PyMemoryView { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.memoryview_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.memoryview_type } } diff --git a/vm/src/builtins/module.rs b/vm/src/builtins/module.rs index c46a03018..37d0bb638 100644 --- a/vm/src/builtins/module.rs +++ b/vm/src/builtins/module.rs @@ -15,8 +15,8 @@ pub struct PyModule {} pub type PyModuleRef = PyRef; impl PyValue for PyModule { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.module_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.module_type } } diff --git a/vm/src/builtins/namespace.rs b/vm/src/builtins/namespace.rs index 8548d6522..796dca3a2 100644 --- a/vm/src/builtins/namespace.rs +++ b/vm/src/builtins/namespace.rs @@ -11,8 +11,8 @@ use crate::vm::VirtualMachine; pub struct PyNamespace; impl PyValue for PyNamespace { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.namespace_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.namespace_type } } diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index d8e97daee..c27369cf4 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -20,8 +20,8 @@ use crate::vm::VirtualMachine; pub struct PyBaseObject; impl PyValue for PyBaseObject { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.object_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.object_type } } diff --git a/vm/src/builtins/property.rs b/vm/src/builtins/property.rs index 63eab85ed..cf18ac968 100644 --- a/vm/src/builtins/property.rs +++ b/vm/src/builtins/property.rs @@ -53,8 +53,8 @@ pub struct PyProperty { } impl PyValue for PyProperty { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.property_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.property_type } } diff --git a/vm/src/builtins/pybool.rs b/vm/src/builtins/pybool.rs index 548612939..38b049c09 100644 --- a/vm/src/builtins/pybool.rs +++ b/vm/src/builtins/pybool.rs @@ -76,7 +76,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { /// Returns True when the argument x is true, False otherwise. /// The builtins True and False are the only two instances of the class bool. /// The class bool is a subclass of the class int, and cannot be subclassed. -#[pyclass(name = "bool", module = false)] +#[pyclass(name = "bool", module = false, base = "PyInt")] pub struct PyBool; #[pyimpl] diff --git a/vm/src/builtins/pystr.rs b/vm/src/builtins/pystr.rs index f3b7a21c8..9bb1a521c 100644 --- a/vm/src/builtins/pystr.rs +++ b/vm/src/builtins/pystr.rs @@ -109,8 +109,8 @@ pub struct PyStrIterator { } impl PyValue for PyStrIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.str_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.str_iterator_type } } @@ -156,8 +156,8 @@ pub struct PyStrReverseIterator { } impl PyValue for PyStrReverseIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.str_reverseiterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.str_reverseiterator_type } } @@ -1113,8 +1113,8 @@ pub(crate) fn encode_string( } impl PyValue for PyStr { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.str_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.str_type } } diff --git a/vm/src/builtins/pysuper.rs b/vm/src/builtins/pysuper.rs index 17782a3a3..908a9a9f6 100644 --- a/vm/src/builtins/pysuper.rs +++ b/vm/src/builtins/pysuper.rs @@ -25,8 +25,8 @@ pub struct PySuper { } impl PyValue for PySuper { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.super_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.super_type } } diff --git a/vm/src/builtins/pytype.rs b/vm/src/builtins/pytype.rs index dbd2396cc..38e6fad0c 100644 --- a/vm/src/builtins/pytype.rs +++ b/vm/src/builtins/pytype.rs @@ -51,8 +51,8 @@ impl fmt::Debug for PyType { pub type PyTypeRef = PyRef; impl PyValue for PyType { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.type_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.type_type } } diff --git a/vm/src/builtins/range.rs b/vm/src/builtins/range.rs index 60bb8d994..52132cd57 100644 --- a/vm/src/builtins/range.rs +++ b/vm/src/builtins/range.rs @@ -32,8 +32,8 @@ pub struct PyRange { } impl PyValue for PyRange { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.range_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.range_type } } @@ -376,8 +376,8 @@ pub struct PyRangeIterator { } impl PyValue for PyRangeIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.range_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.range_iterator_type } } diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index 9d776994b..ccea079ff 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -52,14 +52,14 @@ impl fmt::Debug for PyFrozenSet { } impl PyValue for PySet { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.set_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.set_type } } impl PyValue for PyFrozenSet { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.frozenset_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.frozenset_type } } @@ -792,8 +792,8 @@ impl PySetIterator { } impl PyValue for PySetIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.set_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.set_iterator_type } } diff --git a/vm/src/builtins/singletons.rs b/vm/src/builtins/singletons.rs index 3880945df..a577bfcdd 100644 --- a/vm/src/builtins/singletons.rs +++ b/vm/src/builtins/singletons.rs @@ -10,8 +10,8 @@ pub struct PyNone; pub type PyNoneRef = PyRef; impl PyValue for PyNone { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.none.clone_class() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.none_type } } @@ -56,8 +56,8 @@ pub struct PyNotImplemented; pub type PyNotImplementedRef = PyRef; impl PyValue for PyNotImplemented { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.not_implemented.clone_class() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.not_implemented_type } } diff --git a/vm/src/builtins/slice.rs b/vm/src/builtins/slice.rs index 678c4cdc1..abfa5b9fb 100644 --- a/vm/src/builtins/slice.rs +++ b/vm/src/builtins/slice.rs @@ -21,8 +21,8 @@ pub struct PySlice { } impl PyValue for PySlice { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.slice_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.slice_type } } @@ -287,8 +287,8 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult PyTypeRef { - vm.ctx.ellipsis.clone_class() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.ellipsis_type } } diff --git a/vm/src/builtins/staticmethod.rs b/vm/src/builtins/staticmethod.rs index 6d4adb085..78d2ddfe0 100644 --- a/vm/src/builtins/staticmethod.rs +++ b/vm/src/builtins/staticmethod.rs @@ -10,8 +10,8 @@ pub struct PyStaticMethod { } impl PyValue for PyStaticMethod { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.staticmethod_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.staticmethod_type } } diff --git a/vm/src/builtins/traceback.rs b/vm/src/builtins/traceback.rs index 046be7d51..2155fe303 100644 --- a/vm/src/builtins/traceback.rs +++ b/vm/src/builtins/traceback.rs @@ -15,8 +15,8 @@ pub struct PyTraceback { pub type PyTracebackRef = PyRef; impl PyValue for PyTraceback { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.traceback_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.traceback_type } } diff --git a/vm/src/builtins/tuple.rs b/vm/src/builtins/tuple.rs index 46647c074..93b20c672 100644 --- a/vm/src/builtins/tuple.rs +++ b/vm/src/builtins/tuple.rs @@ -41,8 +41,8 @@ impl<'a> BorrowValue<'a> for PyTuple { } impl PyValue for PyTuple { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.tuple_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.tuple_type } } @@ -288,8 +288,8 @@ pub struct PyTupleIterator { } impl PyValue for PyTupleIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.tuple_iterator_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.tuple_iterator_type } } diff --git a/vm/src/builtins/weakproxy.rs b/vm/src/builtins/weakproxy.rs index 5130063a7..18932628e 100644 --- a/vm/src/builtins/weakproxy.rs +++ b/vm/src/builtins/weakproxy.rs @@ -11,8 +11,8 @@ pub struct PyWeakProxy { } impl PyValue for PyWeakProxy { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.weakproxy_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.weakproxy_type } } diff --git a/vm/src/builtins/weakref.rs b/vm/src/builtins/weakref.rs index 52927346b..f98045b74 100644 --- a/vm/src/builtins/weakref.rs +++ b/vm/src/builtins/weakref.rs @@ -31,8 +31,8 @@ impl PyWeak { } impl PyValue for PyWeak { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.weakref_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.weakref_type } } diff --git a/vm/src/builtins/zip.rs b/vm/src/builtins/zip.rs index 115eea8dc..9791a3af7 100644 --- a/vm/src/builtins/zip.rs +++ b/vm/src/builtins/zip.rs @@ -13,8 +13,8 @@ pub struct PyZip { } impl PyValue for PyZip { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.zip_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.zip_type } } diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index d22c882a7..667edd429 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -6,21 +6,21 @@ use crate::builtins::tuple::{PyTuple, PyTupleRef}; use crate::common::lock::PyRwLock; use crate::function::FuncArgs; use crate::py_io::{self, Write}; +use crate::pyobject::StaticType; use crate::pyobject::{ - BorrowValue, IntoPyObject, PyClassDef, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, - PyResult, PyValue, TryFromObject, TypeProtocol, + BorrowValue, IntoPyObject, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, + PyValue, TryFromObject, TypeProtocol, }; use crate::types::create_type_with_slots; use crate::VirtualMachine; use crate::{py_serde, sysmodule}; +use crossbeam_utils::atomic::AtomicCell; use itertools::Itertools; use std::fmt; use std::fs::File; use std::io::{self, BufRead, BufReader}; -use crossbeam_utils::atomic::AtomicCell; - #[pyclass(module = false, name = "BaseException")] pub struct PyBaseException { traceback: PyRwLock>, @@ -44,8 +44,8 @@ pub trait IntoPyException { } impl PyValue for PyBaseException { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.exceptions.base_exception_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.exceptions.base_exception_type } } @@ -394,7 +394,7 @@ pub fn normalize( Ok(exc) } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExceptionZoo { pub base_exception_type: PyTypeRef, pub system_exit: PyTypeRef, @@ -468,12 +468,17 @@ pub struct ExceptionZoo { } impl ExceptionZoo { - pub fn new(type_type: &PyTypeRef, object_type: &PyTypeRef) -> Self { + pub(crate) fn init() -> Self { + let base_exception_type = PyBaseException::init_bare_type().clone(); let create_exception_type = |name: &str, base: &PyTypeRef| { - create_type_with_slots(name, type_type, base.clone(), PyBaseException::make_slots()) + create_type_with_slots( + name, + PyType::static_type(), + base, + PyBaseException::make_slots(), + ) }; // Sorted By Hierarchy then alphabetized. - let base_exception_type = create_exception_type(PyBaseExceptionRef::NAME, &object_type); let system_exit = create_exception_type("SystemExit", &base_exception_type); let keyboard_interrupt = create_exception_type("KeyboardInterrupt", &base_exception_type); let generator_exit = create_exception_type("GeneratorExit", &base_exception_type); @@ -552,7 +557,7 @@ impl ExceptionZoo { let bytes_warning = create_exception_type("BytesWarning", &warning); let resource_warning = create_exception_type("ResourceWarning", &warning); - ExceptionZoo { + Self { base_exception_type, system_exit, keyboard_interrupt, @@ -624,6 +629,62 @@ impl ExceptionZoo { resource_warning, } } + + pub fn extend(ctx: &PyContext) { + let excs = &ctx.exceptions; + + PyBaseException::extend_class(ctx, &excs.base_exception_type); + + extend_class!(ctx, &excs.syntax_error, { + "msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)), + // TODO: members + "filename" => ctx.none(), + "lineno" => ctx.none(), + "offset" => ctx.none(), + "text" => ctx.none(), + }); + + extend_class!(ctx, &excs.system_exit, { + "code" => ctx.new_readonly_getset("code", system_exit_code), + }); + + extend_class!(ctx, &excs.import_error, { + "__init__" => ctx.new_method(import_error_init), + "msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)), + }); + + extend_class!(ctx, &excs.stop_iteration, { + "value" => ctx.new_readonly_getset("value", make_arg_getter(0)), + }); + + extend_class!(ctx, &excs.key_error, { + "__str__" => ctx.new_method(key_error_str), + }); + + extend_class!(ctx, &excs.unicode_decode_error, { + "encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)), + "object" => ctx.new_readonly_getset("object", make_arg_getter(1)), + "start" => ctx.new_readonly_getset("start", make_arg_getter(2)), + "end" => ctx.new_readonly_getset("end", make_arg_getter(3)), + "reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)), + }); + + extend_class!(ctx, &excs.unicode_encode_error, { + "encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)), + "object" => ctx.new_readonly_getset("object", make_arg_getter(1)), + "start" => ctx.new_readonly_getset("start", make_arg_getter(2)), + "end" => ctx.new_readonly_getset("end", make_arg_getter(3)), + "reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)), + }); + + extend_class!(ctx, &excs.unicode_translate_error, { + "encoding" => ctx.new_readonly_getset("encoding", none_getter), + "object" => ctx.new_readonly_getset("object", make_arg_getter(0)), + "start" => ctx.new_readonly_getset("start", make_arg_getter(1)), + "end" => ctx.new_readonly_getset("end", make_arg_getter(2)), + "reason" => ctx.new_readonly_getset("reason", make_arg_getter(3)), + }); + } } fn import_error_init(exc_self: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { @@ -672,62 +733,6 @@ fn system_exit_code(exc: PyBaseExceptionRef) -> Option { }) } -pub fn init(ctx: &PyContext) { - let excs = &ctx.exceptions; - - PyBaseException::extend_class(ctx, &excs.base_exception_type); - - extend_class!(ctx, &excs.syntax_error, { - "msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)), - // TODO: members - "filename" => ctx.none(), - "lineno" => ctx.none(), - "offset" => ctx.none(), - "text" => ctx.none(), - }); - - extend_class!(ctx, &excs.system_exit, { - "code" => ctx.new_readonly_getset("code", system_exit_code), - }); - - extend_class!(ctx, &excs.import_error, { - "__init__" => ctx.new_method(import_error_init), - "msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)), - }); - - extend_class!(ctx, &excs.stop_iteration, { - "value" => ctx.new_readonly_getset("value", make_arg_getter(0)), - }); - - extend_class!(ctx, &excs.key_error, { - "__str__" => ctx.new_method(key_error_str), - }); - - extend_class!(ctx, &excs.unicode_decode_error, { - "encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)), - "object" => ctx.new_readonly_getset("object", make_arg_getter(1)), - "start" => ctx.new_readonly_getset("start", make_arg_getter(2)), - "end" => ctx.new_readonly_getset("end", make_arg_getter(3)), - "reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)), - }); - - extend_class!(ctx, &excs.unicode_encode_error, { - "encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)), - "object" => ctx.new_readonly_getset("object", make_arg_getter(1)), - "start" => ctx.new_readonly_getset("start", make_arg_getter(2)), - "end" => ctx.new_readonly_getset("end", make_arg_getter(3)), - "reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)), - }); - - extend_class!(ctx, &excs.unicode_translate_error, { - "encoding" => ctx.new_readonly_getset("encoding", none_getter), - "object" => ctx.new_readonly_getset("object", make_arg_getter(0)), - "start" => ctx.new_readonly_getset("start", make_arg_getter(1)), - "end" => ctx.new_readonly_getset("end", make_arg_getter(2)), - "reason" => ctx.new_readonly_getset("reason", make_arg_getter(3)), - }); -} - pub struct SerializeException<'s> { vm: &'s VirtualMachine, exc: &'s PyBaseExceptionRef, diff --git a/vm/src/frame.rs b/vm/src/frame.rs index d829344f9..2fd765c53 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -100,8 +100,8 @@ pub struct Frame { } impl PyValue for Frame { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.ctx.types.frame_type.clone() + fn class(vm: &VirtualMachine) -> &PyTypeRef { + &vm.ctx.types.frame_type } } diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 96710e67a..095ce0365 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -41,7 +41,7 @@ macro_rules! py_class { #[allow(unused_mut)] let mut slots = $crate::slots::PyTypeSlots::from_flags($crate::slots::PyTpFlags::DEFAULT | $flags); $($crate::py_class!(@extract_slots($ctx, &mut slots, $name, $value));)* - let py_class = $ctx.new_class($class_name, $class_base.clone(), slots); + let py_class = $ctx.new_class($class_name, $class_base, slots); $($crate::py_class!(@extract_attrs($ctx, &py_class, $name, $value));)* $ctx.add_tp_new_wrapper(&py_class); py_class diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index e41c04507..cbaa57c0c 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,13 +1,12 @@ +use num_bigint::BigInt; +use num_complex::Complex64; +use num_traits::ToPrimitive; use std::any::Any; use std::collections::HashMap; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; -use num_bigint::BigInt; -use num_complex::Complex64; -use num_traits::ToPrimitive; - use crate::builtins::builtinfunc::PyNativeFuncDef; use crate::builtins::bytearray; use crate::builtins::bytes; @@ -31,18 +30,18 @@ use crate::builtins::slice::PyEllipsis; use crate::builtins::staticmethod::PyStaticMethod; use crate::builtins::tuple::{PyTuple, PyTupleRef}; use crate::bytecode; +pub use crate::common::borrow::BorrowValue; +use crate::common::lock::{PyRwLock, PyRwLockReadGuard}; +use crate::common::rc::PyRc; +use crate::common::static_cell; use crate::exceptions::{self, PyBaseExceptionRef}; use crate::function::{IntoFuncArgs, IntoPyNativeFunc}; use crate::iterator; pub use crate::pyobjectrc::{PyObjectRc, PyObjectWeak}; use crate::scope::Scope; use crate::slots::{PyTpFlags, PyTypeSlots}; -use crate::types::{create_type_with_slots, initialize_types, TypeZoo}; +use crate::types::{create_type_with_slots, TypeZoo}; use crate::vm::VirtualMachine; -use rustpython_common::lock::{PyRwLock, PyRwLockReadGuard}; -use rustpython_common::rc::PyRc; - -pub use crate::common::borrow::BorrowValue; /* Python objects and references. @@ -92,7 +91,7 @@ impl fmt::Display for PyObject { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PyContext { pub true_value: PyIntRef, pub false_value: PyIntRef, @@ -113,60 +112,62 @@ impl PyContext { pub const INT_CACHE_POOL_MAX: i32 = 256; pub fn new() -> Self { - flame_guard!("init PyContext"); - let types = TypeZoo::new(); - let exceptions = exceptions::ExceptionZoo::new(&types.type_type, &types.object_type); - - fn create_object(payload: T, cls: &PyTypeRef) -> PyRef { - PyRef::new_ref(payload, cls.clone(), None) + use rustpython_common::static_cells; + static_cells! { + static CONTEXT: PyContext; } + static_cell::get_or_init(&CONTEXT, || { + flame_guard!("init PyContext"); + let types = TypeZoo::init(); + let exceptions = exceptions::ExceptionZoo::init(); - let none_type = PyNone::create_bare_type(&types.type_type, types.object_type.clone()); - let none = create_object(PyNone, &none_type); + fn create_object( + payload: T, + cls: &PyTypeRef, + ) -> PyRef { + PyRef::new_ref(payload, cls.clone(), None) + } - let ellipsis_type = - PyEllipsis::create_bare_type(&types.type_type, types.object_type.clone()); - let ellipsis = create_object(PyEllipsis, &ellipsis_type); + let none = create_object(PyNone, PyNone::static_type()); + let ellipsis = create_object(PyEllipsis, PyEllipsis::static_type()); + let not_implemented = create_object(PyNotImplemented, PyNotImplemented::static_type()); - let not_implemented_type = - PyNotImplemented::create_bare_type(&types.type_type, types.object_type.clone()); - let not_implemented = create_object(PyNotImplemented, ¬_implemented_type); + let int_cache_pool = (Self::INT_CACHE_POOL_MIN..=Self::INT_CACHE_POOL_MAX) + .map(|v| PyRef::new_ref(PyInt::from(BigInt::from(v)), types.int_type.clone(), None)) + .collect(); - let int_cache_pool = (Self::INT_CACHE_POOL_MIN..=Self::INT_CACHE_POOL_MAX) - .map(|v| PyRef::new_ref(PyInt::from(BigInt::from(v)), types.int_type.clone(), None)) - .collect(); + let true_value = create_object(PyInt::from(1), &types.bool_type); + let false_value = create_object(PyInt::from(0), &types.bool_type); - let true_value = create_object(PyInt::from(1), &types.bool_type); - let false_value = create_object(PyInt::from(0), &types.bool_type); + let empty_tuple = create_object( + PyTuple::_new(Vec::new().into_boxed_slice()), + &types.tuple_type, + ); - let empty_tuple = create_object( - PyTuple::_new(Vec::new().into_boxed_slice()), - &types.tuple_type, - ); + let tp_new_wrapper = create_object( + PyNativeFuncDef::from(pytype::tp_new_wrapper.into_func()).into_function(), + &types.builtin_function_or_method_type, + ) + .into_object(); - let tp_new_wrapper = create_object( - PyNativeFuncDef::from(pytype::tp_new_wrapper.into_func()).into_function(), - &types.builtin_function_or_method_type, - ) - .into_object(); + let context = PyContext { + true_value, + false_value, + not_implemented, + none, + empty_tuple, + ellipsis, - let context = PyContext { - true_value, - false_value, - not_implemented, - none, - empty_tuple, - ellipsis, - - types, - exceptions, - int_cache_pool, - tp_new_wrapper, - }; - initialize_types(&context); - - exceptions::init(&context); - context + types, + exceptions, + int_cache_pool, + tp_new_wrapper, + }; + TypeZoo::extend(&context); + exceptions::ExceptionZoo::extend(&context); + context + }) + .clone() } pub fn none(&self) -> PyObjectRef { @@ -266,7 +267,7 @@ impl PyContext { PyRef::new_ref(PyDict::default(), self.types.dict_type.clone(), None) } - pub fn new_class(&self, name: &str, base: PyTypeRef, slots: PyTypeSlots) -> PyTypeRef { + pub fn new_class(&self, name: &str, base: &PyTypeRef, slots: PyTypeSlots) -> PyTypeRef { create_type_with_slots(name, &self.types.type_type, base, slots) } @@ -456,7 +457,7 @@ impl PyObjectRef { self, vm: &VirtualMachine, ) -> Result, Self> { - if self.class().is(&T::class(vm)) { + if self.class().is(T::class(vm)) { // TODO: is this always true? assert!( self.payload_is::(), @@ -581,10 +582,10 @@ where T: PyValue, { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - if obj.isinstance(&T::class(vm)) { + let class = T::class(vm); + if obj.isinstance(class) { PyRef::from_obj(obj, vm) } else { - let class = T::class(vm); let expected_type = &class.name; let actual_type = &obj.class().name; Err(vm.new_type_error(format!( @@ -647,7 +648,7 @@ impl TryFromObject for PyCallable { pub type Never = std::convert::Infallible; impl PyValue for Never { - fn class(_vm: &VirtualMachine) -> PyTypeRef { + fn class(_vm: &VirtualMachine) -> &PyTypeRef { unreachable!() } } @@ -1081,7 +1082,7 @@ impl PyObject { &self, vm: &VirtualMachine, ) -> Option<&T> { - if self.class().issubclass(&T::class(vm)) { + if self.class().issubclass(T::class(vm)) { self.payload() } else { None @@ -1118,19 +1119,19 @@ cfg_if::cfg_if! { } pub trait PyValue: fmt::Debug + PyThreadingConstraint + Sized + 'static { - fn class(vm: &VirtualMachine) -> PyTypeRef; + fn class(vm: &VirtualMachine) -> &PyTypeRef; fn into_object(self, vm: &VirtualMachine) -> PyObjectRef { self.into_ref(vm).into_object() } fn into_ref(self, vm: &VirtualMachine) -> PyRef { - self.into_ref_with_type_unchecked(Self::class(vm), vm) + self.into_ref_with_type_unchecked(Self::class(vm).clone(), vm) } fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> { let class = Self::class(vm); - if cls.issubclass(&class) { + if cls.issubclass(class) { Ok(self.into_ref_with_type_unchecked(cls, vm)) } else { let subtype = vm.to_str(&cls.obj)?; @@ -1229,8 +1230,46 @@ pub trait PyClassDef { const MODULE_NAME: Option<&'static str>; const TP_NAME: &'static str; const DOC: Option<&'static str> = None; - fn base_class(ctx: &PyContext) -> PyTypeRef { - ctx.types.object_type.clone() +} + +pub trait StaticType { + // Ideally, saving PyType is better than PyTypeRef + fn static_cell() -> &'static static_cell::StaticCell; + fn static_metaclass() -> &'static PyTypeRef { + crate::builtins::pytype::PyType::static_type() + } + fn static_baseclass() -> &'static PyTypeRef { + crate::builtins::object::PyBaseObject::static_type() + } + fn static_type() -> &'static PyTypeRef { + static_cell::get(Self::static_cell()).unwrap_or_else(|| unsafe { + // SAFETY: object must be initialized by init_* method. + // So this is actually not safe as itself. + // But easy to find out when it happened in debug build + std::hint::unreachable_unchecked() + }) + } + + fn init_manually(typ: PyTypeRef) -> &'static PyTypeRef { + static_cell::init_expect(Self::static_cell(), typ, "init_manually") + } + fn init_bare_type() -> &'static PyTypeRef + where + Self: PyClassImpl, + { + let typ = Self::create_bare_type(); + static_cell::init_expect(Self::static_cell(), typ, Self::NAME) + } + fn create_bare_type() -> PyTypeRef + where + Self: PyClassImpl, + { + create_type_with_slots( + Self::NAME, + Self::static_metaclass(), + Self::static_baseclass(), + Self::make_slots(), + ) } } @@ -1270,18 +1309,16 @@ pub trait PyClassImpl: PyClassDef { } } - fn make_class(ctx: &PyContext) -> PyTypeRef { - Self::make_class_with_base(ctx, Self::base_class(ctx)) - } - - fn make_class_with_base(ctx: &PyContext, base: PyTypeRef) -> PyTypeRef { - let py_class = ctx.new_class(Self::NAME, base, Self::make_slots()); - Self::extend_class(ctx, &py_class); - py_class - } - - fn create_bare_type(type_type: &PyTypeRef, base: PyTypeRef) -> PyTypeRef { - create_type_with_slots(Self::NAME, type_type, base, Self::make_slots()) + fn make_class(ctx: &PyContext) -> PyTypeRef + where + Self: StaticType, + { + static_cell::get_or_init(Self::static_cell(), || { + let typ = Self::create_bare_type(); + Self::extend_class(ctx, &typ); + typ + }) + .clone() } fn extend_slots(slots: &mut PyTypeSlots); @@ -1296,13 +1333,14 @@ pub trait PyClassImpl: PyClassDef { } #[pyimpl] -pub trait PyStructSequence: PyClassImpl + Sized + 'static { +pub trait PyStructSequence: StaticType + PyClassImpl + Sized + 'static { const FIELD_NAMES: &'static [&'static str]; fn into_tuple(self, vm: &VirtualMachine) -> PyTuple; - fn into_struct_sequence(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult { - self.into_tuple(vm).into_ref_with_type(vm, cls) + fn into_struct_sequence(self, vm: &VirtualMachine) -> PyResult { + self.into_tuple(vm) + .into_ref_with_type(vm, Self::static_type().clone()) } #[pymethod(magic)] diff --git a/vm/src/stdlib/array.rs b/vm/src/stdlib/array.rs index 5a5b2956e..ad8badcd6 100644 --- a/vm/src/stdlib/array.rs +++ b/vm/src/stdlib/array.rs @@ -13,7 +13,7 @@ use crate::common::lock::{ use crate::function::OptionalArg; use crate::pyobject::{ BorrowValue, Either, IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyIterable, - PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, TypeProtocol, }; use crate::sliceable::{saturate_index, PySliceableSequence, PySliceableSequenceMut}; use crate::slots::{BufferProtocol, Comparable, PyComparisonOp}; @@ -473,8 +473,8 @@ pub struct PyArray { pub type PyArrayRef = PyRef; impl PyValue for PyArray { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("array", "array") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -914,8 +914,8 @@ pub struct PyArrayIter { } impl PyValue for PyArrayIter { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("array", "arrayiterator") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 094244789..f0f78206c 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -11,20 +11,25 @@ use rustpython_parser::{ast, mode::Mode, parser}; use crate::builtins::list::PyListRef; use crate::builtins::pytype::PyTypeRef; -use crate::pyobject::{IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue}; -use crate::slots::PyTpFlags; +use crate::pyobject::{ + IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, +}; use crate::vm::VirtualMachine; +#[pyclass(module = "_ast", name = "AST")] #[derive(Debug)] struct AstNode; type AstNodeRef = PyRef; +#[pyimpl(flags(HAS_DICT))] +impl AstNode {} + const MODULE_NAME: &str = "_ast"; pub const PY_COMPILE_FLAG_AST_ONLY: i32 = 0x0400; impl PyValue for AstNode { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class(MODULE_NAME, "AST") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -631,7 +636,7 @@ pub(crate) fn parse(vm: &VirtualMachine, source: &str, mode: Mode) -> PyResult { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; - let ast_base = py_class!(ctx, "AST", &ctx.types.object_type, PyTpFlags::HAS_DICT, {}); + let ast_base = AstNode::make_class(ctx); py_module!(vm, MODULE_NAME, { // TODO: There's got to be a better way! "alias" => py_class!(ctx, "alias", &ast_base, {}), diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index 0a720531a..59f088674 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -5,7 +5,9 @@ mod _collections { use crate::builtins::pytype::PyTypeRef; use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::function::OptionalArg; - use crate::pyobject::{PyComparisonValue, PyIterable, PyObjectRef, PyRef, PyResult, PyValue}; + use crate::pyobject::{ + PyComparisonValue, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, StaticType, + }; use crate::slots::{Comparable, PyComparisonOp}; use crate::vm::ReprGuard; use crate::VirtualMachine; @@ -25,8 +27,8 @@ mod _collections { type PyDequeRef = PyRef; impl PyValue for PyDeque { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_collections", "deque") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -357,8 +359,8 @@ mod _collections { } impl PyValue for PyDequeIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_collections", "_deque_iterator") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/csv.rs b/vm/src/stdlib/csv.rs index 05ac2180f..10c06717c 100644 --- a/vm/src/stdlib/csv.rs +++ b/vm/src/stdlib/csv.rs @@ -8,9 +8,9 @@ use crate::common::lock::PyRwLock; use crate::function::FuncArgs; use crate::pyobject::{ BorrowValue, IntoPyObject, PyClassImpl, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, - TryFromObject, TypeProtocol, + StaticType, TryFromObject, TypeProtocol, }; -use crate::types::create_type; +use crate::types::create_simple_type; use crate::VirtualMachine; #[repr(i32)] @@ -135,8 +135,8 @@ impl Debug for Reader { } impl PyValue for Reader { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_csv", "Reader") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -198,11 +198,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let reader_type = Reader::make_class(ctx); - let error = create_type( - "Error", - &ctx.types.type_type, - ctx.exceptions.exception_type.clone(), - ); + let error = create_simple_type("Error", &ctx.exceptions.exception_type); py_module!(vm, "_csv", { "reader" => named_function!(ctx, _csv, reader), diff --git a/vm/src/stdlib/hashlib.rs b/vm/src/stdlib/hashlib.rs index f6893b053..bc560f3f7 100644 --- a/vm/src/stdlib/hashlib.rs +++ b/vm/src/stdlib/hashlib.rs @@ -7,16 +7,15 @@ mod hashlib { use crate::builtins::pytype::PyTypeRef; use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::function::{FuncArgs, OptionalArg}; - use crate::pyobject::{BorrowValue, PyResult, PyValue}; + use crate::pyobject::{BorrowValue, PyResult, PyValue, StaticType}; use crate::vm::VirtualMachine; - use std::fmt; - use blake2::{Blake2b, Blake2s}; use digest::DynDigest; use md5::Md5; use sha1::Sha1; use sha2::{Sha224, Sha256, Sha384, Sha512}; - use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; // TODO: , Shake128, Shake256}; + use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; // TODO: , Shake128, Shake256; + use std::fmt; #[pyattr] #[pyclass(module = "hashlib", name = "hasher")] @@ -32,8 +31,8 @@ mod hashlib { } impl PyValue for PyHasher { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("hashlib", "hasher") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index caad996de..4af995e84 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -3,10 +3,12 @@ */ use crate::pyobject::PyObjectRef; use crate::VirtualMachine; +pub(crate) use _io::io_open as open; pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { let module = _io::make_module(vm); - _io::extend_more(vm, &module); + #[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))] + fileio::extend_module(vm, &module); module } @@ -32,7 +34,7 @@ mod _io { use crate::exceptions::{IntoPyException, PyBaseExceptionRef}; use crate::function::{FuncArgs, OptionalArg, OptionalOption}; use crate::pyobject::{ - BorrowValue, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + BorrowValue, IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -210,10 +212,10 @@ mod _io { #[pyattr] #[pyclass(name = "_IOBase")] - struct IOBase; + struct _IOBase; #[pyimpl(flags(BASETYPE))] - impl IOBase { + impl _IOBase { #[pyattr] fn __closed(ctx: &PyContext) -> PyObjectRef { ctx.new_bool(false) @@ -380,11 +382,12 @@ mod _io { } } - #[pyclass(name = "_RawIOBase", noattr)] - struct RawIOBase; + #[pyattr] + #[pyclass(name = "_RawIOBase", base = "_IOBase")] + pub(super) struct _RawIOBase; #[pyimpl(flags(BASETYPE))] - impl RawIOBase { + impl _RawIOBase { #[pymethod] fn read(instance: PyObjectRef, size: OptionalSize, vm: &VirtualMachine) -> PyResult { if let Some(size) = size.to_usize() { @@ -406,11 +409,12 @@ mod _io { } } - #[pyclass(name = "_BufferedIOBase", noattr)] - struct BufferedIOBase; + #[pyattr] + #[pyclass(name = "_BufferedIOBase", base = "_IOBase")] + struct _BufferedIOBase; #[pyimpl(flags(BASETYPE))] - impl BufferedIOBase { + impl _BufferedIOBase { // #[pymethod(magic)] fn init( instance: PyObjectRef, @@ -460,13 +464,15 @@ mod _io { } // TextIO Base has no public constructor - #[pyclass(name = "_TextIOBase", noattr)] - struct TextIOBase; + #[pyattr] + #[pyclass(name = "_TextIOBase", base = "_IOBase")] + struct _TextIOBase; #[pyimpl(flags(BASETYPE))] - impl TextIOBase {} + impl _TextIOBase {} - #[pyclass(name = "BufferedReader", noattr)] + #[pyattr] + #[pyclass(name = "BufferedReader", base = "_BufferedIOBase")] struct BufferedReader; #[pyimpl(flags(BASETYPE))] @@ -482,32 +488,32 @@ mod _io { buffer_size: OptionalArg, vm: &VirtualMachine, ) -> PyResult<()> { - BufferedIOBase::init(instance, raw, buffer_size, vm) + _BufferedIOBase::init(instance, raw, buffer_size, vm) } #[pymethod] fn fileno(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::fileno(instance, vm) + _BufferedIOBase::fileno(instance, vm) } #[pyproperty] fn mode(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::mode(instance, vm) + _BufferedIOBase::mode(instance, vm) } #[pyproperty] fn name(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::name(instance, vm) + _BufferedIOBase::name(instance, vm) } #[pymethod] fn tell(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::tell(instance, vm) + _BufferedIOBase::tell(instance, vm) } #[pymethod] fn close(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - BufferedIOBase::close(instance, vm) + _BufferedIOBase::close(instance, vm) } #[pymethod] @@ -537,7 +543,8 @@ mod _io { } } - #[pyclass(name = "BufferedWriter", noattr)] + #[pyattr] + #[pyclass(name = "BufferedWriter", base = "_BufferedIOBase")] struct BufferedWriter; #[pyimpl(flags(BASETYPE))] @@ -553,32 +560,32 @@ mod _io { buffer_size: OptionalArg, vm: &VirtualMachine, ) -> PyResult<()> { - BufferedIOBase::init(instance, raw, buffer_size, vm) + _BufferedIOBase::init(instance, raw, buffer_size, vm) } #[pymethod] fn fileno(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::fileno(instance, vm) + _BufferedIOBase::fileno(instance, vm) } #[pyproperty] fn mode(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::mode(instance, vm) + _BufferedIOBase::mode(instance, vm) } #[pyproperty] fn name(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::name(instance, vm) + _BufferedIOBase::name(instance, vm) } #[pymethod] fn tell(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult { - BufferedIOBase::tell(instance, vm) + _BufferedIOBase::tell(instance, vm) } #[pymethod] fn close(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - BufferedIOBase::close(instance, vm) + _BufferedIOBase::close(instance, vm) } #[pymethod] @@ -634,7 +641,8 @@ mod _io { } } - #[pyclass(name = "TextIOWrapper", noattr)] + #[pyattr] + #[pyclass(name = "TextIOWrapper", base = "_TextIOBase")] struct TextIOWrapper; #[pyimpl] @@ -722,7 +730,7 @@ mod _io { size: OptionalOption, vm: &VirtualMachine, ) -> PyResult { - let buffered_reader_class = vm.try_class("_io", "BufferedReader")?; + let buffered_reader_class = BufferedReader::static_type(); let raw = vm.get_attribute(instance, "buffer").unwrap(); if !raw.isinstance(&buffered_reader_class) { @@ -746,7 +754,7 @@ mod _io { fn write(instance: PyObjectRef, obj: PyStrRef, vm: &VirtualMachine) -> PyResult { use std::str::from_utf8; - let buffered_writer_class = vm.try_class("_io", "BufferedWriter")?; + let buffered_writer_class = BufferedWriter::static_type(); let raw = vm.get_attribute(instance, "buffer").unwrap(); if !raw.isinstance(&buffered_writer_class) { @@ -773,7 +781,7 @@ mod _io { size: OptionalOption, vm: &VirtualMachine, ) -> PyResult { - let buffered_reader_class = vm.try_class("_io", "BufferedReader")?; + let buffered_reader_class = BufferedReader::static_type(); let raw = vm.get_attribute(instance, "buffer").unwrap(); if !raw.isinstance(&buffered_reader_class) { @@ -802,7 +810,8 @@ mod _io { newline: Option, } - #[pyclass(name = "StringIO", noattr)] + #[pyattr] + #[pyclass(name = "StringIO", base = "_TextIOBase")] #[derive(Debug)] struct StringIO { buffer: PyRwLock, @@ -812,8 +821,8 @@ mod _io { type StringIORef = PyRef; impl PyValue for StringIO { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("io", "StringIO") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -935,7 +944,8 @@ mod _io { } } - #[pyclass(name = "BytesIO", noattr)] + #[pyattr] + #[pyclass(name = "BytesIO", base = "_BufferedIOBase")] #[derive(Debug)] struct BytesIO { buffer: PyRwLock, @@ -947,8 +957,8 @@ mod _io { type BytesIORef = PyRef; impl PyValue for BytesIO { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("io", "BytesIO") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1304,55 +1314,6 @@ mod _io { } } - pub(crate) fn extend_more(vm: &VirtualMachine, module: &PyObjectRef) { - let ctx = &vm.ctx; - - // IOBase the abstract base class of the IO Module - let io_base = IOBase::make_class(&vm.ctx); - extend_class!(ctx, &io_base, {}); - - // IOBase Subclasses - let raw_io_base = RawIOBase::make_class_with_base(&vm.ctx, io_base.clone()); - let buffered_io_base = BufferedIOBase::make_class_with_base(&vm.ctx, io_base.clone()); - let text_io_base = TextIOBase::make_class_with_base(&vm.ctx, io_base.clone()); - - // BufferedIOBase Subclasses - let buffered_reader = - BufferedReader::make_class_with_base(&vm.ctx, buffered_io_base.clone()); - let buffered_writer = - BufferedWriter::make_class_with_base(&vm.ctx, buffered_io_base.clone()); - - //TextIOBase Subclass - let text_io_wrapper = TextIOWrapper::make_class_with_base(&vm.ctx, text_io_base.clone()); - - //StringIO: in-memory text - let string_io = StringIO::make_class_with_base(&vm.ctx, text_io_base.clone()); - extend_class!(ctx, &string_io, { - "__module__" => ctx.new_str("_io"), - }); - - //BytesIO: in-memory bytes - let bytes_io = BytesIO::make_class_with_base(&vm.ctx, buffered_io_base.clone()); - extend_class!(ctx, &bytes_io, {}); - - #[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))] - extend_module!(vm, module, { - "FileIO" => super::fileio::make_fileio(ctx, raw_io_base.clone()), - }); - - extend_module!(vm, module, { - "_IOBase" => io_base, - "_RawIOBase" => raw_io_base, - "_BufferedIOBase" => buffered_io_base, - "_TextIOBase" => text_io_base, - "BufferedReader" => buffered_reader, - "BufferedWriter" => buffered_writer, - "TextIOWrapper" => text_io_wrapper, - "StringIO" => string_io, - "BytesIO" => bytes_io, - }); - } - #[cfg(test)] mod tests { use super::*; @@ -1476,6 +1437,7 @@ mod _io { // disable FileIO on WASM #[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))] +#[pymodule] mod fileio { use super::_io::*; use crate::builtins::pystr::PyStrRef; @@ -1484,7 +1446,7 @@ mod fileio { use crate::exceptions::IntoPyException; use crate::function::{FuncArgs, OptionalArg}; use crate::pyobject::{ - BorrowValue, Either, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, Either, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, }; use crate::stdlib::os; use crate::vm::VirtualMachine; @@ -1505,9 +1467,10 @@ mod fileio { flag as u32 } - #[pyclass(module = "io", name)] + #[pyattr] + #[pyclass(module = "io", name, base = "_RawIOBase")] #[derive(Debug)] - struct FileIO { + pub(super) struct FileIO { fd: AtomicCell, closefd: AtomicCell, } @@ -1515,8 +1478,8 @@ mod fileio { type FileIORef = PyRef; impl PyValue for FileIO { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_io", "FileIO") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1716,8 +1679,4 @@ mod fileio { Ok(pos) } } - - pub fn make_fileio(ctx: &crate::pyobject::PyContext, raw_io_base: PyTypeRef) -> PyTypeRef { - FileIO::make_class_with_base(ctx, raw_io_base) - } } diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index f7a0f0c55..a2b886066 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -17,7 +17,7 @@ mod decl { use crate::iterator::{call_next, get_all, get_iter, get_next_object}; use crate::pyobject::{ BorrowValue, IdProtocol, IntoPyRef, PyCallable, PyObjectRc, PyObjectRef, PyObjectWeak, - PyRef, PyResult, PyValue, TypeProtocol, + PyRef, PyResult, PyValue, StaticType, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -31,8 +31,8 @@ mod decl { } impl PyValue for PyItertoolsChain { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "chain") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -116,8 +116,8 @@ mod decl { } impl PyValue for PyItertoolsCompress { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "compress") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -168,8 +168,8 @@ mod decl { } impl PyValue for PyItertoolsCount { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "count") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -222,8 +222,8 @@ mod decl { } impl PyValue for PyItertoolsCycle { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "cycle") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -283,8 +283,8 @@ mod decl { } impl PyValue for PyItertoolsRepeat { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "repeat") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -341,8 +341,8 @@ mod decl { } impl PyValue for PyItertoolsStarmap { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "starmap") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -384,8 +384,8 @@ mod decl { } impl PyValue for PyItertoolsTakewhile { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "takewhile") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -444,8 +444,8 @@ mod decl { } impl PyValue for PyItertoolsDropwhile { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "dropwhile") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -528,8 +528,8 @@ mod decl { } impl PyValue for PyItertoolsGroupBy { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "groupby") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -635,8 +635,8 @@ mod decl { type PyItertoolsGrouperRef = PyRef; impl PyValue for PyItertoolsGrouper { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "_grouper") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -689,8 +689,8 @@ mod decl { } impl PyValue for PyItertoolsIslice { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "islice") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -813,8 +813,8 @@ mod decl { } impl PyValue for PyItertoolsFilterFalse { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "filterfalse") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -871,8 +871,8 @@ mod decl { } impl PyValue for PyItertoolsAccumulate { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "accumulate") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -955,23 +955,24 @@ mod decl { } impl PyValue for PyItertoolsTee { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "tee") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } #[pyimpl] impl PyItertoolsTee { fn from_iter(iterable: PyObjectRef, vm: &VirtualMachine) -> PyResult { + let class = PyItertoolsTee::class(vm); let it = get_iter(vm, &iterable)?; - if it.class().is(&PyItertoolsTee::class(vm)) { + if it.class().is(PyItertoolsTee::class(vm)) { return vm.call_method(&it, "__copy__", ()); } Ok(PyItertoolsTee { tee_data: PyItertoolsTeeData::new(it, vm)?, index: AtomicCell::new(0), } - .into_ref_with_type(vm, PyItertoolsTee::class(vm))? + .into_ref_with_type(vm, class.clone())? .into_object()) } @@ -1007,7 +1008,7 @@ mod decl { tee_data: PyRc::clone(&self.tee_data), index: AtomicCell::new(self.index.load()), } - .into_ref_with_type(vm, Self::class(vm))? + .into_ref_with_type(vm, Self::class(vm).clone())? .into_object()) } @@ -1035,8 +1036,8 @@ mod decl { } impl PyValue for PyItertoolsProduct { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "product") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1152,8 +1153,8 @@ mod decl { } impl PyValue for PyItertoolsCombinations { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "combinations") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1252,8 +1253,8 @@ mod decl { } impl PyValue for PyItertoolsCombinationsWithReplacement { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "combinations_with_replacement") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1349,8 +1350,8 @@ mod decl { } impl PyValue for PyItertoolsPermutations { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "permutations") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -1476,8 +1477,8 @@ mod decl { } impl PyValue for PyItertoolsZipLongest { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("itertools", "zip_longest") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 7fa2dd8e1..267d716c1 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -10,7 +10,8 @@ mod _json { use crate::function::{FuncArgs, OptionalArg}; use crate::iterator; use crate::pyobject::{ - BorrowValue, IdProtocol, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, IdProtocol, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, StaticType, + TryFromObject, }; use crate::slots::Callable; use crate::VirtualMachine; @@ -32,8 +33,8 @@ mod _json { } impl PyValue for JsonScanner { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_json", "make_scanner") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 60c17a9d4..7815c2b87 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -23,7 +23,7 @@ use crate::exceptions::{IntoPyException, PyBaseExceptionRef}; use crate::function::{FuncArgs, IntoPyNativeFunc, OptionalArg}; use crate::pyobject::{ BorrowValue, Either, IntoPyObject, ItemProtocol, PyObjectRef, PyRef, PyResult, - PyStructSequence, PyValue, TryFromObject, TypeProtocol, + PyStructSequence, PyValue, StaticType, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -464,8 +464,8 @@ mod _os { } impl PyValue for DirEntry { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class(super::MODULE_NAME, "DirEntry") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -549,8 +549,8 @@ mod _os { } impl PyValue for ScandirIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class(super::MODULE_NAME, "ScandirIter") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -636,9 +636,7 @@ mod _os { #[pyimpl(with(PyStructSequence))] impl StatResult { pub(super) fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef { - self.into_struct_sequence(vm, vm.class(super::MODULE_NAME, "stat_result")) - .unwrap() - .into_object() + self.into_struct_sequence(vm).unwrap().into_object() } } @@ -1745,9 +1743,7 @@ mod posix { #[pyimpl(with(PyStructSequence))] impl UnameResult { fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef { - self.into_struct_sequence(vm, vm.class(super::MODULE_NAME, "uname_result")) - .unwrap() - .into_object() + self.into_struct_sequence(vm).unwrap().into_object() } } @@ -2143,8 +2139,7 @@ mod posix { (w.ws_col.into(), w.ws_row.into()) } }; - super::_os::PyTerminalSize { columns, lines } - .into_struct_sequence(vm, vm.try_class(super::MODULE_NAME, "terminal_size")?) + super::_os::PyTerminalSize { columns, lines }.into_struct_sequence(vm) } // from libstd: @@ -2466,8 +2461,7 @@ mod nt { ) } }; - super::_os::PyTerminalSize { columns, lines } - .into_struct_sequence(vm, vm.try_class(super::MODULE_NAME, "terminal_size")?) + super::_os::PyTerminalSize { columns, lines }.into_struct_sequence(vm) } #[cfg(target_env = "msvc")] diff --git a/vm/src/stdlib/pwd.rs b/vm/src/stdlib/pwd.rs index 994d7561e..07a793ec1 100644 --- a/vm/src/stdlib/pwd.rs +++ b/vm/src/stdlib/pwd.rs @@ -48,9 +48,7 @@ impl From for Passwd { fn pwd_getpwnam(name: PyStrRef, vm: &VirtualMachine) -> PyResult { match User::from_name(name.borrow_value()).map_err(|err| err.into_pyexception(vm))? { - Some(user) => Ok(Passwd::from(user) - .into_struct_sequence(vm, vm.try_class("pwd", "struct_passwd")?)? - .into_object()), + Some(user) => Ok(Passwd::from(user).into_struct_sequence(vm)?.into_object()), None => { let name_repr = vm.to_repr(name.as_object())?; let message = vm @@ -68,9 +66,7 @@ fn pwd_getpwuid(uid: PyIntRef, vm: &VirtualMachine) -> PyResult { Err(_) => None, }; match user { - Some(user) => Ok(Passwd::from(user) - .into_struct_sequence(vm, vm.try_class("pwd", "struct_passwd")?)? - .into_object()), + Some(user) => Ok(Passwd::from(user).into_struct_sequence(vm)?.into_object()), None => { let message = vm .ctx @@ -86,14 +82,11 @@ fn pwd_getpwall(vm: &VirtualMachine) -> PyResult { static GETPWALL: parking_lot::Mutex<()> = parking_lot::const_mutex(()); let _guard = GETPWALL.lock(); let mut list = Vec::new(); - let cls = vm.try_class("pwd", "struct_passwd")?; unsafe { libc::setpwent() }; while let Some(ptr) = NonNull::new(unsafe { libc::getpwent() }) { let user = User::from(unsafe { ptr.as_ref() }); - let passwd = Passwd::from(user) - .into_struct_sequence(vm, cls.clone())? - .into_object(); + let passwd = Passwd::from(user).into_struct_sequence(vm)?.into_object(); list.push(passwd); } unsafe { libc::endpwent() }; diff --git a/vm/src/stdlib/pystruct.rs b/vm/src/stdlib/pystruct.rs index 137a2a976..70692166e 100644 --- a/vm/src/stdlib/pystruct.rs +++ b/vm/src/stdlib/pystruct.rs @@ -30,7 +30,7 @@ pub(crate) mod _struct { use crate::exceptions::PyBaseExceptionRef; use crate::function::Args; use crate::pyobject::{ - BorrowValue, Either, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, Either, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, }; use crate::VirtualMachine; @@ -841,8 +841,8 @@ pub(crate) mod _struct { } impl PyValue for UnpackIterator { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_struct", "unpack_iterator") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -896,8 +896,8 @@ pub(crate) mod _struct { } impl PyValue for PyStruct { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_struct", "Struct") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -988,7 +988,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { let struct_error = ctx.new_class( "struct.error", - ctx.exceptions.exception_type.clone(), + &ctx.exceptions.exception_type, Default::default(), ); diff --git a/vm/src/stdlib/random.rs b/vm/src/stdlib/random.rs index 9da2a83fc..ff604381d 100644 --- a/vm/src/stdlib/random.rs +++ b/vm/src/stdlib/random.rs @@ -8,7 +8,7 @@ mod _random { use crate::builtins::pytype::PyTypeRef; use crate::common::lock::PyMutex; use crate::function::OptionalOption; - use crate::pyobject::{BorrowValue, PyRef, PyResult, PyValue}; + use crate::pyobject::{BorrowValue, PyRef, PyResult, PyValue, StaticType}; use crate::VirtualMachine; use num_bigint::{BigInt, Sign}; use num_traits::Signed; @@ -61,8 +61,8 @@ mod _random { } impl PyValue for PyRandom { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_random", "Random") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index 747511b96..25c996686 100644 --- a/vm/src/stdlib/re.rs +++ b/vm/src/stdlib/re.rs @@ -14,7 +14,8 @@ use crate::builtins::pystr::{PyStr, PyStrRef}; use crate::builtins::pytype::PyTypeRef; use crate::function::{Args, OptionalArg}; use crate::pyobject::{ - BorrowValue, IntoPyObject, PyClassImpl, PyObjectRef, PyResult, PyValue, TryFromObject, + BorrowValue, IntoPyObject, PyClassImpl, PyObjectRef, PyResult, PyValue, StaticType, + TryFromObject, }; use crate::vm::VirtualMachine; @@ -65,8 +66,8 @@ impl PyRegexFlags { } impl PyValue for PyPattern { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("re", "Pattern") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -84,8 +85,8 @@ impl fmt::Debug for PyMatch { } impl PyValue for PyMatch { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("re", "Match") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index fd2acf643..02794251f 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -1,14 +1,12 @@ -use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; -use std::io::{self, prelude::*}; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; -use std::time::Duration; - use byteorder::{BigEndian, ByteOrder}; use crossbeam_utils::atomic::AtomicCell; use gethostname::gethostname; #[cfg(all(unix, not(target_os = "redox")))] use nix::unistd::sethostname; use socket2::{Domain, Protocol, Socket, Type as SocketType}; +use std::io::{self, prelude::*}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; +use std::time::Duration; use crate::builtins::bytearray::PyByteArrayRef; use crate::builtins::bytes::PyBytesRef; @@ -16,11 +14,12 @@ use crate::builtins::pystr::{PyStr, PyStrRef}; use crate::builtins::pytype::PyTypeRef; use crate::builtins::tuple::PyTupleRef; use crate::byteslike::PyBytesLike; +use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::exceptions::{IntoPyException, PyBaseExceptionRef}; use crate::function::{FuncArgs, OptionalArg}; use crate::pyobject::{ BorrowValue, Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, - TryFromObject, + StaticType, TryFromObject, }; use crate::vm::VirtualMachine; @@ -64,8 +63,8 @@ pub struct PySocket { } impl PyValue for PySocket { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_socket", "socket") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -787,12 +786,12 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; let socket_timeout = ctx.new_class( "socket.timeout", - vm.ctx.exceptions.os_error.clone(), + &vm.ctx.exceptions.os_error, Default::default(), ); let socket_gaierror = ctx.new_class( "socket.gaierror", - vm.ctx.exceptions.os_error.clone(), + &vm.ctx.exceptions.os_error, Default::default(), ); diff --git a/vm/src/stdlib/ssl.rs b/vm/src/stdlib/ssl.rs index 09a877fd6..10488dfe4 100644 --- a/vm/src/stdlib/ssl.rs +++ b/vm/src/stdlib/ssl.rs @@ -8,9 +8,9 @@ use crate::exceptions::{IntoPyException, PyBaseExceptionRef}; use crate::function::OptionalArg; use crate::pyobject::{ BorrowValue, Either, IntoPyObject, ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, - PyValue, + PyValue, StaticType, }; -use crate::types::create_type; +use crate::types::create_simple_type; use crate::VirtualMachine; use foreign_types_shared::{ForeignType, ForeignTypeRef}; @@ -241,8 +241,8 @@ impl fmt::Debug for PySslContext { } impl PyValue for PySslContext { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_ssl", "_SSLContext") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -520,8 +520,8 @@ impl fmt::Debug for PySslSocket { } impl PyValue for PySslSocket { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_ssl", "_SSLSocket") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -751,11 +751,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { } openssl::init(); let ctx = &vm.ctx; - let ssl_error = create_type( - "SSLError", - &vm.ctx.types.type_type, - vm.ctx.exceptions.os_error.clone(), - ); + let ssl_error = create_simple_type("SSLError", &vm.ctx.exceptions.os_error); let module = py_module!(vm, "_ssl", { "_SSLContext" => PySslContext::make_class(ctx), "_SSLSocket" => PySslSocket::make_class(ctx), diff --git a/vm/src/stdlib/symtable.rs b/vm/src/stdlib/symtable.rs index ebbec6720..25573e4d1 100644 --- a/vm/src/stdlib/symtable.rs +++ b/vm/src/stdlib/symtable.rs @@ -6,7 +6,7 @@ mod decl { use crate::builtins::pystr::PyStrRef; use crate::builtins::pytype::PyTypeRef; - use crate::pyobject::{BorrowValue, PyRef, PyResult, PyValue}; + use crate::pyobject::{BorrowValue, PyRef, PyResult, PyValue, StaticType}; use crate::vm::VirtualMachine; use rustpython_compiler::{compile, error::CompileError, symboltable}; use rustpython_parser::parser; @@ -73,8 +73,8 @@ mod decl { } impl PyValue for PySymbolTable { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("symtable", "SymbolTable") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -191,8 +191,8 @@ mod decl { } impl PyValue for PySymbol { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("symtable", "Symbol") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index ac4c7cab5..8c48761d8 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -7,7 +7,7 @@ use crate::exceptions::{self, IntoPyException}; use crate::function::{FuncArgs, OptionalArg}; use crate::pyobject::{ BorrowValue, Either, IdProtocol, ItemProtocol, PyCallable, PyClassImpl, PyObjectRef, PyRef, - PyResult, PyValue, TypeProtocol, + PyResult, PyValue, StaticType, TypeProtocol, }; use crate::slots::SlotGetattro; use crate::vm::VirtualMachine; @@ -100,8 +100,8 @@ struct PyLock { type PyLockRef = PyRef; impl PyValue for PyLock { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_thread", "LockType") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -153,8 +153,8 @@ struct PyRLock { } impl PyValue for PyRLock { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_thread", "RLock") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -291,8 +291,8 @@ struct PyLocal { } impl PyValue for PyLocal { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_thread", "_local") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/time_module.rs b/vm/src/stdlib/time_module.rs index 15b005a27..267fc6457 100644 --- a/vm/src/stdlib/time_module.rs +++ b/vm/src/stdlib/time_module.rs @@ -218,14 +218,13 @@ impl PyStructTime { } fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef { - self.into_struct_sequence(vm, vm.class("time", "struct_time")) - .unwrap() - .into_object() + self.into_struct_sequence(vm).unwrap().into_object() } #[pyslot] - fn tp_new(cls: PyTypeRef, seq: PyObjectRef, vm: &VirtualMachine) -> PyResult { - Self::try_from_object(vm, seq)?.into_struct_sequence(vm, cls) + fn tp_new(_cls: PyTypeRef, seq: PyObjectRef, vm: &VirtualMachine) -> PyResult { + // cls is ignorable because this is not a basetype + Self::try_from_object(vm, seq)?.into_struct_sequence(vm) } } diff --git a/vm/src/stdlib/unicodedata.rs b/vm/src/stdlib/unicodedata.rs index 7b3e5ddd4..30628f798 100644 --- a/vm/src/stdlib/unicodedata.rs +++ b/vm/src/stdlib/unicodedata.rs @@ -5,7 +5,9 @@ use crate::builtins::pystr::PyStrRef; use crate::builtins::pytype::PyTypeRef; use crate::function::OptionalArg; -use crate::pyobject::{BorrowValue, PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue}; +use crate::pyobject::{ + BorrowValue, PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue, StaticType, +}; use crate::vm::VirtualMachine; use itertools::Itertools; @@ -61,8 +63,8 @@ struct PyUCD { } impl PyValue for PyUCD { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("unicodedata", "UCD") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/winreg.rs b/vm/src/stdlib/winreg.rs index 29a86072b..f04ed7697 100644 --- a/vm/src/stdlib/winreg.rs +++ b/vm/src/stdlib/winreg.rs @@ -5,7 +5,7 @@ use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard}; use crate::exceptions::IntoPyException; use crate::function::OptionalArg; use crate::pyobject::{ - BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, }; use crate::VirtualMachine; @@ -25,8 +25,8 @@ type PyHKEYRef = PyRef; unsafe impl Sync for PyHKEY {} impl PyValue for PyHKEY { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("winreg", "HKEYType") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/stdlib/zlib.rs b/vm/src/stdlib/zlib.rs index 37e090a4c..36a7aeb90 100644 --- a/vm/src/stdlib/zlib.rs +++ b/vm/src/stdlib/zlib.rs @@ -8,8 +8,8 @@ mod decl { use crate::common::lock::PyMutex; use crate::exceptions::PyBaseExceptionRef; use crate::function::OptionalArg; - use crate::pyobject::{BorrowValue, IntoPyRef, PyResult, PyValue}; - use crate::types::create_type; + use crate::pyobject::{BorrowValue, IntoPyRef, PyResult, PyValue, StaticType}; + use crate::types::create_simple_type; use crate::vm::VirtualMachine; use adler32::RollingAdler32 as Adler32; @@ -36,11 +36,7 @@ mod decl { #[pyattr] fn error(vm: &VirtualMachine) -> PyTypeRef { - create_type( - "error", - &vm.ctx.types.type_type, - vm.ctx.exceptions.exception_type.clone(), - ) + create_simple_type("error", &vm.ctx.exceptions.exception_type) } /// Compute an Adler-32 checksum of data. @@ -218,8 +214,8 @@ mod decl { unconsumed_tail: PyMutex, } impl PyValue for PyDecompress { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("zlib", "Decompress") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } #[pyimpl] @@ -377,8 +373,8 @@ mod decl { } impl PyValue for PyCompress { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("zlib", "Compress") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index 3908eebf0..23425e5fc 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -287,44 +287,44 @@ fn sys_getwindowsversion(vm: &VirtualMachine) -> PyResult() as u32; let result = unsafe { let osvi = &mut version as LPOSVERSIONINFOEXW as LPOSVERSIONINFOW; - // SAFE: GetVersionExW accepts a pointer of OSVERSIONINFOW, but winapi crate's type currently doesn't allow to do so. + // SAFETY: GetVersionExW accepts a pointer of OSVERSIONINFOW, but winapi crate's type currently doesn't allow to do so. // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexw#parameters GetVersionExW(osvi) }; if result == 0 { - Err(vm.new_os_error("failed to get windows version".to_owned())) - } else { - let service_pack = { - let (last, _) = version - .szCSDVersion - .iter() - .take_while(|&x| x != &0) - .enumerate() - .last() - .unwrap_or((0, &0)); - let sp = OsString::from_wide(&version.szCSDVersion[..last]); - sp.into_string() - .map_err(|_| vm.new_os_error("service pack is not ASCII".to_owned()))? - }; - WindowsVersion { - major: version.dwMajorVersion, - minor: version.dwMinorVersion, - build: version.dwBuildNumber, - platform: version.dwPlatformId, - service_pack, - service_pack_major: version.wServicePackMajor, - service_pack_minor: version.wServicePackMinor, - suite_mask: version.wSuiteMask, - product_type: version.wProductType, - platform_version: ( - version.dwMajorVersion, - version.dwMinorVersion, - version.dwBuildNumber, - ), // TODO Provide accurate version, like CPython impl - } - .into_struct_sequence(vm, vm.try_class("sys", "_getwindowsversion_type")?) + return Err(vm.new_os_error("failed to get windows version".to_owned())); } + + let service_pack = { + let (last, _) = version + .szCSDVersion + .iter() + .take_while(|&x| x != &0) + .enumerate() + .last() + .unwrap_or((0, &0)); + let sp = OsString::from_wide(&version.szCSDVersion[..last]); + sp.into_string() + .map_err(|_| vm.new_os_error("service pack is not ASCII".to_owned()))? + }; + WindowsVersion { + major: version.dwMajorVersion, + minor: version.dwMinorVersion, + build: version.dwBuildNumber, + platform: version.dwPlatformId, + service_pack, + service_pack_major: version.wServicePackMajor, + service_pack_minor: version.wServicePackMinor, + suite_mask: version.wSuiteMask, + product_type: version.wProductType, + platform_version: ( + version.dwMajorVersion, + version.dwMinorVersion, + version.dwBuildNumber, + ), // TODO Provide accurate version, like CPython impl + } + .into_struct_sequence(vm) } pub fn get_stdin(vm: &VirtualMachine) -> PyResult { @@ -485,30 +485,24 @@ impl PyIntInfo { pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectRef) { let ctx = &vm.ctx; - let flags_type = SysFlags::make_class(ctx); + let _flags_type = SysFlags::make_class(ctx); let flags = SysFlags::from_settings(&vm.state.settings) - .into_struct_sequence(vm, flags_type) + .into_struct_sequence(vm) .unwrap(); - let version_info_type = version::VersionInfo::make_class(ctx); + let _version_info_type = version::VersionInfo::make_class(ctx); let version_info = version::VersionInfo::VERSION - .into_struct_sequence(vm, version_info_type) + .into_struct_sequence(vm) .unwrap(); - let hash_info_type = PyHashInfo::make_class(ctx); - let hash_info = PyHashInfo::INFO - .into_struct_sequence(vm, hash_info_type) - .unwrap(); + let _hash_info_type = PyHashInfo::make_class(ctx); + let hash_info = PyHashInfo::INFO.into_struct_sequence(vm).unwrap(); - let float_info_type = PyFloatInfo::make_class(ctx); - let float_info = PyFloatInfo::INFO - .into_struct_sequence(vm, float_info_type) - .unwrap(); + let _float_info_type = PyFloatInfo::make_class(ctx); + let float_info = PyFloatInfo::INFO.into_struct_sequence(vm).unwrap(); - let int_info_type = PyIntInfo::make_class(ctx); - let int_info = PyIntInfo::INFO - .into_struct_sequence(vm, int_info_type) - .unwrap(); + let _int_info_type = PyIntInfo::make_class(ctx); + let int_info = PyIntInfo::INFO.into_struct_sequence(vm).unwrap(); // TODO Add crate version to this namespace let implementation = py_namespace!(vm, { @@ -710,7 +704,6 @@ settrace() -- set the global debug tracing function let getwindowsversion = WindowsVersion::make_class(ctx); extend_module!(vm, module, { "getwindowsversion" => named_function!(ctx, sys, getwindowsversion), - "_getwindowsversion_type" => getwindowsversion, // XXX: This is not a python spec but required by current RustPython implementation }) } diff --git a/vm/src/types.rs b/vm/src/types.rs index c4279b0de..67e97e251 100644 --- a/vm/src/types.rs +++ b/vm/src/types.rs @@ -39,7 +39,7 @@ use crate::builtins::weakproxy; use crate::builtins::weakref; use crate::builtins::zip; use crate::pyobject::{ - PyAttributes, PyClassDef, PyClassImpl, PyContext, PyObject, PyObjectRc, PyObjectRef, + PyAttributes, PyClassDef, PyClassImpl, PyContext, PyObject, PyObjectRc, PyObjectRef, StaticType, }; use crate::slots::PyTypeSlots; use rustpython_common::{lock::PyRwLock, rc::PyRc}; @@ -47,7 +47,7 @@ use std::mem::MaybeUninit; use std::ptr; /// Holder of references to builtin types. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TypeZoo { pub async_generator: PyTypeRef, pub async_generator_asend: PyTypeRef, @@ -114,106 +114,148 @@ pub struct TypeZoo { pub mappingproxy_type: PyTypeRef, pub traceback_type: PyTypeRef, pub object_type: PyTypeRef, -} - -impl Default for TypeZoo { - fn default() -> Self { - Self::new() - } + pub ellipsis_type: PyTypeRef, + pub none_type: PyTypeRef, + pub not_implemented_type: PyTypeRef, } impl TypeZoo { - pub fn new() -> Self { + pub(crate) fn init() -> Self { let (type_type, object_type) = init_type_hierarchy(); - - macro_rules! create_type { - ($class:ty) => { - <$class>::create_bare_type(&type_type, object_type.clone()) - }; - ($class:ty, $base:expr) => { - <$class>::create_bare_type(&type_type, $base.clone()) - }; - } - - let int_type = create_type!(int::PyInt); Self { - async_generator: create_type!(asyncgenerator::PyAsyncGen), - async_generator_asend: create_type!(asyncgenerator::PyAsyncGenASend), - async_generator_athrow: create_type!(asyncgenerator::PyAsyncGenAThrow), - async_generator_wrapped_value: create_type!(asyncgenerator::PyAsyncGenWrappedValue), - bool_type: create_type!(pybool::PyBool, int_type), - bound_method_type: create_type!(function::PyBoundMethod), - builtin_function_or_method_type: create_type!(builtinfunc::PyBuiltinFunction), - bytearray_type: create_type!(bytearray::PyByteArray), - bytearray_iterator_type: create_type!(bytearray::PyByteArrayIterator), - bytes_type: create_type!(bytes::PyBytes), - bytes_iterator_type: create_type!(bytes::PyBytesIterator), - callable_iterator: create_type!(iter::PyCallableIterator), - classmethod_type: create_type!(classmethod::PyClassMethod), - code_type: create_type!(code::PyCodeRef), - complex_type: create_type!(complex::PyComplex), - coroutine_type: create_type!(coroutine::PyCoroutine), - coroutine_wrapper_type: create_type!(coroutine::PyCoroutineWrapper), - dict_type: create_type!(dict::PyDict), - dict_keys_type: create_type!(dict::PyDictKeys), - dict_values_type: create_type!(dict::PyDictValues), - dict_items_type: create_type!(dict::PyDictItems), - dict_keyiterator_type: create_type!(dict::PyDictKeyIterator), - dict_reversekeyiterator_type: create_type!(dict::PyDictReverseKeyIterator), - dict_valueiterator_type: create_type!(dict::PyDictValueIterator), - dict_reversevalueiterator_type: create_type!(dict::PyDictReverseValueIterator), - dict_itemiterator_type: create_type!(dict::PyDictItemIterator), - dict_reverseitemiterator_type: create_type!(dict::PyDictReverseItemIterator), - enumerate_type: create_type!(enumerate::PyEnumerate), - filter_type: create_type!(filter::PyFilter), - float_type: create_type!(float::PyFloat), - frame_type: create_type!(crate::frame::FrameRef), - frozenset_type: create_type!(set::PyFrozenSet), - function_type: create_type!(function::PyFunction), - generator_type: create_type!(generator::PyGenerator), - getset_type: create_type!(getset::PyGetSet), - int_type, - iter_type: create_type!(iter::PySequenceIterator), - list_type: create_type!(list::PyList), - list_iterator_type: create_type!(list::PyListIterator), - list_reverseiterator_type: create_type!(list::PyListReverseIterator), - map_type: create_type!(map::PyMap), - mappingproxy_type: create_type!(mappingproxy::PyMappingProxy), - memoryview_type: create_type!(memory::PyMemoryView), - module_type: create_type!(module::PyModule), - namespace_type: create_type!(namespace::PyNamespace), - property_type: create_type!(property::PyProperty), - range_type: create_type!(range::PyRange), - range_iterator_type: create_type!(range::PyRangeIterator), - set_type: create_type!(set::PySet), - set_iterator_type: create_type!(set::PySetIterator), - slice_type: create_type!(slice::PySlice), - staticmethod_type: create_type!(staticmethod::PyStaticMethod), - str_type: create_type!(pystr::PyStr), - str_iterator_type: create_type!(pystr::PyStrIterator), - str_reverseiterator_type: create_type!(pystr::PyStrReverseIterator), - super_type: create_type!(pysuper::PySuper), - traceback_type: create_type!(traceback::PyTraceback), - tuple_type: create_type!(tuple::PyTuple), - tuple_iterator_type: create_type!(tuple::PyTupleIterator), - weakproxy_type: create_type!(weakproxy::PyWeakProxy), - weakref_type: create_type!(weakref::PyWeak), - method_descriptor_type: create_type!(builtinfunc::PyBuiltinMethod), - zip_type: create_type!(zip::PyZip), - type_type, - object_type, + // the order matters for type, object and int + type_type: pytype::PyType::init_manually(type_type).clone(), + object_type: object::PyBaseObject::init_manually(object_type).clone(), + int_type: int::PyInt::init_bare_type().clone(), + + // types exposed as builtins + bool_type: pybool::PyBool::init_bare_type().clone(), + bytearray_type: bytearray::PyByteArray::init_bare_type().clone(), + bytes_type: bytes::PyBytes::init_bare_type().clone(), + classmethod_type: classmethod::PyClassMethod::init_bare_type().clone(), + complex_type: complex::PyComplex::init_bare_type().clone(), + dict_type: dict::PyDict::init_bare_type().clone(), + enumerate_type: enumerate::PyEnumerate::init_bare_type().clone(), + float_type: float::PyFloat::init_bare_type().clone(), + frozenset_type: set::PyFrozenSet::init_bare_type().clone(), + filter_type: filter::PyFilter::init_bare_type().clone(), + list_type: list::PyList::init_bare_type().clone(), + map_type: map::PyMap::init_bare_type().clone(), + memoryview_type: memory::PyMemoryView::init_bare_type().clone(), + property_type: property::PyProperty::init_bare_type().clone(), + range_type: range::PyRange::init_bare_type().clone(), + set_type: set::PySet::init_bare_type().clone(), + slice_type: slice::PySlice::init_bare_type().clone(), + staticmethod_type: staticmethod::PyStaticMethod::init_bare_type().clone(), + str_type: pystr::PyStr::init_bare_type().clone(), + super_type: pysuper::PySuper::init_bare_type().clone(), + tuple_type: tuple::PyTuple::init_bare_type().clone(), + zip_type: zip::PyZip::init_bare_type().clone(), + + // hidden internal types. is this really need to be cached here? + async_generator: asyncgenerator::PyAsyncGen::init_bare_type().clone(), + async_generator_asend: asyncgenerator::PyAsyncGenASend::init_bare_type().clone(), + async_generator_athrow: asyncgenerator::PyAsyncGenAThrow::init_bare_type().clone(), + async_generator_wrapped_value: asyncgenerator::PyAsyncGenWrappedValue::init_bare_type() + .clone(), + bound_method_type: function::PyBoundMethod::init_bare_type().clone(), + builtin_function_or_method_type: builtinfunc::PyBuiltinFunction::init_bare_type() + .clone(), + bytearray_iterator_type: bytearray::PyByteArrayIterator::init_bare_type().clone(), + bytes_iterator_type: bytes::PyBytesIterator::init_bare_type().clone(), + callable_iterator: iter::PyCallableIterator::init_bare_type().clone(), + code_type: code::PyCode::init_bare_type().clone(), + coroutine_type: coroutine::PyCoroutine::init_bare_type().clone(), + coroutine_wrapper_type: coroutine::PyCoroutineWrapper::init_bare_type().clone(), + dict_keys_type: dict::PyDictKeys::init_bare_type().clone(), + dict_values_type: dict::PyDictValues::init_bare_type().clone(), + dict_items_type: dict::PyDictItems::init_bare_type().clone(), + dict_keyiterator_type: dict::PyDictKeyIterator::init_bare_type().clone(), + dict_reversekeyiterator_type: dict::PyDictReverseKeyIterator::init_bare_type().clone(), + dict_valueiterator_type: dict::PyDictValueIterator::init_bare_type().clone(), + dict_reversevalueiterator_type: dict::PyDictReverseValueIterator::init_bare_type() + .clone(), + dict_itemiterator_type: dict::PyDictItemIterator::init_bare_type().clone(), + dict_reverseitemiterator_type: dict::PyDictReverseItemIterator::init_bare_type() + .clone(), + ellipsis_type: slice::PyEllipsis::init_bare_type().clone(), + frame_type: crate::frame::Frame::init_bare_type().clone(), + function_type: function::PyFunction::init_bare_type().clone(), + generator_type: generator::PyGenerator::init_bare_type().clone(), + getset_type: getset::PyGetSet::init_bare_type().clone(), + iter_type: iter::PySequenceIterator::init_bare_type().clone(), + list_iterator_type: list::PyListIterator::init_bare_type().clone(), + list_reverseiterator_type: list::PyListReverseIterator::init_bare_type().clone(), + mappingproxy_type: mappingproxy::PyMappingProxy::init_bare_type().clone(), + module_type: module::PyModule::init_bare_type().clone(), + namespace_type: namespace::PyNamespace::init_bare_type().clone(), + range_iterator_type: range::PyRangeIterator::init_bare_type().clone(), + set_iterator_type: set::PySetIterator::init_bare_type().clone(), + str_iterator_type: pystr::PyStrIterator::init_bare_type().clone(), + str_reverseiterator_type: pystr::PyStrReverseIterator::init_bare_type().clone(), + traceback_type: traceback::PyTraceback::init_bare_type().clone(), + tuple_iterator_type: tuple::PyTupleIterator::init_bare_type().clone(), + weakproxy_type: weakproxy::PyWeakProxy::init_bare_type().clone(), + weakref_type: weakref::PyWeak::init_bare_type().clone(), + method_descriptor_type: builtinfunc::PyBuiltinMethod::init_bare_type().clone(), + none_type: singletons::PyNone::init_bare_type().clone(), + not_implemented_type: singletons::PyNotImplemented::init_bare_type().clone(), } } + + /// Fill attributes of builtin types. + pub(crate) fn extend(context: &PyContext) { + pytype::init(&context); + object::init(&context); + list::init(&context); + set::init(&context); + tuple::init(&context); + dict::init(&context); + builtinfunc::init(&context); + function::init(&context); + staticmethod::init(&context); + classmethod::init(&context); + generator::init(&context); + coroutine::init(&context); + asyncgenerator::init(&context); + int::init(&context); + float::init(&context); + complex::init(&context); + bytes::init(&context); + bytearray::init(&context); + property::init(&context); + getset::init(&context); + memory::init(&context); + pystr::init(&context); + range::init(&context); + slice::init(&context); + pysuper::init(&context); + iter::init(&context); + enumerate::init(&context); + filter::init(&context); + map::init(&context); + zip::init(&context); + pybool::init(&context); + code::init(&context); + frame::init(&context); + weakref::init(&context); + weakproxy::init(&context); + singletons::init(&context); + module::init(&context); + namespace::init(&context); + mappingproxy::init(&context); + traceback::init(&context); + } } -pub fn create_type(name: &str, type_type: &PyTypeRef, base: PyTypeRef) -> PyTypeRef { - create_type_with_slots(name, type_type, base, Default::default()) +pub fn create_simple_type(name: &str, base: &PyTypeRef) -> PyTypeRef { + create_type_with_slots(name, PyType::static_type(), base, Default::default()) } pub fn create_type_with_slots( name: &str, type_type: &PyTypeRef, - base: PyTypeRef, + base: &PyTypeRef, slots: PyTypeSlots, ) -> PyTypeRef { let dict = PyAttributes::new(); @@ -221,7 +263,7 @@ pub fn create_type_with_slots( type_type.clone(), name, base.clone(), - vec![base], + vec![base.clone()], dict, slots, ) @@ -328,47 +370,3 @@ fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef) { (type_type, object_type) } - -/// Fill attributes of builtin types. -pub fn initialize_types(context: &PyContext) { - pytype::init(&context); - object::init(&context); - list::init(&context); - set::init(&context); - tuple::init(&context); - dict::init(&context); - builtinfunc::init(&context); - function::init(&context); - staticmethod::init(&context); - classmethod::init(&context); - generator::init(&context); - coroutine::init(&context); - asyncgenerator::init(&context); - int::init(&context); - float::init(&context); - complex::init(&context); - bytes::init(&context); - bytearray::init(&context); - property::init(&context); - getset::init(&context); - memory::init(&context); - pystr::init(&context); - range::init(&context); - slice::init(&context); - pysuper::init(&context); - iter::init(&context); - enumerate::init(&context); - filter::init(&context); - map::init(&context); - zip::init(&context); - pybool::init(&context); - code::init(&context); - frame::init(&context); - weakref::init(&context); - weakproxy::init(&context); - singletons::init(&context); - module::init(&context); - namespace::init(&context); - mappingproxy::init(&context); - traceback::init(&context); -} diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 8dab54d40..090205214 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -320,9 +320,13 @@ impl VirtualMachine { // builtins.open to io.OpenWrapper, but this is easier, since it doesn't // require the Python stdlib to be present let io = import::import_builtin(self, "_io")?; - let io_open = self.get_attribute(io, "open")?; let set_stdio = |name, fd, mode: &str| { - let stdio = self.invoke(&io_open, (fd, mode))?; + let stdio = crate::stdlib::io::open( + self.ctx.new_int(fd), + Some(mode), + Default::default(), + self, + )?; self.set_attr( &self.sys_module, format!("__{}__", name), // e.g. __stdin__ @@ -335,6 +339,7 @@ impl VirtualMachine { set_stdio("stdout", 1, "w")?; set_stdio("stderr", 2, "w")?; + let io_open = self.get_attribute(io, "open")?; self.set_attr(&self.builtins, "open", io_open)?; } diff --git a/wasm/lib/Cargo.toml b/wasm/lib/Cargo.toml index df4a21cb4..a5d7b5588 100644 --- a/wasm/lib/Cargo.toml +++ b/wasm/lib/Cargo.toml @@ -17,6 +17,7 @@ freeze-stdlib = ["rustpython-vm/freeze-stdlib"] [dependencies] rustpython-compiler = { path = "../../compiler" } rustpython-parser = { path = "../../parser" } +rustpython-common = { path = "../../common" } # no threading feature for rustpython-vm -- doesn't much matter anyway, but it might be more optimized rustpython-vm = { path = "../../vm", default-features = false, features = ["compile-parse"] } wasm-bindgen = "0.2" diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index df00a9779..9bfa5a2d6 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -9,6 +9,7 @@ use rustpython_vm::function::OptionalArg; use rustpython_vm::import::import_file; use rustpython_vm::pyobject::{ BorrowValue, IntoPyObject, PyCallable, PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue, + StaticType, }; use rustpython_vm::VirtualMachine; @@ -160,8 +161,8 @@ struct Document { } impl PyValue for Document { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("browser", "Document") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -186,8 +187,8 @@ struct Element { } impl PyValue for Element { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("browser", "Element") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 83adda99f..391cb3c81 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -12,9 +12,9 @@ use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::{Args, OptionalArg}; use rustpython_vm::pyobject::{ BorrowValue, IntoPyObject, PyCallable, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, - TryFromObject, + StaticType, TryFromObject, }; -use rustpython_vm::types::create_type; +use rustpython_vm::types::create_simple_type; use rustpython_vm::VirtualMachine; #[wasm_bindgen(inline_js = " @@ -58,8 +58,8 @@ pub struct PyJsValue { type PyJsValueRef = PyRef; impl PyValue for PyJsValue { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_js", "JSValue") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -289,8 +289,8 @@ impl fmt::Debug for JsClosure { } impl PyValue for JsClosure { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("_js", "JSClosure") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -378,8 +378,8 @@ pub struct PyPromise { pub type PyPromiseRef = PyRef; impl PyValue for PyPromise { - fn class(vm: &VirtualMachine) -> PyTypeRef { - vm.class("browser", "Promise") + fn class(_vm: &VirtualMachine) -> &PyTypeRef { + Self::static_type() } } @@ -474,11 +474,7 @@ fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyBaseExceptionRef { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; - let js_error = create_type( - "JSError", - &ctx.types.type_type, - ctx.exceptions.exception_type.clone(), - ); + let js_error = create_simple_type("JSError", &ctx.exceptions.exception_type); extend_class!(ctx, &js_error, { "value" => ctx.new_readonly_getset("value", |exc: PyBaseExceptionRef| exc.get_arg(0)), });