ares: refactor hints to use option; fix hint tag bug

This commit is contained in:
Alex Shelkovnykov 2023-06-08 01:49:00 +00:00
parent b804a549a8
commit bae335275b
2 changed files with 115 additions and 51 deletions

View File

@ -318,28 +318,27 @@ pub fn interpret(
} }
} }
Nock11ComputeHint => { Nock11ComputeHint => {
let hint = *stack.local_noun_pointer(1); let hint = (*stack.local_noun_pointer(1))
if let Ok(hint_cell) = hint.as_cell() { .as_cell()
.expect("IMPOSSIBLE: tried to compute a dynamic hint but hint is an atom");
let formula = *stack.local_noun_pointer(2); let formula = *stack.local_noun_pointer(2);
if let Ok(found) =
match_pre_hint(stack, newt, subject, hint_cell, formula, &cache) if let Some(found) =
match_hint_pre_hint(stack, newt, subject, hint, formula, &cache)
{ {
res = found; res = found;
stack.preserve(&mut cache); stack.preserve(&mut cache);
stack.preserve(&mut res); stack.preserve(&mut res);
stack.frame_pop(); stack.frame_pop();
} else { } else {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock11ComputeResult); *(stack.local_noun_pointer(0)) = work_to_noun(Nock11ComputeResult);
push_formula(stack, hint_cell.tail()); push_formula(stack, hint.tail());
}
} else {
panic!("IMPOSSIBLE: tried to compute a dynamic hint but hint is an atom");
} }
} }
Nock11ComputeResult => { Nock11ComputeResult => {
let hint = *stack.local_noun_pointer(1); let hint = *stack.local_noun_pointer(1);
if let Ok(found) = match_post_hint(stack, newt, subject, hint, res) {
if let Some(found) = match_hint_pre_nock(stack, newt, subject, hint, res) {
res = found; res = found;
stack.preserve(&mut cache); stack.preserve(&mut cache);
@ -353,7 +352,11 @@ pub fn interpret(
} }
Nock11Done => { Nock11Done => {
let hint = *stack.local_noun_pointer(1); let hint = *stack.local_noun_pointer(1);
let _ = match_post_hinted(stack, subject, hint, res, &mut cache);
if let Some(found) = match_hint_post_nock(stack, subject, hint, res, &mut cache)
{
res = found;
}
stack.preserve(&mut cache); stack.preserve(&mut cache);
stack.preserve(&mut res); stack.preserve(&mut res);
@ -638,23 +641,24 @@ pub fn inc(stack: &mut NockStack, atom: Atom) -> Atom {
} }
} }
/** Match hints which apply before the formula is evaluated */ /** Match dynamic hints before the hint formula is evaluated */
fn match_pre_hint( fn match_hint_pre_hint(
stack: &mut NockStack, stack: &mut NockStack,
newt: &mut Option<&mut Newt>, newt: &mut Option<&mut Newt>,
subject: Noun, subject: Noun,
cell: Cell, hint: Cell,
formula: Noun, formula: Noun,
cache: &Hamt<Noun>, cache: &Hamt<Noun>,
) -> Result<Noun, ()> { ) -> Option<Noun> {
let direct = cell.head().as_direct()?; let tag = hint.head().direct()?;
match direct.data() {
match tag.data() {
// %sham hints are scaffolding until we have a real jet dashboard // %sham hints are scaffolding until we have a real jet dashboard
tas!(b"sham") => { tas!(b"sham") => {
let jet_formula = cell.tail().as_cell()?; let jet_formula = hint.tail().cell()?;
let jet_name = jet_formula.tail(); let jet_name = jet_formula.tail();
let jet = jets::get_jet(jet_name).ok_or(())?; let jet = jets::get_jet(jet_name)?;
if let Ok(mut jet_res) = jet(stack, subject) { if let Ok(mut jet_res) = jet(stack, subject) {
// if in test mode, check that the jet returns the same result as the raw nock // if in test mode, check that the jet returns the same result as the raw nock
if jets::get_jet_test_mode(jet_name) { if jets::get_jet_test_mode(jet_name) {
@ -664,69 +668,73 @@ fn match_pre_hint(
"\rJet {} failed, raw: {}, jetted: {}", "\rJet {} failed, raw: {}, jetted: {}",
jet_name, nock_res, jet_res jet_name, nock_res, jet_res
); );
return Err(()); return None;
} }
} }
Ok(jet_res) Some(jet_res)
} else { } else {
// Print jet errors and punt to Nock // Print jet errors and punt to Nock
eprintln!("\rJet {} failed", jet_name); eprintln!("\rJet {} failed: ", jet_name);
Err(()) None
} }
} }
tas!(b"memo") => { tas!(b"memo") => {
let formula = unsafe { *stack.local_noun_pointer(2) }; let formula = unsafe { *stack.local_noun_pointer(2) };
let mut key = Cell::new(stack, subject, formula).as_noun(); let mut key = Cell::new(stack, subject, formula).as_noun();
if let Some(res) = cache.lookup(stack, &mut key) { cache.lookup(stack, &mut key)
Ok(res)
} else {
Err(())
} }
} _ => None,
_ => Err(()),
} }
} }
/** Match static hints and dynamic hints after they're evaluated */ /** Match static and dynamic hints before the nock formula is evaluated */
fn match_post_hint( fn match_hint_pre_nock(
stack: &mut NockStack, stack: &mut NockStack,
newt: &mut Option<&mut Newt>, newt: &mut Option<&mut Newt>,
_subject: Noun, _subject: Noun,
hint: Noun, hint: Noun,
res: Noun, res: Noun,
) -> Result<Noun, ()> { ) -> Option<Noun> {
let direct = hint.as_cell()?.head().as_direct()?; let tag = hint
match direct.data() { .as_either_atom_cell()
.either(|a| a.direct(), |c| c.head().direct())?;
match tag.data() {
tas!(b"slog") => { tas!(b"slog") => {
let slog_cell = res.as_cell()?; let slog_cell = res.cell()?;
let pri = slog_cell.head().as_direct()?.data(); let pri = slog_cell.head().direct()?.data();
let tank = slog_cell.tail(); let tank = slog_cell.tail();
if let Some(not) = newt { if let Some(not) = newt {
not.slog(stack, pri, tank); not.slog(stack, pri, tank);
} else { } else {
println!("slog: {} {}", pri, tank); println!("raw slog: {} {}", pri, tank);
} }
Err(())
None
} }
_ => Err(()), _ => None,
} }
} }
fn match_post_hinted( /** Match static and dynamic hints after the nock formula is evaluated */
fn match_hint_post_nock(
stack: &mut NockStack, stack: &mut NockStack,
subject: Noun, subject: Noun,
hint: Noun, hint: Noun,
res: Noun, res: Noun,
cache: &mut Hamt<Noun>, cache: &mut Hamt<Noun>,
) -> Result<(), ()> { ) -> Option<Noun> {
let direct = hint.as_cell()?.head().as_direct()?; let tag = hint
match direct.data() { .as_either_atom_cell()
.either(|a| a.direct(), |c| c.head().direct())?;
match tag.data() {
tas!(b"memo") => { tas!(b"memo") => {
let formula = unsafe { *stack.local_noun_pointer(2) }; let formula = unsafe { *stack.local_noun_pointer(2) };
let mut key = Cell::new(stack, subject, formula).as_noun(); let mut key = Cell::new(stack, subject, formula).as_noun();
*cache = cache.insert(stack, &mut key, res); *cache = cache.insert(stack, &mut key, res);
Ok(()) None
} }
_ => Err(()), _ => None,
} }
} }

