mirror of
https://github.com/urbit/ares.git
synced 2024-11-29 22:56:28 +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") => {
|
tas!(b"sham") => {
|
||||||
let jet_formula = cell.tail().as_cell()?;
|
let jet_formula = cell.tail().as_cell()?;
|
||||||
let jet = jets::get_jet(jet_formula.tail())?;
|
let jet = jets::get_jet(jet_formula.tail())?;
|
||||||
return Ok(jet(stack, subject));
|
return Ok(jet(stack, subject)?); // Punt all errors to Nock
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,29 @@ use crate::noun::{DirectAtom, IndirectAtom, Noun};
|
|||||||
use ares_macros::tas;
|
use ares_macros::tas;
|
||||||
use either::Either::*;
|
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() {
|
match jet_name.as_direct()?.data() {
|
||||||
tas!(b"dec") => Ok(jet_dec),
|
tas!(b"dec") => Ok(jet_dec),
|
||||||
tas!(b"cut") => Ok(jet_cut),
|
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);
|
let arg = raw_slot(subject, 6);
|
||||||
if let Ok(atom) = arg.as_atom() {
|
if let Ok(atom) = arg.as_atom() {
|
||||||
match atom.as_either() {
|
match atom.as_either() {
|
||||||
Left(direct) => {
|
Left(direct) => {
|
||||||
if direct.data() == 0 {
|
if direct.data() == 0 {
|
||||||
panic!("Decrementing 0");
|
Err(Deterministic)
|
||||||
} else {
|
} else {
|
||||||
unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun()
|
Ok(unsafe { DirectAtom::new_unchecked(direct.data() - 1) }.as_noun())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Right(indirect) => {
|
Right(indirect) => {
|
||||||
let indirect_slice = indirect.as_bitslice();
|
let indirect_slice = indirect.as_bitslice();
|
||||||
match indirect_slice.first_one() {
|
match indirect_slice.first_one() {
|
||||||
None => {
|
None => {
|
||||||
panic!("Decrementing 0");
|
panic!("Decrementing 0 stored as an indirect atom");
|
||||||
}
|
}
|
||||||
Some(first_one) => {
|
Some(first_one) => {
|
||||||
let (mut new_indirect, new_slice) =
|
let (mut new_indirect, new_slice) =
|
||||||
@ -39,27 +61,30 @@ fn jet_dec(stack: &mut NockStack, subject: Noun) -> Noun {
|
|||||||
new_slice[first_one + 1..]
|
new_slice[first_one + 1..]
|
||||||
.copy_from_bitslice(&indirect_slice[first_one + 1..]);
|
.copy_from_bitslice(&indirect_slice[first_one + 1..]);
|
||||||
let res = unsafe { new_indirect.normalize_as_atom() };
|
let res = unsafe { new_indirect.normalize_as_atom() };
|
||||||
res.as_noun()
|
Ok(res.as_noun())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 arg = raw_slot(subject, 6);
|
||||||
let bloq = raw_slot(arg, 2).as_direct().unwrap().data();
|
let bloq = raw_slot(arg, 2).as_direct()?.data();
|
||||||
let start = raw_slot(arg, 12).as_direct().unwrap().data();
|
let start = raw_slot(arg, 12).as_direct()?.data();
|
||||||
let run = raw_slot(arg, 13).as_direct().unwrap().data();
|
let run = raw_slot(arg, 13).as_direct()?.data();
|
||||||
let atom = raw_slot(arg, 7).as_atom().unwrap();
|
let atom = raw_slot(arg, 7).as_atom()?;
|
||||||
let slice = atom.as_bitslice();
|
let slice = atom.as_bitslice();
|
||||||
let unit = 1 << bloq;
|
let unit = 1 << bloq;
|
||||||
let (mut new_indirect, new_slice) =
|
let new_indirect = unsafe {
|
||||||
unsafe { IndirectAtom::new_raw_mut_bitslice(stack, ((run * unit + 63) >> 6) as usize) };
|
let (mut new_indirect, new_slice) =
|
||||||
new_slice[..(unit * run) as usize]
|
IndirectAtom::new_raw_mut_bitslice(stack, ((run * unit + 63) >> 6) as usize);
|
||||||
.copy_from_bitslice(&slice[(unit * start) as usize..(unit * (start + run)) as usize]);
|
new_slice[..(unit * run) as usize]
|
||||||
unsafe { new_indirect.normalize_as_atom().as_noun() }
|
.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