jets: mink jet compiles and passes trivial tests

This commit is contained in:
Philip Monk 2023-08-08 12:34:50 -07:00
parent fbb24d170c
commit ad357352ac
8 changed files with 274 additions and 95 deletions

View File

@ -4,7 +4,7 @@ use crate::jets;
use crate::mem::unifying_equality; use crate::mem::unifying_equality;
use crate::mem::NockStack; use crate::mem::NockStack;
use crate::newt::Newt; 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 ares_macros::tas;
use assert_no_alloc::assert_no_alloc; use assert_no_alloc::assert_no_alloc;
use bitvec::prelude::{BitSlice, Lsb0}; use bitvec::prelude::{BitSlice, Lsb0};
@ -69,16 +69,25 @@ fn noun_to_work(noun: Noun) -> NockWork {
} }
} }
#[derive(Debug)]
pub enum NockErr { pub enum NockErr {
Blocked(Noun), Blocked(Noun),
Error(Noun), Error(Noun),
} }
pub fn early_exit(stack: &mut NockStack, virtual_frame: *u64, cache: &mut Hamt::<Noun>::new()) { impl From<NockErr> for () {
while stack.frame_pointer() != virtual_frame { fn from(_: NockErr) -> Self {
// TODO: also preserve trace ()
stack.preserve(&mut cache); }
stack.pop(); }
pub fn early_exit(stack: &mut NockStack, virtual_frame: *const u64, cache: &mut Hamt<Noun>) {
unsafe {
while stack.frame_pointer() != virtual_frame {
// TODO: also preserve trace
stack.preserve(cache);
stack.pop();
}
} }
} }
@ -89,7 +98,7 @@ pub fn interpret(
mut subject: Noun, mut subject: Noun,
formula: Noun, formula: Noun,
) -> Result<Noun, NockErr> { ) -> Result<Noun, NockErr> {
let mut res = unsafe { D(0) }; let mut res = D(0);
let virtual_frame = stack.frame_pointer(); // before or after the push? let virtual_frame = stack.frame_pointer(); // before or after the push?
stack.push(1); stack.push(1);
let mut cache = Hamt::<Noun>::new(); let mut cache = Hamt::<Noun>::new();
@ -97,15 +106,14 @@ pub fn interpret(
*(stack.local_noun_pointer(0)) = work_to_noun(Done); *(stack.local_noun_pointer(0)) = work_to_noun(Done);
} }
push_formula(stack, formula)?; push_formula(stack, formula)?;
let tone = let tone = assert_no_alloc(|| unsafe {
assert_no_alloc(|| unsafe {
loop { loop {
match noun_to_work(*(stack.local_noun_pointer(0))) { match noun_to_work(*(stack.local_noun_pointer(0))) {
Done => { Done => {
stack.preserve(&mut cache); stack.preserve(&mut cache);
stack.preserve(&mut res); stack.preserve(&mut res);
stack.pop(); stack.pop();
break; break Ok(res);
} }
NockCellComputeHead => { NockCellComputeHead => {
*stack.local_noun_pointer(0) = work_to_noun(NockCellComputeTail); *stack.local_noun_pointer(0) = work_to_noun(NockCellComputeTail);
@ -127,15 +135,16 @@ pub fn interpret(
} }
Nock0Axis => { Nock0Axis => {
if let Ok(atom) = (*(stack.local_noun_pointer(1))).as_atom() { if let Ok(atom) = (*(stack.local_noun_pointer(1))).as_atom() {
if let Ok(res) = slot(subject, atom.as_bitslice()) { if let Ok(x) = slot(subject, atom.as_bitslice()) {
res = x;
stack.preserve(&mut cache); stack.preserve(&mut cache);
stack.preserve(&mut res); stack.preserve(&mut res);
stack.pop(); stack.pop();
} else { } else {
return Err(Error(D(1)); break Err(NockErr::Error(D(1)));
} }
} else { } else {
return Err(Error(D(0))); // Axis must be atom break Err(NockErr::Error(D(0))); // Axis must be atom
}; };
} }
Nock1Constant => { Nock1Constant => {
@ -194,7 +203,7 @@ pub fn interpret(
stack.preserve(&mut res); stack.preserve(&mut res);
stack.pop(); stack.pop();
} else { } else {
return Err(Error(D(2))); // Cannot increment (Nock 4) a cell break Err(NockErr::Error(D(2))); // Cannot increment (Nock 4) a cell
}; };
} }
Nock5ComputeLeftChild => { Nock5ComputeLeftChild => {
@ -234,10 +243,10 @@ pub fn interpret(
let formula = *stack.local_noun_pointer(3); let formula = *stack.local_noun_pointer(3);
push_formula(stack, formula)?; push_formula(stack, formula)?;
} else { } else {
return Err(Error(D(3))); // 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 { } else {
return Err(Error(D(4))); // 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 => { Nock6Done => {
@ -291,9 +300,14 @@ pub fn interpret(
*(stack.local_noun_pointer(0)) = work_to_noun(Nock9RestoreSubject); *(stack.local_noun_pointer(0)) = work_to_noun(Nock9RestoreSubject);
*(stack.local_noun_pointer(2)) = subject; *(stack.local_noun_pointer(2)) = subject;
subject = res; 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 { } else {
return Err(Error(D(5))); // Axis into core must be atom break Err(NockErr::Error(D(5))); // Axis into core must be atom
} }
} }
Nock9RestoreSubject => { Nock9RestoreSubject => {
@ -321,7 +335,7 @@ pub fn interpret(
stack.preserve(&mut res); stack.preserve(&mut res);
stack.pop(); stack.pop();
} else { } else {
return Err(Error(D(6))); // Axis into tree must be atom break Err(NockErr::Error(D(6))); // Axis into tree must be atom
} }
} }
Nock11ComputeHint => { Nock11ComputeHint => {
@ -371,12 +385,12 @@ pub fn interpret(
Ok(res) => Ok(res), Ok(res) => Ok(res),
Err(err) => { Err(err) => {
early_exit(stack, virtual_frame, &mut cache); early_exit(stack, virtual_frame, &mut cache);
Err(err); Err(err)
} }
} }
} }
fn push_formula(stack: &mut NockStack, formula: Noun) -> Result((), NockErr) { fn push_formula(stack: &mut NockStack, formula: Noun) -> Result<(), NockErr> {
if let Ok(formula_cell) = formula.as_cell() { if let Ok(formula_cell) = formula.as_cell() {
// Formula // Formula
match formula_cell.head().as_either_atom_cell() { match formula_cell.head().as_either_atom_cell() {
@ -546,7 +560,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) -> Result((), NockErr) {
} }
} }
} else { } else {
return Err(Error(D(10))); // Bad formula: atoms are not formulas: {} return Err(NockErr::Error(D(10))); // Bad formula: atoms are not formulas: {}
} }
Ok(()) Ok(())
} }
@ -558,9 +572,9 @@ pub fn raw_slot(noun: Noun, axis: u64) -> Noun {
pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Result<Noun, ()> { pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Result<Noun, ()> {
let mut cursor = if let Some(x) = axis.last_one() { let mut cursor = if let Some(x) = axis.last_one() {
Ok(x) x
} else { } else {
Err(()) // 0 is not allowed as an axis return Err(()); // 0 is not allowed as an axis
}; };
loop { loop {
if cursor == 0 { if cursor == 0 {
@ -574,7 +588,7 @@ pub fn slot(mut noun: Noun, axis: &BitSlice<u64, Lsb0>) -> Result<Noun, ()> {
noun = cell.head(); noun = cell.head();
} }
} else { } else {
Err(()) // Axis tried to descend through atom: {} return Err(()); // Axis tried to descend through atom: {}
}; };
} }
Ok(noun) Ok(noun)
@ -667,10 +681,12 @@ fn match_pre_hint(
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).ok_or(())?;
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 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) {
let mut nock_res = interpret(stack, newt, subject, formula); // Throw away trace because we'll regenerate it later, and this is in test mode
// so it's okay if it runs twice
let mut nock_res = interpret(stack, newt, subject, formula)?;
if unsafe { !unifying_equality(stack, &mut nock_res, &mut jet_res) } { if unsafe { !unifying_equality(stack, &mut nock_res, &mut jet_res) } {
eprintln!( eprintln!(
"\rJet {} failed, raw: {}, jetted: {}", "\rJet {} failed, raw: {}, jetted: {}",

View File

@ -1,8 +1,10 @@
pub mod math; pub mod math;
pub mod mink;
use crate::jets::math::*; use crate::jets::math::*;
use crate::jets::virtual::*; use crate::jets::mink::*;
use crate::mem::NockStack; use crate::mem::NockStack;
use crate::newt::Newt;
use crate::noun::{self, Noun}; use crate::noun::{self, Noun};
use ares_macros::tas; use ares_macros::tas;

View File

@ -16,6 +16,7 @@ use crate::interpreter::raw_slot;
use crate::jets::{JetErr, JetErr::*}; use crate::jets::{JetErr, JetErr::*};
use crate::mem::NockStack; use crate::mem::NockStack;
use crate::mug::mug; use crate::mug::mug;
use crate::newt::Newt;
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES}; use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
use bitvec::prelude::{BitSlice, Lsb0}; use bitvec::prelude::{BitSlice, Lsb0};
use either::Either::*; use either::Either::*;
@ -25,7 +26,11 @@ use std::{cmp, convert::TryFrom};
crate::gdb!(); 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); 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() {
@ -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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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; let arg = raw_slot(subject, 6).as_direct()?.data() as usize;
if arg < 63 { 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 arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?; let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?; 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 arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?; let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?; 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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let a = raw_slot(arg, 2).as_atom()?; let a = raw_slot(arg, 2).as_atom()?;
let b = raw_slot(arg, 3).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 arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?; let (bloq, step) = bite(raw_slot(arg, 2))?;
let a = raw_slot(arg, 3).as_atom()?; 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 arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 { 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 arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 { 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 arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?; let (bloq, step) = bite(raw_slot(arg, 2))?;
let original_list = raw_slot(arg, 3); 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 arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 { if bloq >= 64 {
@ -552,7 +641,11 @@ pub fn jet_cut(stack: &mut NockStack, subject: Noun) -> Result<Noun, JetErr> {
Ok(new_indirect.as_noun()) 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 arg = raw_slot(subject, 6);
let (bloq, step) = bite(raw_slot(arg, 2))?; let (bloq, step) = bite(raw_slot(arg, 2))?;
let atom = raw_slot(arg, 3).as_atom()?; 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) 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 arg = raw_slot(subject, 6);
let bloq = raw_slot(arg, 2).as_direct()?.data() as usize; let bloq = raw_slot(arg, 2).as_direct()?.data() as usize;
if bloq >= 64 { 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)) 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); let arg = raw_slot(subject, 6);
Ok(mug(stack, arg).as_noun()) 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 arg = raw_slot(subject, 6);
let boz = raw_slot(arg, 2).as_atom()?.as_direct()?.data(); 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) { fn assert_jet(stack: &mut NockStack, jet: Jet, sam: Noun, res: Noun) {
let sam = T(stack, &[D(0), sam, D(0)]); 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); 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) { fn assert_jet_err(stack: &mut NockStack, jet: Jet, sam: Noun, err: JetErr) {
let sam = T(stack, &[D(0), sam, D(0)]); let sam = T(stack, &[D(0), sam, D(0)]);
let jet_res = jet(stack, sam); let jet_res = jet(stack, &mut None, sam);
assert!( assert!(
jet_res.is_err(), jet_res.is_err(),
"with sample: {}, expected err: {:?}, got: {:?}", "with sample: {}, expected err: {:?}, got: {:?}",

View File

@ -0,0 +1,71 @@
/** 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!();
// TODO: interpret should accept optional scry function and potentially produce blocked
// TODO: what do we do with the trace, if it's on the stack?
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(1)]);
assert_jet(s, jet_mink, sam, res);
}
}

View File

@ -1,30 +0,0 @@
/** Virtualization jets
*/
use crate::interpreter::raw_slot;
use crate::jets::{JetErr, JetErr::*};
use crate::mem::NockStack;
use crate::mug::mug;
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
use bitvec::prelude::{BitSlice, Lsb0};
use either::Either::*;
use std::{cmp, convert::TryFrom};
crate::gdb!();
// can we reuse stack like this?
// interpret should accept optional scry function and potentially produce blocked
// what do we do with the trace, if it's on the stack?
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 {
Blocked(block) => Ok(T(stack, &[D(1), block])),
Error(error) => Ok(T(stack, &[D(2), error])),
}
}
}

View File

@ -20,7 +20,7 @@ fn main() -> io::Result<()> {
ares::interpreter::use_gdb(); ares::interpreter::use_gdb();
ares::jets::use_gdb(); ares::jets::use_gdb();
ares::jets::math::use_gdb(); ares::jets::math::use_gdb();
ares::jets::virtual::use_gdb(); ares::jets::mink::use_gdb();
ares::mem::use_gdb(); ares::mem::use_gdb();
ares::mug::use_gdb(); ares::mug::use_gdb();
ares::newt::use_gdb(); ares::newt::use_gdb();
@ -53,7 +53,8 @@ fn main() -> io::Result<()> {
let input_cell = input let input_cell = input
.as_cell() .as_cell()
.expect("Input must be jam of subject/formula pair"); .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() { if let Ok(atom) = result.as_atom() {
println!("Result: {}", atom); println!("Result: {}", atom);
} }

View File

@ -114,7 +114,7 @@ impl NockStack {
} }
/** Current frame pointer of this NockStack */ /** Current frame pointer of this NockStack */
pub fn frame_pointer(&self) -> *u64 { pub fn frame_pointer(&self) -> *const u64 {
self.frame_pointer self.frame_pointer
} }

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