View File

@ -678,6 +678,22 @@ impl Atom {
} }
} }
pub fn direct(&self) -> Option<DirectAtom> {
if self.is_direct() {
unsafe { Some(self.direct) }
} else {
None
}
}
pub fn indirect(&self) -> Option<IndirectAtom> {
if self.is_indirect() {
unsafe { Some(self.indirect) }
} else {
None
}
}
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
match self.as_either() { match self.as_either() {
Either::Left(_direct) => 1, Either::Left(_direct) => 1,
@ -882,6 +898,46 @@ impl Noun {
} }
} }
pub fn atom(&self) -> Option<Atom> {
if self.is_atom() {
unsafe { Some(self.atom) }
} else {
None
}
}
pub fn cell(&self) -> Option<Cell> {
if self.is_cell() {
unsafe { Some(self.cell) }
} else {
None
}
}
pub fn direct(&self) -> Option<DirectAtom> {
if self.is_direct() {
unsafe { Some(self.direct) }
} else {
None
}
}
pub fn indirect(&self) -> Option<IndirectAtom> {
if self.is_indirect() {
unsafe { Some(self.indirect) }
} else {
None
}
}
pub fn allocated(&self) -> Option<Allocated> {
if self.is_allocated() {
unsafe { Some(self.allocated) }
} else {
None
}
}
/** Are these the same noun */ /** Are these the same noun */
pub unsafe fn raw_equals(self, other: Noun) -> bool { pub unsafe fn raw_equals(self, other: Noun) -> bool {
self.raw == other.raw self.raw == other.raw