From 43489bed4c7aa7458b233f4fe2f0fa901de496b8 Mon Sep 17 00:00:00 2001 From: rmliddle Date: Mon, 10 Sep 2018 23:01:07 +1000 Subject: [PATCH 1/5] added abs builtin, __abs__ attributes on float and int objects --- tests/snippets/builtin_abs.py | 5 +++++ vm/src/builtins.rs | 21 +++++++++++++++++++-- vm/src/obj/objfloat.rs | 6 ++++++ vm/src/obj/objint.rs | 6 ++++++ vm/src/vm.rs | 1 + 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/snippets/builtin_abs.py diff --git a/tests/snippets/builtin_abs.py b/tests/snippets/builtin_abs.py new file mode 100644 index 000000000..1b744978e --- /dev/null +++ b/tests/snippets/builtin_abs.py @@ -0,0 +1,5 @@ +assert abs(-3) == 3 +assert abs(7) == 7 +assert abs(-3.21) == 3.21 +assert abs(6.25) == 6.25 + diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 4ecdc2b1b..62d7405cc 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -44,7 +44,13 @@ fn dir_object(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyObjectRef { vm.ctx.new_list(members_pystr) } -// builtin_abs +fn builtin_abs(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(x, None)]); + match vm.get_attribute(x.clone(), &"__abs__") { + Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![], vec![])), + Err(..) => Err(vm.new_type_error("bad operand for abs".to_string())), + } +} fn builtin_all(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { for item in args.args { @@ -347,7 +353,17 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_sorted // builtin_staticmethod -// builtin_sum +// fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { +// arg_check!(vm, args, required = [(obj, None)]); +// match obj.borrow().kind { + +// PyObjectKind::List { ref elements } => { +// Ok(vm.context().new_int(elements.len() as i32)) +// } +// _ => Err(vm.new_type_error("unsupported operand type(s) for mod".to_string())) +// } +// } + // builtin_super // builtin_vars // builtin_zip @@ -356,6 +372,7 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { pub fn make_module(ctx: &PyContext) -> PyObjectRef { // scope[String::from("print")] = print; let mut dict = HashMap::new(); + dict.insert(String::from("abs"), ctx.new_rustfunc(builtin_abs)); dict.insert(String::from("all"), ctx.new_rustfunc(builtin_all)); dict.insert(String::from("any"), ctx.new_rustfunc(builtin_any)); dict.insert(String::from("bool"), ctx.bool_type()); diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 376627ee4..bb51aa064 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -61,6 +61,11 @@ fn float_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_bool(result)) } +fn float_abs(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(i, Some(vm.ctx.float_type()))]); + Ok(vm.ctx.new_float(get_value(i).abs())) +} + fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -117,6 +122,7 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { pub fn init(context: &PyContext) { let ref float_type = context.float_type; float_type.set_attr("__eq__", context.new_rustfunc(float_eq)); + float_type.set_attr("__abs__", context.new_rustfunc(float_abs)); float_type.set_attr("__add__", context.new_rustfunc(float_add)); float_type.set_attr("__init__", context.new_rustfunc(float_init)); float_type.set_attr("__pow__", context.new_rustfunc(float_pow)); diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 061d4b39b..7aff1daec 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -99,6 +99,11 @@ fn int_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_bool(result)) } +fn int_abs(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(i, Some(vm.ctx.int_type()))]); + Ok(vm.ctx.new_int(get_value(i).abs())) +} + fn int_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -240,6 +245,7 @@ fn int_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { pub fn init(context: &PyContext) { let ref int_type = context.int_type; int_type.set_attr("__eq__", context.new_rustfunc(int_eq)); + int_type.set_attr("__abs__", context.new_rustfunc(int_abs)); int_type.set_attr("__add__", context.new_rustfunc(int_add)); int_type.set_attr("__and__", context.new_rustfunc(int_and)); int_type.set_attr("__new__", context.new_rustfunc(int_new)); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index a50b2eb4b..b81d9acab 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -428,6 +428,7 @@ impl VirtualMachine { // self.invoke('__neg__' match a.borrow().kind { PyObjectKind::Integer { value: ref value1 } => Ok(self.ctx.new_int(-*value1)), + PyObjectKind::Float { value: ref value1 } => Ok(self.ctx.new_float(-*value1)), _ => panic!("Not impl {:?}", a), } } From 256d518c4a71a9e6e563f63b1c907e03721b4968 Mon Sep 17 00:00:00 2001 From: rmliddle Date: Tue, 11 Sep 2018 21:56:08 +1000 Subject: [PATCH 2/5] floordiv, float mod --- vm/src/obj/objfloat.rs | 34 ++++++++++++++++++++++++++++++++++ vm/src/obj/objint.rs | 16 ++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index bb51aa064..8045fe48f 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -83,6 +83,21 @@ fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.float_type())), (i2, None)] + ); + if objtype::isinstance(i2, vm.ctx.float_type()) { + Ok(vm.ctx.new_float((get_value(i) / get_value(i2)).floor())) + } else if objtype::isinstance(i2, vm.ctx.int_type()) { + Ok(vm.ctx.new_float((get_value(i) / objint::get_value(i2) as f64).floor())) + } else { + Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2))) + } +} + fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -100,6 +115,22 @@ fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.float_type())), (i2, None)] + ); + + if objtype::isinstance(i2, vm.ctx.float_type()) { + Ok(vm.ctx.new_float(get_value(i) % get_value(i2))) + } else if objtype::isinstance(i2, vm.ctx.int_type()) { + Ok(vm.ctx.new_float(get_value(i) % objint::get_value(i2) as f64)) + } else { + Err(vm.new_type_error(format!("Cannot mod {:?} and {:?}", i, i2))) + } +} + fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -124,8 +155,11 @@ pub fn init(context: &PyContext) { float_type.set_attr("__eq__", context.new_rustfunc(float_eq)); float_type.set_attr("__abs__", context.new_rustfunc(float_abs)); float_type.set_attr("__add__", context.new_rustfunc(float_add)); + float_type.set_attr("__floordiv__", context.new_rustfunc(float_floordiv)); float_type.set_attr("__init__", context.new_rustfunc(float_init)); + float_type.set_attr("__mod__", context.new_rustfunc(float_mod)); float_type.set_attr("__pow__", context.new_rustfunc(float_pow)); float_type.set_attr("__sub__", context.new_rustfunc(float_sub)); float_type.set_attr("__repr__", context.new_rustfunc(float_repr)); + } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 7aff1daec..9326bdce2 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -120,6 +120,19 @@ fn int_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +fn int_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.int_type())), (i2, None)] + ); + if objtype::isinstance(i2, vm.ctx.int_type()) { + Ok(vm.ctx.new_int(get_value(i) / get_value(i2))) + } else { + Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2))) + } +} + fn int_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -144,6 +157,8 @@ fn int_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); if objtype::isinstance(i2, vm.ctx.int_type()) { Ok(vm.ctx.new_int(get_value(i) * get_value(i2))) + } else if objtype::isinstance(i2, vm.ctx.float_type()) { + Ok(vm.ctx.new_float(get_value(i) as f64 * objfloat::get_value(i2))) } else { Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", i, i2))) } @@ -248,6 +263,7 @@ pub fn init(context: &PyContext) { int_type.set_attr("__abs__", context.new_rustfunc(int_abs)); int_type.set_attr("__add__", context.new_rustfunc(int_add)); int_type.set_attr("__and__", context.new_rustfunc(int_and)); + int_type.set_attr("__floordiv__", context.new_rustfunc(int_floordiv)); 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)); From 77772abedfa24d8556f1c09d826e53dae85f6321 Mon Sep 17 00:00:00 2001 From: rmliddle Date: Wed, 12 Sep 2018 22:56:57 +1000 Subject: [PATCH 3/5] div_mod attribute on float and int --- vm/src/obj/objfloat.rs | 20 +++++++++++++++++--- vm/src/obj/objint.rs | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 8045fe48f..bc55f5d60 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -83,6 +83,22 @@ fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } +fn float_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.float_type())), (i2, None)] + ); + let args = PyFuncArgs::new(vec![i.clone(), i2.clone()], vec![]); + if objtype::isinstance(i2, vm.ctx.float_type()) || objtype::isinstance(i2, vm.ctx.int_type()){ + let r1 = float_floordiv(vm, args.clone()); + let r2 = float_mod(vm, args.clone()); + Ok(vm.ctx.new_tuple(vec![r1.unwrap(), r2.unwrap()])) + } else { + Err(vm.new_type_error(format!("Cannot divmod power {:?} and {:?}", i, i2))) + } +} + fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -104,7 +120,6 @@ fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(i, Some(vm.ctx.float_type())), (i2, None)] ); - let v1 = get_value(i); if objtype::isinstance(i2, vm.ctx.float_type()) { Ok(vm.ctx.new_float(v1 - get_value(i2))) @@ -121,7 +136,6 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { args, required = [(i, Some(vm.ctx.float_type())), (i2, None)] ); - if objtype::isinstance(i2, vm.ctx.float_type()) { Ok(vm.ctx.new_float(get_value(i) % get_value(i2))) } else if objtype::isinstance(i2, vm.ctx.int_type()) { @@ -155,11 +169,11 @@ pub fn init(context: &PyContext) { float_type.set_attr("__eq__", context.new_rustfunc(float_eq)); float_type.set_attr("__abs__", context.new_rustfunc(float_abs)); float_type.set_attr("__add__", context.new_rustfunc(float_add)); + float_type.set_attr("__divmod__", context.new_rustfunc(float_divmod)); float_type.set_attr("__floordiv__", context.new_rustfunc(float_floordiv)); float_type.set_attr("__init__", context.new_rustfunc(float_init)); float_type.set_attr("__mod__", context.new_rustfunc(float_mod)); float_type.set_attr("__pow__", context.new_rustfunc(float_pow)); float_type.set_attr("__sub__", context.new_rustfunc(float_sub)); float_type.set_attr("__repr__", context.new_rustfunc(float_repr)); - } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 9326bdce2..c8869ef33 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -212,6 +212,23 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } + +fn int_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(i, Some(vm.ctx.int_type())), (i2, None)] + ); + let args = PyFuncArgs::new(vec![i.clone(), i2.clone()], vec![]); + if objtype::isinstance(i2, vm.ctx.int_type()) { + let r1 = int_floordiv(vm, args.clone()); + let r2 = int_mod(vm, args.clone()); + Ok(vm.ctx.new_tuple(vec![r1.unwrap(), r2.unwrap()])) + } else { + Err(vm.new_type_error(format!("Cannot divmod power {:?} and {:?}", i, i2))) + } +} + fn int_xor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, @@ -263,6 +280,7 @@ pub fn init(context: &PyContext) { int_type.set_attr("__abs__", context.new_rustfunc(int_abs)); int_type.set_attr("__add__", context.new_rustfunc(int_add)); int_type.set_attr("__and__", context.new_rustfunc(int_and)); + int_type.set_attr("__divmod__", context.new_rustfunc(int_divmod)); int_type.set_attr("__floordiv__", context.new_rustfunc(int_floordiv)); int_type.set_attr("__new__", context.new_rustfunc(int_new)); int_type.set_attr("__mod__", context.new_rustfunc(int_mod)); From 1e1e9d26698fee6e757b61259fc5642f066e3a7d Mon Sep 17 00:00:00 2001 From: rmliddle Date: Thu, 13 Sep 2018 08:00:52 +1000 Subject: [PATCH 4/5] divmod builtin --- tests/snippets/builtin_divmod.py | 3 +++ vm/src/builtins.rs | 10 +++++++++- vm/src/obj/objfloat.rs | 12 ++++++++---- vm/src/obj/objint.rs | 5 +++-- 4 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 tests/snippets/builtin_divmod.py diff --git a/tests/snippets/builtin_divmod.py b/tests/snippets/builtin_divmod.py new file mode 100644 index 000000000..7bab71c99 --- /dev/null +++ b/tests/snippets/builtin_divmod.py @@ -0,0 +1,3 @@ +assert divmod(11, 3) == (3, 2) +assert divmod(8,11) == (0, 8) +assert divmod(0.873, 0.252) == (3.0, 0.11699999999999999) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 62d7405cc..d58a25208 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -127,7 +127,14 @@ fn builtin_dir(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } -// builtin_divmod +fn builtin_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(x, None), (y, None)]); + match vm.get_attribute(x.clone(), &"__divmod__") { + Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])), + Err(..) => Err(vm.new_type_error("unsupported operand type(s) for divmod".to_string())), + } +} + // builtin_enumerate fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -380,6 +387,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { dict.insert(String::from("chr"), ctx.new_rustfunc(builtin_chr)); dict.insert(String::from("compile"), ctx.new_rustfunc(builtin_compile)); dict.insert(String::from("dict"), ctx.dict_type()); + dict.insert(String::from("divmod"), ctx.new_rustfunc(builtin_divmod)); dict.insert(String::from("dir"), ctx.new_rustfunc(builtin_dir)); dict.insert(String::from("eval"), ctx.new_rustfunc(builtin_eval)); dict.insert(String::from("float"), ctx.float_type()); diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index bc55f5d60..affd18a95 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -90,7 +90,7 @@ fn float_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(i, Some(vm.ctx.float_type())), (i2, None)] ); let args = PyFuncArgs::new(vec![i.clone(), i2.clone()], vec![]); - if objtype::isinstance(i2, vm.ctx.float_type()) || objtype::isinstance(i2, vm.ctx.int_type()){ + if objtype::isinstance(i2, vm.ctx.float_type()) || objtype::isinstance(i2, vm.ctx.int_type()) { let r1 = float_floordiv(vm, args.clone()); let r2 = float_mod(vm, args.clone()); Ok(vm.ctx.new_tuple(vec![r1.unwrap(), r2.unwrap()])) @@ -108,7 +108,9 @@ fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, vm.ctx.float_type()) { Ok(vm.ctx.new_float((get_value(i) / get_value(i2)).floor())) } else if objtype::isinstance(i2, vm.ctx.int_type()) { - Ok(vm.ctx.new_float((get_value(i) / objint::get_value(i2) as f64).floor())) + Ok(vm + .ctx + .new_float((get_value(i) / objint::get_value(i2) as f64).floor())) } else { Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2))) } @@ -137,9 +139,11 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { required = [(i, Some(vm.ctx.float_type())), (i2, None)] ); if objtype::isinstance(i2, vm.ctx.float_type()) { - Ok(vm.ctx.new_float(get_value(i) % get_value(i2))) + Ok(vm.ctx.new_float(get_value(i) % get_value(i2))) } else if objtype::isinstance(i2, vm.ctx.int_type()) { - Ok(vm.ctx.new_float(get_value(i) % objint::get_value(i2) as f64)) + Ok(vm + .ctx + .new_float(get_value(i) % objint::get_value(i2) as f64)) } else { Err(vm.new_type_error(format!("Cannot mod {:?} and {:?}", i, i2))) } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index c8869ef33..22835fa6a 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -158,7 +158,9 @@ fn int_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { if objtype::isinstance(i2, vm.ctx.int_type()) { Ok(vm.ctx.new_int(get_value(i) * get_value(i2))) } else if objtype::isinstance(i2, vm.ctx.float_type()) { - Ok(vm.ctx.new_float(get_value(i) as f64 * objfloat::get_value(i2))) + Ok(vm + .ctx + .new_float(get_value(i) as f64 * objfloat::get_value(i2))) } else { Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", i, i2))) } @@ -212,7 +214,6 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } } - fn int_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( vm, From e19c3c113bf1f46f7196c12c4fe062b819cd4318 Mon Sep 17 00:00:00 2001 From: rmliddle Date: Thu, 13 Sep 2018 08:07:52 +1000 Subject: [PATCH 5/5] removed commented out function in builtins --- vm/src/builtins.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index d58a25208..fb31120af 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -359,18 +359,7 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_slice // builtin_sorted // builtin_staticmethod - -// fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { -// arg_check!(vm, args, required = [(obj, None)]); -// match obj.borrow().kind { - -// PyObjectKind::List { ref elements } => { -// Ok(vm.context().new_int(elements.len() as i32)) -// } -// _ => Err(vm.new_type_error("unsupported operand type(s) for mod".to_string())) -// } -// } - +// builtin_sum // builtin_super // builtin_vars // builtin_zip