mirror of
https://github.com/urbit/ares.git
synced 2024-11-27 05:06:32 +03:00
Merge branch 'status' into ut1
This commit is contained in:
commit
0b97e55fc4
@ -209,6 +209,7 @@
|
||||
++ flop :: reverse
|
||||
~/ %flop
|
||||
|* a=(list)
|
||||
~> %sham.%flop
|
||||
=> .(a (homo a))
|
||||
^+ a
|
||||
=+ b=`_a`~
|
||||
@ -413,6 +414,13 @@
|
||||
|= [a=bloq b=@]
|
||||
(rep a (flop (rip a b)))
|
||||
::
|
||||
++ xeb :: binary logarithm
|
||||
~/ %xeb
|
||||
|= a=@
|
||||
~> %sham.%xeb
|
||||
^- @
|
||||
(met 0 a)
|
||||
::
|
||||
:: Modular arithmetic
|
||||
::
|
||||
++ fe :: modulo bloq
|
||||
|
@ -5,11 +5,12 @@ pub mod warm;
|
||||
pub mod bits;
|
||||
pub mod form;
|
||||
pub mod hash;
|
||||
pub mod list;
|
||||
pub mod lute;
|
||||
pub mod math;
|
||||
pub mod nock;
|
||||
pub mod serial;
|
||||
pub mod sort;
|
||||
pub mod text;
|
||||
pub mod tree;
|
||||
|
||||
use crate::interpreter::{Context, Error};
|
||||
@ -18,17 +19,18 @@ use crate::jets::cold::Cold;
|
||||
use crate::jets::form::*;
|
||||
use crate::jets::hash::*;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::list::*;
|
||||
use crate::jets::math::*;
|
||||
use crate::jets::nock::*;
|
||||
use crate::jets::serial::*;
|
||||
use crate::jets::sort::*;
|
||||
use crate::jets::text::*;
|
||||
|
||||
use crate::jets::tree::*;
|
||||
use crate::jets::warm::Warm;
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{self, Noun, Slots, D};
|
||||
use ares_macros::tas;
|
||||
use std::cmp;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
@ -46,15 +48,15 @@ pub enum JetErr {
|
||||
Fail(Error), // Error; do not retry
|
||||
}
|
||||
|
||||
impl From<noun::Error> for JetErr {
|
||||
fn from(_err: noun::Error) -> Self {
|
||||
Self::Fail(Error::Deterministic(D(0)))
|
||||
impl From<Error> for JetErr {
|
||||
fn from(err: Error) -> Self {
|
||||
Self::Fail(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for JetErr {
|
||||
fn from(e: Error) -> Self {
|
||||
Self::Fail(e)
|
||||
impl From<noun::Error> for JetErr {
|
||||
fn from(_err: noun::Error) -> Self {
|
||||
Self::Fail(Error::Deterministic(D(0)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,6 +90,7 @@ pub fn get_jet(jet_name: Noun) -> Option<Jet> {
|
||||
tas!(b"cap") => Some(jet_cap),
|
||||
tas!(b"mas") => Some(jet_mas),
|
||||
//
|
||||
tas!(b"flop") => Some(jet_flop),
|
||||
tas!(b"lent") => Some(jet_lent),
|
||||
//
|
||||
tas!(b"bex") => Some(jet_bex),
|
||||
@ -102,6 +105,7 @@ pub fn get_jet(jet_name: Noun) -> Option<Jet> {
|
||||
tas!(b"rev") => Some(jet_rev),
|
||||
tas!(b"rip") => Some(jet_rip),
|
||||
tas!(b"rsh") => Some(jet_rsh),
|
||||
tas!(b"xeb") => Some(jet_xeb),
|
||||
//
|
||||
tas!(b"con") => Some(jet_con),
|
||||
tas!(b"dis") => Some(jet_dis),
|
||||
@ -113,6 +117,9 @@ pub fn get_jet(jet_name: Noun) -> Option<Jet> {
|
||||
tas!(b"gor") => Some(jet_gor),
|
||||
tas!(b"mor") => Some(jet_mor),
|
||||
//
|
||||
tas!(b"cue") => Some(jet_cue),
|
||||
tas!(b"jam") => Some(jet_jam),
|
||||
//
|
||||
tas!(b"scow") => Some(jet_scow),
|
||||
//
|
||||
tas!(b"mink") => Some(jet_mink),
|
||||
@ -135,10 +142,8 @@ pub fn get_jet_test_mode(_jet_name: Noun) -> bool {
|
||||
|
||||
pub mod util {
|
||||
use super::*;
|
||||
use crate::noun::Error::NotRepresentable;
|
||||
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, Noun, D};
|
||||
use crate::noun::{Noun, D};
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use ibig::UBig;
|
||||
use std::result;
|
||||
|
||||
/**
|
||||
@ -237,86 +242,6 @@ pub mod util {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Subtraction
|
||||
pub fn sub(stack: &mut NockStack, a: Atom, b: Atom) -> noun::Result<Atom> {
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
let a_small = a.data();
|
||||
let b_small = b.data();
|
||||
|
||||
if a_small < b_small {
|
||||
Err(NotRepresentable)
|
||||
} else {
|
||||
Ok(Atom::new(stack, a_small - b_small))
|
||||
}
|
||||
} else {
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
|
||||
if a_big < b_big {
|
||||
Err(NotRepresentable)
|
||||
} else {
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
let res = UBig::sub_stack(stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(stack, &res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary exponent
|
||||
pub fn bex(stack: &mut NockStack, arg: usize) -> Atom {
|
||||
unsafe {
|
||||
if arg < 63 {
|
||||
DirectAtom::new_unchecked(1 << arg).as_atom()
|
||||
} else {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, (arg + 7) >> 3);
|
||||
dest.set(arg, true);
|
||||
atom.normalize_as_atom()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Measure the number of bloqs in an atom
|
||||
pub fn met(bloq: usize, a: Atom) -> usize {
|
||||
if unsafe { a.as_noun().raw_equals(D(0)) } {
|
||||
0
|
||||
} else if bloq < 6 {
|
||||
(a.bit_size() + ((1 << bloq) - 1)) >> bloq
|
||||
} else {
|
||||
let bloq_word = bloq - 6;
|
||||
(a.size() + ((1 << bloq_word) - 1)) >> bloq_word
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rip(stack: &mut NockStack, bloq: usize, step: usize, atom: Atom) -> Result {
|
||||
let len = (met(bloq, atom) + step - 1) / step;
|
||||
let mut list = D(0);
|
||||
for i in (0..len).rev() {
|
||||
let new_atom = unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(stack, step << bloq);
|
||||
chop(bloq, i * step, step, 0, new_slice, atom.as_bitslice())?;
|
||||
new_indirect.normalize_as_atom()
|
||||
};
|
||||
list = Cell::new(stack, new_atom.as_noun(), list).as_noun();
|
||||
}
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
|
||||
/// Binary OR
|
||||
pub fn con(stack: &mut NockStack, a: Atom, b: Atom) -> Atom {
|
||||
let new_size = cmp::max(a.size(), b.size());
|
||||
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, new_size);
|
||||
let a_bit = a.as_bitslice();
|
||||
dest[..a_bit.len()].copy_from_bitslice(a_bit);
|
||||
*dest |= b.as_bitslice();
|
||||
atom.normalize_as_atom()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::hamt::Hamt;
|
||||
@ -415,40 +340,4 @@ pub mod util {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::test::{init_context, A};
|
||||
use super::*;
|
||||
use ibig::ubig;
|
||||
|
||||
#[test]
|
||||
fn test_met() {
|
||||
let c = &mut init_context();
|
||||
let s = &mut c.stack;
|
||||
|
||||
let a = A(s, &ubig!(0xdeadbeef12345678fedcba9876543210))
|
||||
.as_atom()
|
||||
.unwrap();
|
||||
assert_eq!(met(0, a), 128);
|
||||
assert_eq!(met(1, a), 64);
|
||||
assert_eq!(met(2, a), 32);
|
||||
assert_eq!(met(3, a), 16);
|
||||
assert_eq!(met(4, a), 8);
|
||||
assert_eq!(met(5, a), 4);
|
||||
assert_eq!(met(6, a), 2);
|
||||
assert_eq!(met(7, a), 1);
|
||||
assert_eq!(met(8, a), 1);
|
||||
|
||||
let a = D(0x7fffffffffffffff).as_atom().unwrap();
|
||||
assert_eq!(met(0, a), 63);
|
||||
assert_eq!(met(1, a), 32);
|
||||
assert_eq!(met(2, a), 16);
|
||||
assert_eq!(met(3, a), 8);
|
||||
assert_eq!(met(4, a), 4);
|
||||
assert_eq!(met(5, a), 2);
|
||||
assert_eq!(met(6, a), 1);
|
||||
assert_eq!(met(7, a), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ crate::gdb!();
|
||||
|
||||
pub fn jet_bex(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?.as_direct()?.data() as usize;
|
||||
Ok(bex(&mut context.stack, arg).as_noun())
|
||||
Ok(util::bex(&mut context.stack, arg).as_noun())
|
||||
}
|
||||
|
||||
pub fn jet_can(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -70,8 +70,8 @@ pub fn jet_cat(context: &mut Context, subject: Noun) -> Result {
|
||||
let a = slot(arg, 6)?.as_atom()?;
|
||||
let b = slot(arg, 7)?.as_atom()?;
|
||||
|
||||
let len_a = met(bloq, a);
|
||||
let len_b = met(bloq, b);
|
||||
let len_a = util::met(bloq, a);
|
||||
let len_b = util::met(bloq, b);
|
||||
let new_len = bite_to_word(bloq, checked_add(len_a, len_b)?)?;
|
||||
if new_len == 0 {
|
||||
Ok(a.as_noun())
|
||||
@ -113,7 +113,7 @@ pub fn jet_end(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
if step == 0 {
|
||||
Ok(D(0))
|
||||
} else if step >= met(bloq, a) {
|
||||
} else if step >= util::met(bloq, a) {
|
||||
Ok(a.as_noun())
|
||||
} else {
|
||||
unsafe {
|
||||
@ -130,7 +130,7 @@ pub fn jet_lsh(context: &mut Context, subject: Noun) -> Result {
|
||||
let (bloq, step) = bite(slot(arg, 2)?)?;
|
||||
let a = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
let len = met(bloq, a);
|
||||
let len = util::met(bloq, a);
|
||||
if len == 0 {
|
||||
return Ok(D(0));
|
||||
}
|
||||
@ -148,7 +148,7 @@ pub fn jet_met(_context: &mut Context, subject: Noun) -> Result {
|
||||
let bloq = bloq(slot(arg, 2)?)?;
|
||||
let a = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(D(met(bloq, a) as u64))
|
||||
Ok(D(util::met(bloq, a) as u64))
|
||||
}
|
||||
|
||||
pub fn jet_rap(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -165,7 +165,7 @@ pub fn jet_rap(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let cell = list.as_cell()?;
|
||||
|
||||
len = checked_add(len, met(bloq, cell.head().as_atom()?))?;
|
||||
len = checked_add(len, util::met(bloq, cell.head().as_atom()?))?;
|
||||
list = cell.tail();
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ pub fn jet_rap(context: &mut Context, subject: Noun) -> Result {
|
||||
|
||||
let cell = list.as_cell()?;
|
||||
let atom = cell.head().as_atom()?;
|
||||
let step = met(bloq, atom);
|
||||
let step = util::met(bloq, atom);
|
||||
chop(bloq, 0, step, pos, new_slice, atom.as_bitslice())?;
|
||||
|
||||
pos += step;
|
||||
@ -282,7 +282,7 @@ pub fn jet_rip(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
let (bloq, step) = bite(slot(arg, 2)?)?;
|
||||
let atom = slot(arg, 3)?.as_atom()?;
|
||||
rip(&mut context.stack, bloq, step, atom)
|
||||
util::rip(&mut context.stack, bloq, step, atom)
|
||||
}
|
||||
|
||||
pub fn jet_rsh(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -290,7 +290,7 @@ pub fn jet_rsh(context: &mut Context, subject: Noun) -> Result {
|
||||
let (bloq, step) = bite(slot(arg, 2)?)?;
|
||||
let a = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
let len = met(bloq, a);
|
||||
let len = util::met(bloq, a);
|
||||
if step >= len {
|
||||
return Ok(D(0));
|
||||
}
|
||||
@ -312,7 +312,7 @@ pub fn jet_con(context: &mut Context, subject: Noun) -> Result {
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(con(&mut context.stack, a, b).as_noun())
|
||||
Ok(util::con(&mut context.stack, a, b).as_noun())
|
||||
}
|
||||
|
||||
pub fn jet_dis(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -347,6 +347,114 @@ pub fn jet_mix(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_xeb(_context: &mut Context, subject: Noun) -> Result {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 1)?.as_atom()?;
|
||||
Ok(D(util::met(0, a) as u64))
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::Result;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Atom, Cell, DirectAtom, IndirectAtom, D};
|
||||
use std::cmp;
|
||||
|
||||
/// Binary exponent
|
||||
pub fn bex(stack: &mut NockStack, arg: usize) -> Atom {
|
||||
unsafe {
|
||||
if arg < 63 {
|
||||
DirectAtom::new_unchecked(1 << arg).as_atom()
|
||||
} else {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, (arg + 7) >> 3);
|
||||
dest.set(arg, true);
|
||||
atom.normalize_as_atom()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Measure the number of bloqs in an atom
|
||||
pub fn met(bloq: usize, a: Atom) -> usize {
|
||||
if unsafe { a.as_noun().raw_equals(D(0)) } {
|
||||
0
|
||||
} else if bloq < 6 {
|
||||
(a.bit_size() + ((1 << bloq) - 1)) >> bloq
|
||||
} else {
|
||||
let bloq_word = bloq - 6;
|
||||
(a.size() + ((1 << bloq_word) - 1)) >> bloq_word
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rip(stack: &mut NockStack, bloq: usize, step: usize, atom: Atom) -> Result {
|
||||
let len = (met(bloq, atom) + step - 1) / step;
|
||||
let mut list = D(0);
|
||||
for i in (0..len).rev() {
|
||||
let new_atom = unsafe {
|
||||
let (mut new_indirect, new_slice) =
|
||||
IndirectAtom::new_raw_mut_bitslice(stack, step << bloq);
|
||||
chop(bloq, i * step, step, 0, new_slice, atom.as_bitslice())?;
|
||||
new_indirect.normalize_as_atom()
|
||||
};
|
||||
list = Cell::new(stack, new_atom.as_noun(), list).as_noun();
|
||||
}
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
|
||||
/// Binary OR
|
||||
pub fn con(stack: &mut NockStack, a: Atom, b: Atom) -> Atom {
|
||||
let new_size = cmp::max(a.size(), b.size());
|
||||
|
||||
unsafe {
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut_bitslice(stack, new_size);
|
||||
let a_bit = a.as_bitslice();
|
||||
dest[..a_bit.len()].copy_from_bitslice(a_bit);
|
||||
*dest |= b.as_bitslice();
|
||||
atom.normalize_as_atom()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::A;
|
||||
use crate::noun::D;
|
||||
use ibig::ubig;
|
||||
|
||||
fn init_stack() -> NockStack {
|
||||
NockStack::new(8 << 10 << 10, 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_met() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
let a = A(s, &ubig!(0xdeadbeef12345678fedcba9876543210))
|
||||
.as_atom()
|
||||
.unwrap();
|
||||
assert_eq!(met(0, a), 128);
|
||||
assert_eq!(met(1, a), 64);
|
||||
assert_eq!(met(2, a), 32);
|
||||
assert_eq!(met(3, a), 16);
|
||||
assert_eq!(met(4, a), 8);
|
||||
assert_eq!(met(5, a), 4);
|
||||
assert_eq!(met(6, a), 2);
|
||||
assert_eq!(met(7, a), 1);
|
||||
assert_eq!(met(8, a), 1);
|
||||
|
||||
let a = D(0x7fffffffffffffff).as_atom().unwrap();
|
||||
assert_eq!(met(0, a), 63);
|
||||
assert_eq!(met(1, a), 32);
|
||||
assert_eq!(met(2, a), 16);
|
||||
assert_eq!(met(3, a), 8);
|
||||
assert_eq!(met(4, a), 4);
|
||||
assert_eq!(met(5, a), 2);
|
||||
assert_eq!(met(6, a), 1);
|
||||
assert_eq!(met(7, a), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -740,4 +848,16 @@ mod tests {
|
||||
let sam = T(&mut c.stack, &[a128, a0]);
|
||||
assert_jet(c, jet_mix, sam, a128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xeb() {
|
||||
let c = &mut init_context();
|
||||
|
||||
let (a0, a24, a63, a96, a128) = atoms(&mut c.stack);
|
||||
assert_jet(c, jet_xeb, a0, D(0));
|
||||
assert_jet(c, jet_xeb, a24, D(24));
|
||||
assert_jet(c, jet_xeb, a63, D(63));
|
||||
assert_jet(c, jet_xeb, a96, D(96));
|
||||
assert_jet(c, jet_xeb, a128, D(128));
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ const HOT_STATE: &[(&[Either<u64, (u64, u64)>], u64, Jet)] = &[
|
||||
(&[A_50, Left(tas!(b"mas"))], 1, jet_mas),
|
||||
//
|
||||
(&[A_50, Left(tas!(b"lent"))], 1, jet_lent),
|
||||
(&[A_50, Left(tas!(b"flop"))], 1, jet_flop),
|
||||
//
|
||||
(&[A_50, Left(tas!(b"bex"))], 1, jet_bex),
|
||||
(&[A_50, Left(tas!(b"can"))], 1, jet_can),
|
||||
@ -38,6 +39,7 @@ const HOT_STATE: &[(&[Either<u64, (u64, u64)>], u64, Jet)] = &[
|
||||
(&[A_50, Left(tas!(b"rev"))], 1, jet_rev),
|
||||
(&[A_50, Left(tas!(b"rip"))], 1, jet_rip),
|
||||
(&[A_50, Left(tas!(b"rsh"))], 1, jet_rsh),
|
||||
(&[A_50, Left(tas!(b"xeb"))], 1, jet_xeb),
|
||||
//
|
||||
(&[A_50, Left(tas!(b"con"))], 1, jet_con),
|
||||
(&[A_50, Left(tas!(b"dis"))], 1, jet_dis),
|
||||
|
122
rust/ares/src/jets/list.rs
Normal file
122
rust/ares/src/jets/list.rs
Normal file
@ -0,0 +1,122 @@
|
||||
/** Text processing jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
pub fn jet_flop(context: &mut Context, subject: Noun) -> Result {
|
||||
let sam = slot(subject, 6)?;
|
||||
Ok(util::flop(&mut context.stack, sam)?)
|
||||
}
|
||||
|
||||
pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
|
||||
let tape = slot(subject, 6)?;
|
||||
util::lent(tape).map(|x| D(x as u64))
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::JetErr;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Noun, D, T};
|
||||
use std::result::Result;
|
||||
|
||||
/// Reverse order of list
|
||||
pub fn flop(stack: &mut NockStack, noun: Noun) -> Result<Noun, Error> {
|
||||
let mut list = noun;
|
||||
let mut tsil = D(0);
|
||||
loop {
|
||||
if unsafe { list.raw_equals(D(0)) } {
|
||||
break;
|
||||
}
|
||||
|
||||
let cell = list.as_cell()?;
|
||||
tsil = T(stack, &[cell.head(), tsil]);
|
||||
list = cell.tail();
|
||||
}
|
||||
|
||||
Ok(tsil)
|
||||
}
|
||||
|
||||
pub fn lent(tape: Noun) -> Result<usize, JetErr> {
|
||||
let mut len = 0usize;
|
||||
let mut list = tape;
|
||||
loop {
|
||||
if let Some(atom) = list.atom() {
|
||||
if atom.as_bitslice().first_one().is_none() {
|
||||
break;
|
||||
} else {
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
let cell = list.as_cell()?;
|
||||
// don't need checked_add or indirect atom result: 2^63-1 atoms would be 64 ebibytes
|
||||
len += 1;
|
||||
list = cell.tail();
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{D, T};
|
||||
|
||||
#[test]
|
||||
fn test_flop() {
|
||||
let c = &mut init_context();
|
||||
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3), D(0)]);
|
||||
let res = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_flop, sam, res);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let sam = T(
|
||||
&mut c.stack,
|
||||
&[
|
||||
D(0xd), D(0xe), D(0xa), D(0xd), D(0xb), D(0xe), D(0xe), D(0xf),
|
||||
D(0x1), D(0x2), D(0x3), D(0x4), D(0x5), D(0x6), D(0x7), D(0x8),
|
||||
D(0xf), D(0xe), D(0xd), D(0xc), D(0xb), D(0xa), D(0x9), D(0x8),
|
||||
D(0x7), D(0x6), D(0x5), D(0x4), D(0x3), D(0x2), D(0x1), D(0x0),
|
||||
D(0x0),
|
||||
],
|
||||
);
|
||||
#[rustfmt::skip]
|
||||
let res = T(
|
||||
&mut c.stack,
|
||||
&[
|
||||
D(0x0), D(0x1), D(0x2), D(0x3), D(0x4), D(0x5), D(0x6), D(0x7),
|
||||
D(0x8), D(0x9), D(0xa), D(0xb), D(0xc), D(0xd), D(0xe), D(0xf),
|
||||
D(0x8), D(0x7), D(0x6), D(0x5), D(0x4), D(0x3), D(0x2), D(0x1),
|
||||
D(0xf), D(0xe), D(0xe), D(0xb), D(0xd), D(0xa), D(0xe), D(0xd),
|
||||
D(0x0),
|
||||
],
|
||||
);
|
||||
assert_jet(c, jet_flop, sam, res);
|
||||
|
||||
assert_jet_err(c, jet_flop, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3)]);
|
||||
assert_jet_err(c, jet_flop, sam, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lent() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_lent, D(0), D(0));
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
||||
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
@ -250,12 +250,13 @@ pub fn jet_sub(context: &mut Context, subject: Noun) -> Result {
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
Ok(sub(&mut context.stack, a, b)?.as_noun())
|
||||
Ok(util::sub(&mut context.stack, a, b)?.as_noun())
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{Atom, Noun, NO, YES};
|
||||
use crate::noun::{Atom, Error, Noun, Result, NO, YES};
|
||||
use ibig::UBig;
|
||||
|
||||
pub fn lth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
@ -274,6 +275,32 @@ pub mod util {
|
||||
NO
|
||||
}
|
||||
}
|
||||
|
||||
/// Subtraction
|
||||
pub fn sub(stack: &mut NockStack, a: Atom, b: Atom) -> Result<Atom> {
|
||||
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
|
||||
let a_small = a.data();
|
||||
let b_small = b.data();
|
||||
|
||||
if a_small < b_small {
|
||||
Err(Error::NotRepresentable)
|
||||
} else {
|
||||
Ok(Atom::new(stack, a_small - b_small))
|
||||
}
|
||||
} else {
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
|
||||
if a_big < b_big {
|
||||
Err(Error::NotRepresentable)
|
||||
} else {
|
||||
let a_big = a.as_ubig(stack);
|
||||
let b_big = b.as_ubig(stack);
|
||||
let res = UBig::sub_stack(stack, a_big, b_big);
|
||||
Ok(Atom::from_ubig(stack, &res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,10 +1,10 @@
|
||||
/** Virtualization jets
|
||||
*/
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, T};
|
||||
use crate::noun::{Cell, Noun, D, NO, T, YES};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
@ -77,11 +77,69 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_mole(context: &mut Context, subject: Noun) -> Result {
|
||||
jet_mure(context, subject)
|
||||
}
|
||||
|
||||
pub fn jet_mule(context: &mut Context, subject: Noun) -> Result {
|
||||
jet_mute(context, subject)
|
||||
}
|
||||
|
||||
pub fn jet_mure(context: &mut Context, subject: Noun) -> Result {
|
||||
let tap = slot(subject, 6)?;
|
||||
let fol = util::slam_gate_fol(&mut context.stack);
|
||||
let scry = util::pass_thru_scry(&mut context.stack);
|
||||
|
||||
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
|
||||
match interpret(context, tap, fol) {
|
||||
Ok(res) => {
|
||||
context.scry_stack = context.scry_stack.as_cell()?.tail();
|
||||
Ok(T(&mut context.stack, &[D(0), res]))
|
||||
}
|
||||
Err(error) => match error {
|
||||
// Since we are using the pass-through scry handler, we know for a fact that a scry
|
||||
// crash must have come from a senior virtualization context.
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
|
||||
Error::Deterministic(_) | Error::ScryBlocked(_) => Ok(D(0)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_mute(context: &mut Context, subject: Noun) -> Result {
|
||||
let tap = slot(subject, 6)?;
|
||||
let fol = util::slam_gate_fol(&mut context.stack);
|
||||
let scry = util::pass_thru_scry(&mut context.stack);
|
||||
|
||||
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
|
||||
match interpret(context, tap, fol) {
|
||||
Ok(res) => {
|
||||
context.scry_stack = context.scry_stack.as_cell()?.tail();
|
||||
Ok(T(&mut context.stack, &[YES, res]))
|
||||
}
|
||||
Err(error) => match error {
|
||||
// Since we are using the pass-through scry handler, we know for a fact that a scry
|
||||
// crash must have come from a senior virtualization context.
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryBlocked(path) => {
|
||||
// XX: Need to check that result is actually of type path
|
||||
// return [[%leaf "mute.hunk"] ~] if not
|
||||
let bon = util::smyt(&mut context.stack, path)?;
|
||||
Ok(T(&mut context.stack, &[NO, bon, D(0)]))
|
||||
}
|
||||
Error::Deterministic(trace) => {
|
||||
let ton = Cell::new(&mut context.stack, D(2), trace);
|
||||
let tun = util::mook(context, ton, false)?;
|
||||
Ok(T(&mut context.stack, &[NO, tun.tail()]))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::jets;
|
||||
use crate::jets::bits::util::rip;
|
||||
use crate::jets::form::util::scow;
|
||||
use crate::jets::util::rip;
|
||||
use crate::jets::JetErr;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{tape, Cell, Noun, D, T};
|
||||
@ -92,6 +150,32 @@ pub mod util {
|
||||
pub const LEAF: Noun = D(tas!(b"leaf"));
|
||||
pub const ROSE: Noun = D(tas!(b"rose"));
|
||||
|
||||
/// The classic "slam gate" formula.
|
||||
pub fn slam_gate_fol(stack: &mut NockStack) -> Noun {
|
||||
T(stack, &[D(9), D(2), D(0), D(1)])
|
||||
}
|
||||
|
||||
/// The classic "pass-through" scry handler.
|
||||
pub fn pass_thru_scry(stack: &mut NockStack) -> Noun {
|
||||
// > .* 0 != => ~ |=(a=^ ``.*(a [%12 [%0 2] %0 3]))
|
||||
// [[[1 0] [1 0] 2 [0 6] 1 12 [0 2] 0 3] [0 0] 0]
|
||||
let sig = T(stack, &[D(1), D(0)]);
|
||||
let sam = T(stack, &[D(0), D(6)]);
|
||||
let hed = T(stack, &[D(0), D(2)]);
|
||||
let tel = T(stack, &[D(0), D(3)]);
|
||||
let zap = T(stack, &[D(0), D(0)]);
|
||||
|
||||
let cry = T(stack, &[D(12), hed, tel]);
|
||||
let fol = T(stack, &[D(1), cry]);
|
||||
let res = T(stack, &[D(2), sam, fol]);
|
||||
let uno = T(stack, &[sig, res]);
|
||||
let dos = T(stack, &[sig, uno]);
|
||||
|
||||
let gat = T(stack, &[zap, D(0)]);
|
||||
|
||||
T(stack, &[dos, gat])
|
||||
}
|
||||
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Error> {
|
||||
match interpret(context, subject, formula) {
|
||||
Ok(res) => Ok(T(&mut context.stack, &[D(0), res])),
|
||||
|
46
rust/ares/src/jets/serial.rs
Normal file
46
rust/ares/src/jets/serial.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use crate::interpreter::Context;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::Noun;
|
||||
use crate::serialization::{cue, jam};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
pub fn jet_cue(context: &mut Context, subject: Noun) -> Result {
|
||||
Ok(cue(&mut context.stack, slot(subject, 6)?.as_atom()?))
|
||||
}
|
||||
|
||||
pub fn jet_jam(context: &mut Context, subject: Noun) -> Result {
|
||||
Ok(jam(&mut context.stack, slot(subject, 6)?).as_noun())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::*;
|
||||
use crate::noun::{D, T};
|
||||
|
||||
#[test]
|
||||
fn test_jam() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_jam, D(0x0), D(0x2));
|
||||
assert_jet(c, jet_jam, D(0x1), D(0xc));
|
||||
let sam = T(&mut c.stack, &[D(0x0), D(0x0)]);
|
||||
assert_jet(c, jet_jam, sam, D(0x29));
|
||||
let sam = T(&mut c.stack, &[D(0x1), D(0x2), D(0x3), D(0x0)]);
|
||||
assert_jet(c, jet_jam, sam, D(0x2d0c871));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cue() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_cue, D(0x2), D(0x0));
|
||||
assert_jet(c, jet_cue, D(0xc), D(0x1));
|
||||
let res = T(&mut c.stack, &[D(0x0), D(0x0)]);
|
||||
assert_jet(c, jet_cue, D(0x29), res);
|
||||
let res = T(&mut c.stack, &[D(0x1), D(0x2), D(0x3), D(0x0)]);
|
||||
assert_jet(c, jet_cue, D(0x2d0c871), res);
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/** Text processing jets
|
||||
*/
|
||||
use crate::interpreter::Context;
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
pub fn jet_lent(_context: &mut Context, subject: Noun) -> Result {
|
||||
let tape = slot(subject, 6)?;
|
||||
util::lent(tape).map(|x| D(x as u64))
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{Noun, D};
|
||||
|
||||
pub fn lent(tape: Noun) -> Result<usize, JetErr> {
|
||||
let mut len = 0usize;
|
||||
let mut list = tape;
|
||||
loop {
|
||||
if let Some(atom) = list.atom() {
|
||||
if atom.as_bitslice().first_one().is_none() {
|
||||
break;
|
||||
} else {
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
||||
let cell = list.as_cell()?;
|
||||
// don't need checked_add or indirect atom result: 2^63-1 atoms would be 64 ebibytes
|
||||
len += 1;
|
||||
list = cell.tail();
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::interpreter::Error;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_context};
|
||||
use crate::jets::JetErr;
|
||||
use crate::noun::{D, T};
|
||||
|
||||
#[test]
|
||||
fn test_lent() {
|
||||
let c = &mut init_context();
|
||||
|
||||
assert_jet(c, jet_lent, D(0), D(0));
|
||||
let sam = T(&mut c.stack, &[D(1), D(2), D(3), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1), D(0)]);
|
||||
assert_jet(c, jet_lent, sam, D(3));
|
||||
assert_jet_err(c, jet_lent, D(1), JetErr::Fail(Error::Deterministic(D(0))));
|
||||
let sam = T(&mut c.stack, &[D(3), D(2), D(1)]);
|
||||
assert_jet_err(c, jet_lent, sam, JetErr::Fail(Error::Deterministic(D(0))));
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/** Tree jets
|
||||
*/
|
||||
use crate::interpreter::{Context, Error};
|
||||
use crate::jets::bits::util::*;
|
||||
use crate::jets::math::util::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Noun, D};
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::mem::{word_size_of, NockStack};
|
||||
use ares_macros::tas;
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use either::{Either, Left, Right};
|
||||
use ibig::{Stack, UBig};
|
||||
|
@ -3,8 +3,8 @@ use crate::interpreter;
|
||||
use crate::interpreter::{inc, interpret, Error};
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::list::util::lent;
|
||||
use crate::jets::nock::util::mook;
|
||||
use crate::jets::text::util::lent;
|
||||
use crate::jets::warm::Warm;
|
||||
use crate::mem::NockStack;
|
||||
use crate::mug::mug_u32;
|
||||
|
Loading…
Reference in New Issue
Block a user