From 19ed4f85e72b665abd74b13c05f6b7b49ae9f78a Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Mon, 12 Oct 2020 18:34:28 +0900 Subject: [PATCH] clean up vm::builtins --- common/src/str.rs | 22 +++++++++ src/main.rs | 6 +-- src/shell.rs | 5 +- vm/src/builtins/asyncgenerator.rs | 18 ++++---- vm/src/builtins/builtinfunc.rs | 36 ++++----------- vm/src/builtins/bytearray.rs | 2 +- vm/src/builtins/bytes.rs | 2 +- vm/src/builtins/classmethod.rs | 7 +-- vm/src/builtins/complex.rs | 8 ++-- vm/src/builtins/coroutine.rs | 4 +- vm/src/builtins/dict.rs | 6 +-- vm/src/builtins/enumerate.rs | 3 +- vm/src/builtins/filter.rs | 6 +-- vm/src/builtins/float.rs | 8 ++-- vm/src/builtins/frame.rs | 2 +- vm/src/builtins/generator.rs | 6 +-- vm/src/builtins/getset.rs | 2 - vm/src/builtins/int.rs | 20 ++++---- vm/src/builtins/iter.rs | 10 ++-- vm/src/builtins/list.rs | 2 +- vm/src/builtins/make_module.rs | 60 +++++++----------------- vm/src/builtins/map.rs | 3 +- vm/src/builtins/mappingproxy.rs | 12 ++--- vm/src/builtins/memory.rs | 6 +-- vm/src/builtins/mod.rs | 77 +++++++++++++++---------------- vm/src/builtins/module.rs | 2 +- vm/src/builtins/property.rs | 10 ++-- vm/src/builtins/pybool.rs | 42 +++++++---------- vm/src/builtins/pystr.rs | 4 +- vm/src/builtins/pysuper.rs | 14 +++--- vm/src/builtins/pytype.rs | 47 ++++++++++--------- vm/src/builtins/range.rs | 4 +- vm/src/builtins/set.rs | 31 ++++++------- vm/src/builtins/singletons.rs | 2 +- vm/src/builtins/slice.rs | 2 +- vm/src/builtins/staticmethod.rs | 7 +-- vm/src/builtins/traceback.rs | 4 +- vm/src/builtins/weakproxy.rs | 4 +- vm/src/builtins/weakref.rs | 2 - vm/src/cformat.rs | 18 ++++---- vm/src/coroutine.rs | 10 ++-- vm/src/exceptions.rs | 6 +-- vm/src/format.rs | 4 +- vm/src/frame.rs | 10 ++-- vm/src/function.rs | 4 +- vm/src/import.rs | 6 +-- vm/src/py_serde.rs | 14 +++--- vm/src/pyobject.rs | 29 +++++++----- vm/src/stdlib/functools.rs | 5 +- vm/src/stdlib/io.rs | 18 ++++---- vm/src/stdlib/itertools.rs | 8 ++-- vm/src/stdlib/math.rs | 10 ++-- vm/src/stdlib/operator.rs | 4 +- vm/src/stdlib/warnings.rs | 4 +- vm/src/sysmodule.rs | 2 +- vm/src/types.rs | 2 +- vm/src/vm.rs | 19 +++----- wasm/lib/src/convert.rs | 7 +-- 58 files changed, 313 insertions(+), 375 deletions(-) diff --git a/common/src/str.rs b/common/src/str.rs index a89c25f49..8e5a62634 100644 --- a/common/src/str.rs +++ b/common/src/str.rs @@ -29,6 +29,28 @@ pub fn zfill(bytes: &[u8], width: usize) -> Vec { } } +/// Convert a string to ascii compatible, escaping unicodes into escape +/// sequences. +pub fn to_ascii(value: &str) -> String { + let mut ascii = String::new(); + for c in value.chars() { + if c.is_ascii() { + ascii.push(c) + } else { + let c = c as i64; + let hex = if c < 0x100 { + format!("\\x{:02x}", c) + } else if c < 0x10000 { + format!("\\u{:04x}", c) + } else { + format!("\\U{:08x}", c) + }; + ascii.push_str(&hex) + } + } + ascii +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/main.rs b/src/main.rs index 49c2ce99f..28709e017 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,10 @@ extern crate log; use clap::{App, AppSettings, Arg, ArgMatches}; use rustpython_compiler::compile; use rustpython_vm::{ - builtins::{isinstance, PyInt}, + builtins::PyInt, exceptions::print_exception, match_class, - pyobject::{BorrowValue, ItemProtocol, PyResult}, + pyobject::{BorrowValue, ItemProtocol, PyResult, TypeProtocol}, scope::Scope, util, InitParameter, Interpreter, PySettings, VirtualMachine, }; @@ -67,7 +67,7 @@ fn main() { // See if any exception leaked out: let exitcode = match res { Ok(()) => 0, - Err(err) if isinstance(&err, &vm.ctx.exceptions.system_exit) => { + Err(err) if err.isinstance(&vm.ctx.exceptions.system_exit) => { let args = err.args(); match args.borrow_value().len() { 0 => 0, diff --git a/src/shell.rs b/src/shell.rs index 5deafcf94..e971c5777 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -4,9 +4,8 @@ use rustpython_compiler::{compile, error::CompileError, error::CompileErrorType} use rustpython_parser::error::{LexicalErrorType, ParseErrorType}; use rustpython_vm::readline::{Readline, ReadlineResult}; use rustpython_vm::{ - builtins::isinstance, exceptions::{print_exception, PyBaseExceptionRef}, - pyobject::{BorrowValue, PyResult}, + pyobject::{BorrowValue, PyResult, TypeProtocol}, scope::Scope, VirtualMachine, }; @@ -127,7 +126,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> { }; if let Err(exc) = result { - if isinstance(&exc, &vm.ctx.exceptions.system_exit) { + if exc.isinstance(&vm.ctx.exceptions.system_exit) { repl.save_history(&repl_history_path).unwrap(); return Err(exc); } diff --git a/vm/src/builtins/asyncgenerator.rs b/vm/src/builtins/asyncgenerator.rs index c59a46e29..fdd4658ac 100644 --- a/vm/src/builtins/asyncgenerator.rs +++ b/vm/src/builtins/asyncgenerator.rs @@ -1,10 +1,12 @@ use super::code::PyCodeRef; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use crate::coroutine::{Coro, Variant}; use crate::exceptions::PyBaseExceptionRef; use crate::frame::FrameRef; use crate::function::OptionalArg; -use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::pyobject::{ + PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, +}; use crate::vm::VirtualMachine; use crossbeam_utils::atomic::AtomicCell; @@ -15,7 +17,7 @@ pub struct PyAsyncGen { inner: Coro, running_async: AtomicCell, } -pub type PyAsyncGenRef = PyRef; +type PyAsyncGenRef = PyRef; impl PyValue for PyAsyncGen { fn class(vm: &VirtualMachine) -> PyTypeRef { @@ -29,7 +31,7 @@ impl PyAsyncGen { &self.inner } - pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyAsyncGenRef { + pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef { PyAsyncGen { inner: Coro::new(frame, Variant::AsyncGen), running_async: AtomicCell::new(false), @@ -127,8 +129,8 @@ impl PyAsyncGenWrappedValue {} impl PyAsyncGenWrappedValue { fn unbox(ag: &PyAsyncGen, val: PyResult, vm: &VirtualMachine) -> PyResult { if let Err(ref e) = val { - if pytype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration) - || pytype::isinstance(&e, &vm.ctx.exceptions.generator_exit) + if e.isinstance(&vm.ctx.exceptions.stop_async_iteration) + || e.isinstance(&vm.ctx.exceptions.generator_exit) { ag.inner.closed.store(true); } @@ -385,8 +387,8 @@ impl PyAsyncGenAThrow { self.ag.running_async.store(false); self.state.store(AwaitableState::Closed); if self.aclose - && (pytype::isinstance(&exc, &vm.ctx.exceptions.stop_async_iteration) - || pytype::isinstance(&exc, &vm.ctx.exceptions.generator_exit)) + && (exc.isinstance(&vm.ctx.exceptions.stop_async_iteration) + || exc.isinstance(&vm.ctx.exceptions.generator_exit)) { vm.new_exception_empty(vm.ctx.exceptions.stop_iteration.clone()) } else { diff --git a/vm/src/builtins/builtinfunc.rs b/vm/src/builtins/builtinfunc.rs index e660c6117..c70f0773a 100644 --- a/vm/src/builtins/builtinfunc.rs +++ b/vm/src/builtins/builtinfunc.rs @@ -11,13 +11,13 @@ use crate::pyobject::{ use crate::slots::{Callable, SlotDescriptor}; use crate::vm::VirtualMachine; -pub struct PyFuncDef { +pub struct PyNativeFuncDef { pub func: PyNativeFunc, pub name: Option, pub doc: Option, } -impl From for PyFuncDef { +impl From for PyNativeFuncDef { fn from(func: PyNativeFunc) -> Self { Self { func, @@ -27,7 +27,7 @@ impl From for PyFuncDef { } } -impl PyFuncDef { +impl PyNativeFuncDef { pub fn with_doc(mut self, doc: String, ctx: &PyContext) -> Self { self.doc = Some(ctx.new_stringref(doc)); self @@ -58,7 +58,7 @@ impl PyFuncDef { #[pyclass(name = "builtin_function_or_method", module = false)] pub struct PyBuiltinFunction { - value: PyFuncDef, + value: PyNativeFuncDef, module: Option, } @@ -80,11 +80,11 @@ impl fmt::Debug for PyBuiltinFunction { impl From for PyBuiltinFunction { fn from(value: PyNativeFunc) -> Self { - PyFuncDef::from(value).into() + PyNativeFuncDef::from(value).into() } } -impl From for PyBuiltinFunction { - fn from(value: PyFuncDef) -> Self { +impl From for PyBuiltinFunction { + fn from(value: PyNativeFuncDef) -> Self { Self { value, module: None, @@ -135,7 +135,7 @@ impl PyBuiltinFunction { #[pyclass(module = false, name = "method_descriptor")] pub struct PyBuiltinMethod { - value: PyFuncDef, + value: PyNativeFuncDef, } impl PyValue for PyBuiltinMethod { @@ -150,28 +150,12 @@ impl fmt::Debug for PyBuiltinMethod { } } -impl From for PyBuiltinMethod { - fn from(value: PyFuncDef) -> Self { +impl From for PyBuiltinMethod { + fn from(value: PyNativeFuncDef) -> Self { Self { value } } } -impl PyBuiltinMethod { - pub fn new_with_name(func: PyNativeFunc, name: PyStrRef) -> Self { - Self { - value: PyFuncDef { - func, - name: Some(name), - doc: None, - }, - } - } - - pub fn as_func(&self) -> &PyNativeFunc { - &self.value.func - } -} - impl SlotDescriptor for PyBuiltinMethod { fn descr_get( zelf: PyObjectRef, diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index 2d7aba8ea..d985441e5 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -107,7 +107,7 @@ impl PyByteArray { cls: PyTypeRef, options: ByteInnerNewOptions, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { PyByteArray::from_inner(options.get_value(vm)?).into_ref_with_type(vm, cls) } diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 546de1fd8..855d802a9 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -111,7 +111,7 @@ impl PyBytes { cls: PyTypeRef, options: ByteInnerNewOptions, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { PyBytes { inner: options.get_value(vm)?, buffer_options: OnceCell::new(), diff --git a/vm/src/builtins/classmethod.rs b/vm/src/builtins/classmethod.rs index 5d3ea6f91..d166487e7 100644 --- a/vm/src/builtins/classmethod.rs +++ b/vm/src/builtins/classmethod.rs @@ -30,7 +30,6 @@ use crate::vm::VirtualMachine; pub struct PyClassMethod { callable: PyObjectRef, } -pub type PyClassMethodRef = PyRef; impl From for PyClassMethod { fn from(value: PyObjectRef) -> Self { @@ -60,11 +59,7 @@ impl SlotDescriptor for PyClassMethod { #[pyimpl(with(SlotDescriptor), flags(BASETYPE, HAS_DICT))] impl PyClassMethod { #[pyslot] - fn tp_new( - cls: PyTypeRef, - callable: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { + fn tp_new(cls: PyTypeRef, callable: PyObjectRef, vm: &VirtualMachine) -> PyResult> { PyClassMethod { callable }.into_ref_with_type(vm, cls) } diff --git a/vm/src/builtins/complex.rs b/vm/src/builtins/complex.rs index 6905baf99..6dcf86906 100644 --- a/vm/src/builtins/complex.rs +++ b/vm/src/builtins/complex.rs @@ -3,7 +3,7 @@ use num_traits::Zero; use super::float; use super::pystr::PyStr; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use crate::pyobject::{ BorrowValue, IntoPyObject, Never, PyArithmaticValue, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, @@ -21,8 +21,6 @@ pub struct PyComplex { value: Complex64, } -type PyComplexRef = PyRef; - impl PyValue for PyComplex { fn class(vm: &VirtualMachine) -> PyTypeRef { vm.ctx.types.complex_type.clone() @@ -223,7 +221,7 @@ impl PyComplex { } #[pyslot] - fn tp_new(cls: PyTypeRef, args: ComplexArgs, vm: &VirtualMachine) -> PyResult { + fn tp_new(cls: PyTypeRef, args: ComplexArgs, vm: &VirtualMachine) -> PyResult> { let real = match args.real { None => Complex64::new(0.0, 0.0), Some(obj) => { @@ -253,7 +251,7 @@ impl PyComplex { Some(obj) => { if let Some(c) = try_complex(&obj, vm)? { c - } else if pytype::issubclass(obj.class(), &vm.ctx.types.str_type) { + } else if obj.class().issubclass(&vm.ctx.types.str_type) { return Err( vm.new_type_error("complex() second arg can't be a string".to_owned()) ); diff --git a/vm/src/builtins/coroutine.rs b/vm/src/builtins/coroutine.rs index ee939dfcb..3562855f0 100644 --- a/vm/src/builtins/coroutine.rs +++ b/vm/src/builtins/coroutine.rs @@ -7,7 +7,7 @@ use crate::function::OptionalArg; use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; -pub type PyCoroutineRef = PyRef; +type PyCoroutineRef = PyRef; #[pyclass(module = false, name = "coroutine")] #[derive(Debug)] @@ -27,7 +27,7 @@ impl PyCoroutine { &self.inner } - pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyCoroutineRef { + pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef { PyCoroutine { inner: Coro::new(frame, Variant::Coroutine), } diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index 13a4cfebe..0600b0a2f 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -4,7 +4,7 @@ use std::mem::size_of; use super::iter; use super::pystr; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use super::set::PySet; use crate::dictdatatype::{self, DictKey}; use crate::exceptions::PyBaseExceptionRef; @@ -468,7 +468,7 @@ impl PyDictRef { // We can take the short path here! match self.inner_getitem_option(key, vm) { Err(exc) => { - if pytype::isinstance(&exc, &vm.ctx.exceptions.key_error) { + if exc.isinstance(&vm.ctx.exceptions.key_error) { Ok(None) } else { Err(exc) @@ -482,7 +482,7 @@ impl PyDictRef { match self.get_item(key, vm) { Ok(value) => Ok(Some(value)), Err(exc) => { - if pytype::isinstance(&exc, &vm.ctx.exceptions.key_error) { + if exc.isinstance(&vm.ctx.exceptions.key_error) { Ok(None) } else { Err(exc) diff --git a/vm/src/builtins/enumerate.rs b/vm/src/builtins/enumerate.rs index 33d3f08b1..e77a46974 100644 --- a/vm/src/builtins/enumerate.rs +++ b/vm/src/builtins/enumerate.rs @@ -17,7 +17,6 @@ pub struct PyEnumerate { counter: PyRwLock, iterator: PyObjectRef, } -type PyEnumerateRef = PyRef; impl PyValue for PyEnumerate { fn class(vm: &VirtualMachine) -> PyTypeRef { @@ -33,7 +32,7 @@ impl PyEnumerate { iterable: PyObjectRef, start: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let counter = match start { OptionalArg::Present(start) => start.borrow_value().clone(), OptionalArg::Missing => BigInt::zero(), diff --git a/vm/src/builtins/filter.rs b/vm/src/builtins/filter.rs index 06e9d82e4..7c566b276 100644 --- a/vm/src/builtins/filter.rs +++ b/vm/src/builtins/filter.rs @@ -4,8 +4,6 @@ use super::pytype::PyTypeRef; use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; -pub type PyFilterRef = PyRef; - /// filter(function or None, iterable) --> filter object /// /// Return an iterator yielding those items of iterable for which function(item) @@ -31,10 +29,10 @@ impl PyFilter { function: PyObjectRef, iterable: PyObjectRef, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let iterator = iter::get_iter(vm, &iterable)?; - PyFilter { + Self { predicate: function, iterator, } diff --git a/vm/src/builtins/float.rs b/vm/src/builtins/float.rs index d9c8ee1d3..8e4518681 100644 --- a/vm/src/builtins/float.rs +++ b/vm/src/builtins/float.rs @@ -140,7 +140,7 @@ impl PyFloat { cls: PyTypeRef, arg: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let float_val = match arg { OptionalArg::Present(val) => to_float(vm, &val), OptionalArg::Missing => Ok(0f64), @@ -388,12 +388,12 @@ impl PyFloat { } #[pymethod(name = "__float__")] - fn float(zelf: PyRef) -> PyFloatRef { + fn float(zelf: PyRef) -> PyRef { zelf } #[pyproperty] - fn real(zelf: PyRef) -> PyFloatRef { + fn real(zelf: PyRef) -> PyRef { zelf } @@ -403,7 +403,7 @@ impl PyFloat { } #[pymethod(name = "conjugate")] - fn conjugate(zelf: PyRef) -> PyFloatRef { + fn conjugate(zelf: PyRef) -> PyRef { zelf } diff --git a/vm/src/builtins/frame.rs b/vm/src/builtins/frame.rs index 2ecb6c860..410772b44 100644 --- a/vm/src/builtins/frame.rs +++ b/vm/src/builtins/frame.rs @@ -55,7 +55,7 @@ impl FrameRef { } #[pyproperty] - fn f_back(self, vm: &VirtualMachine) -> Option { + fn f_back(self, vm: &VirtualMachine) -> Option { // TODO: actually store f_back inside Frame struct // get the frame in the frame stack that appears before this one. diff --git a/vm/src/builtins/generator.rs b/vm/src/builtins/generator.rs index 1e8788b6d..4c1aaf627 100644 --- a/vm/src/builtins/generator.rs +++ b/vm/src/builtins/generator.rs @@ -10,8 +10,6 @@ use crate::function::OptionalArg; use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; -pub type PyGeneratorRef = PyRef; - #[pyclass(module = false, name = "generator")] #[derive(Debug)] pub struct PyGenerator { @@ -30,7 +28,7 @@ impl PyGenerator { &self.inner } - pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyGeneratorRef { + pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef { PyGenerator { inner: Coro::new(frame, Variant::Gen), } @@ -44,7 +42,7 @@ impl PyGenerator { } #[pymethod(name = "__iter__")] - fn iter(zelf: PyGeneratorRef) -> PyGeneratorRef { + fn iter(zelf: PyRef) -> PyRef { zelf } diff --git a/vm/src/builtins/getset.rs b/vm/src/builtins/getset.rs index 45e82efe4..d43973c19 100644 --- a/vm/src/builtins/getset.rs +++ b/vm/src/builtins/getset.rs @@ -178,8 +178,6 @@ impl PyValue for PyGetSet { } } -pub type PyGetSetRef = PyRef; - impl SlotDescriptor for PyGetSet { fn descr_get( zelf: PyObjectRef, diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 5571d7ac0..45e84ca8d 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -231,7 +231,7 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult { #[pyimpl(flags(BASETYPE), with(Comparable, Hashable))] impl PyInt { - fn with_value(cls: PyTypeRef, value: T, vm: &VirtualMachine) -> PyResult + fn with_value(cls: PyTypeRef, value: T, vm: &VirtualMachine) -> PyResult> where T: Into + ToPrimitive, { @@ -249,7 +249,7 @@ impl PyInt { } #[pyslot] - fn tp_new(cls: PyTypeRef, options: IntOptions, vm: &VirtualMachine) -> PyResult { + fn tp_new(cls: PyTypeRef, options: IntOptions, vm: &VirtualMachine) -> PyResult> { let value = if let OptionalArg::Present(val) = options.val_options { if let OptionalArg::Present(base) = options.base { let base = vm @@ -447,7 +447,7 @@ impl PyInt { zelf: PyRef, precision: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { match precision { OptionalArg::Missing => (), OptionalArg::Present(ref value) => { @@ -471,7 +471,7 @@ impl PyInt { } #[pymethod(name = "__int__")] - fn int(zelf: PyRef) -> PyIntRef { + fn int(zelf: PyRef) -> PyRef { zelf } @@ -486,22 +486,22 @@ impl PyInt { } #[pymethod(name = "__trunc__")] - fn trunc(zelf: PyRef) -> PyIntRef { + fn trunc(zelf: PyRef) -> PyRef { zelf } #[pymethod(name = "__floor__")] - fn floor(zelf: PyRef) -> PyIntRef { + fn floor(zelf: PyRef) -> PyRef { zelf } #[pymethod(name = "__ceil__")] - fn ceil(zelf: PyRef) -> PyIntRef { + fn ceil(zelf: PyRef) -> PyRef { zelf } #[pymethod(name = "__index__")] - fn index(zelf: PyRef) -> PyIntRef { + fn index(zelf: PyRef) -> PyRef { zelf } @@ -549,7 +549,7 @@ impl PyInt { } #[pymethod] - fn conjugate(zelf: PyRef) -> PyIntRef { + fn conjugate(zelf: PyRef) -> PyRef { zelf } @@ -645,7 +645,7 @@ impl PyInt { } #[pyproperty] - fn numerator(zelf: PyRef) -> PyIntRef { + fn numerator(zelf: PyRef) -> PyRef { zelf } diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index f762e054c..1645bfbea 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -6,7 +6,7 @@ use crossbeam_utils::atomic::AtomicCell; use num_traits::Signed; use super::int::{self, PyInt}; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use crate::exceptions::PyBaseExceptionRef; use crate::pyobject::{ BorrowValue, PyCallable, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, @@ -58,7 +58,7 @@ pub fn get_next_object( Ok(value) => Ok(Some(value)), Err(next_error) => { // Check if we have stopiteration, or something else: - if pytype::isinstance(&next_error, &vm.ctx.exceptions.stop_iteration) { + if next_error.isinstance(&vm.ctx.exceptions.stop_iteration) { Ok(None) } else { Err(next_error) @@ -103,7 +103,7 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult return Ok(Some(len)), Err(e) => { - if !pytype::isinstance(&e, &vm.ctx.exceptions.type_error) { + if !e.isinstance(&vm.ctx.exceptions.type_error) { return Err(e); } } @@ -116,7 +116,7 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult res, Err(e) => { - return if pytype::isinstance(&e, &vm.ctx.exceptions.type_error) { + return if e.isinstance(&vm.ctx.exceptions.type_error) { Ok(None) } else { Err(e) @@ -177,7 +177,7 @@ impl PySequenceIterator { let pos = self.position.fetch_add(step); if pos >= 0 { match vm.call_method(&self.obj, "__getitem__", (pos,)) { - Err(ref e) if pytype::isinstance(&e, &vm.ctx.exceptions.index_error) => { + Err(ref e) if e.isinstance(&vm.ctx.exceptions.index_error) => { Err(new_stop_iteration(vm)) } // also catches stop_iteration => stop_iteration diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 41ed689b1..4a3ef5724 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -395,7 +395,7 @@ impl PyList { cls: PyTypeRef, iterable: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let elements = if let OptionalArg::Present(iterable) = iterable { vm.extract_elements(&iterable)? } else { diff --git a/vm/src/builtins/make_module.rs b/vm/src/builtins/make_module.rs index 6970a7878..f5afb3773 100644 --- a/vm/src/builtins/make_module.rs +++ b/vm/src/builtins/make_module.rs @@ -9,14 +9,6 @@ use crate::vm::VirtualMachine; /// Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices. #[pymodule(name = "builtins")] mod decl { - use num_bigint::Sign; - use num_traits::{Signed, ToPrimitive, Zero}; - #[cfg(feature = "rustpython-compiler")] - use rustpython_compiler::compile; - #[cfg(feature = "rustpython-parser")] - use rustpython_parser::parser; - - use super::to_ascii; use crate::builtins::bytes::PyBytesRef; use crate::builtins::code::PyCodeRef; use crate::builtins::dict::PyDictRef; @@ -26,8 +18,9 @@ mod decl { use crate::builtins::list::{PyList, SortOptions}; use crate::builtins::pybool::{self, IntoPyBool}; use crate::builtins::pystr::{PyStr, PyStrRef}; - use crate::builtins::pytype::{self, PyTypeRef}; + use crate::builtins::pytype::PyTypeRef; use crate::byteslike::PyBytesLike; + use crate::common::{hash::PyHash, str::to_ascii}; use crate::exceptions::PyBaseExceptionRef; use crate::function::{single_or_tuple_any, Args, FuncArgs, KwArgs, OptionalArg}; use crate::pyobject::{ @@ -38,11 +31,12 @@ mod decl { use crate::scope::Scope; use crate::sliceable; use crate::slots::PyComparisonOp; - #[cfg(feature = "rustpython-parser")] - use crate::stdlib::ast; use crate::vm::VirtualMachine; use crate::{py_io, sysmodule}; - use rustpython_common::hash::PyHash; + use num_bigint::Sign; + use num_traits::{Signed, ToPrimitive, Zero}; + #[cfg(feature = "rustpython-compiler")] + use rustpython_compiler::compile; #[pyfunction] fn abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult { @@ -73,7 +67,7 @@ mod decl { } #[pyfunction] - fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { + pub fn ascii(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { let repr = vm.to_repr(&obj)?; let ascii = to_ascii(repr.borrow_value()); Ok(ascii) @@ -138,6 +132,9 @@ mod decl { #[cfg(feature = "rustpython-parser")] { + use crate::stdlib::ast; + use rustpython_parser::parser; + if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { let mode = mode_str .parse::() @@ -292,7 +289,7 @@ mod decl { default: T, vm: &VirtualMachine, ) -> PyResult { - if pytype::isinstance(&ex, &vm.ctx.exceptions.attribute_error) { + if ex.isinstance(&vm.ctx.exceptions.attribute_error) { Ok(default) } else { Err(ex) @@ -568,7 +565,7 @@ mod decl { match vm.call_method(&iterator, "__next__", ()) { Ok(value) => Ok(value), Err(value) => { - if pytype::isinstance(&value, &vm.ctx.exceptions.stop_iteration) { + if value.isinstance(&vm.ctx.exceptions.stop_iteration) { match default_value { OptionalArg::Missing => Err(value), OptionalArg::Present(value) => Ok(value), @@ -639,9 +636,7 @@ mod decl { } OptionalArg::Present(m) => { // Check if the 3rd argument is defined and perform modulus on the result - if !(pytype::isinstance(&x, &vm.ctx.types.int_type) - && pytype::isinstance(&y, &vm.ctx.types.int_type)) - { + if !(x.isinstance(&vm.ctx.types.int_type) && y.isinstance(&vm.ctx.types.int_type)) { return Err(vm.new_type_error( "pow() 3rd argument not allowed unless all arguments are integers" .to_owned(), @@ -825,9 +820,9 @@ mod decl { for base in bases.clone() { let base_class = base.class(); - if pytype::issubclass(&base_class, &metaclass) { + if base_class.issubclass(&metaclass) { metaclass = base.clone_class(); - } else if !pytype::issubclass(&metaclass, &base_class) { + } else if !metaclass.issubclass(&base_class) { return Err(vm.new_type_error( "metaclass conflict: the metaclass of a derived class must be a (non-strict) \ subclass of the metaclasses of all its bases" @@ -862,30 +857,7 @@ mod decl { } } -pub use decl::isinstance as builtin_isinstance; -pub use decl::print as builtin_print; - -/// Convert a string to ascii compatible, escaping unicodes into escape -/// sequences. -pub fn to_ascii(value: &str) -> String { - let mut ascii = String::new(); - for c in value.chars() { - if c.is_ascii() { - ascii.push(c) - } else { - let c = c as i64; - let hex = if c < 0x100 { - format!("\\x{:02x}", c) - } else if c < 0x10000 { - format!("\\u{:04x}", c) - } else { - format!("\\U{:08x}", c) - }; - ascii.push_str(&hex) - } - } - ascii -} +pub use decl::{ascii, isinstance, print}; pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) { let ctx = &vm.ctx; diff --git a/vm/src/builtins/map.rs b/vm/src/builtins/map.rs index 3f4be4eb2..0cd94462c 100644 --- a/vm/src/builtins/map.rs +++ b/vm/src/builtins/map.rs @@ -14,7 +14,6 @@ pub struct PyMap { mapper: PyObjectRef, iterators: Vec, } -type PyMapRef = PyRef; impl PyValue for PyMap { fn class(vm: &VirtualMachine) -> PyTypeRef { @@ -30,7 +29,7 @@ impl PyMap { function: PyObjectRef, iterables: Args, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let iterators = iterables .into_iter() .map(|iterable| iter::get_iter(vm, &iterable)) diff --git a/vm/src/builtins/mappingproxy.rs b/vm/src/builtins/mappingproxy.rs index 2da34eb9f..e3d0e0c2b 100644 --- a/vm/src/builtins/mappingproxy.rs +++ b/vm/src/builtins/mappingproxy.rs @@ -21,25 +21,25 @@ enum MappingProxyInner { Dict(PyObjectRef), } -pub type PyMappingProxyRef = PyRef; - impl PyValue for PyMappingProxy { fn class(vm: &VirtualMachine) -> PyTypeRef { vm.ctx.types.mappingproxy_type.clone() } } -#[pyimpl] impl PyMappingProxy { - pub fn new(class: PyTypeRef) -> PyMappingProxy { - PyMappingProxy { + pub fn new(class: PyTypeRef) -> Self { + Self { mapping: MappingProxyInner::Class(class), } } +} +#[pyimpl] +impl PyMappingProxy { #[pyslot] fn tp_new(cls: PyTypeRef, mapping: PyObjectRef, vm: &VirtualMachine) -> PyResult> { - PyMappingProxy { + Self { mapping: MappingProxyInner::Dict(mapping), } .into_ref_with_type(vm, cls) diff --git a/vm/src/builtins/memory.rs b/vm/src/builtins/memory.rs index 0eae01707..e2c64a392 100644 --- a/vm/src/builtins/memory.rs +++ b/vm/src/builtins/memory.rs @@ -127,7 +127,7 @@ pub struct PyMemoryView { format_spec: FormatSpec, } -pub type PyMemoryViewRef = PyRef; +type PyMemoryViewRef = PyRef; #[pyimpl(with(Hashable, Comparable, BufferProtocol))] impl PyMemoryView { @@ -168,7 +168,7 @@ impl PyMemoryView { } #[pyslot] - fn tp_new(_cls: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn tp_new(_cls: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult> { let buffer = try_buffer_from_object(vm, &obj)?; Ok(PyMemoryView::from_buffer(obj, buffer, vm)?.into_ref(vm)) } @@ -567,7 +567,7 @@ impl PyMemoryView { } #[pymethod] - fn toreadonly(zelf: PyRef, vm: &VirtualMachine) -> PyResult { + fn toreadonly(zelf: PyRef, vm: &VirtualMachine) -> PyResult> { zelf.try_not_released(vm)?; let buffer = BufferRef(Box::new(zelf.clone())); Ok(PyMemoryView { diff --git a/vm/src/builtins/mod.rs b/vm/src/builtins/mod.rs index 301fe0f43..a81ea0f8c 100644 --- a/vm/src/builtins/mod.rs +++ b/vm/src/builtins/mod.rs @@ -1,85 +1,82 @@ //! This package contains the python basic/builtin types pub(crate) mod asyncgenerator; -pub use asyncgenerator::*; +pub use asyncgenerator::PyAsyncGen; pub(crate) mod builtinfunc; -pub use builtinfunc::*; pub(crate) mod bytearray; -pub use bytearray::*; +pub use bytearray::PyByteArray; pub(crate) mod bytes; -pub use bytes::*; +pub use bytes::PyBytes; pub(crate) mod classmethod; -pub use classmethod::*; +pub use classmethod::PyClassMethod; pub(crate) mod code; -pub use code::*; +pub use code::PyCode; pub(crate) mod complex; -pub use complex::*; +pub use complex::PyComplex; pub(crate) mod coroutine; -pub use coroutine::*; +pub use coroutine::PyCoroutine; pub(crate) mod dict; -pub use dict::*; +pub use dict::{PyDict, PyDictRef}; pub(crate) mod enumerate; -pub use enumerate::*; +pub use enumerate::PyEnumerate; pub(crate) mod filter; -pub use filter::*; +pub use filter::PyFilter; pub(crate) mod float; -pub use float::*; +pub use float::{PyFloat, PyFloatRef}; pub(crate) mod frame; -pub use frame::*; pub(crate) mod function; -pub use function::*; +pub use function::PyFunction; pub(crate) mod generator; -pub use generator::*; +pub use generator::PyGenerator; pub(crate) mod getset; -pub use getset::*; pub(crate) mod int; -pub use int::*; +pub use int::{PyInt, PyIntRef}; pub(crate) mod iter; pub use iter::*; pub(crate) mod list; -pub use list::*; +pub use list::PyList; pub(crate) mod map; -pub use map::*; +pub use map::PyMap; pub(crate) mod mappingproxy; -pub use mappingproxy::*; +pub use mappingproxy::PyMappingProxy; pub(crate) mod memory; -pub use memory::*; +pub use memory::PyMemoryView; pub(crate) mod module; -pub use module::*; +pub use module::PyModule; pub(crate) mod namespace; -pub use namespace::*; +pub use namespace::PyNamespace; pub(crate) mod object; -pub use object::*; +pub use object::PyBaseObject; pub(crate) mod property; -pub use property::*; +pub use property::PyProperty; pub(crate) mod pybool; -pub use pybool::*; +pub use pybool::{IntoPyBool, PyBool}; pub(crate) mod pystr; -pub use pystr::*; +pub use pystr::{PyStr, PyStrRef}; pub(crate) mod pysuper; -pub use pysuper::*; +pub use pysuper::PySuper; pub(crate) mod pytype; -pub use pytype::*; +pub use pytype::{PyType, PyTypeRef}; pub(crate) mod range; -pub use range::*; +pub use range::PyRange; pub(crate) mod set; -pub use set::*; +pub use set::PySet; pub(crate) mod singletons; -pub use singletons::*; +pub use singletons::{PyNone, PyNotImplemented}; pub(crate) mod slice; -pub use slice::*; +pub use slice::PySlice; pub(crate) mod staticmethod; -pub use staticmethod::*; +pub use staticmethod::PyStaticMethod; pub(crate) mod traceback; -pub use traceback::*; +pub use traceback::PyTraceback; pub(crate) mod tuple; -pub use tuple::*; +pub use tuple::PyTuple; pub(crate) mod weakproxy; -pub use weakproxy::*; +pub use weakproxy::PyWeakProxy; pub(crate) mod weakref; -pub use weakref::*; +pub use weakref::PyWeak; pub(crate) mod zip; -pub use zip::*; +pub use zip::PyZip; mod make_module; -pub use make_module::*; +pub use make_module::{ascii, isinstance, make_module, print}; diff --git a/vm/src/builtins/module.rs b/vm/src/builtins/module.rs index 6607831ac..c46a03018 100644 --- a/vm/src/builtins/module.rs +++ b/vm/src/builtins/module.rs @@ -46,7 +46,7 @@ pub fn init_module_dict( #[pyimpl(with(SlotGetattro), flags(BASETYPE, HAS_DICT))] impl PyModule { #[pyslot] - fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult { + fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult> { PyModule {}.into_ref_with_type(vm, cls) } diff --git a/vm/src/builtins/property.rs b/vm/src/builtins/property.rs index 98da89658..63eab85ed 100644 --- a/vm/src/builtins/property.rs +++ b/vm/src/builtins/property.rs @@ -58,8 +58,6 @@ impl PyValue for PyProperty { } } -pub type PyPropertyRef = PyRef; - #[derive(FromArgs)] struct PropertyArgs { #[pyarg(any, default)] @@ -93,7 +91,7 @@ impl SlotDescriptor for PyProperty { #[pyimpl(with(SlotDescriptor), flags(BASETYPE))] impl PyProperty { #[pyslot] - fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult { + fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult> { PyProperty { getter: PyRwLock::new(None), setter: PyRwLock::new(None), @@ -162,7 +160,7 @@ impl PyProperty { zelf: PyRef, getter: Option, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { PyProperty { getter: PyRwLock::new(getter.or_else(|| zelf.fget())), setter: PyRwLock::new(zelf.fset()), @@ -177,7 +175,7 @@ impl PyProperty { zelf: PyRef, setter: Option, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { PyProperty { getter: PyRwLock::new(zelf.fget()), setter: PyRwLock::new(setter.or_else(|| zelf.fset())), @@ -192,7 +190,7 @@ impl PyProperty { zelf: PyRef, deleter: Option, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { PyProperty { getter: PyRwLock::new(zelf.fget()), setter: PyRwLock::new(zelf.fset()), diff --git a/vm/src/builtins/pybool.rs b/vm/src/builtins/pybool.rs index 1ab69afdc..548612939 100644 --- a/vm/src/builtins/pybool.rs +++ b/vm/src/builtins/pybool.rs @@ -1,6 +1,8 @@ use num_bigint::Sign; use num_traits::Zero; +use super::int::PyInt; +use super::pystr::PyStrRef; use crate::function::OptionalArg; use crate::pyobject::{ BorrowValue, IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, @@ -8,10 +10,6 @@ use crate::pyobject::{ }; use crate::vm::VirtualMachine; -use super::int::PyInt; -use super::pystr::PyStrRef; -use super::pytype; - impl IntoPyObject for bool { fn into_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { vm.ctx.new_bool(self) @@ -20,7 +18,7 @@ impl IntoPyObject for bool { impl TryFromObject for bool { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - if pytype::isinstance(&obj, &vm.ctx.types.int_type) { + if obj.isinstance(&vm.ctx.types.int_type) { Ok(get_value(&obj)) } else { Err(vm.new_type_error(format!("Expected type bool, not {}", obj.class().name))) @@ -41,7 +39,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { // If descriptor returns Error, propagate it further let method = method_or_err?; let bool_obj = vm.invoke(&method, ())?; - if !pytype::isinstance(&bool_obj, &vm.ctx.types.bool_type) { + if !bool_obj.isinstance(&vm.ctx.types.bool_type) { return Err(vm.new_type_error(format!( "__bool__ should return bool, returned type {}", bool_obj.class().name @@ -79,7 +77,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { /// 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)] -pub(crate) struct PyBool; +pub struct PyBool; #[pyimpl] impl PyBool { @@ -100,9 +98,7 @@ impl PyBool { #[pymethod(name = "__ror__")] #[pymethod(magic)] fn or(lhs: PyObjectRef, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - if pytype::isinstance(&lhs, &vm.ctx.types.bool_type) - && pytype::isinstance(&rhs, &vm.ctx.types.bool_type) - { + if lhs.isinstance(&vm.ctx.types.bool_type) && rhs.isinstance(&vm.ctx.types.bool_type) { let lhs = get_value(&lhs); let rhs = get_value(&rhs); (lhs || rhs).into_pyobject(vm) @@ -114,9 +110,7 @@ impl PyBool { #[pymethod(name = "__rand__")] #[pymethod(magic)] fn and(lhs: PyObjectRef, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - if pytype::isinstance(&lhs, &vm.ctx.types.bool_type) - && pytype::isinstance(&rhs, &vm.ctx.types.bool_type) - { + if lhs.isinstance(&vm.ctx.types.bool_type) && rhs.isinstance(&vm.ctx.types.bool_type) { let lhs = get_value(&lhs); let rhs = get_value(&rhs); (lhs && rhs).into_pyobject(vm) @@ -128,9 +122,7 @@ impl PyBool { #[pymethod(name = "__rxor__")] #[pymethod(magic)] fn xor(lhs: PyObjectRef, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef { - if pytype::isinstance(&lhs, &vm.ctx.types.bool_type) - && pytype::isinstance(&rhs, &vm.ctx.types.bool_type) - { + if lhs.isinstance(&vm.ctx.types.bool_type) && rhs.isinstance(&vm.ctx.types.bool_type) { let lhs = get_value(&lhs); let rhs = get_value(&rhs); (lhs ^ rhs).into_pyobject(vm) @@ -141,7 +133,7 @@ impl PyBool { #[pyslot] fn tp_new(zelf: PyObjectRef, x: OptionalArg, vm: &VirtualMachine) -> PyResult { - if !pytype::isinstance(&zelf, &vm.ctx.types.type_type) { + if !zelf.isinstance(&vm.ctx.types.type_type) { let actual_type = &zelf.class().name; return Err(vm.new_type_error(format!( "requires a 'type' object but received a '{}'", @@ -160,14 +152,14 @@ pub(crate) fn init(context: &PyContext) { PyBool::extend_class(context, &context.types.bool_type); } -pub fn not(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { - if pytype::isinstance(obj, &vm.ctx.types.bool_type) { - let value = get_value(obj); - Ok(!value) - } else { - Err(vm.new_type_error(format!("Can only invert a bool, on {:?}", obj))) - } -} +// pub fn not(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { +// if obj.isinstance(&vm.ctx.types.bool_type) { +// let value = get_value(obj); +// Ok(!value) +// } else { +// Err(vm.new_type_error(format!("Can only invert a bool, on {:?}", obj))) +// } +// } // Retrieve inner int value: pub fn get_value(obj: &PyObjectRef) -> bool { diff --git a/vm/src/builtins/pystr.rs b/vm/src/builtins/pystr.rs index 022bb6027..7c12d8752 100644 --- a/vm/src/builtins/pystr.rs +++ b/vm/src/builtins/pystr.rs @@ -16,7 +16,7 @@ use super::bytes::{PyBytes, PyBytesRef}; use super::dict::PyDict; use super::int::{PyInt, PyIntRef}; use super::iter; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use crate::anystr::{self, adjust_indices, AnyStr, AnyStrContainer, AnyStrWrapper}; use crate::exceptions::IntoPyException; use crate::format::{FormatSpec, FormatString, FromTemplate}; @@ -241,7 +241,7 @@ impl PyStr { #[pymethod(name = "__add__")] fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if pytype::isinstance(&other, &vm.ctx.types.str_type) { + if other.isinstance(&vm.ctx.types.str_type) { Ok(self.value.py_add(borrow_value(&other))) } else { Err(vm.new_type_error(format!("Cannot add {} and {}", self, other))) diff --git a/vm/src/builtins/pysuper.rs b/vm/src/builtins/pysuper.rs index b851e3717..17782a3a3 100644 --- a/vm/src/builtins/pysuper.rs +++ b/vm/src/builtins/pysuper.rs @@ -7,7 +7,7 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/ */ use super::pystr::PyStrRef; -use super::pytype::{self, PyType, PyTypeRef}; +use super::pytype::{PyType, PyTypeRef}; use crate::function::OptionalArg; use crate::pyobject::{ BorrowValue, IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, @@ -17,8 +17,6 @@ use crate::scope::NameProtocol; use crate::slots::{SlotDescriptor, SlotGetattro}; use crate::vm::VirtualMachine; -pub type PySuperRef = PyRef; - #[pyclass(module = false, name = "super")] #[derive(Debug)] pub struct PySuper { @@ -59,7 +57,7 @@ impl PySuper { py_type: OptionalArg, py_obj: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { // Get the type: let typ = if let OptionalArg::Present(ty) = py_type { ty @@ -77,7 +75,7 @@ impl PySuper { }; // Check type argument: - if !pytype::isinstance(typ.as_object(), &vm.ctx.types.type_type) { + if !typ.as_object().isinstance(&vm.ctx.types.type_type) { return Err(vm.new_type_error(format!( "super() argument 1 must be type, not {}", typ.class().name @@ -159,16 +157,16 @@ impl SlotDescriptor for PySuper { fn supercheck(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { if let Ok(cls) = obj.clone().downcast::() { - if pytype::issubclass(&cls, &ty) { + if cls.issubclass(&ty) { return Ok(cls); } } - if pytype::isinstance(&obj, &ty) { + if obj.isinstance(&ty) { return Ok(obj.clone_class()); } let class_attr = vm.get_attribute(obj, "__class__")?; if let Ok(cls) = class_attr.downcast::() { - if !cls.is(&ty) && pytype::issubclass(&cls, &ty) { + if !cls.is(&ty) && cls.issubclass(&ty) { return Ok(cls); } } diff --git a/vm/src/builtins/pytype.rs b/vm/src/builtins/pytype.rs index 440a2db04..dbd2396cc 100644 --- a/vm/src/builtins/pytype.rs +++ b/vm/src/builtins/pytype.rs @@ -199,6 +199,10 @@ impl PyType { } impl PyTypeRef { + pub fn issubclass(&self, cls: R) -> bool { + self._issubclass(cls) + } + pub fn iter_mro(&self) -> impl Iterator + DoubleEndedIterator { std::iter::once(self).chain(self.mro.iter()) } @@ -254,12 +258,12 @@ impl PyType { #[pymethod(magic)] fn instancecheck(zelf: PyRef, obj: PyObjectRef) -> bool { - isinstance(&obj, &zelf) + obj.isinstance(&zelf) } #[pymethod(magic)] fn subclasscheck(zelf: PyRef, subclass: PyTypeRef) -> bool { - issubclass(&subclass, &zelf) + subclass.issubclass(&zelf) } #[pyproperty(magic)] @@ -546,8 +550,7 @@ impl Callable for PyType { vm_trace!("type_call: {:?}", zelf); let obj = call_tp_new(zelf.clone(), zelf.clone(), args.clone(), vm)?; - if (zelf.is(&vm.ctx.types.type_type) && args.kwargs.is_empty()) || !isinstance(&obj, &zelf) - { + if (zelf.is(&vm.ctx.types.type_type) && args.kwargs.is_empty()) || !obj.isinstance(&zelf) { return Ok(obj); } @@ -616,8 +619,24 @@ pub(crate) fn init(ctx: &PyContext) { PyType::extend_class(ctx, &ctx.types.type_type); } +impl PyLease<'_, PyType> { + pub fn issubclass(&self, cls: R) -> bool { + self._issubclass(cls) + } +} + pub trait DerefToPyType { fn deref_to_type(&self) -> &PyType; + + /// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__, + /// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic + /// method. + fn _issubclass(&self, cls: R) -> bool + where + Self: IdProtocol, + { + self.is(&cls) || self.deref_to_type().mro.iter().any(|c| c.is(&cls)) + } } impl DerefToPyType for PyTypeRef { @@ -638,20 +657,6 @@ impl DerefToPyType for &'_ T { } } -/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only -/// use this if `cls` is known to have not overridden the base __instancecheck__ magic method. -#[inline] -pub fn isinstance(obj: &T, cls: &PyTypeRef) -> bool { - issubclass(obj.class(), &cls) -} - -/// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__, -/// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic -/// method. -pub fn issubclass(subclass: T, cls: R) -> bool { - subclass.is(&cls) || subclass.deref_to_type().mro.iter().any(|c| c.is(&cls)) -} - fn call_tp_new( typ: PyTypeRef, subtype: PyTypeRef, @@ -678,7 +683,7 @@ pub fn tp_new_wrapper( args: FuncArgs, vm: &VirtualMachine, ) -> PyResult { - if !issubclass(&cls, &zelf) { + if !cls.issubclass(&zelf) { return Err(vm.new_type_error(format!( "{zelf}.__new__({cls}): {cls} is not a subtype of {zelf}", zelf = zelf.name, @@ -811,9 +816,9 @@ fn calculate_meta_class( let mut winner = metatype; for base in bases { let base_type = base.class(); - if issubclass(&winner, &base_type) { + if winner.issubclass(&base_type) { continue; - } else if issubclass(&base_type, &winner) { + } else if base_type.issubclass(&winner) { winner = PyLease::into_pyref(base_type); continue; } diff --git a/vm/src/builtins/range.rs b/vm/src/builtins/range.rs index 5cb9de106..582e38514 100644 --- a/vm/src/builtins/range.rs +++ b/vm/src/builtins/range.rs @@ -132,7 +132,7 @@ type PyRangeRef = PyRef; #[pyimpl(with(Hashable, Comparable))] impl PyRange { - fn new(cls: PyTypeRef, stop: PyIntRef, vm: &VirtualMachine) -> PyResult { + fn new(cls: PyTypeRef, stop: PyIntRef, vm: &VirtualMachine) -> PyResult> { PyRange { start: (0).into_pyref(vm), stop, @@ -147,7 +147,7 @@ impl PyRange { stop: PyIntRef, step: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { let step = step.unwrap_or_else(|| (1).into_pyref(vm)); if step.borrow_value().is_zero() { return Err(vm.new_value_error("range() arg 3 must not be zero".to_owned())); diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index 430f820c0..3985f3611 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -5,7 +5,7 @@ use rustpython_common::rc::PyRc; use std::fmt; use super::iter; -use super::pytype::{self, PyTypeRef}; +use super::pytype::PyTypeRef; use crate::dictdatatype; use crate::function::{Args, OptionalArg}; use crate::pyobject::{ @@ -38,7 +38,6 @@ pub type PySetRef = PyRef; pub struct PyFrozenSet { inner: PySetInner, } -pub type PyFrozenSetRef = PyRef; impl fmt::Debug for PySet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -321,7 +320,7 @@ impl PySet { cls: PyTypeRef, iterable: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { Self { inner: PySetInner::from_arg(iterable, vm)?, } @@ -554,23 +553,23 @@ macro_rules! multi_args_frozenset { #[pyimpl(flags(BASETYPE), with(Hashable, Comparable))] impl PyFrozenSet { - pub fn from_iter( - vm: &VirtualMachine, - it: impl IntoIterator, - ) -> PyResult { - let inner = PySetInner::default(); - for elem in it { - inner.add(elem, vm)?; - } - Ok(Self { inner }) - } + // pub fn from_iter( + // vm: &VirtualMachine, + // it: impl IntoIterator, + // ) -> PyResult { + // let inner = PySetInner::default(); + // for elem in it { + // inner.add(elem, vm)?; + // } + // Ok(Self { inner }) + // } #[pyslot] fn tp_new( cls: PyTypeRef, iterable: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { Self { inner: PySetInner::from_arg(iterable, vm)?, } @@ -723,8 +722,8 @@ struct SetIterable { impl TryFromObject for SetIterable { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { let class = obj.class(); - if pytype::issubclass(&class, &vm.ctx.types.set_type) - || pytype::issubclass(&class, &vm.ctx.types.frozenset_type) + if class.issubclass(&vm.ctx.types.set_type) + || class.issubclass(&vm.ctx.types.frozenset_type) { // the class lease needs to be drop to be able to return the object drop(class); diff --git a/vm/src/builtins/singletons.rs b/vm/src/builtins/singletons.rs index ce10ff6cb..3880945df 100644 --- a/vm/src/builtins/singletons.rs +++ b/vm/src/builtins/singletons.rs @@ -35,7 +35,7 @@ impl IntoPyObject for Option { #[pyimpl] impl PyNone { #[pyslot] - fn tp_new(_: PyTypeRef, vm: &VirtualMachine) -> PyNoneRef { + fn tp_new(_: PyTypeRef, vm: &VirtualMachine) -> PyRef { vm.ctx.none.clone() } diff --git a/vm/src/builtins/slice.rs b/vm/src/builtins/slice.rs index 46664edea..678c4cdc1 100644 --- a/vm/src/builtins/slice.rs +++ b/vm/src/builtins/slice.rs @@ -94,7 +94,7 @@ impl PySlice { } #[pyslot] - fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { + fn tp_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult> { let slice: PySlice = match args.args.len() { 0 => { return Err( diff --git a/vm/src/builtins/staticmethod.rs b/vm/src/builtins/staticmethod.rs index 2f060d724..6d4adb085 100644 --- a/vm/src/builtins/staticmethod.rs +++ b/vm/src/builtins/staticmethod.rs @@ -8,7 +8,6 @@ use crate::vm::VirtualMachine; pub struct PyStaticMethod { pub callable: PyObjectRef, } -pub type PyStaticMethodRef = PyRef; impl PyValue for PyStaticMethod { fn class(vm: &VirtualMachine) -> PyTypeRef { @@ -37,11 +36,7 @@ impl From for PyStaticMethod { #[pyimpl(with(SlotDescriptor), flags(BASETYPE, HAS_DICT))] impl PyStaticMethod { #[pyslot] - fn tp_new( - cls: PyTypeRef, - callable: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult { + fn tp_new(cls: PyTypeRef, callable: PyObjectRef, vm: &VirtualMachine) -> PyResult> { PyStaticMethod { callable }.into_ref_with_type(vm, cls) } } diff --git a/vm/src/builtins/traceback.rs b/vm/src/builtins/traceback.rs index ec3fd7fd2..046be7d51 100644 --- a/vm/src/builtins/traceback.rs +++ b/vm/src/builtins/traceback.rs @@ -22,7 +22,7 @@ impl PyValue for PyTraceback { #[pyimpl] impl PyTraceback { - pub fn new(next: Option, frame: FrameRef, lasti: usize, lineno: usize) -> Self { + pub fn new(next: Option>, frame: FrameRef, lasti: usize, lineno: usize) -> Self { PyTraceback { next, frame, @@ -47,7 +47,7 @@ impl PyTraceback { } #[pyproperty(name = "tb_next")] - fn next_get(&self) -> Option { + fn next_get(&self) -> Option> { self.next.as_ref().cloned() } } diff --git a/vm/src/builtins/weakproxy.rs b/vm/src/builtins/weakproxy.rs index 7cef00c2b..5130063a7 100644 --- a/vm/src/builtins/weakproxy.rs +++ b/vm/src/builtins/weakproxy.rs @@ -16,8 +16,6 @@ impl PyValue for PyWeakProxy { } } -pub type PyWeakProxyRef = PyRef; - #[pyimpl] impl PyWeakProxy { // TODO: callbacks @@ -27,7 +25,7 @@ impl PyWeakProxy { referent: PyObjectRef, callback: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult> { if callback.is_present() { panic!("Passed a callback to weakproxy, but weakproxy does not yet support proxies."); } diff --git a/vm/src/builtins/weakref.rs b/vm/src/builtins/weakref.rs index 6e63b195b..52927346b 100644 --- a/vm/src/builtins/weakref.rs +++ b/vm/src/builtins/weakref.rs @@ -36,8 +36,6 @@ impl PyValue for PyWeak { } } -pub type PyWeakRef = PyRef; - impl Callable for PyWeak { fn call(zelf: &PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { args.bind::<()>(vm)?; diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index 80b588f5e..054864d78 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -1,4 +1,4 @@ -use crate::builtins::{float, int, pystr, pytype, tuple}; +use crate::builtins::{float, int, pystr, tuple}; /// Implementation of Printf-Style string formatting /// [https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting] use crate::format::get_num_digits; @@ -342,7 +342,7 @@ impl CFormatSpec { } CFormatType::Character => { let ch = { - if pytype::isinstance(&obj, &vm.ctx.types.int_type) { + if obj.isinstance(&vm.ctx.types.int_type) { // BigInt truncation is fine in this case because only the unicode range is relevant int::get_value(&obj) .to_u32() @@ -350,7 +350,7 @@ impl CFormatSpec { .ok_or_else(|| { vm.new_overflow_error("%c arg not in range(0x110000)".to_owned()) }) - } else if pytype::isinstance(&obj, &vm.ctx.types.str_type) { + } else if obj.isinstance(&vm.ctx.types.str_type) { let s = pystr::borrow_value(&obj); let num_chars = s.chars().count(); if num_chars != 1 { @@ -435,7 +435,7 @@ impl CFormatString { Some(CFormatQuantity::FromValuesTuple) => match elements.next() { Some(width_obj) => { tuple_index += 1; - if !pytype::isinstance(&width_obj, &vm.ctx.types.int_type) { + if !width_obj.isinstance(&vm.ctx.types.int_type) { Err(vm.new_type_error("* wants int".to_owned())) } else { let i = int::get_value(&width_obj); @@ -469,16 +469,16 @@ impl CFormatString { .all(|(_, part)| CFormatPart::has_key(part)); let values = if mapping_required { - if !pytype::isinstance(&values_obj, &vm.ctx.types.dict_type) { + if !values_obj.isinstance(&vm.ctx.types.dict_type) { return Err(vm.new_type_error("format requires a mapping".to_owned())); } values_obj.clone() } else { // check for only literal parts, in which case only dict or empty tuple is allowed if num_specifiers == 0 - && !(pytype::isinstance(&values_obj, &vm.ctx.types.tuple_type) + && !(values_obj.isinstance(&vm.ctx.types.tuple_type) && tuple::get_value(&values_obj).is_empty()) - && !pytype::isinstance(&values_obj, &vm.ctx.types.dict_type) + && !values_obj.isinstance(&vm.ctx.types.dict_type) { return Err(vm.new_type_error( "not all arguments converted during string formatting".to_owned(), @@ -486,7 +486,7 @@ impl CFormatString { } // convert `values_obj` to a new tuple if it's not a tuple - if !pytype::isinstance(&values_obj, &vm.ctx.types.tuple_type) { + if !values_obj.isinstance(&vm.ctx.types.tuple_type) { vm.ctx.new_tuple(vec![values_obj.clone()]) } else { values_obj.clone() @@ -542,7 +542,7 @@ impl CFormatString { // check that all arguments were converted if (!mapping_required && tuple::get_value(&values).get(tuple_index).is_some()) - && !pytype::isinstance(&values_obj, &vm.ctx.types.dict_type) + && !values_obj.isinstance(&vm.ctx.types.dict_type) { return Err(vm.new_type_error( "not all arguments converted during string formatting".to_owned(), diff --git a/vm/src/coroutine.rs b/vm/src/coroutine.rs index c190544f6..dc119f07c 100644 --- a/vm/src/coroutine.rs +++ b/vm/src/coroutine.rs @@ -1,7 +1,7 @@ -use crate::builtins::pytype::{self, PyTypeRef}; +use crate::builtins::pytype::PyTypeRef; use crate::exceptions::{self, PyBaseExceptionRef}; use crate::frame::{ExecutionResult, FrameRef}; -use crate::pyobject::{PyObjectRef, PyResult}; +use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use crate::common::lock::PyRwLock; @@ -98,13 +98,13 @@ impl Coro { match result { Ok(exec_res) => self.variant.exec_result(exec_res, vm), Err(e) => { - if pytype::isinstance(&e, &vm.ctx.exceptions.stop_iteration) { + if e.isinstance(&vm.ctx.exceptions.stop_iteration) { let err = vm .new_runtime_error(format!("{} raised StopIteration", self.variant.name())); err.set_cause(Some(e)); Err(err) } else if self.variant == Variant::AsyncGen - && pytype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration) + && e.isinstance(&vm.ctx.exceptions.stop_async_iteration) { let err = vm .new_runtime_error("async generator raised StopAsyncIteration".to_owned()); @@ -171,5 +171,5 @@ impl Coro { } pub fn is_gen_exit(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> bool { - pytype::isinstance(exc, &vm.ctx.exceptions.generator_exit) + exc.isinstance(&vm.ctx.exceptions.generator_exit) } diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 7ddb94c22..e27f14f18 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -1,5 +1,5 @@ use crate::builtins::pystr::{PyStr, PyStrRef}; -use crate::builtins::pytype::{self, PyType, PyTypeRef}; +use crate::builtins::pytype::{PyType, PyTypeRef}; use crate::builtins::singletons::{PyNone, PyNoneRef}; use crate::builtins::traceback::PyTracebackRef; use crate::builtins::tuple::{PyTuple, PyTupleRef}; @@ -303,7 +303,7 @@ impl TryFromObject for ExceptionCtor { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { obj.downcast::() .and_then(|cls| { - if pytype::issubclass(&cls, &vm.ctx.exceptions.base_exception_type) { + if cls.issubclass(&vm.ctx.exceptions.base_exception_type) { Ok(Self::Class(cls)) } else { Err(cls.into_object()) @@ -352,7 +352,7 @@ impl ExceptionCtor { // if the "type" is an instance and the value isn't, use the "type" (Self::Instance(exc), None) => Ok(exc), // if the value is an instance of the type, use the instance value - (Self::Class(cls), Some(exc)) if pytype::isinstance(&exc, &cls) => Ok(exc), + (Self::Class(cls), Some(exc)) if exc.isinstance(&cls) => Ok(exc), // otherwise; construct an exception of the type using the value as args (Self::Class(cls), _) => { let args = match_class!(match value { diff --git a/vm/src/format.rs b/vm/src/format.rs index 5ee0516e6..9b0a6a0a0 100644 --- a/vm/src/format.rs +++ b/vm/src/format.rs @@ -1,4 +1,4 @@ -use crate::builtins::{pystr, pytype}; +use crate::builtins::pystr; use crate::exceptions::{IntoPyException, PyBaseExceptionRef}; use crate::function::FuncArgs; use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TypeProtocol}; @@ -901,7 +901,7 @@ fn call_object_format( None => argument, }; let result = vm.call_method(&argument, "__format__", (format_spec,))?; - if !pytype::isinstance(&result, &vm.ctx.types.str_type) { + if !result.isinstance(&vm.ctx.types.str_type) { return Err(vm.new_type_error(format!( "__format__ must return a str, not {}", &result.class().name diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 092540390..1ce361f5f 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -4,14 +4,14 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use indexmap::IndexMap; use itertools::Itertools; +use crate::builtins; use crate::builtins::asyncgenerator::PyAsyncGenWrappedValue; -use crate::builtins::builtin_isinstance; use crate::builtins::code::PyCodeRef; use crate::builtins::coroutine::PyCoroutine; use crate::builtins::dict::{PyDict, PyDictRef}; use crate::builtins::generator::PyGenerator; use crate::builtins::pystr::{self, PyStr, PyStrRef}; -use crate::builtins::pytype::{self, PyTypeRef}; +use crate::builtins::pytype::PyTypeRef; use crate::builtins::slice::PySlice; use crate::builtins::traceback::PyTraceback; use crate::builtins::tuple::PyTuple; @@ -116,7 +116,7 @@ impl ExecutionResult { match res { Ok(val) => Ok(ExecutionResult::Yield(val)), Err(err) => { - if pytype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { + if err.isinstance(&vm.ctx.exceptions.stop_iteration) { iter::stop_iter_value(vm, &err).map(ExecutionResult::Return) } else { Err(err) @@ -725,7 +725,7 @@ impl ExecutingFrame<'_> { let value = match conversion { Some(Str) => vm.to_str(&self.pop_value())?.into_object(), Some(Repr) => vm.to_repr(&self.pop_value())?.into_object(), - Some(Ascii) => vm.to_ascii(&self.pop_value())?, + Some(Ascii) => vm.ctx.new_str(builtins::ascii(self.pop_value(), vm)?), None => self.pop_value(), }; @@ -1421,7 +1421,7 @@ impl ExecutingFrame<'_> { bytecode::ComparisonOperator::In => vm.ctx.new_bool(self._in(vm, a, b)?), bytecode::ComparisonOperator::NotIn => vm.ctx.new_bool(self._not_in(vm, a, b)?), bytecode::ComparisonOperator::ExceptionMatch => { - vm.ctx.new_bool(builtin_isinstance(a, b, vm)?) + vm.ctx.new_bool(builtins::isinstance(a, b, vm)?) } }; diff --git a/vm/src/function.rs b/vm/src/function.rs index 5262940e6..593242752 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -1,5 +1,5 @@ use self::OptionalArg::*; -use crate::builtins::pytype::{isinstance, PyTypeRef}; +use crate::builtins::pytype::PyTypeRef; use crate::builtins::tuple::PyTupleRef; use crate::exceptions::PyBaseExceptionRef; use crate::pyobject::{ @@ -140,7 +140,7 @@ impl FuncArgs { ) -> PyResult> { match self.get_optional_kwarg(key) { Some(kwarg) => { - if isinstance(&kwarg, &ty) { + if kwarg.isinstance(&ty) { Ok(Some(kwarg)) } else { let expected_ty_name = &ty.name; diff --git a/vm/src/import.rs b/vm/src/import.rs index 87fd0c3c0..553f477ff 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -4,10 +4,10 @@ use rand::Rng; use crate::builtins::traceback::{PyTraceback, PyTracebackRef}; -use crate::builtins::{code, list, pytype}; +use crate::builtins::{code, list}; use crate::bytecode::CodeObject; use crate::exceptions::PyBaseExceptionRef; -use crate::pyobject::{ItemProtocol, PyResult, PyValue, TryFromObject}; +use crate::pyobject::{ItemProtocol, PyResult, PyValue, TryFromObject, TypeProtocol}; use crate::scope::Scope; use crate::version::get_git_revision; use crate::vm::{InitParameter, VirtualMachine}; @@ -174,7 +174,7 @@ pub fn remove_importlib_frames( vm: &VirtualMachine, exc: &PyBaseExceptionRef, ) -> PyBaseExceptionRef { - let always_trim = pytype::isinstance(exc, &vm.ctx.exceptions.import_error); + let always_trim = exc.isinstance(&vm.ctx.exceptions.import_error); if let Some(tb) = exc.traceback() { let trimmed_tb = remove_importlib_frames_inner(vm, Some(tb), always_trim).0; diff --git a/vm/src/py_serde.rs b/vm/src/py_serde.rs index c4feb6310..3345d90e0 100644 --- a/vm/src/py_serde.rs +++ b/vm/src/py_serde.rs @@ -3,9 +3,7 @@ use num_traits::sign::Signed; use serde::de::{DeserializeSeed, Visitor}; use serde::ser::{Serialize, SerializeMap, SerializeSeq}; -use crate::builtins::{ - dict::PyDictRef, float, int, list::PyList, pybool, pystr, pytype, tuple::PyTuple, -}; +use crate::builtins::{dict::PyDictRef, float, int, list::PyList, pybool, pystr, tuple::PyTuple}; use crate::pyobject::{BorrowValue, ItemProtocol, PyObjectRef, TypeProtocol}; use crate::VirtualMachine; @@ -65,13 +63,13 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> { } seq.end() }; - if pytype::isinstance(self.pyobject, &self.vm.ctx.types.str_type) { + if self.pyobject.isinstance(&self.vm.ctx.types.str_type) { serializer.serialize_str(pystr::borrow_value(&self.pyobject)) - } else if pytype::isinstance(self.pyobject, &self.vm.ctx.types.float_type) { + } else if self.pyobject.isinstance(&self.vm.ctx.types.float_type) { serializer.serialize_f64(float::get_value(self.pyobject)) - } else if pytype::isinstance(self.pyobject, &self.vm.ctx.types.bool_type) { + } else if self.pyobject.isinstance(&self.vm.ctx.types.bool_type) { serializer.serialize_bool(pybool::get_value(self.pyobject)) - } else if pytype::isinstance(self.pyobject, &self.vm.ctx.types.int_type) { + } else if self.pyobject.isinstance(&self.vm.ctx.types.int_type) { let v = int::get_value(self.pyobject); let int_too_large = || serde::ser::Error::custom("int too large to serialize"); // TODO: serialize BigInt when it does not fit into i64 @@ -87,7 +85,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> { serialize_seq_elements(serializer, &list.borrow_value()) } else if let Some(tuple) = self.pyobject.payload_if_subclass::(self.vm) { serialize_seq_elements(serializer, tuple.borrow_value()) - } else if pytype::isinstance(self.pyobject, &self.vm.ctx.types.dict_type) { + } else if self.pyobject.isinstance(&self.vm.ctx.types.dict_type) { let dict: PyDictRef = self.pyobject.clone().downcast().unwrap(); let pairs: Vec<_> = dict.into_iter().collect(); let mut map = serializer.serialize_map(Some(pairs.len()))?; diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 3d25dd635..3788a0562 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -8,7 +8,7 @@ use num_bigint::BigInt; use num_complex::Complex64; use num_traits::ToPrimitive; -use crate::builtins::builtinfunc::PyFuncDef; +use crate::builtins::builtinfunc::PyNativeFuncDef; use crate::builtins::bytearray; use crate::builtins::bytes; use crate::builtins::code; @@ -144,7 +144,7 @@ impl PyContext { ); let tp_new_wrapper = create_object( - PyFuncDef::from(pytype::tp_new_wrapper.into_func()).into_function(), + PyNativeFuncDef::from(pytype::tp_new_wrapper.into_func()).into_function(), &types.builtin_function_or_method_type, ) .into_object(); @@ -281,18 +281,18 @@ impl PyContext { where F: IntoPyNativeFunc, { - PyFuncDef::from(f.into_func()).build_function(self) + PyNativeFuncDef::from(f.into_func()).build_function(self) } pub(crate) fn new_stringref(&self, s: String) -> pystr::PyStrRef { PyRef::new_ref(pystr::PyStr::from(s), self.types.str_type.clone(), None) } - pub fn new_function_named(&self, f: F, name: String) -> PyFuncDef + pub fn new_function_named(&self, f: F, name: String) -> PyNativeFuncDef where F: IntoPyNativeFunc, { - let mut f = PyFuncDef::from(f.into_func()); + let mut f = PyNativeFuncDef::from(f.into_func()); f.name = Some(self.new_stringref(name)); f } @@ -301,14 +301,14 @@ impl PyContext { where F: IntoPyNativeFunc, { - PyFuncDef::from(f.into_func()).build_method(self) + PyNativeFuncDef::from(f.into_func()).build_method(self) } pub fn new_classmethod(&self, f: F) -> PyObjectRef where F: IntoPyNativeFunc, { - PyFuncDef::from(f.into_func()).build_classmethod(self) + PyNativeFuncDef::from(f.into_func()).build_classmethod(self) } pub fn new_staticmethod(&self, f: F) -> PyObjectRef where @@ -580,7 +580,7 @@ where T: PyValue, { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - if pytype::isinstance(&obj, &T::class(vm)) { + if obj.isinstance(&T::class(vm)) { PyRef::from_obj(obj, vm) } else { let class = T::class(vm); @@ -736,6 +736,13 @@ pub trait TypeProtocol { fn has_class_attr(&self, attr_name: &str) -> bool { self.class().has_attr(attr_name) } + + /// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only + /// use this if `cls` is known to have not overridden the base __instancecheck__ magic method. + #[inline] + fn isinstance(&self, cls: &PyTypeRef) -> bool { + self.class().issubclass(cls) + } } impl TypeProtocol for PyObjectRef { @@ -857,7 +864,7 @@ where match self.vm.call_method(&self.obj, "__next__", ()) { Ok(value) => Some(T::try_from_object(self.vm, value)), Err(err) => { - if pytype::isinstance(&err, &self.vm.ctx.exceptions.stop_iteration) { + if err.isinstance(&self.vm.ctx.exceptions.stop_iteration) { None } else { Some(Err(err)) @@ -1073,7 +1080,7 @@ impl PyObject { &self, vm: &VirtualMachine, ) -> Option<&T> { - if pytype::issubclass(self.class(), &T::class(vm)) { + if self.class().issubclass(&T::class(vm)) { self.payload() } else { None @@ -1122,7 +1129,7 @@ pub trait PyValue: fmt::Debug + PyThreadingConstraint + Sized + 'static { fn into_ref_with_type(self, vm: &VirtualMachine, cls: PyTypeRef) -> PyResult> { let class = Self::class(vm); - if pytype::issubclass(&cls, &class) { + if cls.issubclass(&class) { Ok(self.into_ref_with_type_unchecked(cls, vm)) } else { let subtype = vm.to_str(&cls.obj)?; diff --git a/vm/src/stdlib/functools.rs b/vm/src/stdlib/functools.rs index b9288512a..093edc651 100644 --- a/vm/src/stdlib/functools.rs +++ b/vm/src/stdlib/functools.rs @@ -3,9 +3,8 @@ pub(crate) use _functools::make_module; #[pymodule] mod _functools { use crate::builtins::iter; - use crate::builtins::pytype; use crate::function::OptionalArg; - use crate::pyobject::{PyObjectRef, PyResult}; + use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; #[pyfunction] @@ -21,7 +20,7 @@ mod _functools { val } else { iter::call_next(vm, &iterator).map_err(|err| { - if pytype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { + if err.isinstance(&vm.ctx.exceptions.stop_iteration) { let exc_type = vm.ctx.exceptions.type_error.clone(); vm.new_exception_msg( exc_type, diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 1e9eb436f..02355d052 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -21,12 +21,10 @@ mod _io { use crate::builtins::bytes::PyBytesRef; use crate::builtins::int; use crate::builtins::iter; - use crate::builtins::memory::{ - Buffer, BufferOptions, BufferRef, PyMemoryView, PyMemoryViewRef, - }; + use crate::builtins::memory::{Buffer, BufferOptions, BufferRef, PyMemoryView}; use crate::builtins::pybool; use crate::builtins::pystr::{self, PyStr, PyStrRef}; - use crate::builtins::pytype::{self, PyTypeRef}; + use crate::builtins::pytype::PyTypeRef; use crate::byteslike::{PyBytesLike, PyRwBytesLike}; use crate::common::borrow::{BorrowedValue, BorrowedValueMut}; use crate::common::lock::{ @@ -36,7 +34,7 @@ mod _io { use crate::function::{FuncArgs, OptionalArg, OptionalOption}; use crate::pyobject::{ BorrowValue, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, - TryFromObject, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -728,7 +726,7 @@ mod _io { let buffered_reader_class = vm.try_class("_io", "BufferedReader")?; let raw = vm.get_attribute(instance, "buffer").unwrap(); - if !pytype::isinstance(&raw, &buffered_reader_class) { + if !raw.isinstance(&buffered_reader_class) { // TODO: this should be io.UnsupportedOperation error which derives both from ValueError *and* OSError return Err(vm.new_value_error("not readable".to_owned())); } @@ -752,7 +750,7 @@ mod _io { let buffered_writer_class = vm.try_class("_io", "BufferedWriter")?; let raw = vm.get_attribute(instance, "buffer").unwrap(); - if !pytype::isinstance(&raw, &buffered_writer_class) { + if !raw.isinstance(&buffered_writer_class) { // TODO: this should be io.UnsupportedOperation error which derives from ValueError and OSError return Err(vm.new_value_error("not writable".to_owned())); } @@ -779,7 +777,7 @@ mod _io { let buffered_reader_class = vm.try_class("_io", "BufferedReader")?; let raw = vm.get_attribute(instance, "buffer").unwrap(); - if !pytype::isinstance(&raw, &buffered_reader_class) { + if !raw.isinstance(&buffered_reader_class) { // TODO: this should be io.UnsupportedOperation error which derives both from ValueError *and* OSError return Err(vm.new_value_error("not readable".to_owned())); } @@ -1076,12 +1074,12 @@ mod _io { } #[pymethod] - fn getbuffer(self, vm: &VirtualMachine) -> PyResult { + fn getbuffer(self, vm: &VirtualMachine) -> PyResult { let buffer: Box = Box::new(self.clone()); let buffer = BufferRef::from(buffer); let view = PyMemoryView::from_buffer(self.clone().into_object(), buffer, vm)?; self.exports.fetch_add(1); - Ok(view.into_ref(vm)) + Ok(view) } } diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index d6115ba60..f95364780 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -13,7 +13,7 @@ mod decl { call_next, get_all, get_iter, get_next_object, new_stop_iteration, }; use crate::builtins::pybool; - use crate::builtins::pytype::{self, PyTypeRef}; + use crate::builtins::pytype::PyTypeRef; use crate::builtins::tuple::PyTupleRef; use crate::common::lock::{PyMutex, PyRwLock, PyRwLockWriteGuard}; use crate::common::rc::PyRc; @@ -74,7 +74,7 @@ mod decl { match call_next(vm, &cur_iter) { Ok(ok) => return Ok(ok), Err(err) => { - if pytype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { + if err.isinstance(&vm.ctx.exceptions.stop_iteration) { self.cur_idx.fetch_add(1); *self.cached_iter.write() = None; } else { @@ -698,7 +698,7 @@ mod decl { } fn pyobject_to_opt_usize(obj: PyObjectRef, vm: &VirtualMachine) -> Option { - let is_int = pytype::isinstance(&obj, &vm.ctx.types.int_type); + let is_int = obj.isinstance(&vm.ctx.types.int_type); if is_int { int::get_value(&obj).to_usize() } else { @@ -1524,7 +1524,7 @@ mod decl { let next_obj = match call_next(vm, &self.iterators[idx]) { Ok(obj) => obj, Err(err) => { - if !pytype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { + if !err.isinstance(&vm.ctx.exceptions.stop_iteration) { return Err(err); } numactive -= 1; diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index 45fffe56c..883c08ce0 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -3,15 +3,13 @@ * */ +use num_bigint::BigInt; +use num_traits::{One, Signed, Zero}; use statrs::function::erf::{erf, erfc}; use statrs::function::gamma::{gamma, ln_gamma}; -use num_bigint::BigInt; -use num_traits::{One, Signed, Zero}; - use crate::builtins::float::{self, IntoPyFloat, PyFloatRef}; use crate::builtins::int::{self, PyInt, PyIntRef}; -use crate::builtins::pytype; use crate::function::{Args, OptionalArg}; use crate::pyobject::{BorrowValue, Either, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; @@ -265,7 +263,7 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { /// * `value` - Either a float or a python object which implements __ceil__ /// * `vm` - Represents the python state. fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if pytype::isinstance(&value, &vm.ctx.types.float_type) { + if value.isinstance(&vm.ctx.types.float_type) { let v = float::get_value(&value); let v = float::try_bigint(v.ceil(), vm)?; Ok(vm.ctx.new_int(v)) @@ -281,7 +279,7 @@ fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { /// * `value` - Either a float or a python object which implements __ceil__ /// * `vm` - Represents the python state. fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if pytype::isinstance(&value, &vm.ctx.types.float_type) { + if value.isinstance(&vm.ctx.types.float_type) { let v = float::get_value(&value); let v = float::try_bigint(v.floor(), vm)?; Ok(vm.ctx.new_int(v)) diff --git a/vm/src/stdlib/operator.rs b/vm/src/stdlib/operator.rs index 14dea746e..5dbe8339d 100644 --- a/vm/src/stdlib/operator.rs +++ b/vm/src/stdlib/operator.rs @@ -1,5 +1,5 @@ +use crate::builtins::iter; use crate::builtins::pystr::PyStrRef; -use crate::builtins::{iter, pytype}; use crate::byteslike::PyBytesLike; use crate::function::OptionalArg; use crate::pyobject::{BorrowValue, Either, PyObjectRef, PyResult, TypeProtocol}; @@ -8,7 +8,7 @@ use volatile::Volatile; fn _operator_length_hint(obj: PyObjectRef, default: OptionalArg, vm: &VirtualMachine) -> PyResult { let default = default.unwrap_or_else(|| vm.ctx.new_int(0)); - if !pytype::isinstance(&default, &vm.ctx.types.int_type) { + if !default.isinstance(&vm.ctx.types.int_type) { return Err(vm.new_type_error(format!( "'{}' type cannot be interpreted as an integer", default.class().name diff --git a/vm/src/stdlib/warnings.rs b/vm/src/stdlib/warnings.rs index 65324ecac..4a9059b8e 100644 --- a/vm/src/stdlib/warnings.rs +++ b/vm/src/stdlib/warnings.rs @@ -3,7 +3,7 @@ pub(crate) use _warnings::make_module; #[pymodule] mod _warnings { use crate::builtins::pystr::PyStrRef; - use crate::builtins::pytype::{self, PyTypeRef}; + use crate::builtins::pytype::PyTypeRef; use crate::function::OptionalArg; use crate::pyobject::{PyResult, TypeProtocol}; use crate::vm::VirtualMachine; @@ -23,7 +23,7 @@ mod _warnings { // TODO: Implement correctly let level = args.stacklevel.unwrap_or(1); let category = if let OptionalArg::Present(category) = args.category { - if !pytype::issubclass(&category, &vm.ctx.exceptions.warning) { + if !category.issubclass(&vm.ctx.exceptions.warning) { return Err(vm.new_type_error(format!( "category must be a Warning subclass, not '{}'", category.class().name diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index 574f296ad..3908eebf0 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -250,7 +250,7 @@ fn sys_displayhook(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { vm.set_attr(&vm.builtins, "_", vm.ctx.none())?; // TODO: catch encoding errors let repr = vm.to_repr(&obj)?.into_object(); - builtins::builtin_print(Args::new(vec![repr]), Default::default(), vm)?; + builtins::print(Args::new(vec![repr]), Default::default(), vm)?; vm.set_attr(&vm.builtins, "_", obj)?; Ok(()) } diff --git a/vm/src/types.rs b/vm/src/types.rs index c83b88633..c4279b0de 100644 --- a/vm/src/types.rs +++ b/vm/src/types.rs @@ -267,7 +267,7 @@ fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef) { mro: vec![], subclasses: PyRwLock::default(), attributes: PyRwLock::new(PyAttributes::new()), - slots: pytype::PyType::make_slots(), + slots: PyType::make_slots(), }; let object_payload = PyType { name: object::PyBaseObject::NAME.to_owned(), diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 29cb39da0..79951b938 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -13,6 +13,7 @@ use arr_macro::arr; use crossbeam_utils::atomic::AtomicCell; use num_traits::{Signed, ToPrimitive}; +use crate::builtins; use crate::builtins::code::{PyCode, PyCodeRef}; use crate::builtins::dict::PyDictRef; use crate::builtins::int::{PyInt, PyIntRef}; @@ -22,9 +23,8 @@ use crate::builtins::module::{self, PyModule}; use crate::builtins::object; use crate::builtins::pybool; use crate::builtins::pystr::{PyStr, PyStrRef}; -use crate::builtins::pytype::{self, PyTypeRef}; +use crate::builtins::pytype::PyTypeRef; use crate::builtins::tuple::PyTuple; -use crate::builtins::{self, to_ascii}; use crate::bytecode; use crate::common::{hash::HashSecret, lock::PyMutex, rc::PyRc}; use crate::exceptions::{self, PyBaseException, PyBaseExceptionRef}; @@ -71,7 +71,7 @@ pub struct VirtualMachine { } pub(crate) mod thread { - use super::{PyObjectRef, VirtualMachine}; + use super::{PyObjectRef, TypeProtocol, VirtualMachine}; use itertools::Itertools; use std::cell::RefCell; use std::ptr::NonNull; @@ -97,7 +97,7 @@ pub(crate) mod thread { let vm_owns_obj = |intp: NonNull| { // SAFETY: all references in VM_STACK should be valid let vm = unsafe { intp.as_ref() }; - crate::builtins::pytype::isinstance(obj, &vm.ctx.types.object_type) + obj.isinstance(&vm.ctx.types.object_type) }; VM_STACK.with(|vms| { let intp = match vms.borrow().iter().copied().exactly_one() { @@ -418,7 +418,7 @@ impl VirtualMachine { for (func, args) in self.state.atexit_funcs.lock().drain(..).rev() { if let Err(e) = self.invoke(&func, args) { last_exc = Some(e.clone()); - if !pytype::isinstance(&e, &self.ctx.exceptions.system_exit) { + if !e.isinstance(&self.ctx.exceptions.system_exit) { writeln!(sysmodule::PyStderr(self), "Error in atexit._run_exitfuncs:"); exceptions::print_exception(self, e); } @@ -770,13 +770,6 @@ impl VirtualMachine { TryFromObject::try_from_object(self, repr) } - pub fn to_ascii(&self, obj: &PyObjectRef) -> PyResult { - let repr = self.call_method(obj, "__repr__", ())?; - let repr: PyStrRef = TryFromObject::try_from_object(self, repr)?; - let ascii = to_ascii(repr.borrow_value()); - Ok(self.ctx.new_str(ascii)) - } - pub fn to_index(&self, obj: &PyObjectRef) -> Option> { Some( if let Ok(val) = TryFromObject::try_from_object(self, obj.clone()) { @@ -1434,7 +1427,7 @@ impl VirtualMachine { let is_strict_subclass = { let v_class = v.class(); let w_class = w.class(); - !v_class.is(&w_class) && pytype::issubclass(&w_class, &v_class) + !v_class.is(&w_class) && w_class.issubclass(&v_class) }; if is_strict_subclass { let res = call_cmp(w, v, swapped)?; diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index b311847e3..4ce453a99 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -3,11 +3,12 @@ use wasm_bindgen::{closure::Closure, prelude::*, JsCast}; use rustpython_compiler::error::{CompileError, CompileErrorType}; use rustpython_parser::error::ParseErrorType; -use rustpython_vm::builtins::isinstance; use rustpython_vm::byteslike::PyBytesLike; use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::FuncArgs; -use rustpython_vm::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue, TryFromObject}; +use rustpython_vm::pyobject::{ + ItemProtocol, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol, +}; use rustpython_vm::VirtualMachine; use rustpython_vm::{exceptions, py_serde}; @@ -67,7 +68,7 @@ pub fn js_err_to_py_err(vm: &VirtualMachine, js_err: &JsValue) -> PyBaseExceptio pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue { if let Some(ref wasm_id) = vm.wasm_id { - if isinstance(&py_obj, &vm.ctx.types.function_type) { + if py_obj.isinstance(&vm.ctx.types.function_type) { let wasm_vm = WASMVirtualMachine { id: wasm_id.clone(), };