From abba4ae9cca1072cd05fbde76bdadd567d9de319 Mon Sep 17 00:00:00 2001 From: rmliddle Date: Sun, 9 Sep 2018 00:05:13 +1000 Subject: [PATCH 1/2] implemented pow builtin --- tests/snippets/builtin_pow.py | 6 ++++++ vm/src/builtins.rs | 38 ++++++++++++++++++++++++++++++++++- vm/src/obj/objint.rs | 4 ++-- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/snippets/builtin_pow.py diff --git a/tests/snippets/builtin_pow.py b/tests/snippets/builtin_pow.py new file mode 100644 index 000000000..cd8321da5 --- /dev/null +++ b/tests/snippets/builtin_pow.py @@ -0,0 +1,6 @@ +assert pow(3,2) == 9 +assert pow(5,3, 100) == 25 + +#causes overflow +# assert pow(41, 7, 2) == 1 +assert pow(7, 2, 49) == 0 diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 3db700026..69f4ac5ca 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -259,7 +259,42 @@ fn builtin_locals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_oct // builtin_open // builtin_ord -// builtin_pow + +fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!( + vm, + args, + required = [(x, None), (y, None)], + optional=[(mod_value, Some(vm.ctx.int_type()))] + ); + let pow_method_name = "__pow__".to_string(); + let result = match vm.get_attribute(x.clone(), &pow_method_name) { + Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])), + Err(..) => Err(vm.new_type_error("unsupported operand type(s) for pow".to_string())) + }; + //Check if the 3rd argument is defined and perform modulus on the result + //this should be optimized in the future to perform a "power-mod" algorithm in + //order to improve performance + match mod_value { + Some(mod_value) => { + let mod_method_name = "__mod__".to_string(); + match vm.get_attribute( + result.expect("result not defined").clone(), + &mod_method_name + ) { + Ok(value) => vm.invoke( + value, + PyFuncArgs::new(vec![mod_value.clone()], vec![]) + ), + Err(..) => Err( + vm.new_type_error("unsupported operand type(s) for mod".to_string()) + ) + } + } + None => result + } +} + pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("print called with {:?}", args); @@ -350,6 +385,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef { dict.insert(String::from("len"), ctx.new_rustfunc(builtin_len)); dict.insert(String::from("list"), ctx.list_type()); dict.insert(String::from("locals"), ctx.new_rustfunc(builtin_locals)); + dict.insert(String::from("pow"), ctx.new_rustfunc(builtin_pow)); dict.insert(String::from("print"), ctx.new_rustfunc(builtin_print)); dict.insert(String::from("range"), ctx.new_rustfunc(builtin_range)); dict.insert(String::from("repr"), ctx.new_rustfunc(builtin_repr)); diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index 7620fbb8d..061d4b39b 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -156,7 +156,7 @@ fn int_truediv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else if objtype::isinstance(i2, vm.ctx.float_type()) { Ok(vm.ctx.new_float(v1 as f64 / objfloat::get_value(i2))) } else { - Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", i, i2))) + Err(vm.new_type_error(format!("Cannot divide {:?} and {:?}", i, i2))) } } @@ -188,7 +188,7 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { let v2 = objfloat::get_value(i2); Ok(vm.ctx.new_float((v1 as f64).powf(v2))) } else { - Err(vm.new_type_error(format!("Cannot modulo {:?} and {:?}", i, i2))) + Err(vm.new_type_error(format!("Cannot raise power {:?} and {:?}", i, i2))) } } From 06f3506b62725829f6ff36199b20b0910ed24a8b Mon Sep 17 00:00:00 2001 From: rmliddle Date: Sun, 9 Sep 2018 00:33:29 +1000 Subject: [PATCH 2/2] formatting fixes on builtin_pow --- vm/src/builtins.rs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 69f4ac5ca..4ecdc2b1b 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -262,15 +262,15 @@ fn builtin_locals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!( - vm, - args, - required = [(x, None), (y, None)], - optional=[(mod_value, Some(vm.ctx.int_type()))] + vm, + args, + required = [(x, None), (y, None)], + optional = [(mod_value, Some(vm.ctx.int_type()))] ); let pow_method_name = "__pow__".to_string(); let result = match vm.get_attribute(x.clone(), &pow_method_name) { Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])), - Err(..) => Err(vm.new_type_error("unsupported operand type(s) for pow".to_string())) + Err(..) => Err(vm.new_type_error("unsupported operand type(s) for pow".to_string())), }; //Check if the 3rd argument is defined and perform modulus on the result //this should be optimized in the future to perform a "power-mod" algorithm in @@ -279,23 +279,19 @@ fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Some(mod_value) => { let mod_method_name = "__mod__".to_string(); match vm.get_attribute( - result.expect("result not defined").clone(), - &mod_method_name - ) { - Ok(value) => vm.invoke( - value, - PyFuncArgs::new(vec![mod_value.clone()], vec![]) - ), - Err(..) => Err( - vm.new_type_error("unsupported operand type(s) for mod".to_string()) - ) + result.expect("result not defined").clone(), + &mod_method_name, + ) { + Ok(value) => vm.invoke(value, PyFuncArgs::new(vec![mod_value.clone()], vec![])), + Err(..) => { + Err(vm.new_type_error("unsupported operand type(s) for mod".to_string())) + } } } - None => result + None => result, } } - pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { trace!("print called with {:?}", args); for a in args.args {