pre-recording backup

This commit is contained in:
2023-05-17 03:49:26 +01:00
parent 126494c63f
commit 330ddbe399
29 changed files with 404 additions and 195 deletions

View File

@@ -5,4 +5,4 @@ mod run;
pub use context::{Context, Return};
pub use error::RuntimeError;
pub use run::{run};
pub use run::{run, run_handler, Handler, HandlerParm, HandlerRes};

View File

@@ -1,4 +1,7 @@
use crate::foreign::AtomicReturn;
use std::mem;
use std::rc::Rc;
use crate::foreign::{AtomicReturn, Atomic, ExternError, Atom};
use crate::representations::Primitive;
use crate::representations::interpreted::{Clause, ExprInst};
@@ -6,9 +9,10 @@ use super::apply::apply;
use super::error::RuntimeError;
use super::context::{Context, Return};
pub fn run(expr: ExprInst, mut ctx: Context)
-> Result<Return, RuntimeError>
{
pub fn run(
expr: ExprInst,
mut ctx: Context
) -> Result<Return, RuntimeError> {
let (state, (gas, inert)) = expr.try_normalize(|cls| -> Result<(Clause, _), RuntimeError> {
let mut i = cls.clone();
while ctx.gas.map(|g| g > 0).unwrap_or(true) {
@@ -39,4 +43,67 @@ pub fn run(expr: ExprInst, mut ctx: Context)
Ok((i, (ctx.gas, false)))
})?;
Ok(Return { state, gas, inert })
}
pub type HandlerParm = Box<dyn Atomic>;
pub type HandlerRes = Result<
Result<ExprInst, Rc<dyn ExternError>>,
HandlerParm
>;
pub trait Handler {
fn resolve(&mut self, data: HandlerParm) -> HandlerRes;
fn then<T: Handler>(self, t: T) -> impl Handler
where Self: Sized {
Pair(self, t)
}
}
impl<F> Handler for F
where F: FnMut(HandlerParm) -> HandlerRes
{
fn resolve(&mut self, data: HandlerParm) -> HandlerRes {
self(data)
}
}
pub struct Pair<T, U>(T, U);
impl<T: Handler, U: Handler> Handler for Pair<T, U> {
fn resolve(&mut self, data: HandlerParm) -> HandlerRes {
match self.0.resolve(data) {
Ok(out) => Ok(out),
Err(data) => self.1.resolve(data)
}
}
}
pub fn run_handler(
mut expr: ExprInst,
mut handler: impl Handler,
mut ctx: Context
) -> Result<Return, RuntimeError> {
loop {
let ret = run(expr.clone(), ctx.clone())?;
if ret.gas == Some(0) {
return Ok(ret)
}
let state_ex = ret.state.expr();
let a = if let Clause::P(Primitive::Atom(a)) = &state_ex.clause {a}
else {
mem::drop(state_ex);
return Ok(ret)
};
let boxed = a.clone().0;
expr = match handler.resolve(boxed) {
Ok(r) => r.map_err(RuntimeError::Extern)?,
Err(e) => return Ok(Return{
gas: ret.gas,
inert: ret.inert,
state: Clause::P(Primitive::Atom(Atom(e))).wrap()
})
};
ctx.gas = ret.gas;
}
}