mirror of
https://github.com/urbit/ares.git
synced 2024-12-24 13:55:23 +03:00
Rework +mink scry failure logic
This commit is contained in:
parent
7e4bf3ae5d
commit
7992d02766
@ -230,7 +230,6 @@ struct Nock12 {
|
||||
reff: Noun,
|
||||
path: Noun,
|
||||
hand: Noun,
|
||||
flag: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -267,41 +266,42 @@ pub struct Context {
|
||||
pub scry_stack: Noun,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Error {
|
||||
Nock(NockError),
|
||||
Scry(ScryError),
|
||||
}
|
||||
// #[derive(Clone, Copy, Debug)]
|
||||
// pub enum Error {
|
||||
// Nock(NockError),
|
||||
// Scry(ScryError),
|
||||
// }
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum NockError {
|
||||
Deterministic(Noun), // trace
|
||||
NonDeterministic(Noun), // trace
|
||||
}
|
||||
// #[derive(Clone, Copy, Debug)]
|
||||
// pub enum NockError {
|
||||
// Deterministic(Noun), // trace
|
||||
// NonDeterministic(Noun), // trace
|
||||
// }
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ScryError {
|
||||
Blocked(Noun), // path
|
||||
Deterministic(Noun), // trace
|
||||
NonDeterministic(Noun), // trace
|
||||
}
|
||||
// #[derive(Clone, Copy, Debug)]
|
||||
// pub enum ScryError {
|
||||
// Blocked(Noun), // path
|
||||
// Deterministic(Noun), // trace
|
||||
// NonDeterministic(Noun), // trace
|
||||
// }
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Failure {
|
||||
Blocked(Noun), // path
|
||||
Deterministic,
|
||||
NonDeterministic,
|
||||
pub enum Error {
|
||||
ScryBlocked(Noun), // path
|
||||
ScryCrashed(Noun), // trace
|
||||
Deterministic(Noun), // trace
|
||||
NonDeterministic(Noun), // trace
|
||||
}
|
||||
|
||||
impl From<noun::Error> for Failure {
|
||||
impl From<noun::Error> for Error {
|
||||
fn from(_: noun::Error) -> Self {
|
||||
Failure::Deterministic
|
||||
Error::Deterministic(D(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<cold::Error> for Failure {
|
||||
impl From<cold::Error> for Error {
|
||||
fn from(_: cold::Error) -> Self {
|
||||
Failure::Deterministic
|
||||
Error::Deterministic(D(0))
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,7 +318,6 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
let orig_subject = subject; // for debugging
|
||||
let virtual_frame: *const u64 = context.stack.get_frame_pointer();
|
||||
let mut res: Noun = D(0);
|
||||
let mut scry_flag: bool = false;
|
||||
|
||||
// Setup stack for Nock computation
|
||||
unsafe {
|
||||
@ -403,7 +402,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
context.stack.pop::<NockWork>();
|
||||
} else {
|
||||
// Axis invalid for input Noun
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
NockWork::Work1(once) => {
|
||||
@ -412,7 +411,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
}
|
||||
NockWork::Work2(mut vale) => {
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
break Err(Failure::NonDeterministic);
|
||||
break Err(Error::NonDeterministic(D(0)));
|
||||
}
|
||||
|
||||
match vale.todo {
|
||||
@ -502,7 +501,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
context.stack.pop::<NockWork>();
|
||||
} else {
|
||||
// Cannot increment (Nock 4) a cell
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -545,11 +544,11 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
push_formula(stack, cond.once, cond.tail)?;
|
||||
} else {
|
||||
// Test branch of Nock 6 must return 0 or 1
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
} else {
|
||||
// Test branch of Nock 6 must return a direct atom
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -605,7 +604,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
},
|
||||
NockWork::Work9(mut kale) => {
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
break Err(Failure::NonDeterministic);
|
||||
break Err(Error::NonDeterministic(D(0)));
|
||||
}
|
||||
|
||||
match kale.todo {
|
||||
@ -657,7 +656,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
}
|
||||
} else {
|
||||
// Axis into core must be atom
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
Todo9::RestoreSubject => {
|
||||
@ -799,54 +798,64 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
push_formula(stack, scry.path, false)?;
|
||||
}
|
||||
Todo12::Scry => {
|
||||
let stack = &mut context.stack;
|
||||
if let Some(cell) = context.scry_stack.cell() {
|
||||
let scry_stack = context.scry_stack;
|
||||
let scry_handler = cell.head();
|
||||
let scry_gate = scry_handler.as_cell()?;
|
||||
let payload = T(stack, &[scry.reff, res]);
|
||||
let payload = T(&mut context.stack, &[scry.reff, res]);
|
||||
let scry_core = T(
|
||||
stack,
|
||||
&mut context.stack,
|
||||
&[
|
||||
scry_gate.head(),
|
||||
payload,
|
||||
scry_gate.tail().as_cell()?.tail(),
|
||||
],
|
||||
);
|
||||
let scry_form = T(stack, &[D(9), D(2), D(1), scry_core]);
|
||||
let scry_form = T(&mut context.stack, &[D(9), D(2), D(1), scry_core]);
|
||||
|
||||
scry.todo = Todo12::Done;
|
||||
scry.path = res;
|
||||
scry.hand = context.scry_stack;
|
||||
scry.flag = Some(scry_flag);
|
||||
scry_flag = true;
|
||||
context.scry_stack = cell.tail();
|
||||
*stack.top() = NockWork::Work12(scry);
|
||||
push_formula(stack, scry_form, false)?;
|
||||
match interpret(context, subject, scry_form) {
|
||||
Ok(noun) => {
|
||||
scry.todo = Todo12::Done;
|
||||
scry.path = res;
|
||||
scry.hand = scry_stack;
|
||||
*context.stack.top() = NockWork::Work12(scry);
|
||||
res = noun;
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::Deterministic(trace) | Error::ScryCrashed(trace) => {
|
||||
break Err(Error::ScryCrashed(trace));
|
||||
}
|
||||
Error::NonDeterministic(_) => {
|
||||
break Err(error);
|
||||
}
|
||||
Error::ScryBlocked(_) => {
|
||||
break Err(Error::NonDeterministic(D(0)));
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// No scry handler
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
Todo12::Done => match res.as_either_atom_cell() {
|
||||
Left(atom) => {
|
||||
if atom.as_noun().raw_equals(D(0)) {
|
||||
break Err(Failure::Blocked(scry.path));
|
||||
break Err(Error::ScryBlocked(scry.path));
|
||||
} else {
|
||||
// XX: mink crash
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::ScryCrashed(D(0)));
|
||||
}
|
||||
}
|
||||
Right(cell) => match cell.tail().as_either_atom_cell() {
|
||||
Left(_) => {
|
||||
let stack = &mut context.stack;
|
||||
scry_flag = scry.flag.unwrap();
|
||||
let hunk = T(stack, &[D(tas!(b"hunk")), scry.reff, scry.path]);
|
||||
mean_push(stack, hunk);
|
||||
break Err(Failure::Deterministic);
|
||||
break Err(Error::ScryCrashed(D(0)));
|
||||
}
|
||||
Right(cell) => {
|
||||
res = cell.tail();
|
||||
scry_flag = scry.flag.unwrap();
|
||||
context.scry_stack = scry.hand;
|
||||
context.stack.pop::<NockWork>();
|
||||
}
|
||||
@ -859,11 +868,11 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
|
||||
match nock {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => Err(exit(context, virtual_frame, err, scry_flag)),
|
||||
Err(err) => Err(exit(context, virtual_frame, err)),
|
||||
}
|
||||
}
|
||||
|
||||
fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(), Failure> {
|
||||
fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(), Error> {
|
||||
unsafe {
|
||||
if let Ok(formula_cell) = formula.as_cell() {
|
||||
// Formula
|
||||
@ -883,7 +892,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
*stack.push() = NockWork::Work0(Nock0 { axis: axis_atom });
|
||||
} else {
|
||||
// Axis for Nock 0 must be an atom
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
@ -901,7 +910,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Argument to Nock 2 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
3 => {
|
||||
@ -925,7 +934,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Argument to Nock 5 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
6 => {
|
||||
@ -940,11 +949,11 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Argument tail to Nock 6 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
} else {
|
||||
// Argument to Nock 6 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
7 => {
|
||||
@ -957,7 +966,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Argument to Nock 7 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
8 => {
|
||||
@ -970,7 +979,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Argument to Nock 8 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
9 => {
|
||||
@ -984,11 +993,11 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Axis for Nock 9 must be an atom
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
} else {
|
||||
// Argument to Nock 9 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
10 => {
|
||||
@ -1003,15 +1012,15 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Axis for Nock 10 must be an atom
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
} else {
|
||||
// Heah of argument to Nock 10 must be a cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
} else {
|
||||
// Argument to Nock 10 must be a cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
11 => {
|
||||
@ -1036,13 +1045,13 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
});
|
||||
} else {
|
||||
// Hint tag must be an atom
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Argument for Nock 11 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
};
|
||||
}
|
||||
12 => {
|
||||
@ -1052,44 +1061,42 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
reff: arg_cell.head(),
|
||||
path: arg_cell.tail(),
|
||||
hand: D(0),
|
||||
flag: None,
|
||||
});
|
||||
} else {
|
||||
// Argument for Nock 12 must be cell
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Invalid formula opcode
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Formula opcode must be direct atom
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Bad formula: atoms are not formulas
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exit(
|
||||
context: &mut Context,
|
||||
virtual_frame: *const u64,
|
||||
error: Failure,
|
||||
scry_flag: bool,
|
||||
) -> Error {
|
||||
pub fn exit(context: &mut Context, virtual_frame: *const u64, error: Error) -> Error {
|
||||
unsafe {
|
||||
let stack = &mut context.stack;
|
||||
|
||||
let mut preserve = match error {
|
||||
Failure::Blocked(path) => path,
|
||||
_ => *(stack.local_noun_pointer(0)),
|
||||
Error::ScryBlocked(path) => path,
|
||||
Error::Deterministic(t) | Error::NonDeterministic(t) | Error::ScryCrashed(t) => {
|
||||
// Return $tang of traces
|
||||
let h = *(stack.local_noun_pointer(0));
|
||||
T(stack, &[h, t])
|
||||
}
|
||||
};
|
||||
|
||||
while (stack).get_frame_pointer() != virtual_frame {
|
||||
@ -1098,27 +1105,10 @@ pub fn exit(
|
||||
}
|
||||
|
||||
match error {
|
||||
Failure::Blocked(_) => {
|
||||
if scry_flag {
|
||||
Error::Scry(ScryError::Blocked(preserve))
|
||||
} else {
|
||||
panic!("serf: blocked outside of scry");
|
||||
}
|
||||
}
|
||||
Failure::Deterministic => {
|
||||
if scry_flag {
|
||||
Error::Scry(ScryError::Deterministic(preserve))
|
||||
} else {
|
||||
Error::Nock(NockError::Deterministic(preserve))
|
||||
}
|
||||
}
|
||||
Failure::NonDeterministic => {
|
||||
if scry_flag {
|
||||
Error::Scry(ScryError::NonDeterministic(preserve))
|
||||
} else {
|
||||
Error::Nock(NockError::NonDeterministic(preserve))
|
||||
}
|
||||
}
|
||||
Error::Deterministic(_) => Error::Deterministic(preserve),
|
||||
Error::NonDeterministic(_) => Error::NonDeterministic(preserve),
|
||||
Error::ScryCrashed(_) => Error::ScryCrashed(preserve),
|
||||
Error::ScryBlocked(_) => error,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1256,7 +1246,7 @@ mod hint {
|
||||
tag: Atom,
|
||||
hint: Noun,
|
||||
body: Noun,
|
||||
) -> Result<Option<Noun>, Failure> {
|
||||
) -> Result<Option<Noun>, Error> {
|
||||
// XX: handle IndirectAtom tags
|
||||
match tag.as_direct()?.data() {
|
||||
tas!(b"sham") => {
|
||||
@ -1292,7 +1282,7 @@ mod hint {
|
||||
let tape = tape(stack, "jet mismatch");
|
||||
let mean = T(stack, &[D(tas!(b"mean")), tape]);
|
||||
mean_push(stack, mean);
|
||||
Err(Failure::Deterministic)
|
||||
Err(Error::Deterministic(D(0)))
|
||||
} else {
|
||||
Ok(Some(nock_res))
|
||||
}
|
||||
@ -1310,10 +1300,10 @@ mod hint {
|
||||
mean_push(stack, mean);
|
||||
|
||||
match error {
|
||||
Error::Nock(NockError::NonDeterministic(_)) => {
|
||||
Err(Failure::NonDeterministic)
|
||||
Error::NonDeterministic(_) => {
|
||||
Err(Error::NonDeterministic(D(0)))
|
||||
}
|
||||
_ => Err(Failure::Deterministic),
|
||||
_ => Err(Error::Deterministic(D(0))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1355,14 +1345,14 @@ mod hint {
|
||||
tag: Atom,
|
||||
hint: Option<(Noun, Noun)>,
|
||||
_body: Noun,
|
||||
) -> Result<Option<Noun>, Failure> {
|
||||
) -> Result<Option<Noun>, Error> {
|
||||
// XX: handle IndirectAtom tags
|
||||
match tag.as_direct()?.data() {
|
||||
tas!(b"slog") => {
|
||||
let stack = &mut context.stack;
|
||||
let newt = &mut context.newt;
|
||||
|
||||
let (_form, clue) = hint.ok_or(Failure::Deterministic)?;
|
||||
let (_form, clue) = hint.ok_or(Error::Deterministic(D(0)))?;
|
||||
let slog_cell = clue.as_cell()?;
|
||||
let pri = slog_cell.head().as_direct()?.data();
|
||||
let tank = slog_cell.tail();
|
||||
@ -1373,19 +1363,19 @@ mod hint {
|
||||
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
||||
let terminator = Arc::clone(&TERMINATOR);
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
return Err(Failure::NonDeterministic);
|
||||
return Err(Error::NonDeterministic(D(0)));
|
||||
}
|
||||
|
||||
let stack = &mut context.stack;
|
||||
let (_form, clue) = hint.ok_or(Failure::Deterministic)?;
|
||||
let (_form, clue) = hint.ok_or(Error::Deterministic(D(0)))?;
|
||||
let noun = T(stack, &[tag.as_noun(), clue]);
|
||||
mean_push(stack, noun);
|
||||
Ok(None)
|
||||
}
|
||||
tas!(b"hela") => {
|
||||
// XX: should this be virtualized?
|
||||
// pretty sure we should be bailing on error
|
||||
// might need to switch return type to Result<Option<Noun>, Failure>
|
||||
// XX: This only prints the trace down to the bottom of THIS
|
||||
// interpret call. We'll need to recursively work down
|
||||
// frames to get the stack trace all the way to the root.
|
||||
let mean = unsafe { *(context.stack.local_noun_pointer(0)) };
|
||||
let tone = Cell::new(&mut context.stack, D(2), mean);
|
||||
|
||||
@ -1398,7 +1388,7 @@ mod hint {
|
||||
let tape = tape(stack, "%hela failed: toon not %2");
|
||||
let mean = T(stack, &[D(tas!(b"mean")), tape]);
|
||||
mean_push(stack, mean);
|
||||
return Err(Failure::Deterministic);
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
|
||||
let mut list = toon.tail();
|
||||
@ -1436,7 +1426,7 @@ mod hint {
|
||||
hint: Option<Noun>,
|
||||
body: Noun,
|
||||
res: Noun,
|
||||
) -> Result<Option<Noun>, Failure> {
|
||||
) -> Result<Option<Noun>, Error> {
|
||||
let stack = &mut context.stack;
|
||||
let newt = &mut context.newt;
|
||||
let cold = &mut context.cold;
|
||||
|
@ -10,7 +10,7 @@ pub mod nock;
|
||||
pub mod text;
|
||||
pub mod tree;
|
||||
|
||||
use crate::interpreter::{Context, Failure};
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::bits::*;
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::form::*;
|
||||
@ -23,7 +23,7 @@ use crate::jets::tree::*;
|
||||
use crate::jets::warm::Warm;
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{self, Noun, Slots};
|
||||
use crate::noun::{self, Noun, Slots, D};
|
||||
use ares_macros::tas;
|
||||
use std::cmp;
|
||||
|
||||
@ -39,13 +39,13 @@ pub type Jet = fn(&mut Context, Noun) -> Result;
|
||||
*/
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum JetErr {
|
||||
Punt, // Retry with the raw nock
|
||||
Fail(Failure), // Error; do not retry
|
||||
Punt, // Retry with the raw nock
|
||||
Fail(Error), // Error; do not retry
|
||||
}
|
||||
|
||||
impl From<noun::Error> for JetErr {
|
||||
fn from(_err: noun::Error) -> Self {
|
||||
Self::Fail(Failure::Deterministic)
|
||||
Self::Fail(Error::Deterministic(D(0)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ impl From<JetErr> for () {
|
||||
fn from(_: JetErr) -> Self {}
|
||||
}
|
||||
|
||||
impl From<JetErr> for Failure {
|
||||
impl From<JetErr> for Error {
|
||||
fn from(e: JetErr) -> Self {
|
||||
match e {
|
||||
JetErr::Fail(f) => f,
|
||||
@ -138,13 +138,13 @@ pub mod util {
|
||||
pub fn checked_add(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
||||
a.checked_add(b)
|
||||
.filter(|x| x <= &MAX_BIT_LENGTH)
|
||||
.ok_or(JetErr::Fail(Failure::NonDeterministic))
|
||||
.ok_or(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
}
|
||||
|
||||
/// Performs addition that returns None on Noun size overflow
|
||||
pub fn checked_sub(a: usize, b: usize) -> result::Result<usize, JetErr> {
|
||||
a.checked_sub(b)
|
||||
.ok_or(JetErr::Fail(Failure::NonDeterministic))
|
||||
.ok_or(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
}
|
||||
|
||||
pub fn checked_left_shift(bloq: usize, a: usize) -> result::Result<usize, JetErr> {
|
||||
@ -152,7 +152,7 @@ pub mod util {
|
||||
|
||||
// Catch overflow
|
||||
if (res >> bloq) < a || res > MAX_BIT_LENGTH {
|
||||
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
@ -170,14 +170,14 @@ pub mod util {
|
||||
|
||||
pub fn slot(noun: Noun, axis: u64) -> Result {
|
||||
noun.slot(axis)
|
||||
.map_err(|_e| JetErr::Fail(Failure::Deterministic))
|
||||
.map_err(|_e| JetErr::Fail(Error::Deterministic(D(0))))
|
||||
}
|
||||
|
||||
/// Extract a bloq and check that it's computable by the current system
|
||||
pub fn bloq(a: Noun) -> result::Result<usize, JetErr> {
|
||||
let bloq = a.as_direct()?.data() as usize;
|
||||
if bloq >= 47 {
|
||||
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
|
||||
} else {
|
||||
Ok(bloq)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/** Bit arithmetic & logic jets
|
||||
*/
|
||||
use crate::interpreter::{Context, Failure};
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{DirectAtom, IndirectAtom, Noun, D};
|
||||
@ -245,7 +245,7 @@ pub fn jet_rev(context: &mut Context, subject: Noun) -> Result {
|
||||
let boz = slot(arg, 2)?.as_atom()?.as_direct()?.data();
|
||||
|
||||
if boz >= 64 {
|
||||
return Err(JetErr::Fail(Failure::Deterministic));
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
let boz = boz as usize;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Another approach is use a global custom allocator. This is fairly involved, but it would allow
|
||||
* us to use any library without worrying whether it allocates.
|
||||
*/
|
||||
use crate::interpreter::{Context, Failure};
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
|
||||
@ -44,7 +44,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
||||
match atom.as_either() {
|
||||
Left(direct) => {
|
||||
if direct.data() == 0 {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
||||
}
|
||||
@ -72,7 +72,7 @@ pub fn jet_dec(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ pub fn jet_div(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() / b.data()) }.as_noun())
|
||||
} else {
|
||||
@ -101,7 +101,7 @@ pub fn jet_dvr(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
let (div, rem) = if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
let (div, rem) = (a.data() / b.data(), a.data() % b.data());
|
||||
@ -222,7 +222,7 @@ pub fn jet_mod(context: &mut Context, subject: Noun) -> Result {
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if unsafe { b.as_noun().raw_equals(D(0)) } {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
Ok(unsafe { DirectAtom::new_unchecked(a.data() % b.data()) }.as_noun())
|
||||
} else {
|
||||
@ -270,7 +270,7 @@ pub fn jet_sub(context: &mut Context, subject: Noun) -> Result {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Failure;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{
|
||||
assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_context, A,
|
||||
};
|
||||
@ -377,7 +377,7 @@ mod tests {
|
||||
let (a0, _a24, a63, _a96, a128) = atoms(s);
|
||||
assert_jet_ubig(c, jet_dec, a128, ubig!(0xdeadbeef12345678fedcba987654320f));
|
||||
assert_jet(c, jet_dec, a63, D(0x7ffffffffffffffe));
|
||||
assert_jet_err(c, jet_dec, a0, JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_dec, a0, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -403,13 +403,13 @@ mod tests {
|
||||
c,
|
||||
jet_div,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_div,
|
||||
&[atom_0, atom_0],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ mod tests {
|
||||
c,
|
||||
jet_dvr,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
@ -540,13 +540,13 @@ mod tests {
|
||||
c,
|
||||
jet_mod,
|
||||
&[atom_63, atom_0],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
assert_math_jet_err(
|
||||
c,
|
||||
jet_mod,
|
||||
&[atom_0, atom_0],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ mod tests {
|
||||
c,
|
||||
jet_sub,
|
||||
&[atom_63, atom_96],
|
||||
JetErr::Fail(Failure::Deterministic),
|
||||
JetErr::Fail(Error::Deterministic(D(0))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,33 @@
|
||||
use crate::hamt::Hamt;
|
||||
/** Virtualization jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::Result;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, T};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
// XX: interpret should accept optional scry function and potentially produce blocked
|
||||
// Determinist scry crashes should have the following behaviour:
|
||||
//
|
||||
// root <-- Deterministic
|
||||
// mink <-- Deterministic
|
||||
// scry <-- ScryCrashed
|
||||
//
|
||||
// root <-- Deterministic
|
||||
// mink <-- Deterministic
|
||||
// mink <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
//
|
||||
// root
|
||||
// mink <-- Tone
|
||||
// mink <-- Deterministic
|
||||
// mink <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry <-- ScryCrashed
|
||||
// scry
|
||||
//
|
||||
pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
// mink sample = [nock scry_namespace]
|
||||
@ -23,14 +42,30 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
context.cache = Hamt::<Noun>::new();
|
||||
context.scry_stack = T(&mut context.stack, &[scry_handler, old_scry_stack]);
|
||||
|
||||
let res = util::mink(context, v_subject, v_formula);
|
||||
context.cache = old_cache;
|
||||
context.scry_stack = old_scry_stack;
|
||||
res
|
||||
match util::mink(context, v_subject, v_formula) {
|
||||
Ok(noun) => {
|
||||
context.cache = old_cache;
|
||||
context.scry_stack = old_scry_stack;
|
||||
Ok(noun)
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::NonDeterministic(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryCrashed(trace) => {
|
||||
if unsafe { context.scry_stack.raw_equals(old_scry_stack) } {
|
||||
Err(JetErr::Fail(Error::Deterministic(trace)))
|
||||
} else {
|
||||
Err(JetErr::Fail(error))
|
||||
}
|
||||
}
|
||||
Error::Deterministic(_) | Error::ScryBlocked(_) => {
|
||||
panic!("scry: mink: unhandled errors in helper")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::{interpret, Context, Error, Failure, NockError, ScryError};
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::jets;
|
||||
use crate::jets::form::util::scow;
|
||||
use crate::jets::util::rip;
|
||||
@ -44,26 +79,13 @@ pub mod util {
|
||||
pub const LEAF: Noun = D(tas!(b"leaf"));
|
||||
pub const ROSE: Noun = D(tas!(b"rose"));
|
||||
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> jets::Result {
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Error> {
|
||||
match interpret(context, subject, formula) {
|
||||
Ok(res) => Ok(T(&mut context.stack, &[D(0), res])),
|
||||
Err(err) => match err {
|
||||
Error::Nock(nock_err) => match nock_err {
|
||||
NockError::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||
NockError::NonDeterministic(_trace) => {
|
||||
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||
}
|
||||
},
|
||||
Error::Scry(scry_err) => match scry_err {
|
||||
ScryError::Blocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||
ScryError::Deterministic(_trace) => Err(JetErr::Fail(Failure::Deterministic)),
|
||||
// XX: trace is unused; needs to be printed or welded to trace from outer context
|
||||
ScryError::NonDeterministic(_trace) => {
|
||||
Err(JetErr::Fail(Failure::NonDeterministic))
|
||||
}
|
||||
},
|
||||
Error::ScryBlocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
||||
Error::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(err),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -77,14 +99,14 @@ pub mod util {
|
||||
|
||||
match tag.data() {
|
||||
x if x < 2 => return Ok(tone),
|
||||
x if x > 2 => return Err(JetErr::Fail(Failure::Deterministic)),
|
||||
x if x > 2 => return Err(JetErr::Fail(Error::Deterministic(D(0)))),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if unsafe { original_list.raw_equals(D(0)) } {
|
||||
return Ok(tone);
|
||||
} else if original_list.atom().is_some() {
|
||||
return Err(JetErr::Fail(Failure::Deterministic));
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
// XX: trim traces longer than 1024 frames
|
||||
@ -134,15 +156,21 @@ pub mod util {
|
||||
T(stack, &[LEAF, tape])
|
||||
}
|
||||
Right(cell) => {
|
||||
let tone = mink(context, dat, cell.head())?.as_cell()?;
|
||||
if !tone.head().raw_equals(D(0)) {
|
||||
'tank: {
|
||||
if let Ok(tone) = mink(context, dat, cell.head()) {
|
||||
if let Some(cell) = tone.cell() {
|
||||
if cell.head().raw_equals(D(0)) {
|
||||
// XX: need to check that this is
|
||||
// actually a path;
|
||||
// return leaf+"mook.mean" if not
|
||||
break 'tank cell.tail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let stack = &mut context.stack;
|
||||
let tape = tape(stack, "####");
|
||||
T(stack, &[LEAF, tape])
|
||||
} else {
|
||||
// XX: need to check that this is actually a tank
|
||||
// return leaf+"mook.mean" if not
|
||||
tone.tail()
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -326,7 +354,7 @@ mod tests {
|
||||
let nock = T(stack, &[subj, form]);
|
||||
let scry = D(0);
|
||||
let samp = T(stack, &[nock, scry]);
|
||||
let rest = T(stack, &[D(2), D(0)]);
|
||||
let rest = T(stack, &[D(2), D(0), D(0)]);
|
||||
assert_jet(context, jet_mink, samp, rest);
|
||||
}
|
||||
|
||||
@ -412,7 +440,7 @@ mod tests {
|
||||
|
||||
let t1 = T(stack, &[tt1, tt2, D(0)]);
|
||||
|
||||
let rest = T(stack, &[D(2), t1]);
|
||||
let rest = T(stack, &[D(2), t1, D(0)]);
|
||||
|
||||
assert_jet(context, jet_mink, samp, rest);
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::Failure;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::Noun;
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
pub fn lent(tape: Noun) -> Result<usize, JetErr> {
|
||||
let mut len = 0usize;
|
||||
@ -25,7 +25,7 @@ pub mod util {
|
||||
if atom.as_bitslice().first_one().is_none() {
|
||||
break;
|
||||
} else {
|
||||
return Err(JetErr::Fail(Failure::Deterministic));
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
let cell = list.as_cell()?;
|
||||
@ -40,7 +40,7 @@ pub mod util {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Failure;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{D, T};
|
||||
@ -54,8 +54,8 @@ mod tests {
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
||||
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/** Tree jets
|
||||
*/
|
||||
use crate::interpreter::{Context, Failure};
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, D};
|
||||
@ -14,7 +14,7 @@ pub fn jet_cap(_context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
unsafe {
|
||||
if met < 2 {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else if *(tom.as_bitslice().get_unchecked(met - 2)) {
|
||||
Ok(D(3))
|
||||
} else {
|
||||
@ -30,7 +30,7 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
||||
let met = met(0, tom);
|
||||
|
||||
if met < 2 {
|
||||
Err(JetErr::Fail(Failure::Deterministic))
|
||||
Err(JetErr::Fail(Error::Deterministic(D(0))))
|
||||
} else {
|
||||
let c = bex(stack, met - 1);
|
||||
let d = bex(stack, met - 2);
|
||||
@ -43,7 +43,7 @@ pub fn jet_mas(context: &mut Context, subject: Noun) -> Result {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Failure;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::D;
|
||||
@ -52,8 +52,8 @@ mod tests {
|
||||
fn test_cap() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet_err(c, jet_cap, D(0), JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_cap, D(1), JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_cap, D(0), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
assert_jet_err(c, jet_cap, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
|
||||
assert_jet(c, jet_cap, D(2), D(2));
|
||||
assert_jet(c, jet_cap, D(3), D(3));
|
||||
@ -68,8 +68,8 @@ mod tests {
|
||||
fn test_mas() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet_err(c, jet_mas, D(0), JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_mas, D(1), JetErr::Fail(Failure::Deterministic));
|
||||
assert_jet_err(c, jet_mas, D(0), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
assert_jet_err(c, jet_mas, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
|
||||
assert_jet(c, jet_mas, D(2), D(1));
|
||||
assert_jet(c, jet_mas, D(3), D(1));
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter;
|
||||
use crate::interpreter::{inc, interpret, Error, NockError};
|
||||
use crate::interpreter::{inc, interpret, Error};
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::nock::util::mook;
|
||||
@ -264,7 +264,10 @@ fn slam(context: &mut Context, axis: u64, ovo: Noun) -> Result<Noun, Error> {
|
||||
}
|
||||
|
||||
fn goof(context: &mut Context, trace: Noun) -> Noun {
|
||||
let tone = Cell::new(&mut context.nock_context.stack, D(2), trace);
|
||||
// XX: trace is a $tang with at least one $tank, which we pick off the top.
|
||||
// Actual input to +mook should be (roll trace weld) ( or (zing trace)).
|
||||
let head = trace.cell().unwrap().head();
|
||||
let tone = Cell::new(&mut context.nock_context.stack, D(2), head);
|
||||
let tang = mook(&mut context.nock_context, tone, false)
|
||||
.expect("serf: goof: +mook crashed on bail")
|
||||
.tail();
|
||||
@ -279,12 +282,12 @@ fn soft(context: &mut Context, ovo: Noun) -> Result<Noun, Noun> {
|
||||
match slam(context, POKE_AXIS, ovo) {
|
||||
Ok(res) => Ok(res),
|
||||
Err(error) => match error {
|
||||
Error::Nock(nock_err) => match nock_err {
|
||||
NockError::Deterministic(trace) | NockError::NonDeterministic(trace) => {
|
||||
Err(goof(context, trace))
|
||||
}
|
||||
},
|
||||
Error::Scry(_) => panic!("serf: soft: .^ invalid outside of virtual Nock"),
|
||||
Error::Deterministic(trace) | Error::NonDeterministic(trace) => {
|
||||
Err(goof(context, trace))
|
||||
}
|
||||
Error::ScryBlocked(_) | Error::ScryCrashed(_) => {
|
||||
panic!("serf: soft: .^ invalid outside of virtual Nock")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -302,13 +305,13 @@ fn play_life(context: &mut Context, eve: Noun) {
|
||||
context.play_done();
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::Nock(nock_err) => match nock_err {
|
||||
NockError::Deterministic(trace) | NockError::NonDeterministic(trace) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
},
|
||||
Error::Scry(_) => panic!("serf: soft: .^ invalid outside of virtual Nock"),
|
||||
Error::Deterministic(trace) | Error::NonDeterministic(trace) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
Error::ScryBlocked(_) | Error::ScryCrashed(_) => {
|
||||
panic!("serf: soft: .^ invalid outside of virtual Nock")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user