diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 48fa0ce7a..a78a286b8 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -3,7 +3,8 @@ use crate::obj::objsequence; use crate::obj::objtuple::{PyTuple, PyTupleRef}; use crate::obj::objtype; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{create_type, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::types::create_type; use crate::vm::VirtualMachine; use itertools::Itertools; use std::fs::File; diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 766ece06f..0f66f7f8b 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -68,6 +68,7 @@ pub mod scope; pub mod stdlib; mod sysmodule; mod traceback; +pub mod types; pub mod util; mod version; mod vm; diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 6988028ea..68e122e21 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -66,7 +66,7 @@ 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."; - let bool_type = &context.bool_type; + let bool_type = &context.types.bool_type; extend_class!(context, bool_type, { "__new__" => context.new_rustfunc(bool_new), "__repr__" => context.new_rustfunc(bool_repr), diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index 51d608b09..c3d722ea7 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -78,14 +78,14 @@ impl PyValue for PyByteArray { /// Fill bytearray class methods dictionary. pub fn init(context: &PyContext) { - PyByteArrayRef::extend_class(context, &context.bytearray_type); - let bytearray_type = &context.bytearray_type; + PyByteArrayRef::extend_class(context, &context.types.bytearray_type); + let bytearray_type = &context.types.bytearray_type; extend_class!(context, bytearray_type, { "fromhex" => context.new_rustfunc(PyByteArrayRef::fromhex), "maketrans" => context.new_rustfunc(PyByteInner::maketrans), }); - PyByteArrayIterator::extend_class(context, &context.bytearrayiterator_type); + PyByteArrayIterator::extend_class(context, &context.types.bytearrayiterator_type); } #[pyimpl] diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index c67a044b2..c39b3203d 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -85,14 +85,14 @@ pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref> + 'a } pub fn init(context: &PyContext) { - PyBytesRef::extend_class(context, &context.bytes_type); - let bytes_type = &context.bytes_type; + PyBytesRef::extend_class(context, &context.types.bytes_type); + let bytes_type = &context.types.bytes_type; extend_class!(context, bytes_type, { "fromhex" => context.new_rustfunc(PyBytesRef::fromhex), "maketrans" => context.new_rustfunc(PyByteInner::maketrans), }); - PyBytesIterator::extend_class(context, &context.bytesiterator_type); + PyBytesIterator::extend_class(context, &context.types.bytesiterator_type); } #[pyimpl] diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs index 10b3106ec..38ef47d9e 100644 --- a/vm/src/obj/objclassmethod.rs +++ b/vm/src/obj/objclassmethod.rs @@ -65,5 +65,5 @@ impl PyClassMethod { } pub fn init(context: &PyContext) { - PyClassMethod::extend_class(context, &context.classmethod_type); + PyClassMethod::extend_class(context, &context.types.classmethod_type); } diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 51a73d614..a1671d0ef 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -81,7 +81,7 @@ impl PyCodeRef { } pub fn init(context: &PyContext) { - extend_class!(context, &context.code_type, { + extend_class!(context, &context.types.code_type, { "__new__" => context.new_rustfunc(PyCodeRef::new), "__repr__" => context.new_rustfunc(PyCodeRef::repr), diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index b32fd8f74..59b9ab251 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -41,7 +41,7 @@ impl From for PyComplex { } pub fn init(context: &PyContext) { - PyComplex::extend_class(context, &context.complex_type); + PyComplex::extend_class(context, &context.types.complex_type); } pub fn get_value(obj: &PyObjectRef) -> Complex64 { diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index e68c6b6a4..03ea6cb41 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -423,7 +423,7 @@ macro_rules! dict_iterator { impl PyValue for $name { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.$class.clone() + vm.ctx.types.$class.clone() } } @@ -473,7 +473,7 @@ macro_rules! dict_iterator { impl PyValue for $iter_name { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.$iter_class.clone() + vm.ctx.types.$iter_class.clone() } } }; @@ -511,7 +511,7 @@ dict_iterator! { } pub fn init(context: &PyContext) { - extend_class!(context, &context.dict_type, { + extend_class!(context, &context.types.dict_type, { "__bool__" => context.new_rustfunc(PyDictRef::bool), "__len__" => context.new_rustfunc(PyDictRef::len), "__contains__" => context.new_rustfunc(PyDictRef::contains), @@ -536,10 +536,10 @@ pub fn init(context: &PyContext) { "popitem" => context.new_rustfunc(PyDictRef::popitem), }); - PyDictKeys::extend_class(context, &context.dictkeys_type); - PyDictKeyIterator::extend_class(context, &context.dictkeyiterator_type); - PyDictValues::extend_class(context, &context.dictvalues_type); - PyDictValueIterator::extend_class(context, &context.dictvalueiterator_type); - PyDictItems::extend_class(context, &context.dictitems_type); - PyDictItemIterator::extend_class(context, &context.dictitemiterator_type); + PyDictKeys::extend_class(context, &context.types.dictkeys_type); + PyDictKeyIterator::extend_class(context, &context.types.dictkeyiterator_type); + PyDictValues::extend_class(context, &context.types.dictvalues_type); + PyDictValueIterator::extend_class(context, &context.types.dictvalueiterator_type); + PyDictItems::extend_class(context, &context.types.dictitems_type); + PyDictItemIterator::extend_class(context, &context.types.dictitemiterator_type); } diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index 56d232272..0ce34c689 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -68,8 +68,8 @@ impl PyEnumerate { } pub fn init(context: &PyContext) { - PyEnumerate::extend_class(context, &context.enumerate_type); - extend_class!(context, &context.enumerate_type, { + PyEnumerate::extend_class(context, &context.types.enumerate_type); + extend_class!(context, &context.types.enumerate_type, { "__new__" => context.new_rustfunc(enumerate_new), }); } diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 24800d6aa..4e0d9980b 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -67,8 +67,8 @@ impl PyFilter { } pub fn init(context: &PyContext) { - PyFilter::extend_class(context, &context.filter_type); - extend_class!(context, &context.filter_type, { + PyFilter::extend_class(context, &context.types.filter_type); + extend_class!(context, &context.types.filter_type, { "__new__" => context.new_rustfunc(filter_new), }); } diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index cfac52aa9..22aa9f9d3 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -619,5 +619,5 @@ pub fn make_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - PyFloat::extend_class(context, &context.float_type); + PyFloat::extend_class(context, &context.types.float_type); } diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs index 73f4e9b91..efc833270 100644 --- a/vm/src/obj/objframe.rs +++ b/vm/src/obj/objframe.rs @@ -9,7 +9,7 @@ use crate::pyobject::{PyContext, PyObjectRef, PyResult}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { - extend_class!(context, &context.frame_type, { + extend_class!(context, &context.types.frame_type, { "__new__" => context.new_rustfunc(FrameRef::new), "__repr__" => context.new_rustfunc(FrameRef::repr), "f_locals" => context.new_property(FrameRef::flocals), diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 1c7ff642a..1af408509 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -78,7 +78,7 @@ impl PyValue for PyMethod { } pub fn init(context: &PyContext) { - let function_type = &context.function_type; + let function_type = &context.types.function_type; extend_class!(context, function_type, { "__get__" => context.new_rustfunc(bind_method), "__call__" => context.new_rustfunc(PyFunctionRef::call), @@ -87,7 +87,7 @@ pub fn init(context: &PyContext) { "__kwdefaults__" => context.new_property(PyFunctionRef::kwdefaults), }); - let builtin_function_or_method_type = &context.builtin_function_or_method_type; + let builtin_function_or_method_type = &context.types.builtin_function_or_method_type; extend_class!(context, builtin_function_or_method_type, { "__get__" => context.new_rustfunc(bind_method) }); diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 2c51778fd..a26be543d 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -75,5 +75,5 @@ fn handle_execution_result(result: ExecutionResult, vm: &VirtualMachine) -> PyRe } pub fn init(ctx: &PyContext) { - PyGenerator::extend_class(ctx, &ctx.generator_type); + PyGenerator::extend_class(ctx, &ctx.types.generator_type); } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 847ba4a15..897a8ce54 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -671,7 +671,7 @@ impl IntOptions { fn get_int_value(self, vm: &VirtualMachine) -> PyResult { if let OptionalArg::Present(val) = self.val_options { let base = if let OptionalArg::Present(base) = self.base { - if !objtype::isinstance(&val, &vm.ctx.str_type) { + if !objtype::isinstance(&val, &vm.ctx.str_type()) { return Err(vm.new_type_error( "int() can't convert non-string with explicit base".to_string(), )); @@ -766,8 +766,8 @@ fn div_ints(vm: &VirtualMachine, i1: &BigInt, i2: &BigInt) -> PyResult { } pub fn init(context: &PyContext) { - PyInt::extend_class(context, &context.int_type); - extend_class!(context, &context.int_type, { + PyInt::extend_class(context, &context.types.int_type); + extend_class!(context, &context.types.int_type, { "__new__" => context.new_rustfunc(int_new), }); } diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 0fcd078c7..aaeec3ea9 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -122,5 +122,5 @@ impl PySequenceIterator { } pub fn init(context: &PyContext) { - PySequenceIterator::extend_class(context, &context.iter_type); + PySequenceIterator::extend_class(context, &context.types.iter_type); } diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index e9b4b40d5..b7476dbe6 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -859,7 +859,7 @@ impl PyListReverseIterator { #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - let list_type = &context.list_type; + let list_type = &context.types.list_type; let list_doc = "Built-in mutable sequence.\n\n\ If no argument is given, the constructor creates a new empty list.\n\ @@ -901,6 +901,6 @@ pub fn init(context: &PyContext) { "remove" => context.new_rustfunc(PyListRef::remove) }); - PyListIterator::extend_class(context, &context.listiterator_type); - PyListReverseIterator::extend_class(context, &context.listreverseiterator_type); + PyListIterator::extend_class(context, &context.types.listiterator_type); + PyListReverseIterator::extend_class(context, &context.types.listreverseiterator_type); } diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 61fe67c0d..a37dcc633 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -61,8 +61,8 @@ impl PyMap { } pub fn init(context: &PyContext) { - PyMap::extend_class(context, &context.map_type); - extend_class!(context, &context.map_type, { + PyMap::extend_class(context, &context.types.map_type); + extend_class!(context, &context.types.map_type, { "__new__" => context.new_rustfunc(map_new), }); } diff --git a/vm/src/obj/objmappingproxy.rs b/vm/src/obj/objmappingproxy.rs index 243a8c89c..b38e9d1ef 100644 --- a/vm/src/obj/objmappingproxy.rs +++ b/vm/src/obj/objmappingproxy.rs @@ -13,7 +13,7 @@ pub type PyMappingProxyRef = PyRef; impl PyValue for PyMappingProxy { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.mappingproxy_type.clone() + vm.ctx.types.mappingproxy_type.clone() } } @@ -38,5 +38,5 @@ impl PyMappingProxy { } pub fn init(context: &PyContext) { - PyMappingProxy::extend_class(context, &context.mappingproxy_type) + PyMappingProxy::extend_class(context, &context.types.mappingproxy_type) } diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 7e1628d13..ed4687032 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -47,5 +47,5 @@ impl PyValue for PyMemoryView { } pub fn init(ctx: &PyContext) { - PyMemoryView::extend_class(ctx, &ctx.memoryview_type) + PyMemoryView::extend_class(ctx, &ctx.types.memoryview_type) } diff --git a/vm/src/obj/objmodule.rs b/vm/src/obj/objmodule.rs index 99dff3b26..b768b454a 100644 --- a/vm/src/obj/objmodule.rs +++ b/vm/src/obj/objmodule.rs @@ -25,7 +25,7 @@ impl PyModuleRef { } pub fn init(context: &PyContext) { - extend_class!(&context, &context.module_type, { + extend_class!(&context, &context.types.module_type, { "__init__" => context.new_rustfunc(PyModuleRef::init), }); } diff --git a/vm/src/obj/objnamespace.rs b/vm/src/obj/objnamespace.rs index f8bfc9369..7ef304c1e 100644 --- a/vm/src/obj/objnamespace.rs +++ b/vm/src/obj/objnamespace.rs @@ -28,5 +28,5 @@ impl PyNamespace { } pub fn init(context: &PyContext) { - PyNamespace::extend_class(context, &context.namespace_type); + PyNamespace::extend_class(context, &context.types.namespace_type); } diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 8f2408dba..a157de50b 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -24,7 +24,7 @@ impl PyValue for PyInstance { pub fn new_instance(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResult { // more or less __new__ operator let cls = PyClassRef::try_from_object(vm, args.shift())?; - let dict = if cls.is(&vm.ctx.object) { + let dict = if cls.is(&vm.ctx.object()) { None } else { Some(vm.ctx.new_dict()) @@ -149,7 +149,7 @@ fn object_format( } pub fn init(context: &PyContext) { - let object = &context.object; + let object = &context.types.object_type; let object_doc = "The most base type"; extend_class!(context, object, { diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index 9c8394a4c..12cb7ed30 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -293,6 +293,6 @@ impl<'a> PropertyBuilder<'a> { } pub fn init(context: &PyContext) { - PyReadOnlyProperty::extend_class(context, &context.readonly_property_type); - PyProperty::extend_class(context, &context.property_type); + PyReadOnlyProperty::extend_class(context, &context.types.readonly_property_type); + PyProperty::extend_class(context, &context.types.property_type); } diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index 905550f50..99584a292 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -105,8 +105,8 @@ pub fn get_value(obj: &PyObjectRef) -> PyRange { } pub fn init(context: &PyContext) { - PyRange::extend_class(context, &context.range_type); - PyRangeIterator::extend_class(context, &context.rangeiterator_type); + PyRange::extend_class(context, &context.types.range_type); + PyRangeIterator::extend_class(context, &context.types.rangeiterator_type); } type PyRangeRef = PyRef; diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index cfa8e1701..dc4a3ca95 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -748,6 +748,6 @@ impl TryFromObject for SetIterable { } pub fn init(context: &PyContext) { - PySet::extend_class(context, &context.set_type); - PyFrozenSet::extend_class(context, &context.frozenset_type); + PySet::extend_class(context, &context.types.set_type); + PyFrozenSet::extend_class(context, &context.types.frozenset_type); } diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 82e4cef8c..0de224d36 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -114,7 +114,7 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult context.new_rustfunc(slice_new), diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs index a33acf176..e330652a5 100644 --- a/vm/src/obj/objstaticmethod.rs +++ b/vm/src/obj/objstaticmethod.rs @@ -32,7 +32,7 @@ impl PyStaticMethodRef { } pub fn init(context: &PyContext) { - let staticmethod_type = &context.staticmethod_type; + let staticmethod_type = &context.types.staticmethod_type; extend_class!(context, staticmethod_type, { "__get__" => context.new_rustfunc(PyStaticMethodRef::get), "__new__" => context.new_rustfunc(PyStaticMethodRef::new), diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index ff609eaad..15db1c47e 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1145,10 +1145,10 @@ impl IntoPyObject for &String { } pub fn init(ctx: &PyContext) { - PyString::extend_class(ctx, &ctx.str_type); + PyString::extend_class(ctx, &ctx.types.str_type); - PyStringIterator::extend_class(ctx, &ctx.striterator_type); - PyStringReverseIterator::extend_class(ctx, &ctx.strreverseiterator_type); + PyStringIterator::extend_class(ctx, &ctx.types.striterator_type); + PyStringReverseIterator::extend_class(ctx, &ctx.types.strreverseiterator_type); } pub fn get_value(obj: &PyObjectRef) -> String { @@ -1312,9 +1312,9 @@ fn do_cformat( } else { // check for only literal parts, in which case only dict or empty tuple is allowed if num_specifiers == 0 - && !(objtype::isinstance(&values_obj, &vm.ctx.tuple_type) + && !(objtype::isinstance(&values_obj, &vm.ctx.types.tuple_type) && objtuple::get_value(&values_obj).is_empty()) - && !objtype::isinstance(&values_obj, &vm.ctx.dict_type) + && !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type) { return Err(vm.new_type_error( "not all arguments converted during string formatting".to_string(), @@ -1380,7 +1380,7 @@ fn do_cformat( .into_iter() .nth(tuple_index) .is_some()) - && !objtype::isinstance(&values_obj, &vm.ctx.dict_type) + && !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type) { return Err( vm.new_type_error("not all arguments converted during string formatting".to_string()) diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index a9fb668cb..754fe93d5 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -33,7 +33,7 @@ impl PyValue for PySuper { } pub fn init(context: &PyContext) { - let super_type = &context.super_type; + let super_type = &context.types.super_type; let super_doc = "super() -> same as super(__class__, )\n\ super(type) -> unbound super object\n\ diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 5be1232c0..459f0e9bc 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -276,7 +276,7 @@ impl PyTupleIterator { #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - let tuple_type = &context.tuple_type; + let tuple_type = &context.types.tuple_type; let tuple_doc = "tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items @@ -303,5 +303,5 @@ If the argument is a tuple, the return value is the same object."; "index" => context.new_rustfunc(PyTupleRef::index) }); - PyTupleIterator::extend_class(context, &context.tupleiterator_type); + PyTupleIterator::extend_class(context, &context.types.tupleiterator_type); } diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 9df1a829f..fd50c3bc8 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -212,7 +212,7 @@ pub fn init(ctx: &PyContext) { type(object) -> the object's type\n\ type(name, bases, dict) -> a new type"; - extend_class!(&ctx, &ctx.type_type, { + extend_class!(&ctx, &ctx.types.type_type, { "__call__" => ctx.new_rustfunc(type_call), "__dict__" => PropertyBuilder::new(ctx) @@ -433,8 +433,8 @@ mod tests { #[test] fn test_linearise() { let context = PyContext::new(); - let object: PyClassRef = context.object.clone(); - let type_type = &context.type_type; + let object: PyClassRef = context.object(); + let type_type = &context.types.type_type; let a = new(type_type.clone(), "A", vec![object.clone()], HashMap::new()).unwrap(); let b = new(type_type.clone(), "B", vec![object.clone()], HashMap::new()).unwrap(); diff --git a/vm/src/obj/objweakproxy.rs b/vm/src/obj/objweakproxy.rs index 5d4f68d9d..f510a03ef 100644 --- a/vm/src/obj/objweakproxy.rs +++ b/vm/src/obj/objweakproxy.rs @@ -61,5 +61,5 @@ impl PyWeakProxy { } pub fn init(context: &PyContext) { - PyWeakProxy::extend_class(&context, &context.weakproxy_type); + PyWeakProxy::extend_class(&context, &context.types.weakproxy_type); } diff --git a/vm/src/obj/objweakref.rs b/vm/src/obj/objweakref.rs index b3b7e03c9..ae4375cd0 100644 --- a/vm/src/obj/objweakref.rs +++ b/vm/src/obj/objweakref.rs @@ -48,7 +48,7 @@ impl PyWeakRef { } pub fn init(context: &PyContext) { - extend_class!(context, &context.weakref_type, { + extend_class!(context, &context.types.weakref_type, { "__new__" => context.new_rustfunc(PyWeakRef::create), "__call__" => context.new_rustfunc(PyWeakRef::call) }); diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index d9c577aa0..0223b8bf2 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -51,8 +51,8 @@ impl PyZip { } pub fn init(context: &PyContext) { - PyZip::extend_class(context, &context.zip_type); - extend_class!(context, &context.zip_type, { + PyZip::extend_class(context, &context.types.zip_type); + extend_class!(context, &context.types.zip_type, { "__new__" => context.new_rustfunc(zip_new), }); } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index ba40d5473..563113a41 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,12 +1,9 @@ use std::any::Any; use std::cell::Cell; -use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::marker::PhantomData; -use std::mem; use std::ops::Deref; -use std::ptr; use std::rc::Rc; use num_bigint::BigInt; @@ -16,46 +13,30 @@ use num_traits::{One, Zero}; use crate::bytecode; use crate::exceptions; use crate::function::{IntoPyNativeFunc, PyFuncArgs}; -use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; use crate::obj::objbytes; -use crate::obj::objclassmethod::{self, PyClassMethod}; +use crate::obj::objclassmethod::PyClassMethod; use crate::obj::objcode; use crate::obj::objcode::PyCodeRef; -use crate::obj::objcomplex::{self, PyComplex}; -use crate::obj::objdict::{self, PyDict, PyDictRef}; -use crate::obj::objellipsis; -use crate::obj::objenumerate; -use crate::obj::objfilter; -use crate::obj::objfloat::{self, PyFloat}; -use crate::obj::objframe; -use crate::obj::objfunction::{self, PyFunction, PyMethod}; -use crate::obj::objgenerator; -use crate::obj::objint::{self, PyInt, PyIntRef}; +use crate::obj::objcomplex::PyComplex; +use crate::obj::objdict::{PyDict, PyDictRef}; +use crate::obj::objfloat::PyFloat; +use crate::obj::objfunction::{PyFunction, PyMethod}; +use crate::obj::objint::{PyInt, PyIntRef}; use crate::obj::objiter; -use crate::obj::objlist::{self, PyList}; -use crate::obj::objmap; -use crate::obj::objmappingproxy; -use crate::obj::objmemory; -use crate::obj::objmodule::{self, PyModule}; -use crate::obj::objnamespace::{self, PyNamespace}; -use crate::obj::objnone::{self, PyNone, PyNoneRef}; +use crate::obj::objlist::PyList; +use crate::obj::objmodule::PyModule; +use crate::obj::objnamespace::PyNamespace; +use crate::obj::objnone::{PyNone, PyNoneRef}; use crate::obj::objobject; -use crate::obj::objproperty; use crate::obj::objproperty::PropertyBuilder; -use crate::obj::objrange; -use crate::obj::objset::{self, PySet}; -use crate::obj::objslice; -use crate::obj::objstaticmethod; +use crate::obj::objset::PySet; use crate::obj::objstr; -use crate::obj::objsuper; -use crate::obj::objtuple::{self, PyTuple, PyTupleRef}; +use crate::obj::objtuple::{PyTuple, PyTupleRef}; use crate::obj::objtype::{self, PyClass, PyClassRef}; -use crate::obj::objweakproxy; -use crate::obj::objweakref; -use crate::obj::objzip; use crate::scope::Scope; +use crate::types::{create_type, initialize_types, TypeZoo}; use crate::vm::VirtualMachine; use indexmap::IndexMap; @@ -112,71 +93,16 @@ impl fmt::Display for PyObject { #[derive(Debug)] pub struct PyContext { - pub bytes_type: PyClassRef, - pub bytesiterator_type: PyClassRef, - pub bytearray_type: PyClassRef, - pub bytearrayiterator_type: PyClassRef, - pub bool_type: PyClassRef, - pub classmethod_type: PyClassRef, - pub code_type: PyClassRef, - pub dict_type: PyClassRef, - pub ellipsis_type: PyClassRef, - pub enumerate_type: PyClassRef, - pub filter_type: PyClassRef, - pub float_type: PyClassRef, - pub frame_type: PyClassRef, - pub frozenset_type: PyClassRef, - pub generator_type: PyClassRef, - pub int_type: PyClassRef, - pub iter_type: PyClassRef, - pub complex_type: PyClassRef, pub true_value: PyIntRef, pub false_value: PyIntRef, - pub list_type: PyClassRef, - pub listiterator_type: PyClassRef, - pub listreverseiterator_type: PyClassRef, - pub striterator_type: PyClassRef, - pub strreverseiterator_type: PyClassRef, - pub dictkeyiterator_type: PyClassRef, - pub dictvalueiterator_type: PyClassRef, - pub dictitemiterator_type: PyClassRef, - pub dictkeys_type: PyClassRef, - pub dictvalues_type: PyClassRef, - pub dictitems_type: PyClassRef, - pub map_type: PyClassRef, - pub memoryview_type: PyClassRef, pub none: PyNoneRef, + pub empty_tuple: PyTupleRef, + pub ellipsis_type: PyClassRef, pub ellipsis: PyEllipsisRef, pub not_implemented: PyNotImplementedRef, - pub empty_tuple: PyTupleRef, - pub tuple_type: PyClassRef, - pub tupleiterator_type: PyClassRef, - pub set_type: PyClassRef, - pub staticmethod_type: PyClassRef, - pub super_type: PyClassRef, - pub str_type: PyClassRef, - pub range_type: PyClassRef, - pub rangeiterator_type: PyClassRef, - pub slice_type: PyClassRef, - pub type_type: PyClassRef, - pub zip_type: PyClassRef, - pub function_type: PyClassRef, - pub builtin_function_or_method_type: PyClassRef, - pub property_type: PyClassRef, - pub readonly_property_type: PyClassRef, - pub module_type: PyClassRef, - pub namespace_type: PyClassRef, - pub bound_method_type: PyClassRef, - pub weakref_type: PyClassRef, - pub weakproxy_type: PyClassRef, - pub mappingproxy_type: PyClassRef, - pub object: PyClassRef, - pub exceptions: exceptions::ExceptionZoo, -} -pub fn create_type(name: &str, type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef { - let dict = PyAttributes::new(); - objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap() + pub types: TypeZoo, + pub exceptions: exceptions::ExceptionZoo, } pub type PyNotImplementedRef = PyRef; @@ -201,115 +127,12 @@ impl PyValue for PyEllipsis { } } -fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { - // `type` inherits from `object` - // and both `type` and `object are instances of `type`. - // to produce this circular dependency, we need an unsafe block. - // (and yes, this will never get dropped. TODO?) - let (type_type, object_type) = unsafe { - let object_type = PyObject { - typ: mem::uninitialized(), // ! - dict: None, - payload: PyClass { - name: String::from("object"), - mro: vec![], - subclasses: RefCell::new(vec![]), - attributes: RefCell::new(PyAttributes::new()), - }, - } - .into_ref(); - - let type_type = PyObject { - typ: mem::uninitialized(), // ! - dict: None, - payload: PyClass { - name: String::from("type"), - mro: vec![object_type.clone().downcast().unwrap()], - subclasses: RefCell::new(vec![]), - attributes: RefCell::new(PyAttributes::new()), - }, - } - .into_ref(); - - let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; - let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; - - let type_type: PyClassRef = type_type.downcast().unwrap(); - let object_type: PyClassRef = object_type.downcast().unwrap(); - - ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); - ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); - - (type_type, object_type) - }; - - object_type - .subclasses - .borrow_mut() - .push(objweakref::PyWeak::downgrade(&type_type.as_object())); - - (type_type, object_type) -} - // Basic objects: impl PyContext { pub fn new() -> Self { flame_guard!("init PyContext"); - let (type_type, object_type) = init_type_hierarchy(); - - let dict_type = create_type("dict", &type_type, &object_type); - let module_type = create_type("module", &type_type, &object_type); - let namespace_type = create_type("SimpleNamespace", &type_type, &object_type); - let classmethod_type = create_type("classmethod", &type_type, &object_type); - let staticmethod_type = create_type("staticmethod", &type_type, &object_type); - let function_type = create_type("function", &type_type, &object_type); - let builtin_function_or_method_type = - create_type("builtin_function_or_method", &type_type, &object_type); - let property_type = create_type("property", &type_type, &object_type); - let readonly_property_type = create_type("readonly_property", &type_type, &object_type); - let super_type = create_type("super", &type_type, &object_type); - let weakref_type = create_type("ref", &type_type, &object_type); - let weakproxy_type = create_type("weakproxy", &type_type, &object_type); - let generator_type = create_type("generator", &type_type, &object_type); - let bound_method_type = create_type("method", &type_type, &object_type); - let str_type = create_type("str", &type_type, &object_type); - let list_type = create_type("list", &type_type, &object_type); - let listiterator_type = create_type("list_iterator", &type_type, &object_type); - let listreverseiterator_type = - create_type("list_reverseiterator", &type_type, &object_type); - let striterator_type = create_type("str_iterator", &type_type, &object_type); - let strreverseiterator_type = create_type("str_reverseiterator", &type_type, &object_type); - let dictkeys_type = create_type("dict_keys", &type_type, &object_type); - let dictvalues_type = create_type("dict_values", &type_type, &object_type); - let dictitems_type = create_type("dict_items", &type_type, &object_type); - let dictkeyiterator_type = create_type("dict_keyiterator", &type_type, &object_type); - let dictvalueiterator_type = create_type("dict_valueiterator", &type_type, &object_type); - let dictitemiterator_type = create_type("dict_itemiterator", &type_type, &object_type); - let set_type = create_type("set", &type_type, &object_type); - let frozenset_type = create_type("frozenset", &type_type, &object_type); - let int_type = create_type("int", &type_type, &object_type); - let float_type = create_type("float", &type_type, &object_type); - let frame_type = create_type("frame", &type_type, &object_type); - let complex_type = create_type("complex", &type_type, &object_type); - let bytes_type = create_type("bytes", &type_type, &object_type); - let bytesiterator_type = create_type("bytes_iterator", &type_type, &object_type); - let bytearray_type = create_type("bytearray", &type_type, &object_type); - let bytearrayiterator_type = create_type("bytearray_iterator", &type_type, &object_type); - let tuple_type = create_type("tuple", &type_type, &object_type); - let tupleiterator_type = create_type("tuple_iterator", &type_type, &object_type); - let iter_type = create_type("iter", &type_type, &object_type); - let enumerate_type = create_type("enumerate", &type_type, &object_type); - let filter_type = create_type("filter", &type_type, &object_type); - let map_type = create_type("map", &type_type, &object_type); - let zip_type = create_type("zip", &type_type, &object_type); - let bool_type = create_type("bool", &type_type, &int_type); - let memoryview_type = create_type("memoryview", &type_type, &object_type); - let code_type = create_type("code", &type_type, &object_type); - let range_type = create_type("range", &type_type, &object_type); - let rangeiterator_type = create_type("range_iterator", &type_type, &object_type); - let slice_type = create_type("slice", &type_type, &object_type); - let mappingproxy_type = create_type("mappingproxy", &type_type, &object_type); - let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type); + let types = TypeZoo::new(); + let exceptions = exceptions::ExceptionZoo::new(&types.type_type, &types.object_type); fn create_object(payload: T, cls: &PyClassRef) -> PyRef { PyRef { @@ -318,297 +141,213 @@ impl PyContext { } } - let none_type = create_type("NoneType", &type_type, &object_type); + let none_type = create_type("NoneType", &types.type_type, &types.object_type); let none = create_object(PyNone, &none_type); - let ellipsis_type = create_type("EllipsisType", &type_type, &object_type); + let ellipsis_type = create_type("EllipsisType", &types.type_type, &types.object_type); let ellipsis = create_object(PyEllipsis, &ellipsis_type); - let not_implemented_type = create_type("NotImplementedType", &type_type, &object_type); + let not_implemented_type = + create_type("NotImplementedType", &types.type_type, &types.object_type); let not_implemented = create_object(PyNotImplemented, ¬_implemented_type); - let true_value = create_object(PyInt::new(BigInt::one()), &bool_type); - let false_value = create_object(PyInt::new(BigInt::zero()), &bool_type); + let true_value = create_object(PyInt::new(BigInt::one()), &types.bool_type); + let false_value = create_object(PyInt::new(BigInt::zero()), &types.bool_type); - let empty_tuple = create_object(PyTuple::from(vec![]), &tuple_type); + let empty_tuple = create_object(PyTuple::from(vec![]), &types.tuple_type); let context = PyContext { - bool_type, - memoryview_type, - bytearray_type, - bytearrayiterator_type, - bytes_type, - bytesiterator_type, - code_type, - complex_type, - classmethod_type, - int_type, - float_type, - frame_type, - staticmethod_type, - list_type, - listiterator_type, - listreverseiterator_type, - striterator_type, - strreverseiterator_type, - dictkeys_type, - dictvalues_type, - dictitems_type, - dictkeyiterator_type, - dictvalueiterator_type, - dictitemiterator_type, - set_type, - frozenset_type, true_value, false_value, - tuple_type, - tupleiterator_type, - iter_type, - ellipsis_type, - enumerate_type, - filter_type, - map_type, - zip_type, - dict_type, + not_implemented, none, ellipsis, - not_implemented, - str_type, - range_type, - rangeiterator_type, - slice_type, - object: object_type, - function_type, - builtin_function_or_method_type, - super_type, - mappingproxy_type, - property_type, - readonly_property_type, - generator_type, - module_type, - namespace_type, - bound_method_type, - weakref_type, - weakproxy_type, - type_type, + ellipsis_type, + + types, exceptions, empty_tuple, }; - objtype::init(&context); - objlist::init(&context); - objset::init(&context); - objtuple::init(&context); - objobject::init(&context); - objdict::init(&context); - objfunction::init(&context); - objstaticmethod::init(&context); - objclassmethod::init(&context); - objgenerator::init(&context); - objint::init(&context); - objfloat::init(&context); - objcomplex::init(&context); - objbytes::init(&context); - objbytearray::init(&context); - objproperty::init(&context); - objmemory::init(&context); - objstr::init(&context); - objrange::init(&context); - objslice::init(&context); - objsuper::init(&context); - objtuple::init(&context); - objiter::init(&context); - objellipsis::init(&context); - objenumerate::init(&context); - objfilter::init(&context); - objmap::init(&context); - objzip::init(&context); - objbool::init(&context); - objcode::init(&context); - objframe::init(&context); - objweakref::init(&context); - objweakproxy::init(&context); - objnone::init(&context); - objmodule::init(&context); - objnamespace::init(&context); - objmappingproxy::init(&context); + initialize_types(&context); + exceptions::init(&context); context } pub fn bytearray_type(&self) -> PyClassRef { - self.bytearray_type.clone() + self.types.bytearray_type.clone() } pub fn bytearrayiterator_type(&self) -> PyClassRef { - self.bytearrayiterator_type.clone() + self.types.bytearrayiterator_type.clone() } pub fn bytes_type(&self) -> PyClassRef { - self.bytes_type.clone() + self.types.bytes_type.clone() } pub fn bytesiterator_type(&self) -> PyClassRef { - self.bytesiterator_type.clone() + self.types.bytesiterator_type.clone() } pub fn code_type(&self) -> PyClassRef { - self.code_type.clone() + self.types.code_type.clone() } pub fn complex_type(&self) -> PyClassRef { - self.complex_type.clone() + self.types.complex_type.clone() } pub fn dict_type(&self) -> PyClassRef { - self.dict_type.clone() + self.types.dict_type.clone() } pub fn float_type(&self) -> PyClassRef { - self.float_type.clone() + self.types.float_type.clone() } pub fn frame_type(&self) -> PyClassRef { - self.frame_type.clone() + self.types.frame_type.clone() } pub fn int_type(&self) -> PyClassRef { - self.int_type.clone() + self.types.int_type.clone() } pub fn list_type(&self) -> PyClassRef { - self.list_type.clone() + self.types.list_type.clone() } pub fn listiterator_type(&self) -> PyClassRef { - self.listiterator_type.clone() + self.types.listiterator_type.clone() } pub fn listreverseiterator_type(&self) -> PyClassRef { - self.listreverseiterator_type.clone() + self.types.listreverseiterator_type.clone() } pub fn striterator_type(&self) -> PyClassRef { - self.striterator_type.clone() + self.types.striterator_type.clone() } pub fn strreverseiterator_type(&self) -> PyClassRef { - self.strreverseiterator_type.clone() + self.types.strreverseiterator_type.clone() } pub fn module_type(&self) -> PyClassRef { - self.module_type.clone() + self.types.module_type.clone() } pub fn namespace_type(&self) -> PyClassRef { - self.namespace_type.clone() + self.types.namespace_type.clone() } pub fn set_type(&self) -> PyClassRef { - self.set_type.clone() + self.types.set_type.clone() } pub fn range_type(&self) -> PyClassRef { - self.range_type.clone() + self.types.range_type.clone() } pub fn rangeiterator_type(&self) -> PyClassRef { - self.rangeiterator_type.clone() + self.types.rangeiterator_type.clone() } pub fn slice_type(&self) -> PyClassRef { - self.slice_type.clone() + self.types.slice_type.clone() } pub fn frozenset_type(&self) -> PyClassRef { - self.frozenset_type.clone() + self.types.frozenset_type.clone() } pub fn bool_type(&self) -> PyClassRef { - self.bool_type.clone() + self.types.bool_type.clone() } pub fn memoryview_type(&self) -> PyClassRef { - self.memoryview_type.clone() + self.types.memoryview_type.clone() } pub fn tuple_type(&self) -> PyClassRef { - self.tuple_type.clone() + self.types.tuple_type.clone() } pub fn tupleiterator_type(&self) -> PyClassRef { - self.tupleiterator_type.clone() + self.types.tupleiterator_type.clone() } pub fn iter_type(&self) -> PyClassRef { - self.iter_type.clone() + self.types.iter_type.clone() } pub fn enumerate_type(&self) -> PyClassRef { - self.enumerate_type.clone() + self.types.enumerate_type.clone() } pub fn filter_type(&self) -> PyClassRef { - self.filter_type.clone() + self.types.filter_type.clone() } pub fn map_type(&self) -> PyClassRef { - self.map_type.clone() + self.types.map_type.clone() } pub fn zip_type(&self) -> PyClassRef { - self.zip_type.clone() + self.types.zip_type.clone() } pub fn str_type(&self) -> PyClassRef { - self.str_type.clone() + self.types.str_type.clone() } pub fn super_type(&self) -> PyClassRef { - self.super_type.clone() + self.types.super_type.clone() } pub fn function_type(&self) -> PyClassRef { - self.function_type.clone() + self.types.function_type.clone() } pub fn builtin_function_or_method_type(&self) -> PyClassRef { - self.builtin_function_or_method_type.clone() + self.types.builtin_function_or_method_type.clone() } pub fn property_type(&self) -> PyClassRef { - self.property_type.clone() + self.types.property_type.clone() } pub fn readonly_property_type(&self) -> PyClassRef { - self.readonly_property_type.clone() + self.types.readonly_property_type.clone() } pub fn classmethod_type(&self) -> PyClassRef { - self.classmethod_type.clone() + self.types.classmethod_type.clone() } pub fn staticmethod_type(&self) -> PyClassRef { - self.staticmethod_type.clone() + self.types.staticmethod_type.clone() } pub fn generator_type(&self) -> PyClassRef { - self.generator_type.clone() + self.types.generator_type.clone() } pub fn bound_method_type(&self) -> PyClassRef { - self.bound_method_type.clone() + self.types.bound_method_type.clone() } pub fn weakref_type(&self) -> PyClassRef { - self.weakref_type.clone() + self.types.weakref_type.clone() } pub fn weakproxy_type(&self) -> PyClassRef { - self.weakproxy_type.clone() + self.types.weakproxy_type.clone() } pub fn type_type(&self) -> PyClassRef { - self.type_type.clone() + self.types.type_type.clone() } pub fn none(&self) -> PyObjectRef { @@ -624,7 +363,7 @@ impl PyContext { } pub fn object(&self) -> PyClassRef { - self.object.clone() + self.types.object_type.clone() } pub fn new_int>(&self, i: T) -> PyObjectRef { @@ -696,7 +435,7 @@ impl PyContext { PyModule { name: name.to_string(), }, - self.module_type.clone(), + self.types.module_type.clone(), Some(dict), ) } diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 8b5d21b75..ba8afb12f 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -1,6 +1,7 @@ use crate::obj::objstr::PyStringRef; use crate::py_serde; -use crate::pyobject::{create_type, ItemProtocol, PyObjectRef, PyResult}; +use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult}; +use crate::types::create_type; use crate::VirtualMachine; use serde_json; @@ -39,7 +40,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { // TODO: Make this a proper type with a constructor let json_decode_error = create_type( "JSONDecodeError", - &ctx.type_type, + &ctx.types.type_type, &ctx.exceptions.exception_type, ); diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index 36dad8bca..1bc28ca25 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -191,7 +191,7 @@ fn math_trunc(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { fn math_ceil(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(value, None)]); - if objtype::isinstance(value, &vm.ctx.float_type) { + if objtype::isinstance(value, &vm.ctx.float_type()) { let v = objfloat::get_value(value); Ok(vm.ctx.new_float(v.ceil())) } else { @@ -201,7 +201,7 @@ fn math_ceil(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { fn math_floor(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(value, None)]); - if objtype::isinstance(value, &vm.ctx.float_type) { + if objtype::isinstance(value, &vm.ctx.float_type()) { let v = objfloat::get_value(value); Ok(vm.ctx.new_float(v.floor())) } else { diff --git a/vm/src/stdlib/zlib.rs b/vm/src/stdlib/zlib.rs index b54d82425..59ccf0b8e 100644 --- a/vm/src/stdlib/zlib.rs +++ b/vm/src/stdlib/zlib.rs @@ -1,6 +1,7 @@ use crate::function::OptionalArg; use crate::obj::{objbytes::PyBytesRef, objint::PyIntRef}; -use crate::pyobject::{create_type, ItemProtocol, PyObjectRef, PyResult}; +use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult}; +use crate::types::create_type; use crate::vm::VirtualMachine; use adler32::RollingAdler32 as Adler32; @@ -18,7 +19,11 @@ const DEF_BUF_SIZE: usize = 16 * 1024; pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; - let zlib_error = create_type("error", &ctx.type_type, &ctx.exceptions.exception_type); + let zlib_error = create_type( + "error", + &ctx.types.type_type, + &ctx.exceptions.exception_type, + ); py_module!(vm, "zlib", { "crc32" => ctx.new_rustfunc(zlib_crc32), diff --git a/vm/src/types.rs b/vm/src/types.rs new file mode 100644 index 000000000..048b3d8ad --- /dev/null +++ b/vm/src/types.rs @@ -0,0 +1,313 @@ +use crate::obj::objbool; +use crate::obj::objbytearray; +use crate::obj::objbytes; +use crate::obj::objclassmethod; +use crate::obj::objcode; +use crate::obj::objcomplex; +use crate::obj::objdict; +use crate::obj::objellipsis; +use crate::obj::objenumerate; +use crate::obj::objfilter; +use crate::obj::objfloat; +use crate::obj::objframe; +use crate::obj::objfunction; +use crate::obj::objgenerator; +use crate::obj::objint; +use crate::obj::objiter; +use crate::obj::objlist; +use crate::obj::objmap; +use crate::obj::objmappingproxy; +use crate::obj::objmemory; +use crate::obj::objmodule; +use crate::obj::objnamespace; +use crate::obj::objnone; +use crate::obj::objobject; +use crate::obj::objproperty; +use crate::obj::objrange; +use crate::obj::objset; +use crate::obj::objslice; +use crate::obj::objstaticmethod; +use crate::obj::objstr; +use crate::obj::objsuper; +use crate::obj::objtuple; +use crate::obj::objtype::{self, PyClass, PyClassRef}; +use crate::obj::objweakproxy; +use crate::obj::objweakref; +use crate::obj::objzip; +use crate::pyobject::{PyAttributes, PyContext, PyObject, PyObjectRef}; +use std::cell::RefCell; +use std::mem; +use std::ptr; + +/// Holder of references to builtin types. +#[derive(Debug)] +pub struct TypeZoo { + pub bytes_type: PyClassRef, + pub bytesiterator_type: PyClassRef, + pub bytearray_type: PyClassRef, + pub bytearrayiterator_type: PyClassRef, + pub bool_type: PyClassRef, + pub classmethod_type: PyClassRef, + pub code_type: PyClassRef, + pub dict_type: PyClassRef, + pub enumerate_type: PyClassRef, + pub filter_type: PyClassRef, + pub float_type: PyClassRef, + pub frame_type: PyClassRef, + pub frozenset_type: PyClassRef, + pub generator_type: PyClassRef, + pub int_type: PyClassRef, + pub iter_type: PyClassRef, + pub complex_type: PyClassRef, + pub list_type: PyClassRef, + pub listiterator_type: PyClassRef, + pub listreverseiterator_type: PyClassRef, + pub striterator_type: PyClassRef, + pub strreverseiterator_type: PyClassRef, + pub dictkeyiterator_type: PyClassRef, + pub dictvalueiterator_type: PyClassRef, + pub dictitemiterator_type: PyClassRef, + pub dictkeys_type: PyClassRef, + pub dictvalues_type: PyClassRef, + pub dictitems_type: PyClassRef, + pub map_type: PyClassRef, + pub memoryview_type: PyClassRef, + pub tuple_type: PyClassRef, + pub tupleiterator_type: PyClassRef, + pub set_type: PyClassRef, + pub staticmethod_type: PyClassRef, + pub super_type: PyClassRef, + pub str_type: PyClassRef, + pub range_type: PyClassRef, + pub rangeiterator_type: PyClassRef, + pub slice_type: PyClassRef, + pub type_type: PyClassRef, + pub zip_type: PyClassRef, + pub function_type: PyClassRef, + pub builtin_function_or_method_type: PyClassRef, + pub property_type: PyClassRef, + pub readonly_property_type: PyClassRef, + pub module_type: PyClassRef, + pub namespace_type: PyClassRef, + pub bound_method_type: PyClassRef, + pub weakref_type: PyClassRef, + pub weakproxy_type: PyClassRef, + pub mappingproxy_type: PyClassRef, + pub object_type: PyClassRef, +} + +impl Default for TypeZoo { + fn default() -> Self { + Self::new() + } +} + +impl TypeZoo { + pub fn new() -> Self { + let (type_type, object_type) = init_type_hierarchy(); + + let dict_type = create_type("dict", &type_type, &object_type); + let module_type = create_type("module", &type_type, &object_type); + let namespace_type = create_type("SimpleNamespace", &type_type, &object_type); + let classmethod_type = create_type("classmethod", &type_type, &object_type); + let staticmethod_type = create_type("staticmethod", &type_type, &object_type); + let function_type = create_type("function", &type_type, &object_type); + let builtin_function_or_method_type = + create_type("builtin_function_or_method", &type_type, &object_type); + let property_type = create_type("property", &type_type, &object_type); + let readonly_property_type = create_type("readonly_property", &type_type, &object_type); + let super_type = create_type("super", &type_type, &object_type); + let weakref_type = create_type("ref", &type_type, &object_type); + let weakproxy_type = create_type("weakproxy", &type_type, &object_type); + let generator_type = create_type("generator", &type_type, &object_type); + let bound_method_type = create_type("method", &type_type, &object_type); + let str_type = create_type("str", &type_type, &object_type); + let list_type = create_type("list", &type_type, &object_type); + let listiterator_type = create_type("list_iterator", &type_type, &object_type); + let listreverseiterator_type = + create_type("list_reverseiterator", &type_type, &object_type); + let striterator_type = create_type("str_iterator", &type_type, &object_type); + let strreverseiterator_type = create_type("str_reverseiterator", &type_type, &object_type); + let dictkeys_type = create_type("dict_keys", &type_type, &object_type); + let dictvalues_type = create_type("dict_values", &type_type, &object_type); + let dictitems_type = create_type("dict_items", &type_type, &object_type); + let dictkeyiterator_type = create_type("dict_keyiterator", &type_type, &object_type); + let dictvalueiterator_type = create_type("dict_valueiterator", &type_type, &object_type); + let dictitemiterator_type = create_type("dict_itemiterator", &type_type, &object_type); + let set_type = create_type("set", &type_type, &object_type); + let frozenset_type = create_type("frozenset", &type_type, &object_type); + let int_type = create_type("int", &type_type, &object_type); + let float_type = create_type("float", &type_type, &object_type); + let frame_type = create_type("frame", &type_type, &object_type); + let complex_type = create_type("complex", &type_type, &object_type); + let bytes_type = create_type("bytes", &type_type, &object_type); + let bytesiterator_type = create_type("bytes_iterator", &type_type, &object_type); + let bytearray_type = create_type("bytearray", &type_type, &object_type); + let bytearrayiterator_type = create_type("bytearray_iterator", &type_type, &object_type); + let tuple_type = create_type("tuple", &type_type, &object_type); + let tupleiterator_type = create_type("tuple_iterator", &type_type, &object_type); + let iter_type = create_type("iter", &type_type, &object_type); + let enumerate_type = create_type("enumerate", &type_type, &object_type); + let filter_type = create_type("filter", &type_type, &object_type); + let map_type = create_type("map", &type_type, &object_type); + let zip_type = create_type("zip", &type_type, &object_type); + let bool_type = create_type("bool", &type_type, &int_type); + let memoryview_type = create_type("memoryview", &type_type, &object_type); + let code_type = create_type("code", &type_type, &object_type); + let range_type = create_type("range", &type_type, &object_type); + let rangeiterator_type = create_type("range_iterator", &type_type, &object_type); + let slice_type = create_type("slice", &type_type, &object_type); + let mappingproxy_type = create_type("mappingproxy", &type_type, &object_type); + + Self { + bool_type, + memoryview_type, + bytearray_type, + bytearrayiterator_type, + bytes_type, + bytesiterator_type, + code_type, + complex_type, + classmethod_type, + int_type, + float_type, + frame_type, + staticmethod_type, + list_type, + listiterator_type, + listreverseiterator_type, + striterator_type, + strreverseiterator_type, + dictkeys_type, + dictvalues_type, + dictitems_type, + dictkeyiterator_type, + dictvalueiterator_type, + dictitemiterator_type, + set_type, + frozenset_type, + tuple_type, + tupleiterator_type, + iter_type, + enumerate_type, + filter_type, + map_type, + zip_type, + dict_type, + str_type, + range_type, + rangeiterator_type, + slice_type, + object_type, + function_type, + builtin_function_or_method_type, + super_type, + mappingproxy_type, + property_type, + readonly_property_type, + generator_type, + module_type, + namespace_type, + bound_method_type, + weakref_type, + weakproxy_type, + type_type, + } + } +} + +pub fn create_type(name: &str, type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef { + let dict = PyAttributes::new(); + objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap() +} + +fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { + // `type` inherits from `object` + // and both `type` and `object are instances of `type`. + // to produce this circular dependency, we need an unsafe block. + // (and yes, this will never get dropped. TODO?) + let (type_type, object_type) = unsafe { + let object_type = PyObject { + typ: mem::uninitialized(), // ! + dict: None, + payload: PyClass { + name: String::from("object"), + mro: vec![], + subclasses: RefCell::new(vec![]), + attributes: RefCell::new(PyAttributes::new()), + }, + } + .into_ref(); + + let type_type = PyObject { + typ: mem::uninitialized(), // ! + dict: None, + payload: PyClass { + name: String::from("type"), + mro: vec![object_type.clone().downcast().unwrap()], + subclasses: RefCell::new(vec![]), + attributes: RefCell::new(PyAttributes::new()), + }, + } + .into_ref(); + + let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; + let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; + + let type_type: PyClassRef = type_type.downcast().unwrap(); + let object_type: PyClassRef = object_type.downcast().unwrap(); + + ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); + ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); + + (type_type, object_type) + }; + + object_type + .subclasses + .borrow_mut() + .push(objweakref::PyWeak::downgrade(&type_type.as_object())); + + (type_type, object_type) +} + +/// Fill attributes of builtin types. +pub fn initialize_types(context: &PyContext) { + objtype::init(&context); + objlist::init(&context); + objset::init(&context); + objtuple::init(&context); + objobject::init(&context); + objdict::init(&context); + objfunction::init(&context); + objstaticmethod::init(&context); + objclassmethod::init(&context); + objgenerator::init(&context); + objint::init(&context); + objfloat::init(&context); + objcomplex::init(&context); + objbytes::init(&context); + objbytearray::init(&context); + objproperty::init(&context); + objmemory::init(&context); + objstr::init(&context); + objrange::init(&context); + objslice::init(&context); + objsuper::init(&context); + objtuple::init(&context); + objiter::init(&context); + objellipsis::init(&context); + objenumerate::init(&context); + objfilter::init(&context); + objmap::init(&context); + objzip::init(&context); + objbool::init(&context); + objcode::init(&context); + objframe::init(&context); + objweakref::init(&context); + objweakproxy::init(&context); + objnone::init(&context); + objmodule::init(&context); + objnamespace::init(&context); + objmappingproxy::init(&context); +} diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 9468aa416..9622613f7 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -1,9 +1,8 @@ use js_sys::{Array, Object, Reflect}; use rustpython_vm::function::Args; use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyClassRef}; -use rustpython_vm::pyobject::{ - create_type, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, -}; +use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; +use rustpython_vm::types::create_type; use rustpython_vm::VirtualMachine; use wasm_bindgen::{prelude::*, JsCast}; @@ -244,7 +243,7 @@ fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyObjectRef { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; py_module!(vm, "_js", { - "JsError" => create_type("JsError", &ctx.type_type, &ctx.exceptions.exception_type), + "JsError" => create_type("JsError", &ctx.type_type(), &ctx.exceptions.exception_type), "JsValue" => PyJsValue::make_class(ctx), }) }