Skip to content

Commit 0acfc10

Browse files
committed
Merge with master branch
2 parents 9f06835 + 903bf41 commit 0acfc10

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

tests/snippets/builtin_pow.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
assert pow(3,2) == 9
2+
assert pow(5,3, 100) == 25
3+
4+
#causes overflow
5+
# assert pow(41, 7, 2) == 1
6+
assert pow(7, 2, 49) == 0

vm/src/builtins.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,38 @@ fn builtin_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
290290
// builtin_oct
291291
// builtin_open
292292
// builtin_ord
293-
// builtin_pow
293+
294+
fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
295+
arg_check!(
296+
vm,
297+
args,
298+
required = [(x, None), (y, None)],
299+
optional = [(mod_value, Some(vm.ctx.int_type()))]
300+
);
301+
let pow_method_name = "__pow__".to_string();
302+
let result = match vm.get_attribute(x.clone(), &pow_method_name) {
303+
Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])),
304+
Err(..) => Err(vm.new_type_error("unsupported operand type(s) for pow".to_string())),
305+
};
306+
//Check if the 3rd argument is defined and perform modulus on the result
307+
//this should be optimized in the future to perform a "power-mod" algorithm in
308+
//order to improve performance
309+
match mod_value {
310+
Some(mod_value) => {
311+
let mod_method_name = "__mod__".to_string();
312+
match vm.get_attribute(
313+
result.expect("result not defined").clone(),
314+
&mod_method_name,
315+
) {
316+
Ok(value) => vm.invoke(value, PyFuncArgs::new(vec![mod_value.clone()], vec![])),
317+
Err(..) => {
318+
Err(vm.new_type_error("unsupported operand type(s) for mod".to_string()))
319+
}
320+
}
321+
}
322+
None => result,
323+
}
324+
}
294325

295326
pub fn builtin_print(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
296327
trace!("print called with {:?}", args);
@@ -386,6 +417,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
386417
dict.insert(String::from("list"), ctx.list_type());
387418
dict.insert(String::from("locals"), ctx.new_rustfunc(builtin_locals));
388419
dict.insert(String::from("next"), ctx.new_rustfunc(builtin_next));
420+
dict.insert(String::from("pow"), ctx.new_rustfunc(builtin_pow));
389421
dict.insert(String::from("print"), ctx.new_rustfunc(builtin_print));
390422
dict.insert(String::from("range"), ctx.new_rustfunc(builtin_range));
391423
dict.insert(String::from("repr"), ctx.new_rustfunc(builtin_repr));

vm/src/obj/objint.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn int_truediv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
156156
} else if objtype::isinstance(i2, vm.ctx.float_type()) {
157157
Ok(vm.ctx.new_float(v1 as f64 / objfloat::get_value(i2)))
158158
} else {
159-
Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", i, i2)))
159+
Err(vm.new_type_error(format!("Cannot divide {:?} and {:?}", i, i2)))
160160
}
161161
}
162162

@@ -188,7 +188,7 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
188188
let v2 = objfloat::get_value(i2);
189189
Ok(vm.ctx.new_float((v1 as f64).powf(v2)))
190190
} else {
191-
Err(vm.new_type_error(format!("Cannot modulo {:?} and {:?}", i, i2)))
191+
Err(vm.new_type_error(format!("Cannot raise power {:?} and {:?}", i, i2)))
192192
}
193193
}
194194

0 commit comments

Comments
 (0)