mirror of
https://github.com/urbit/ares.git
synced 2024-11-26 09:57:56 +03:00
[ares] allow jets to fail
This commit is contained in:
parent
bb819abcc2
commit
9f3b4dd781
@ -632,7 +632,7 @@ fn match_pre_hint(stack: &mut NockStack, subject: Noun, cell: Cell) -> Result<No
|
||||
tas!(b"sham") => {
|
||||
let jet_formula = cell.tail().as_cell()?;
|
||||
let jet = jets::get_jet(jet_formula.tail())?;
|
||||
return Ok(jet(stack, subject));
|
||||
return Ok(jet(stack, subject)?); // Punt all errors to Nock
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
|
@ -4,7 +4,29 @@ use crate::noun::{DirectAtom, IndirectAtom, Noun};
|
||||
use ares_macros::tas;
|
||||
use either::Either::*;
|
||||
|
||||
pub fn get_jet(jet_name: Noun) -> Result<fn(&mut NockStack, Noun) -> Noun, ()> {
|
||||
/// Return Err if the computation crashed or should punt to Nock
|
||||
pub type Jet = fn(&mut NockStack, Noun) -> Result<Noun, JetErr>;
|
||||
|
||||
/// Only return a deterministic error if the Nock would have deterministically crashed.
|
||||
pub enum JetErr {
|
||||
Punt, // Retry with the raw nock
|
||||
Deterministic, // The Nock would have crashed
|
||||
NonDeterministic, // Other error
|
||||
}
|
||||
|
||||
impl From<()> for JetErr {
|
||||
fn from(_: ()) -> Self {
|
||||
JetErr::NonDeterministic
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JetErr> for () {
|
||||
fn from(_: JetErr) -> Self {}
|
||||
}
|
||||
|
||||
use JetErr::*;
|
||||
|
||||
pub fn get_jet(jet_name: Noun) -> Result<Jet, ()> {
|
||||
match jet_name.as_direct()?.data() {
|
||||
tas!(b"dec") => Ok(jet_dec),
|
||||
tas!(b"cut") => Ok(jet_cut),
|
||||
@ -12,22 +34,22 @@ pub fn get_jet(jet_name: Noun) -> Result<fn(&mut NockStack, Noun) -> Noun, ()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn jet_dec(stack: &mut NockStack, subject: Noun) -> Noun {
|
||||
fn jet_dec(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
|
||||
let arg = raw_slot(subject, 6);
|
||||
if let Ok(atom) = arg.as_atom() {
|
||||
match atom.as_either() {
|
||||
Left(direct) => {
|
||||
if direct.data() == 0 {
|
||||
panic!("Decrementing 0");
|
||||
Err(Deterministic)
|
||||
} else {
|
||||
unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun()
|
||||
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
||||
}
|
||||
}
|
||||
Right(indirect) => {
|
||||
let indirect_slice = indirect.as_bitslice();
|
||||
match indirect_slice.first_one() {
|
||||
None => {
|
||||
panic!("Decrementing 0");
|
||||
panic!("Decrementing 0 stored as an indirect atom");
|
||||
}
|
||||
Some(first_one) => {
|
||||
let (mut new_indirect, new_slice) =
|
||||
@ -39,27 +61,30 @@ fn jet_dec(stack: &mut NockStack, subject: Noun) -> Noun {
|
||||
new_slice[first_one + 1..]
|
||||
.copy_from_bitslice(&indirect_slice[first_one + 1..]);
|
||||
let res = unsafe { new_indirect.normalize_as_atom() };
|
||||
res.as_noun()
|
||||
Ok(res.as_noun())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Argument to dec must be atom");
|
||||
Err(Deterministic)
|
||||
}
|
||||
}
|
||||
|
||||
fn jet_cut(stack: &mut NockStack, subject: Noun) -> Noun {
|
||||
fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
|
||||
let arg = raw_slot(subject, 6);
|
||||
let bloq = raw_slot(arg, 2).as_direct().unwrap().data();
|
||||
let start = raw_slot(arg, 12).as_direct().unwrap().data();
|
||||
let run = raw_slot(arg, 13).as_direct().unwrap().data();
|
||||
let atom = raw_slot(arg, 7).as_atom().unwrap();
|
||||
let bloq = raw_slot(arg, 2).as_direct()?.data();
|
||||
let start = raw_slot(arg, 12).as_direct()?.data();
|
||||
let run = raw_slot(arg, 13).as_direct()?.data();
|
||||
let atom = raw_slot(arg, 7).as_atom()?;
|
||||
let slice = atom.as_bitslice();
|
||||
let unit = 1 << bloq;
|
||||
let (mut new_indirect, new_slice) =
|
||||
unsafe { IndirectAtom::new_raw_mut_bitslice(stack, ((run * unit + 63) >> 6) as usize) };
|
||||
new_slice[..(unit * run) as usize]
|
||||
.copy_from_bitslice(&slice[(unit * start) as usize..(unit * (start + run)) as usize]);
|
||||
unsafe { new_indirect.normalize_as_atom().as_noun() }
|
||||
let new_indirect = unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(stack, ((run * unit + 63) >> 6) as usize);
|
||||
new_slice[..(unit * run) as usize]
|
||||
.copy_from_bitslice(&slice[(unit * start) as usize..(unit * (start + run)) as usize]);
|
||||
new_indirect.normalize_as_atom()
|
||||
};
|
||||
Ok(new_indirect.as_noun())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user