jets: add mink jet

This commit is contained in:
Alex Shelkovnykov 2023-08-17 10:22:20 -06:00
parent 19048014a3
commit d510a33c02
7 changed files with 352 additions and 95 deletions

View File

@ -4,7 +4,7 @@ use crate::jets;
use crate::mem::unifying_equality;
use crate::mem::NockStack;
use crate::newt::Newt;
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun};
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D};
use ares_macros::tas;
use assert_no_alloc::assert_no_alloc;
use bitvec::prelude::{BitSlice, Lsb0};
@ -69,41 +69,55 @@ fn noun_to_work(noun: Noun) -> NockWork {
}
}
#[derive(Debug)]
pub enum NockErr {
Blocked(Noun),
Error(Noun),
}
impl From<NockErr> for () {
fn from(_: NockErr) -> Self {
()
}
}
/** Interpret nock */
pub fn interpret(
stack: &mut NockStack,
newt: &mut Option<&mut Newt>, // For printing slogs; if None, print to stdout
mut subject: Noun,
formula: Noun,
) -> Noun {
let mut res = unsafe { DirectAtom::new_unchecked(0).as_atom().as_noun() };
) -> Result<Noun, NockErr> {
let mut res: Noun = D(0);
let mut trace: Noun;
let mut cache = Hamt::<Noun>::new();
let virtual_frame = stack.get_frame_pointer();
stack.frame_push(1);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Done);
}
push_formula(stack, formula);
assert_no_alloc(|| unsafe {
push_formula(stack, formula)?;
let tone = assert_no_alloc(|| unsafe {
loop {
match noun_to_work(*(stack.local_noun_pointer(0))) {
Done => {
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.frame_pop();
break;
break Ok(res);
}
NockCellComputeHead => {
*stack.local_noun_pointer(0) = work_to_noun(NockCellComputeTail);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
NockCellComputeTail => {
*(stack.local_noun_pointer(0)) = work_to_noun(NockCellCons);
*(stack.local_noun_pointer(1)) = res;
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
NockCellCons => {
let head = *stack.local_noun_pointer(1);
@ -115,13 +129,16 @@ pub fn interpret(
}
Nock0Axis => {
if let Ok(atom) = (*(stack.local_noun_pointer(1))).as_atom() {
res = slot(subject, atom.as_bitslice());
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.frame_pop();
if let Ok(x) = slot(subject, atom.as_bitslice()) {
res = x;
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.frame_pop();
} else {
break Err(NockErr::Error(D(1)));
}
} else {
panic!("Axis must be atom");
break Err(NockErr::Error(D(0))); // Axis must be atom
};
}
Nock1Constant => {
@ -134,19 +151,19 @@ pub fn interpret(
Nock2ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock2ComputeFormula);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock2ComputeFormula => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock2ComputeResult);
*(stack.local_noun_pointer(1)) = res;
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock2ComputeResult => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock2RestoreSubject);
*(stack.local_noun_pointer(2)) = subject;
subject = *(stack.local_noun_pointer(1));
push_formula(stack, res);
push_formula(stack, res)?;
}
Nock2RestoreSubject => {
subject = *(stack.local_noun_pointer(2));
@ -158,7 +175,7 @@ pub fn interpret(
Nock3ComputeChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock3ComputeType);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock3ComputeType => {
res = if res.is_cell() {
@ -174,7 +191,7 @@ pub fn interpret(
Nock4ComputeChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock4Increment);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock4Increment => {
if let Ok(atom) = res.as_atom() {
@ -184,19 +201,19 @@ pub fn interpret(
stack.preserve(&mut res);
stack.frame_pop();
} else {
panic!("Cannot increment (Nock 4) a cell");
break Err(NockErr::Error(D(2))); // Cannot increment (Nock 4) a cell
};
}
Nock5ComputeLeftChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock5ComputeRightChild);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock5ComputeRightChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock5TestEquals);
*(stack.local_noun_pointer(1)) = res;
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock5TestEquals => {
let saved_value_ptr = stack.local_noun_pointer(1);
@ -213,22 +230,22 @@ pub fn interpret(
Nock6ComputeTest => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock6ComputeBranch);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock6ComputeBranch => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock6Done);
if let Left(direct) = res.as_either_direct_allocated() {
if direct.data() == 0 {
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
} else if direct.data() == 1 {
let formula = *stack.local_noun_pointer(3);
push_formula(stack, formula);
push_formula(stack, formula)?;
} else {
panic!("Test branch of Nock 6 must return 0 or 1");
break Err(NockErr::Error(D(3))); // Test branch of Nock 6 must return 0 or 1
};
} else {
panic!("Test branch of Nock 6 must return a direct atom");
break Err(NockErr::Error(D(4))); // Test branch of Nock 6 must return a direct atom
}
}
Nock6Done => {
@ -239,14 +256,14 @@ pub fn interpret(
Nock7ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock7ComputeResult);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock7ComputeResult => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock7RestoreSubject);
*(stack.local_noun_pointer(1)) = subject;
subject = res;
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock7RestoreSubject => {
subject = *(stack.local_noun_pointer(1));
@ -258,14 +275,14 @@ pub fn interpret(
Nock8ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock8ComputeResult);
let formula = *stack.local_noun_pointer(1);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock8ComputeResult => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock8RestoreSubject);
*(stack.local_noun_pointer(1)) = subject;
subject = Cell::new(stack, res, subject).as_noun();
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock8RestoreSubject => {
subject = *(stack.local_noun_pointer(1));
@ -277,16 +294,21 @@ pub fn interpret(
Nock9ComputeCore => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock9ComputeResult);
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock9ComputeResult => {
if let Ok(formula_axis) = (*(stack.local_noun_pointer(1))).as_atom() {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock9RestoreSubject);
*(stack.local_noun_pointer(2)) = subject;
subject = res;
push_formula(stack, slot(subject, formula_axis.as_bitslice()));
let axis = if let Ok(x) = slot(subject, formula_axis.as_bitslice()) {
x
} else {
break Err(NockErr::Error(D(55))); // Axis must be in subject
};
push_formula(stack, axis)?;
} else {
panic!("Axis into core must be atom");
break Err(NockErr::Error(D(5))); // Axis into core must be atom
}
}
Nock9RestoreSubject => {
@ -299,13 +321,13 @@ pub fn interpret(
Nock10ComputeTree => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock10ComputePatch);
let formula = *stack.local_noun_pointer(3);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock10ComputePatch => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock10Edit);
*(stack.local_noun_pointer(3)) = res;
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
Nock10Edit => {
if let Ok(edit_axis) = (*stack.local_noun_pointer(1)).as_atom() {
@ -316,7 +338,7 @@ pub fn interpret(
stack.preserve(&mut res);
stack.frame_pop();
} else {
panic!("Axis into tree must be atom");
break Err(NockErr::Error(D(6))); // Axis into tree must be atom
}
}
Nock11ComputeHint => {
@ -334,7 +356,7 @@ pub fn interpret(
stack.frame_pop();
} else {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock11ComputeResult);
push_formula(stack, hint.tail());
push_formula(stack, hint.tail())?;
}
}
Nock11ComputeResult => {
@ -349,7 +371,7 @@ pub fn interpret(
} else {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock11Done);
let formula = *stack.local_noun_pointer(2);
push_formula(stack, formula);
push_formula(stack, formula)?;
}
}
Nock11Done => {
@ -367,10 +389,18 @@ pub fn interpret(
};
}
});
res
match tone {
Ok(res) => Ok(res),
Err(_err) => {
trace = stack.get_mean_stack();
exit_early(stack, virtual_frame, &mut trace, &mut cache);
Err(NockErr::Error(trace))
}
}
}
fn push_formula(stack: &mut NockStack, formula: Noun) {
fn push_formula(stack: &mut NockStack, formula: Noun) -> Result<(), NockErr> {
if let Ok(formula_cell) = formula.as_cell() {
// Formula
match formula_cell.head().as_either_atom_cell() {
@ -540,20 +570,31 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
}
} else {
panic!("Bad formula: atoms are not formulas: {}", formula);
return Err(NockErr::Error(D(10))); // Bad formula: atoms are not formulas: {}
}
Ok(())
}
pub fn exit_early(stack: &mut NockStack, virtual_frame: *const u64, trace: &mut Noun, cache: &mut Hamt<Noun>) {
unsafe {
while stack.get_frame_pointer() != virtual_frame {
stack.preserve(trace);
stack.preserve(cache);
stack.frame_pop();
}
}
}
/** Note: axis must fit in a direct atom */
pub fn raw_slot(noun: Noun, axis: u64) -> Noun {
slot(noun, DirectAtom::new(axis).unwrap().as_bitslice())
slot(noun, DirectAtom::new(axis).unwrap().as_bitslice()).unwrap()
}
pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Noun {
pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Result<Noun, ()> {
let mut cursor = if let Some(x) = axis.last_one() {
x
} else {
panic!("0 is not allowed as an axis")
return Err(()); // 0 is not allowed as an axis
};
loop {
if cursor == 0 {
@ -567,10 +608,10 @@ pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Noun {
noun = cell.head();
}
} else {
panic!("Axis tried to descend through atom: {}", noun);
return Err(()); // Axis tried to descend through atom: {}
};
}
noun
Ok(noun)
}
fn edit(
@ -661,19 +702,28 @@ fn match_hint_pre_hint(
let jet_name = jet_formula.tail();
let jet = jets::get_jet(jet_name)?;
if let Ok(mut jet_res) = jet(stack, subject) {
if let Ok(mut jet_res) = jet(stack, newt, subject) {
// if in test mode, check that the jet returns the same result as the raw nock
if jets::get_jet_test_mode(jet_name) {
let mut nock_res = interpret(stack, newt, subject, formula);
if unsafe { !unifying_equality(stack, &mut nock_res, &mut jet_res) } {
eprintln!(
"\rJet {} failed, raw: {}, jetted: {}",
jet_name, nock_res, jet_res
);
return None;
}
// Throw away trace because we'll regenerate it later, and this is in test mode
// so it's okay if it runs twice
interpret(stack, newt, subject, formula)
.ok()
.map(|mut nock_res| {
if unsafe { !unifying_equality(stack, &mut nock_res, &mut jet_res) } {
eprintln!(
"\rJet {} failed, raw: {}, jetted: {}",
jet_name, nock_res, jet_res
);
None
} else {
Some(jet_res)
}
})
.unwrap()
} else {
Some(jet_res)
}
Some(jet_res)
} else {
// Print jet errors and punt to Nock
eprintln!("\rJet {} failed: ", jet_name);

View File

@ -1,14 +1,17 @@
pub mod math;
pub mod mink;
use crate::jets::math::*;
use crate::jets::mink::*;
use crate::mem::NockStack;
use crate::newt::Newt;
use crate::noun::{self, Noun};
use ares_macros::tas;
crate::gdb!();
/// Return Err if the computation crashed or should punt to Nock
pub type Jet = fn(&mut NockStack, Noun) -> Result<Noun, JetErr>;
pub type Jet = fn(&mut NockStack, &mut Option<&mut Newt>, Noun) -> Result<Noun, JetErr>;
/// Only return a deterministic error if the Nock would have deterministically crashed.
#[derive(Debug, PartialEq)]
@ -62,6 +65,7 @@ pub fn get_jet(jet_name: Noun) -> Option<Jet> {
tas!(b"met") => Some(jet_met),
tas!(b"mug") => Some(jet_mug),
tas!(b"rev") => Some(jet_rev),
tas!(b"mink") => Some(jet_mink),
_ => {
// eprintln!("Unknown jet: {:?}", jet_name);
None

View File

@ -16,6 +16,7 @@ use crate::interpreter::raw_slot;
use crate::jets::{JetErr, JetErr::*};
use crate::mem::NockStack;
use crate::mug::mug;
use crate::newt::Newt;
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
use bitvec::prelude::{BitSlice, Lsb0};
use either::Either::*;
@ -25,7 +26,11 @@ use std::{cmp, convert::TryFrom};
crate::gdb!();
pub fn jet_dec(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_dec(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
if let Ok(atom) = arg.as_atom() {
match atom.as_either() {
@ -62,7 +67,11 @@ pub fn jet_dec(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_add(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_add(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -77,7 +86,11 @@ pub fn jet_add(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_sub(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_sub(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -102,7 +115,11 @@ pub fn jet_sub(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_mul(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_mul(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -129,7 +146,11 @@ pub fn jet_mul(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_div(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_div(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -146,7 +167,11 @@ pub fn jet_div(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_mod(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_mod(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -161,7 +186,11 @@ pub fn jet_mod(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_dvr(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_dvr(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -189,7 +218,11 @@ pub fn jet_dvr(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_lth(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_lth(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -211,7 +244,11 @@ pub fn jet_lth(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
})
}
pub fn jet_lte(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_lte(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -233,7 +270,11 @@ pub fn jet_lte(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
})
}
pub fn jet_gth(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_gth(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -255,7 +296,11 @@ pub fn jet_gth(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
})
}
pub fn jet_gte(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_gte(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -277,7 +322,11 @@ pub fn jet_gte(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
})
}
pub fn jet_bex(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_bex(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6).as_direct()?.data() as usize;
if arg < 63 {
@ -291,7 +340,11 @@ pub fn jet_bex(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_lsh(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_lsh(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?;
@ -317,7 +370,11 @@ pub fn jet_lsh(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_rsh(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_rsh(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?;
@ -343,7 +400,11 @@ pub fn jet_rsh(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_con(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_con(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -359,7 +420,11 @@ pub fn jet_con(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_dis(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_dis(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -375,7 +440,11 @@ pub fn jet_dis(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_mix(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_mix(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).as_atom()?;
@ -391,7 +460,11 @@ pub fn jet_mix(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_end(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_end(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?;
@ -416,7 +489,11 @@ pub fn jet_end(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_cat(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_cat(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
@ -440,7 +517,11 @@ pub fn jet_cat(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_can(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_can(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
@ -490,7 +571,11 @@ pub fn jet_can(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_rep(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_rep(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?;
let original_list = raw_slot(arg, 3);
@ -533,7 +618,11 @@ pub fn jet_rep(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
}
}
pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_cut(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
@ -552,7 +641,11 @@ pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
Ok(new_indirect.as_noun())
}
pub fn jet_rip(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_rip(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?;
let atom = raw_slot(arg, 3).as_atom()?;
@ -571,7 +664,11 @@ pub fn jet_rip(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
Ok(list)
}
pub fn jet_met(_stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_met(
_stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 {
@ -582,7 +679,11 @@ pub fn jet_met(_stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
Ok(D(met(bloq, a) as u64))
}
pub fn jet_mug(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_mug(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
Ok(mug(stack, arg).as_noun())
}
@ -651,7 +752,11 @@ pub fn met(bloq: usize, a: Atom) -> usize {
}
}
pub fn jet_rev(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
pub fn jet_rev(
stack: &mut NockStack,
_newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let boz = raw_slot(arg, 2).as_atom()?.as_direct()?.data();
@ -751,7 +856,7 @@ mod tests {
fn assert_jet(stack: &mut NockStack, jet: Jet, sam: Noun, res: Noun) {
let sam = T(stack, &[D(0), sam, D(0)]);
let jet_res = assert_no_alloc(|| jet(stack, sam).unwrap());
let jet_res = assert_no_alloc(|| jet(stack, &mut None, sam).unwrap());
assert_noun_eq(stack, jet_res, res);
}
@ -788,7 +893,7 @@ mod tests {
fn assert_jet_err(stack: &mut NockStack, jet: Jet, sam: Noun, err: JetErr) {
let sam = T(stack, &[D(0), sam, D(0)]);
let jet_res = jet(stack, sam);
let jet_res = jet(stack, &mut None, sam);
assert!(
jet_res.is_err(),
"with sample: {}, expected err: {:?}, got: {:?}",

View File

@ -0,0 +1,70 @@
/** Virtualization jets
*/
use crate::interpreter::{interpret, raw_slot, NockErr};
use crate::jets::JetErr;
use crate::mem::NockStack;
use crate::newt::Newt;
use crate::noun::{Noun, D, T};
crate::gdb!();
// XX: interpret should accept optional scry function and potentially produce blocked
pub fn jet_mink(
stack: &mut NockStack,
newt: &mut Option<&mut Newt>,
subject: Noun,
) -> Result<Noun, JetErr> {
let arg = raw_slot(subject, 6);
let v_subject = raw_slot(arg, 4);
let v_formula = raw_slot(arg, 5);
let _scry = raw_slot(arg, 3);
match interpret(stack, newt, v_subject, v_formula) {
Ok(res) => Ok(T(stack, &[D(0), res])),
Err(err) => match err {
NockErr::Blocked(block) => Ok(T(stack, &[D(1), block])),
NockErr::Error(error) => Ok(T(stack, &[D(2), error])),
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::jets::Jet;
use crate::mem::unifying_equality;
use assert_no_alloc::assert_no_alloc;
fn init() -> NockStack {
NockStack::new(8 << 10 << 10, 0)
}
fn assert_noun_eq(stack: &mut NockStack, mut a: Noun, mut b: Noun) {
let eq = unsafe { unifying_equality(stack, &mut a, &mut b) };
assert!(eq, "got: {}, need: {}", a, b);
}
fn assert_jet(stack: &mut NockStack, jet: Jet, sam: Noun, res: Noun) {
let sam = T(stack, &[D(0), sam, D(0)]);
let jet_res = assert_no_alloc(|| jet(stack, &mut None, sam).unwrap());
assert_noun_eq(stack, jet_res, res);
}
#[test]
fn test_mink_success() {
let s = &mut init();
let n = T(s, &[D(0), D(1), D(53)]);
let sam = T(s, &[n, D(0)]);
let res = T(s, &[D(0), D(53)]);
assert_jet(s, jet_mink, sam, res);
}
#[test]
fn test_mink_zapzap() {
let s = &mut init();
let n = T(s, &[D(0), D(0), D(0)]);
let sam = T(s, &[n, D(0)]);
let res = T(s, &[D(2), D(0)]);
assert_jet(s, jet_mink, sam, res);
}
}

View File

@ -20,6 +20,7 @@ fn main() -> io::Result<()> {
ares::interpreter::use_gdb();
ares::jets::use_gdb();
ares::jets::math::use_gdb();
ares::jets::mink::use_gdb();
ares::mem::use_gdb();
ares::mug::use_gdb();
ares::newt::use_gdb();
@ -52,7 +53,8 @@ fn main() -> io::Result<()> {
let input_cell = input
.as_cell()
.expect("Input must be jam of subject/formula pair");
let result = interpret(&mut stack, &mut None, input_cell.head(), input_cell.tail());
let result = interpret(&mut stack, &mut None, input_cell.head(), input_cell.tail())
.expect("nock failed");
if let Ok(atom) = result.as_atom() {
println!("Result: {}", atom);
}

View File

@ -59,7 +59,7 @@ impl NockStack {
* The initial frame is a west frame. When the stack is initialized, a number of slots is given.
* We add three extra slots to store the previous frame, stack, and allocation pointer. For the
* initial frame, the previous allocation pointer is set to the beginning (low boundary) of the
* arena, the previous frame pointer is set to NULL, and the previous stack pointer is set to XX */
* arena, the previous frame pointer is set to NULL, and the previous stack pointer is set to NULL */
/** size is in 64-bit (i.e. 8-byte) words.
* top_slots is how many slots to allocate to the top stack frame.
@ -91,6 +91,18 @@ impl NockStack {
}
}
/** Current frame pointer of this NockStack */
pub fn get_frame_pointer(&self) -> *const u64 {
self.frame_pointer
}
/** Current frame pointer of this NockStack */
pub fn get_mean_stack(&self) -> Noun {
unsafe {
*self.mean_stack
}
}
/** Checks if the current stack frame has West polarity */
#[inline]
pub fn is_west(&self) -> bool {

View File

@ -1,4 +1,4 @@
use crate::interpreter::{interpret, raw_slot};
use crate::interpreter::{interpret, raw_slot, NockErr};
use crate::mem::NockStack;
use crate::mug::mug_u32;
use crate::newt::Newt;
@ -67,7 +67,8 @@ pub fn serf() -> io::Result<()> {
}
tas!(b"peek") => {
let sam = raw_slot(writ, 7);
let res = slam(stack, newt, arvo, PEEK_AXIS, sam);
let res = slam(stack, newt, arvo, PEEK_AXIS, sam)
.expect("peek error handling unimplemented");
newt.peek_done(stack, res);
}
tas!(b"play") => {
@ -76,7 +77,8 @@ pub fn serf() -> io::Result<()> {
let lit = raw_slot(writ, 7);
let sub = T(stack, &[D(0), D(3)]);
let lyf = T(stack, &[D(2), sub, D(0), D(2)]);
let gat = interpret(stack, &mut Some(newt), lit, lyf);
let gat = interpret(stack, &mut Some(newt), lit, lyf)
.expect("play error handling unimplemented");
arvo = raw_slot(gat, 7);
false
} else {
@ -90,7 +92,10 @@ pub fn serf() -> io::Result<()> {
while let Ok(cell) = lit.as_cell() {
if run {
let ovo = cell.head();
let res = slam(stack, newt, arvo, POKE_AXIS, ovo).as_cell().unwrap();
let res = slam(stack, newt, arvo, POKE_AXIS, ovo)
.expect("play error handling unimplemented")
.as_cell()
.unwrap();
arvo = res.tail();
}
event_number += 1;
@ -102,7 +107,10 @@ pub fn serf() -> io::Result<()> {
}
tas!(b"work") => {
let ovo = raw_slot(writ, 7);
let res = slam(stack, newt, arvo, POKE_AXIS, ovo).as_cell().unwrap();
let res = slam(stack, newt, arvo, POKE_AXIS, ovo)
.expect("work error handling unimplemented")
.as_cell()
.unwrap();
let fec = res.head();
arvo = res.tail();
snap.save(stack, &mut arvo);
@ -118,7 +126,13 @@ pub fn serf() -> io::Result<()> {
Ok(())
}
pub fn slam(stack: &mut NockStack, newt: &mut Newt, core: Noun, axis: u64, ovo: Noun) -> Noun {
pub fn slam(
stack: &mut NockStack,
newt: &mut Newt,
core: Noun,
axis: u64,
ovo: Noun,
) -> Result<Noun, NockErr> {
let pul = T(stack, &[D(9), D(axis), D(0), D(2)]);
let sam = T(stack, &[D(6), D(0), D(7)]);
let fol = T(stack, &[D(8), pul, D(9), D(2), D(10), sam, D(0), D(2)]);