From c8eda3733d211a2b77b5a40f70bc1ce8fbc61821 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Thu, 4 Apr 2019 14:49:10 +0100 Subject: [PATCH] Eliminate ctx.set_attr. --- derive/src/pyclass.rs | 2 +- vm/src/builtins.rs | 17 ++++++++------- vm/src/exceptions.rs | 4 ++-- vm/src/frame.rs | 16 +++++++------- vm/src/import.rs | 2 +- vm/src/macros.rs | 22 +++++++++---------- vm/src/obj/objbytes.rs | 4 +--- vm/src/obj/objcode.rs | 3 +-- vm/src/obj/objdict.rs | 45 ++++++++++++++++++++++++++++----------- vm/src/obj/objellipsis.rs | 3 +-- vm/src/obj/objmemory.rs | 2 +- vm/src/obj/objobject.rs | 8 +++---- vm/src/obj/objstr.rs | 6 ++++++ vm/src/obj/objsuper.rs | 2 +- vm/src/obj/objtype.rs | 7 ++++++ vm/src/pyobject.rs | 28 ++++-------------------- vm/src/stdlib/io.rs | 16 +++++++------- vm/src/stdlib/json.rs | 8 ++++--- vm/src/stdlib/os.rs | 20 ++++++++--------- vm/src/sysmodule.rs | 11 +++++----- vm/src/vm.rs | 24 +++++++++------------ wasm/lib/src/convert.rs | 2 +- wasm/lib/src/vm_class.rs | 3 +-- 23 files changed, 129 insertions(+), 126 deletions(-) diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index ad4ebf66e..e533e8009 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -118,7 +118,7 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> TokenStream2 { }| { let constructor_fn = kind.to_ctx_constructor_fn(); quote! { - ctx.set_attr(class, #py_name, ctx.#constructor_fn(Self::#fn_name)); + class.set_str_attr(#py_name, ctx.#constructor_fn(Self::#fn_name)); } }, ); diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 205d0c66e..7264c9c6e 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -669,7 +669,12 @@ fn builtin_import(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_vars pub fn make_module(ctx: &PyContext) -> PyObjectRef { - let py_mod = py_module!(ctx, "__builtins__", { + #[cfg(target_arch = "wasm32")] + let open = ctx.none(); + #[cfg(not(target_arch = "wasm32"))] + let open = ctx.new_rustfunc(io_open); + + py_module!(ctx, "__builtins__", { //set __name__ fixes: https://github.com/RustPython/RustPython/issues/146 "__name__" => ctx.new_str(String::from("__main__")), @@ -715,6 +720,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { "min" => ctx.new_rustfunc(builtin_min), "object" => ctx.object(), "oct" => ctx.new_rustfunc(builtin_oct), + "open" => open, "ord" => ctx.new_rustfunc(builtin_ord), "next" => ctx.new_rustfunc(builtin_next), "pow" => ctx.new_rustfunc(builtin_pow), @@ -759,12 +765,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { "ZeroDivisionError" => ctx.exceptions.zero_division_error.clone(), "KeyError" => ctx.exceptions.key_error.clone(), "OSError" => ctx.exceptions.os_error.clone(), - }); - - #[cfg(not(target_arch = "wasm32"))] - ctx.set_attr(&py_mod, "open", ctx.new_rustfunc(io_open)); - - py_mod + }) } pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResult { @@ -801,6 +802,6 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu "__call__", vec![name_arg, bases, namespace.into_object()], )?; - cells.set_item(&vm.ctx, "__class__", class.clone()); + cells.set_item("__class__", class.clone(), vm); Ok(class) } diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index fb757cd0f..cec4b3125 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -13,8 +13,8 @@ fn exception_init(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { vm.new_str("No msg".to_string()) }; let traceback = vm.ctx.new_list(Vec::new()); - vm.ctx.set_attr(&zelf, "msg", msg); - vm.ctx.set_attr(&zelf, "__traceback__", traceback); + vm.set_attr(&zelf, "msg", msg)?; + vm.set_attr(&zelf, "__traceback__", traceback)?; Ok(vm.get_none()) } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 6a09f085a..1a0cc4de7 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -132,21 +132,21 @@ pub trait NameProtocol { impl NameProtocol for Scope { fn load_name(&self, vm: &VirtualMachine, name: &str) -> Option { for dict in self.locals.iter() { - if let Some(value) = dict.get_item(name) { + if let Some(value) = dict.get_item(name, vm) { return Some(value); } } - if let Some(value) = self.globals.get_item(name) { + if let Some(value) = self.globals.get_item(name, vm) { return Some(value); } vm.get_attribute(vm.builtins.clone(), name).ok() } - fn load_cell(&self, _vm: &VirtualMachine, name: &str) -> Option { + fn load_cell(&self, vm: &VirtualMachine, name: &str) -> Option { for dict in self.locals.iter().skip(1) { - if let Some(value) = dict.get_item(name) { + if let Some(value) = dict.get_item(name, vm) { return Some(value); } } @@ -154,7 +154,7 @@ impl NameProtocol for Scope { } fn store_name(&self, vm: &VirtualMachine, key: &str, value: PyObjectRef) { - self.get_locals().set_item(&vm.ctx, key, value) + self.get_locals().set_item(key, value, vm) } fn delete_name(&self, _vm: &VirtualMachine, key: &str) { @@ -392,11 +392,11 @@ impl Frame { // Take all key-value pairs from the dict: let dict_elements = objdict::get_key_value_pairs(&obj); for (key, value) in dict_elements.iter() { - map_obj.set_item(&vm.ctx, &objstr::get_value(key), value.clone()); + map_obj.set_item(key.clone(), value.clone(), vm); } } else { let key = self.pop_value(); - map_obj.set_item(&vm.ctx, &objstr::get_value(&key), obj) + map_obj.set_item(key, obj, vm) } } self.push_value(map_obj.into_object()); @@ -585,7 +585,7 @@ impl Frame { let scope = self.scope.clone(); let obj = vm.ctx.new_function(code_obj, scope, defaults); - vm.ctx.set_attr(&obj, "__annotations__", annotations); + vm.set_attr(&obj, "__annotations__", annotations)?; self.push_value(obj); Ok(None) diff --git a/vm/src/import.rs b/vm/src/import.rs index 179dd4321..28b3d02ef 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -39,7 +39,7 @@ fn import_uncached_module(vm: &VirtualMachine, current_path: PathBuf, module: &s // trace!("Code object: {:?}", code_obj); let attrs = vm.ctx.new_dict(); - attrs.set_item(&vm.ctx, "__name__", vm.new_str(module.to_string())); + attrs.set_item("__name__", vm.new_str(module.to_string()), vm); vm.run_code_obj(code_obj, Scope::new(None, attrs.clone()))?; Ok(vm.ctx.new_module(module, attrs)) } diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 47d3c531a..0c37e0dfc 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -114,15 +114,15 @@ macro_rules! no_kwargs { #[macro_export] macro_rules! py_module { - ( $ctx:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => { - { - let py_mod = $ctx.new_module($module_name, $ctx.new_dict()); - $( - $ctx.set_attr(&py_mod, $name, $value); - )* - py_mod - } - } + ( $ctx:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {{ + let mut attributes = $crate::pyobject::PyAttributes::new(); + $( + let value: PyObjectRef = $value.into(); + attributes.insert($name.to_string(), value); + )* + let module_dict = $crate::obj::objdict::PyDictRef::from_attributes($ctx, attributes); + $ctx.new_module($module_name, module_dict) + }}; } #[macro_export] @@ -131,7 +131,7 @@ macro_rules! py_class { { let py_class = $ctx.new_class($class_name, $class_base); $( - $ctx.set_attr(&py_class, $name, $value); + py_class.set_str_attr($name, $value); )* py_class } @@ -143,7 +143,7 @@ macro_rules! extend_class { ( $ctx:expr, $class:expr, { $($name:expr => $value:expr),* $(,)* }) => { let class = $class; $( - $ctx.set_attr(class, $name, $value); + class.set_str_attr($name, $value); )* } } diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 4119d688f..f24c9273c 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -43,8 +43,6 @@ impl PyValue for PyBytes { // Fill bytes class methods: pub fn init(context: &PyContext) { - let bytes_type = context.bytes_type.as_object(); - let bytes_doc = "bytes(iterable_of_ints) -> bytes\n\ bytes(string, encoding[, errors]) -> bytes\n\ @@ -56,7 +54,7 @@ pub fn init(context: &PyContext) { - any object implementing the buffer API.\n \ - an integer"; - extend_class!(context, bytes_type, { + extend_class!(context, &context.bytes_type, { "__new__" => context.new_rustfunc(bytes_new), "__eq__" => context.new_rustfunc(PyBytesRef::eq), "__lt__" => context.new_rustfunc(PyBytesRef::lt), diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index a26645b91..60549cd3a 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -80,8 +80,7 @@ impl PyCodeRef { } pub fn init(context: &PyContext) { - let code_type = context.code_type.as_object(); - extend_class!(context, code_type, { + extend_class!(context, &context.code_type, { "__new__" => context.new_rustfunc(PyCodeRef::new), "__repr__" => context.new_rustfunc(PyCodeRef::repr), diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 15046a405..e110e71f8 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::function::{KwArgs, OptionalArg}; use crate::pyobject::{ - DictProtocol, PyAttributes, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + DictProtocol, IntoPyObject, PyAttributes, PyContext, PyObjectRef, PyRef, PyResult, PyValue, }; use crate::vm::{ReprGuard, VirtualMachine}; @@ -58,7 +58,7 @@ impl PyDictRef { if let OptionalArg::Present(dict_obj) = dict_obj { if objtype::isinstance(&dict_obj, &vm.ctx.dict_type()) { for (needle, value) in get_key_value_pairs(&dict_obj) { - dict.set_item(&vm.ctx, &objstr::get_value(&needle), value); + dict.set_item(needle, value, vm); } } else { let iter = objiter::get_iter(vm, &dict_obj)?; @@ -77,13 +77,12 @@ impl PyDictRef { if objiter::get_next_object(vm, &elem_iter)?.is_some() { return Err(err(vm)); } - dict.set_item(&vm.ctx, &objstr::get_value(&needle), value); + dict.set_item(needle, value, vm); } } } for (needle, value) in kwargs.into_iter() { - let py_needle = vm.new_str(needle); - dict.set_item(&vm.ctx, &objstr::get_value(&py_needle), value); + dict.set_item(vm.new_str(needle), value, vm); } Ok(dict) } @@ -181,7 +180,7 @@ impl PyDictRef { } fn setitem(self, needle: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) { - self.set_item(&vm.ctx, &objstr::get_value(&needle), value) + self.set_item(needle, value, vm) } fn getitem(self, key: PyStringRef, vm: &VirtualMachine) -> PyResult { @@ -216,6 +215,23 @@ impl PyDictRef { } } + // Used during module initialisation when vm isn't available. + pub fn from_attributes(ctx: &PyContext, attributes: PyAttributes) -> PyDictRef { + let dict = ctx.new_dict(); + for (key_str, value) in attributes.into_iter() { + dict.unsafe_str_insert(&key_str, value, ctx); + } + dict + } + + // Pub needed for some nasty edge cases. + // It will be unsafe if there are entries in the dictionary that compare equal. + pub fn unsafe_str_insert(&self, key: &str, value: PyObjectRef, ctx: &PyContext) { + self.entries + .borrow_mut() + .insert(key.to_string(), (ctx.new_str(key.to_string()), value)); + } + /// Take a python dictionary and convert it to attributes. pub fn to_attributes(self) -> PyAttributes { let mut attrs = PyAttributes::new(); @@ -228,12 +244,14 @@ impl PyDictRef { } impl DictProtocol for PyDictRef { - fn contains_key(&self, k: &str) -> bool { - self.entries.borrow().get(k).is_some() + fn contains_key(&self, key: T, vm: &VirtualMachine) -> bool { + let key_str = &objstr::get_value(&key.into_pyobject(vm).unwrap()); + self.entries.borrow().get(key_str).is_some() } - fn get_item(&self, k: &str) -> Option { - match self.entries.borrow().get(k) { + fn get_item(&self, key: T, vm: &VirtualMachine) -> Option { + let key_str = &objstr::get_value(&key.into_pyobject(vm).unwrap()); + match self.entries.borrow().get(key_str) { Some(v) => Some(v.1.clone()), None => None, } @@ -244,10 +262,11 @@ impl DictProtocol for PyDictRef { } // Item set/get: - fn set_item(&self, ctx: &PyContext, key_str: &str, v: PyObjectRef) { - let key = ctx.new_str(key_str.to_string()); + fn set_item(&self, key: T, value: PyObjectRef, vm: &VirtualMachine) { + let key = key.into_pyobject(vm).unwrap(); + let key_str = &objstr::get_value(&key); let elements = &mut self.entries.borrow_mut(); - elements.insert(key_str.to_string(), (key.clone(), v.clone())); + elements.insert(key_str.to_string(), (key.clone(), value)); } fn del_item(&self, key: &str) { diff --git a/vm/src/obj/objellipsis.rs b/vm/src/obj/objellipsis.rs index 8ce843352..6591d8173 100644 --- a/vm/src/obj/objellipsis.rs +++ b/vm/src/obj/objellipsis.rs @@ -3,8 +3,7 @@ use crate::pyobject::{PyContext, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { - let ellipsis_type = context.ellipsis_type.as_object(); - extend_class!(context, ellipsis_type, { + extend_class!(context, &context.ellipsis_type, { "__new__" => context.new_rustfunc(ellipsis_new), "__repr__" => context.new_rustfunc(ellipsis_repr) }); diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 7f53fb5ae..cfe44dea3 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -20,7 +20,7 @@ pub fn new_memory_view( bytes_object: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - vm.ctx.set_attr(&cls, "obj", bytes_object.clone()); + vm.set_attr(cls.as_object(), "obj", bytes_object.clone())?; PyMemoryView { obj: bytes_object }.into_ref_with_type(vm, cls) } diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 11a8309ab..86a56de5d 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -77,7 +77,7 @@ fn object_setattr( } if let Some(ref dict) = obj.clone().dict { - dict.set_item(&vm.ctx, &attr_name.value, value); + dict.set_item(attr_name, value, vm); Ok(()) } else { Err(vm.new_attribute_error(format!( @@ -208,7 +208,7 @@ fn object_getattribute(obj: PyObjectRef, name_str: PyStringRef, vm: &VirtualMach } } - if let Some(obj_attr) = object_getattr(&obj, &name) { + if let Some(obj_attr) = object_getattr(&obj, &name, &vm) { Ok(obj_attr) } else if let Some(attr) = objtype::class_get_attr(&cls, &name) { vm.call_get_descriptor(attr, obj) @@ -219,9 +219,9 @@ fn object_getattribute(obj: PyObjectRef, name_str: PyStringRef, vm: &VirtualMach } } -fn object_getattr(obj: &PyObjectRef, attr_name: &str) -> Option { +fn object_getattr(obj: &PyObjectRef, attr_name: &str, vm: &VirtualMachine) -> Option { if let Some(ref dict) = obj.dict { - dict.get_item(attr_name) + dict.get_item(attr_name, vm) } else { None } diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 592a4950f..62cc923b1 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -762,6 +762,12 @@ impl IntoPyObject for &str { } } +impl IntoPyObject for &String { + fn into_pyobject(self, vm: &VirtualMachine) -> PyResult { + Ok(vm.ctx.new_str(self.clone())) + } +} + pub fn init(ctx: &PyContext) { PyStringRef::extend_class(ctx, &ctx.str_type); } diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index 24424d265..19c7c2ea8 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -124,7 +124,7 @@ fn super_new( } else { let frame = vm.current_frame().expect("no current frame for super()"); if let Some(first_arg) = frame.code.arg_names.get(0) { - match vm.get_locals().get_item(first_arg) { + match vm.get_locals().get_item(first_arg, vm) { Some(obj) => obj.clone(), _ => { return Err(vm diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 16cfbaa5e..b1b50dfbd 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -162,6 +162,13 @@ impl PyClassRef { Ok(()) } + // This is used for class initialisation where the vm is not yet available. + pub fn set_str_attr>(&self, attr_name: &str, value: V) { + self.attributes + .borrow_mut() + .insert(attr_name.to_string(), value.into()); + } + fn subclasses(self, _vm: &VirtualMachine) -> PyList { let mut subclasses = self.subclasses.borrow_mut(); subclasses.retain(|x| x.upgrade().is_some()); diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 12d6fa1ca..0c7d4955b 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -684,24 +684,6 @@ impl PyContext { .into_ref() } - pub fn set_attr<'a, T: Into<&'a PyObjectRef>, V: Into>( - &'a self, - obj: T, - attr_name: &str, - value: V, - ) { - let obj = obj.into(); - if let Some(PyClass { ref attributes, .. }) = obj.payload::() { - attributes - .borrow_mut() - .insert(attr_name.to_string(), value.into()); - } else if let Some(ref dict) = obj.dict { - dict.set_item(self, attr_name, value.into()); - } else { - unimplemented!("set_attr unimplemented for: {:?}", obj); - }; - } - pub fn unwrap_constant(&self, value: &bytecode::Constant) -> PyObjectRef { match *value { bytecode::Constant::Integer { ref value } => self.new_int(value.clone()), @@ -931,16 +913,14 @@ impl TypeProtocol for PyRef { } pub trait DictProtocol { - fn contains_key(&self, k: &str) -> bool; - fn get_item(&self, k: &str) -> Option; + fn contains_key(&self, key: T, vm: &VirtualMachine) -> bool; + fn get_item(&self, key: T, vm: &VirtualMachine) -> Option; fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)>; - fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef); + fn set_item(&self, key: T, value: PyObjectRef, vm: &VirtualMachine); fn del_item(&self, key: &str); } pub trait ItemProtocol { - // // Move: doesn't really belong in this protocol. - // fn get_key_value_pairs(&self, vm: &VirtualMachine) -> PyResult; fn get_item(&self, key: T, vm: &VirtualMachine) -> PyResult; fn set_item( &self, @@ -1280,7 +1260,7 @@ pub trait PyClassImpl: PyClassDef { fn extend_class(ctx: &PyContext, class: &PyClassRef) { Self::impl_extend_class(ctx, class); if let Some(doc) = Self::DOC { - ctx.set_attr(class, "__doc__", ctx.new_str(doc.into())); + class.set_str_attr("__doc__", ctx.new_str(doc.into())); } } diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 9daaf95d2..c6dbbc161 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -99,7 +99,7 @@ fn io_base_cm_exit(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { fn buffered_io_base_init(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(buffered, None), (raw, None)]); - vm.ctx.set_attr(buffered, "raw", raw.clone()); + vm.set_attr(buffered, "raw", raw.clone())?; Ok(vm.get_none()) } @@ -148,10 +148,10 @@ fn file_io_init(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let args = vec![name.clone(), vm.ctx.new_int(os_mode)]; let file_no = os::os_open(vm, PyFuncArgs::new(args, vec![]))?; - vm.ctx.set_attr(file_io, "name", name.clone()); - vm.ctx.set_attr(file_io, "fileno", file_no); - vm.ctx.set_attr(file_io, "closefd", vm.new_bool(false)); - vm.ctx.set_attr(file_io, "closed", vm.new_bool(false)); + vm.set_attr(file_io, "name", name.clone())?; + vm.set_attr(file_io, "fileno", file_no)?; + vm.set_attr(file_io, "closefd", vm.new_bool(false))?; + vm.set_attr(file_io, "closed", vm.new_bool(false))?; Ok(vm.get_none()) } @@ -215,7 +215,7 @@ fn file_io_readinto(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { }; let updated = os::raw_file_number(f.into_inner()); - vm.ctx.set_attr(file_io, "fileno", vm.ctx.new_int(updated)); + vm.set_attr(file_io, "fileno", vm.ctx.new_int(updated))?; Ok(vm.get_none()) } @@ -241,7 +241,7 @@ fn file_io_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(len) => { //reset raw fd on the FileIO object let updated = os::raw_file_number(handle); - vm.ctx.set_attr(file_io, "fileno", vm.ctx.new_int(updated)); + vm.set_attr(file_io, "fileno", vm.ctx.new_int(updated))?; //return number of bytes written Ok(vm.ctx.new_int(len)) @@ -273,7 +273,7 @@ fn text_io_wrapper_init(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(text_io_wrapper, None), (buffer, None)] ); - vm.ctx.set_attr(text_io_wrapper, "buffer", buffer.clone()); + vm.set_attr(text_io_wrapper, "buffer", buffer.clone())?; Ok(vm.get_none()) } diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 80f0f45b6..4695b7acb 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -176,7 +176,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> { Some(PyString { ref value }) => value.clone(), _ => unimplemented!("map keys must be strings"), }; - dict.set_item(&self.vm.ctx, &key, value); + dict.set_item(&key, value, self.vm); } Ok(dict.into_object()) } @@ -208,8 +208,10 @@ pub fn de_pyobject(vm: &VirtualMachine, s: &str) -> PyResult { .unwrap(); let json_decode_error = json_decode_error.downcast().unwrap(); let exc = vm.new_exception(json_decode_error, format!("{}", err)); - vm.ctx.set_attr(&exc, "lineno", vm.ctx.new_int(err.line())); - vm.ctx.set_attr(&exc, "colno", vm.ctx.new_int(err.column())); + vm.set_attr(&exc, "lineno", vm.ctx.new_int(err.line())) + .unwrap(); + vm.set_attr(&exc, "colno", vm.ctx.new_int(err.column())) + .unwrap(); exc }) } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 42b4160ca..31b3ee644 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -114,24 +114,22 @@ fn os_error(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { } pub fn make_module(ctx: &PyContext) -> PyObjectRef { - let py_mod = py_module!(ctx, "os", { + let os_name = if cfg!(windows) { + "nt".to_string() + } else { + "posix".to_string() + }; + + py_module!(ctx, "os", { "open" => ctx.new_rustfunc(os_open), "close" => ctx.new_rustfunc(os_close), "error" => ctx.new_rustfunc(os_error), + "name" => ctx.new_str(os_name), "O_RDONLY" => ctx.new_int(0), "O_WRONLY" => ctx.new_int(1), "O_RDWR" => ctx.new_int(2), "O_NONBLOCK" => ctx.new_int(4), "O_APPEND" => ctx.new_int(8), "O_CREAT" => ctx.new_int(512) - }); - - if cfg!(windows) { - ctx.set_attr(&py_mod, "name", ctx.new_str("nt".to_string())); - } else { - // Assume we're on a POSIX system - ctx.set_attr(&py_mod, "name", ctx.new_str("posix".to_string())); - } - - py_mod + }) } diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index a4a37b350..c803daaad 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -3,7 +3,7 @@ use std::{env, mem}; use crate::frame::FrameRef; use crate::function::{OptionalArg, PyFuncArgs}; -use crate::pyobject::{DictProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; /* @@ -124,8 +124,7 @@ setrecursionlimit() -- set the max recursion depth for the interpreter settrace() -- set the global debug tracing function "; let modules = ctx.new_dict(); - let sys_name = "sys"; - let sys_mod = py_module!(ctx, sys_name, { + let sys_mod = py_module!(ctx, "sys", { "argv" => argv(ctx), "getrefcount" => ctx.new_rustfunc(sys_getrefcount), "getsizeof" => ctx.new_rustfunc(sys_getsizeof), @@ -135,11 +134,11 @@ settrace() -- set the global debug tracing function "ps2" => ctx.new_str("..... ".to_string()), "__doc__" => ctx.new_str(sys_doc.to_string()), "_getframe" => ctx.new_rustfunc(getframe), + "modules" => modules.clone(), }); - modules.set_item(&ctx, sys_name, sys_mod.clone()); - modules.set_item(&ctx, "builtins", builtins); - ctx.set_attr(&sys_mod, "modules", modules); + modules.unsafe_str_insert("sys", sys_mod.clone(), &ctx); + modules.unsafe_str_insert("builtins", builtins, &ctx); sys_mod } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 1649d4efc..6c35983e7 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -419,7 +419,7 @@ impl VirtualMachine { for i in 0..n { let arg_name = &code_object.arg_names[i]; let arg = &args.args[i]; - locals.set_item(&self.ctx, arg_name, arg.clone()); + locals.set_item(arg_name, arg.clone(), self); } // Pack other positional arguments in to *args: @@ -432,7 +432,7 @@ impl VirtualMachine { } let vararg_value = self.ctx.new_tuple(last_args); - locals.set_item(&self.ctx, vararg_name, vararg_value); + locals.set_item(vararg_name, vararg_value, self); } bytecode::Varargs::Unnamed => { // just ignore the rest of the args @@ -452,7 +452,7 @@ impl VirtualMachine { let kwargs = match code_object.varkeywords { bytecode::Varargs::Named(ref kwargs_name) => { let d = self.ctx.new_dict(); - locals.set_item(&self.ctx, kwargs_name, d.as_object().clone()); + locals.set_item(kwargs_name, d.as_object().clone(), self); Some(d) } bytecode::Varargs::Unnamed => Some(self.ctx.new_dict()), @@ -464,15 +464,15 @@ impl VirtualMachine { // Check if we have a parameter with this name: if code_object.arg_names.contains(&name) || code_object.kwonlyarg_names.contains(&name) { - if locals.contains_key(&name) { + if locals.contains_key(&name, self) { return Err( self.new_type_error(format!("Got multiple values for argument '{}'", name)) ); } - locals.set_item(&self.ctx, &name, value); + locals.set_item(&name, value, self); } else if let Some(d) = &kwargs { - d.set_item(&self.ctx, &name, value); + d.set_item(&name, value, self); } else { return Err( self.new_type_error(format!("Got an unexpected keyword argument '{}'", name)) @@ -499,7 +499,7 @@ impl VirtualMachine { let mut missing = vec![]; for i in 0..required_args { let variable_name = &code_object.arg_names[i]; - if !locals.contains_key(variable_name) { + if !locals.contains_key(variable_name, self) { missing.push(variable_name) } } @@ -515,12 +515,8 @@ impl VirtualMachine { // the default if we don't already have a value for (default_index, i) in (required_args..nexpected_args).enumerate() { let arg_name = &code_object.arg_names[i]; - if !locals.contains_key(arg_name) { - locals.set_item( - &self.ctx, - arg_name, - available_defaults[default_index].clone(), - ); + if !locals.contains_key(arg_name, self) { + locals.set_item(arg_name, available_defaults[default_index].clone(), self); } } }; @@ -528,7 +524,7 @@ impl VirtualMachine { // Check if kw only arguments are all present: let kwdefs: HashMap = HashMap::new(); for arg_name in &code_object.kwonlyarg_names { - if !locals.contains_key(arg_name) { + if !locals.contains_key(arg_name, self) { if kwdefs.contains_key(arg_name) { // If not yet specified, take the default value unimplemented!(); diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index af6ad029e..717c9a973 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -192,7 +192,7 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef { for pair in object_entries(&Object::from(js_val)) { let (key, val) = pair.expect("iteration over object to not fail"); let py_val = js_to_py(vm, val); - dict.set_item(&vm.ctx, &String::from(js_sys::JsString::from(key)), py_val); + dict.set_item(&String::from(js_sys::JsString::from(key)), py_val, vm); } dict.into_object() } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index c7e637a9f..6e4ceaee2 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -243,8 +243,7 @@ impl WASMVirtualMachine { } else { return Err(error()); }; - let rustfunc = vm.ctx.new_rustfunc(print_fn); - vm.ctx.set_attr(&vm.builtins, "print", rustfunc); + vm.set_attr(&vm.builtins, "print", vm.ctx.new_rustfunc(print_fn))?; Ok(()) })? }