Do some more refactoring, but better

This commit is contained in:
Noah committed 2020-03-21 00:35:38 -05:00
1 parent c1bf5124b1
commit 08593cd9f3
4 files changed
+94 -52

No files matched your search

+47 -29
View File
@@ -1,6 +1,7 @@
use super::objcode::PyCodeRef;
use super::objcoroinner::{Coro, Variant};
use super::objtype::{self, PyClassRef};
use crate::exceptions::PyBaseExceptionRef;
use crate::frame::FrameRef;
use crate::function::OptionalArg;
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
@@ -36,6 +37,12 @@ impl PyAsyncGen {
.into_ref(vm)
}
// TODO: fix function names situation
#[pyproperty(magic)]
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
vm.get_none()
}
#[pymethod(name = "__aiter__")]
fn aiter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
zelf
@@ -297,7 +304,7 @@ impl PyAsyncGenAThrow {
}
if !vm.is_none(&val) {
return Err(vm.new_runtime_error(
"can't send non-None value to a just-started coroutine".to_owned(),
"can't send non-None value to a just-started async generator".to_owned(),
));
}
self.state.set(AwaitableState::Iter);
@@ -306,18 +313,26 @@ impl PyAsyncGenAThrow {
let (ty, val, tb) = self.value.clone();
let ret = self.ag.inner.throw(ty, val, tb, vm);
let ret = if self.aclose {
self.check_no_ignore(&ret, vm)?;
ret
if self.ignored_close(&ret) {
Err(self.yield_close(vm))
} else {
ret
}
} else {
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
};
self.check_error(ret, vm)
ret.map_err(|e| self.check_error(e, vm))
}
AwaitableState::Iter => {
let ret = self.ag.inner.send(val, vm);
if self.aclose {
self.check_no_ignore(&ret, vm)?;
self.check_error(ret, vm)
match ret {
Ok(v) if v.payload_is::<PyAsyncGenWrappedValue>() => {
Err(self.yield_close(vm))
}
Ok(v) => Ok(v),
Err(e) => Err(self.check_error(e, vm)),
}
} else {
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
}
@@ -339,12 +354,16 @@ impl PyAsyncGenAThrow {
exc_tb.unwrap_or_else(|| vm.get_none()),
vm,
);
if self.aclose {
self.check_no_ignore(&ret, vm)?;
self.check_error(ret, vm)
let res = if self.aclose {
if self.ignored_close(&ret) {
Err(self.yield_close(vm))
} else {
ret
}
} else {
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
}
};
res.map_err(|e| self.check_error(e, vm))
}
#[pymethod]
@@ -352,27 +371,26 @@ impl PyAsyncGenAThrow {
self.state.set(AwaitableState::Closed);
}
fn check_no_ignore(&self, res: &PyResult, vm: &VirtualMachine) -> PyResult<()> {
if let Ok(ref v) = res {
if v.payload_is::<PyAsyncGenWrappedValue>() {
return Err(
vm.new_runtime_error("async generator ignored GeneratorExit".to_owned())
);
}
}
Ok(())
fn ignored_close(&self, res: &PyResult) -> bool {
res.as_ref()
.map_or(false, |v| v.payload_is::<PyAsyncGenWrappedValue>())
}
fn check_error(&self, res: PyResult, vm: &VirtualMachine) -> PyResult {
if self.aclose {
if let Err(ref e) = res {
if objtype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration)
|| objtype::isinstance(&e, &vm.ctx.exceptions.generator_exit)
{
return Err(vm.new_exception_empty(vm.ctx.exceptions.stop_iteration.clone()));
}
}
fn yield_close(&self, vm: &VirtualMachine) -> PyBaseExceptionRef {
self.ag.running_async.set(false);
self.state.set(AwaitableState::Closed);
vm.new_runtime_error("async generator ignored GeneratorExit".to_owned())
}
fn check_error(&self, exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyBaseExceptionRef {
self.ag.running_async.set(false);
self.state.set(AwaitableState::Closed);
if self.aclose
&& (objtype::isinstance(&exc, &vm.ctx.exceptions.stop_async_iteration)
|| objtype::isinstance(&exc, &vm.ctx.exceptions.generator_exit))
{
vm.new_exception_empty(vm.ctx.exceptions.stop_iteration.clone())
} else {
exc
}
res
}
}
+35 -23
View File
@@ -1,4 +1,4 @@
use super::{objiter, objtype};
use super::objtype;
use crate::exceptions::{self, PyBaseExceptionRef};
use crate::frame::{ExecutionResult, FrameRef};
use crate::pyobject::{PyObjectRef, PyResult};
@@ -71,38 +71,47 @@ impl Coro {
);
self.running.set(false);
self.started.set(true);
if let Err(ref e) = result {
if objtype::isinstance(e, &vm.ctx.exceptions.stop_iteration) {
let err =
vm.new_runtime_error(format!("{} raised StopIteration", self.variant.name()));
err.set_cause(Some(e.clone()));
return Err(err);
}
if self.variant == Variant::AsyncGen
&& objtype::isinstance(e, &vm.ctx.exceptions.stop_async_iteration)
{
let err =
vm.new_runtime_error("async generator raise StopAsyncIteration".to_owned());
err.set_cause(Some(e.clone()));
return Err(err);
}
}
result
}
pub fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
if self.closed.get() {
return Err(objiter::new_stop_iteration(vm));
let cls = if let Variant::AsyncGen = self.variant {
vm.ctx.exceptions.stop_async_iteration.clone()
} else {
vm.ctx.exceptions.stop_iteration.clone()
};
return Err(vm.new_exception_empty(cls));
}
if !self.started.get() && !vm.is_none(&value) {
return Err(vm.new_type_error(
"can't send non-None value to a just-started coroutine".to_string(),
));
return Err(vm.new_type_error(format!(
"can't send non-None value to a just-started {}",
self.variant.name()
)));
}
self.frame.push_value(value.clone());
let result = self.run_with_context(|| vm.run_frame(self.frame.clone()), vm);
self.maybe_close(&result);
self.variant.exec_result(result?, vm)
match result {
Ok(exec_res) => self.variant.exec_result(exec_res, vm),
Err(e) => {
if objtype::isinstance(&e, &vm.ctx.exceptions.stop_iteration) {
let err = vm
.new_runtime_error(format!("{} raised StopIteration", self.variant.name()));
err.set_cause(Some(e));
Err(err)
} else if self.variant == Variant::AsyncGen
&& objtype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration)
{
let err = vm
.new_runtime_error("async generator raised StopAsyncIteration".to_owned());
err.set_cause(Some(e));
Err(err)
} else {
Err(e)
}
}
}
}
pub fn throw(
&self,
@@ -142,7 +151,7 @@ impl Coro {
self.closed.set(true);
match result {
Ok(ExecutionResult::Yield(_)) => {
Err(vm.new_runtime_error("generator ignored GeneratorExit".to_owned()))
Err(vm.new_runtime_error(format!("{} ignored GeneratorExit", self.variant.name())))
}
Err(e) if !is_gen_exit(&e, vm) => Err(e),
_ => Ok(()),
@@ -161,6 +170,9 @@ impl Coro {
pub fn frame(&self) -> FrameRef {
self.frame.clone()
}
pub fn name(&self) -> String {
self.frame.code.obj_name.clone()
}
}
pub fn is_gen_exit(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> bool {
+6
View File
@@ -34,6 +34,12 @@ impl PyCoroutine {
.into_ref(vm)
}
// TODO: fix function names situation
#[pyproperty(magic)]
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
vm.get_none()
}
#[pymethod]
fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
self.inner.send(value, vm)
+6
View File
@@ -37,6 +37,12 @@ impl PyGenerator {
.into_ref(vm)
}
// TODO: fix function names situation
#[pyproperty(magic)]
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
vm.get_none()
}
#[pymethod(name = "__iter__")]
fn iter(zelf: PyGeneratorRef) -> PyGeneratorRef {
zelf