diff --git a/stdlib/src/json.rs b/stdlib/src/json.rs index a699d2971..897886023 100644 --- a/stdlib/src/json.rs +++ b/stdlib/src/json.rs @@ -5,13 +5,12 @@ mod machinery; mod _json { use super::machinery; use crate::vm::{ - builtins::PyBaseExceptionRef, - builtins::{PyStrRef, PyTypeRef}, + builtins::{PyBaseExceptionRef, PyStrRef, PyTypeRef}, function::{FuncArgs, OptionalArg}, - iterator, + protocol::PyIterReturn, slots::{Callable, SlotConstructor}, - IdProtocol, IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, - VirtualMachine, + IdProtocol, IntoPyObject, IntoPyResult, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, VirtualMachine, }; use num_bigint::BigInt; use std::str::FromStr; @@ -74,42 +73,48 @@ mod _json { idx: usize, scan_once: PyObjectRef, vm: &VirtualMachine, - ) -> PyResult { - let c = s - .chars() - .next() - .ok_or_else(|| iterator::stop_iter_with_value(vm.ctx.new_int(idx), vm))?; + ) -> PyResult { + let c = match s.chars().next() { + Some(c) => c, + None => return Ok(PyIterReturn::StopIteration(Some(vm.ctx.new_int(idx)))), + }; let next_idx = idx + c.len_utf8(); match c { '"' => { return scanstring(pystr, next_idx, OptionalArg::Present(self.strict), vm) - .map(|x| x.into_pyobject(vm)) + .map(|x| PyIterReturn::Return(x.into_pyobject(vm))) } '{' => { // TODO: parse the object in rust let parse_obj = vm.get_attribute(self.ctx.clone(), "parse_object")?; - return vm.invoke( - &parse_obj, - ( - vm.ctx - .new_tuple(vec![pystr.into_object(), vm.ctx.new_int(next_idx)]), - self.strict, - scan_once, - self.object_hook.clone(), - self.object_pairs_hook.clone(), + return PyIterReturn::from_pyresult( + vm.invoke( + &parse_obj, + ( + vm.ctx + .new_tuple(vec![pystr.into_object(), vm.ctx.new_int(next_idx)]), + self.strict, + scan_once, + self.object_hook.clone(), + self.object_pairs_hook.clone(), + ), ), + vm, ); } '[' => { // TODO: parse the array in rust let parse_array = vm.get_attribute(self.ctx.clone(), "parse_array")?; - return vm.invoke( - &parse_array, - vec![ - vm.ctx - .new_tuple(vec![pystr.into_object(), vm.ctx.new_int(next_idx)]), - scan_once, - ], + return PyIterReturn::from_pyresult( + vm.invoke( + &parse_array, + vec![ + vm.ctx + .new_tuple(vec![pystr.into_object(), vm.ctx.new_int(next_idx)]), + scan_once, + ], + ), + vm, ); } _ => {} @@ -118,7 +123,9 @@ mod _json { macro_rules! parse_const { ($s:literal, $val:expr) => { if s.starts_with($s) { - return Ok(vm.ctx.new_tuple(vec![$val, vm.ctx.new_int(idx + $s.len())])); + return Ok(PyIterReturn::Return( + vm.ctx.new_tuple(vec![$val, vm.ctx.new_int(idx + $s.len())]), + )); } }; } @@ -128,16 +135,18 @@ mod _json { parse_const!("false", vm.ctx.new_bool(false)); if let Some((res, len)) = self.parse_number(s, vm) { - return Ok(vm.ctx.new_tuple(vec![res?, vm.ctx.new_int(idx + len)])); + return Ok(PyIterReturn::Return( + vm.ctx.new_tuple(vec![res?, vm.ctx.new_int(idx + len)]), + )); } macro_rules! parse_constant { ($s:literal) => { if s.starts_with($s) { - return Ok(vm.ctx.new_tuple(vec![ + return Ok(PyIterReturn::Return(vm.ctx.new_tuple(vec![ vm.invoke(&self.parse_constant, ($s.to_owned(),))?, vm.ctx.new_int(idx + $s.len()), - ])); + ]))); } }; } @@ -146,7 +155,7 @@ mod _json { parse_constant!("Infinity"); parse_constant!("-Infinity"); - Err(iterator::stop_iter_with_value(vm.ctx.new_int(idx), vm)) + Ok(PyIterReturn::StopIteration(Some(vm.ctx.new_int(idx)))) } fn parse_number(&self, s: &str, vm: &VirtualMachine) -> Option<(PyResult, usize)> { @@ -185,16 +194,19 @@ mod _json { Some((ret, buf.len())) } - fn call(zelf: &PyRef, pystr: PyStrRef, idx: isize, vm: &VirtualMachine) -> PyResult { + fn call( + zelf: &PyRef, + pystr: PyStrRef, + idx: isize, + vm: &VirtualMachine, + ) -> PyResult { if idx < 0 { return Err(vm.new_value_error("idx cannot be negative".to_owned())); } let idx = idx as usize; let mut chars = pystr.as_str().chars(); - if idx > 0 { - chars - .nth(idx - 1) - .ok_or_else(|| iterator::stop_iter_with_value(vm.ctx.new_int(idx), vm))?; + if idx > 0 && chars.nth(idx - 1).is_none() { + return Ok(PyIterReturn::StopIteration(Some(vm.ctx.new_int(idx)))); } zelf.parse( chars.as_str(), @@ -209,7 +221,7 @@ mod _json { impl Callable for JsonScanner { fn call(zelf: &PyRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { let (pystr, idx) = args.bind::<(PyStrRef, isize)>(vm)?; - JsonScanner::call(zelf, pystr, idx, vm) + JsonScanner::call(zelf, pystr, idx, vm).into_pyresult(vm) } } diff --git a/vm/src/iterator.rs b/vm/src/iterator.rs index 0fb0fa938..718a27636 100644 --- a/vm/src/iterator.rs +++ b/vm/src/iterator.rs @@ -25,11 +25,6 @@ where Ok(results) } -pub fn stop_iter_with_value(val: PyObjectRef, vm: &VirtualMachine) -> PyBaseExceptionRef { - let stop_iteration_type = vm.ctx.exceptions.stop_iteration.clone(); - vm.new_exception(stop_iteration_type, vec![val]) -} - pub fn stop_iter_value(vm: &VirtualMachine, exc: &PyBaseExceptionRef) -> PyObjectRef { let args = exc.args(); vm.unwrap_or_none(args.as_slice().first().cloned()) diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 028e9c875..530ef9b75 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -552,20 +552,17 @@ impl fmt::Debug for AwaitPromise { #[pyimpl(with(SlotIterator))] impl AwaitPromise { #[pymethod] - fn send(&self, val: Option, vm: &VirtualMachine) -> PyResult { + fn send(&self, val: Option, vm: &VirtualMachine) -> PyResult { match self.obj.take() { Some(prom) => { if val.is_some() { Err(vm .new_type_error("can't send non-None value to an awaitpromise".to_owned())) } else { - Ok(prom) + Ok(PyIterReturn::Return(prom)) } } - None => Err(rustpython_vm::iterator::stop_iter_with_value( - vm.unwrap_or_none(val), - vm, - )), + None => Ok(PyIterReturn::StopIteration(val)), } } @@ -590,7 +587,7 @@ impl AwaitPromise { impl IteratorIterable for AwaitPromise {} impl SlotIterator for AwaitPromise { fn next(zelf: &PyRef, vm: &VirtualMachine) -> PyResult { - PyIterReturn::from_pyresult(zelf.send(None, vm), vm) + zelf.send(None, vm) } }