From e68dbf6705ea2d69e2d4836ebfdee671b70d79c5 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Sun, 2 Sep 2018 10:50:03 +0100 Subject: [PATCH 1/4] Ints aren't mutable, change int.__init__ to int.__new__ --- vm/src/obj/objint.rs | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 4b3df926a..92513f485 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -1,6 +1,6 @@ use super::super::pyobject::{ - AttributeProtocol, FromPyObjectRef, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, - TypeProtocol, + AttributeProtocol, FromPyObjectRef, PyContext, PyFuncArgs, PyObject, PyObjectKind, PyObjectRef, + PyResult, TypeProtocol, }; use super::super::vm::VirtualMachine; use super::objfloat; @@ -12,22 +12,16 @@ fn str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.new_str(v.to_string())) } -// __init__ (store value into objectkind) -fn int_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!( - vm, - args, - required = [(zelf, Some(vm.ctx.int_type())), (arg, None)] - ); - - // Try to cast to int: - let val = match to_int(vm, arg) { - Ok(val) => val, - Err(err) => return Err(err), - }; - - set_value(zelf, val); - Ok(vm.get_none()) +fn int_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + let ref cls = args.args[0]; + if !objtype::issubclass(cls.clone(), vm.ctx.int_type()) { + return Err(vm.new_type_error(format!("{:?} is not a subtype of int", cls))); + } + let val = to_int(vm, &args.args[1].clone())?; + Ok(PyObject::new( + PyObjectKind::Integer { value: val }, + cls.clone(), + )) } // Casting function: @@ -51,10 +45,6 @@ pub fn get_value(obj: &PyObjectRef) -> i32 { } } -fn set_value(obj: &PyObjectRef, value: i32) { - obj.borrow_mut().kind = PyObjectKind::Integer { value }; -} - impl FromPyObjectRef for i32 { fn from_pyobj(obj: &PyObjectRef) -> i32 { get_value(obj) @@ -224,7 +214,7 @@ pub fn init(context: &PyContext) { int_type.set_attr("__eq__", context.new_rustfunc(int_eq)); int_type.set_attr("__add__", context.new_rustfunc(int_add)); int_type.set_attr("__and__", context.new_rustfunc(int_and)); - int_type.set_attr("__init__", context.new_rustfunc(int_init)); + int_type.set_attr("__new__", context.new_rustfunc(int_new)); int_type.set_attr("__mod__", context.new_rustfunc(int_mod)); int_type.set_attr("__mul__", context.new_rustfunc(int_mul)); int_type.set_attr("__or__", context.new_rustfunc(int_or)); From e611533d02e06f0e0b1d5161332a36ab9ac26aab Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Sun, 2 Sep 2018 10:51:05 +0100 Subject: [PATCH 2/4] Let getattribute fall through and attribute error on types with dicts. --- vm/src/pyobject.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index ca9d0e0c2..0373ca69b 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -417,7 +417,7 @@ impl AttributeProtocol for PyObjectRef { None } PyObjectKind::Instance { ref dict } => dict.get_item(attr_name), - ref kind => unimplemented!("load_attr unimplemented for: {:?}", kind), + _ => None, } } From 76344e5023368953c605f2ee25fbc2130c202234 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Sun, 2 Sep 2018 10:57:30 +0100 Subject: [PATCH 3/4] Add object.__init__ --- vm/src/obj/objobject.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 9206ba266..0df0ba44e 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -59,12 +59,17 @@ fn object_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { pub fn init(context: &PyContext) { let ref object = context.object; object.set_attr("__new__", context.new_rustfunc(new_instance)); + object.set_attr("__init__", context.new_rustfunc(object_init)); object.set_attr("__eq__", context.new_rustfunc(object_eq)); object.set_attr("__ne__", context.new_rustfunc(object_ne)); object.set_attr("__dict__", context.new_member_descriptor(object_dict)); object.set_attr("__str__", context.new_rustfunc(object_str)); } +fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult { + Ok(vm.ctx.none()) +} + fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { match args.args[0].borrow().kind { PyObjectKind::Class { ref dict, .. } => Ok(dict.clone()), From ec0eb47fc6c63e745ffc964f190cd0a042a56400 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Sun, 2 Sep 2018 10:59:42 +0100 Subject: [PATCH 4/4] Add snippet to check that int.__init__ doesn't mutate int. --- tests/snippets/numbers.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/snippets/numbers.py diff --git a/tests/snippets/numbers.py b/tests/snippets/numbers.py new file mode 100644 index 000000000..eae26b102 --- /dev/null +++ b/tests/snippets/numbers.py @@ -0,0 +1,10 @@ +x = 5 +x.__init__(6) +assert x == 5 + +class A(int): + pass + +x = A(7) +assert x == 7 +assert type(x) is A