Eliminate ctx.set_attr.

This commit is contained in:
Adam Kelly
2019-04-04 14:49:10 +01:00
parent 25c17b4829
commit c8eda3733d
23 changed files with 129 additions and 126 deletions

View File

@@ -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)
}

View File

@@ -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())
}

View File

@@ -132,21 +132,21 @@ pub trait NameProtocol {
impl NameProtocol for Scope {
fn load_name(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> {
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<PyObjectRef> {
fn load_cell(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> {
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)

View File

@@ -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))
}

View File

@@ -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);
)*
}
}

View File

@@ -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),

View File

@@ -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),

View File

@@ -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<T: IntoPyObject>(&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<PyObjectRef> {
match self.entries.borrow().get(k) {
fn get_item<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> Option<PyObjectRef> {
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<T: IntoPyObject>(&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) {

View File

@@ -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)
});

View File

@@ -20,7 +20,7 @@ pub fn new_memory_view(
bytes_object: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<PyMemoryViewRef> {
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)
}

View File

@@ -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<PyObjectRef> {
fn object_getattr(obj: &PyObjectRef, attr_name: &str, vm: &VirtualMachine) -> Option<PyObjectRef> {
if let Some(ref dict) = obj.dict {
dict.get_item(attr_name)
dict.get_item(attr_name, vm)
} else {
None
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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<V: Into<PyObjectRef>>(&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());

View File

@@ -684,24 +684,6 @@ impl PyContext {
.into_ref()
}
pub fn set_attr<'a, T: Into<&'a PyObjectRef>, V: Into<PyObjectRef>>(
&'a self,
obj: T,
attr_name: &str,
value: V,
) {
let obj = obj.into();
if let Some(PyClass { ref attributes, .. }) = obj.payload::<PyClass>() {
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<T> TypeProtocol for PyRef<T> {
}
pub trait DictProtocol {
fn contains_key(&self, k: &str) -> bool;
fn get_item(&self, k: &str) -> Option<PyObjectRef>;
fn contains_key<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> bool;
fn get_item<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> Option<PyObjectRef>;
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)>;
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef);
fn set_item<T: IntoPyObject>(&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<PyListIterator>;
fn get_item<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> PyResult<PyObjectRef>;
fn set_item<T: IntoPyObject>(
&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()));
}
}

View File

@@ -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())
}

View File

@@ -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
})
}

View File

@@ -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
})
}

View File

@@ -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
}

View File

@@ -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<String, String> = 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!();