trait StaticType

This commit is contained in:
Jeong YunWon committed 2020-10-20 01:43:39 +09:00
1 parent 91eb4d42e0
commit 5b32064cd6
13 files changed
+457 -353

No files matched your search

Generated
+1
View File
@@ -1819,6 +1819,7 @@ version = "0.1.2"
dependencies = [
"js-sys",
"parking_lot",
"rustpython-common",
"rustpython-compiler",
"rustpython-parser",
"rustpython-vm",
+1
View File
@@ -5,4 +5,5 @@ pub mod float_ops;
pub mod hash;
pub mod lock;
pub mod rc;
pub mod static_cell;
pub mod str;
+76
View File
@@ -0,0 +1,76 @@
#[cfg(not(feature = "threading"))]
mod non_threading {
use crate::lock::OnceCell;
pub type StaticCell<T> = std::thread::LocalKey<OnceCell<&'static T>>;
#[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<T> {
inner: T,
}
impl<T> StaticKey<T> {
pub const fn new(inner: T) -> Self {
Self { inner }
}
pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
f(&self.inner)
}
}
pub type StaticCell<T> = StaticKey<OnceCell<&'static T>>;
#[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<T>(cell: &'static StaticCell<T>) -> Option<&'static T> {
cell.with(|cell| cell.get().copied())
}
pub fn init_expect<T>(cell: &'static StaticCell<T>, 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<T, F>(cell: &'static StaticCell<T>, f: F) -> &'static T
where
F: FnOnce() -> T,
{
cell.with(|cell| {
*cell.get_or_init(|| {
let value = f();
Box::leak(Box::new(value))
})
})
}
+32 -3
View File
@@ -133,6 +133,7 @@ fn generate_class_def(
ident: &Ident,
name: &str,
module_name: Option<&str>,
base: Option<String>,
attrs: &[Attribute],
) -> std::result::Result<TokenStream, Diagnostic> {
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
+5 -1
View File
@@ -233,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)
@@ -268,6 +268,10 @@ impl ClassItemMeta {
Ok(value)
}
pub fn base(&self) -> Result<Option<String>> {
self.inner()._optional_str("base")
}
pub fn module(&self) -> Result<Option<String>> {
const KEY: &str = "module";
let inner = self.inner();
+3
View File
@@ -42,6 +42,9 @@ impl PyValue for PyCode {
}
}
#[pyimpl(with(PyRef))]
impl PyCode {}
#[pyimpl]
impl PyCodeRef {
#[pyslot]
+5 -2
View File
@@ -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]
+1 -1
View File
@@ -76,7 +76,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
/// 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]
+70 -65
View File
@@ -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<Option<PyTracebackRef>>,
@@ -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.clone(),
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<PyObjectRef> {
})
}
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,
+92 -65
View File
@@ -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<dyn PyObjectPayload> {
}
}
#[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<T: PyObjectPayload + PyValue>(payload: T, cls: &PyTypeRef) -> PyRef<T> {
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<T: PyObjectPayload + PyValue>(
payload: T,
cls: &PyTypeRef,
) -> PyRef<T> {
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, &not_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 {
@@ -1229,8 +1230,31 @@ 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<PyTypeRef>;
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()
}
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(Self::static_metaclass(), Self::static_baseclass().clone());
static_cell::init_expect(Self::static_cell(), typ, Self::NAME)
}
}
@@ -1270,14 +1294,17 @@ 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 make_class(ctx: &PyContext) -> PyTypeRef
where
Self: StaticType,
{
static_cell::get_or_init(Self::static_cell(), || {
let typ =
Self::create_bare_type(Self::static_metaclass(), Self::static_baseclass().clone());
Self::extend_class(ctx, &typ);
typ
})
.clone()
}
fn create_bare_type(type_type: &PyTypeRef, base: PyTypeRef) -> PyTypeRef {
+45 -87
View File
@@ -7,7 +7,8 @@ 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
}
@@ -33,8 +34,8 @@ mod _io {
use crate::exceptions::{IntoPyException, PyBaseExceptionRef};
use crate::function::{FuncArgs, OptionalArg, OptionalOption};
use crate::pyobject::{
BorrowValue, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
TryFromObject, TypeProtocol,
BorrowValue, IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
TypeProtocol,
};
use crate::vm::VirtualMachine;
@@ -211,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)
@@ -381,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() {
@@ -407,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,
@@ -461,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))]
@@ -483,32 +488,32 @@ mod _io {
buffer_size: OptionalArg<usize>,
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]
@@ -538,7 +543,8 @@ mod _io {
}
}
#[pyclass(name = "BufferedWriter", noattr)]
#[pyattr]
#[pyclass(name = "BufferedWriter", base = "_BufferedIOBase")]
struct BufferedWriter;
#[pyimpl(flags(BASETYPE))]
@@ -554,32 +560,32 @@ mod _io {
buffer_size: OptionalArg<usize>,
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]
@@ -635,7 +641,8 @@ mod _io {
}
}
#[pyclass(name = "TextIOWrapper", noattr)]
#[pyattr]
#[pyclass(name = "TextIOWrapper", base = "_TextIOBase")]
struct TextIOWrapper;
#[pyimpl]
@@ -803,7 +810,8 @@ mod _io {
newline: Option<PyStrRef>,
}
#[pyclass(name = "StringIO", noattr)]
#[pyattr]
#[pyclass(name = "StringIO", base = "_TextIOBase")]
#[derive(Debug)]
struct StringIO {
buffer: PyRwLock<BufferedIO>,
@@ -936,7 +944,8 @@ mod _io {
}
}
#[pyclass(name = "BytesIO", noattr)]
#[pyattr]
#[pyclass(name = "BytesIO", base = "_BufferedIOBase")]
#[derive(Debug)]
struct BytesIO {
buffer: PyRwLock<BufferedIO>,
@@ -1305,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::*;
@@ -1477,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;
@@ -1485,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, TryFromObject,
};
use crate::stdlib::os;
use crate::vm::VirtualMachine;
@@ -1506,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<i64>,
closefd: AtomicCell<bool>,
}
@@ -1717,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)
}
}
+125 -129
View File
@@ -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,
@@ -116,93 +116,133 @@ pub struct TypeZoo {
pub object_type: PyTypeRef,
}
impl Default for TypeZoo {
fn default() -> Self {
Self::new()
}
}
impl TypeZoo {
pub fn new() -> Self {
pub(crate) fn init() -> Self {
let (type_type, object_type) = init_type_hierarchy();
let new = Self {
// 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(),
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())
};
}
// 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(),
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,
}
// 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(),
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(),
};
singletons::PyNone::init_bare_type();
singletons::PyNotImplemented::init_bare_type();
slice::PyEllipsis::init_bare_type();
new
}
/// 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);
}
}
@@ -328,47 +368,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);
}
+1
View File
@@ -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"