mirror of
https://github.com/urbit/ares.git
synced 2024-11-22 15:08:54 +03:00
commit
66d51f555c
@ -6,6 +6,7 @@ pub mod bits;
|
||||
pub mod form;
|
||||
pub mod hash;
|
||||
pub mod list;
|
||||
pub mod lute;
|
||||
pub mod math;
|
||||
pub mod nock;
|
||||
pub mod serial;
|
||||
|
218
rust/ares/src/jets/lute.rs
Normal file
218
rust/ares/src/jets/lute.rs
Normal file
@ -0,0 +1,218 @@
|
||||
/** ++ut jets (compiler backend and pretty-printer)
|
||||
*/
|
||||
use crate::interpreter::{interpret, Context};
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::{Noun, D, NO, NONE, T, YES};
|
||||
use ares_macros::tas;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
pub fn jet_crop(context: &mut Context, subject: Noun) -> Result {
|
||||
let rff = slot(subject, 6)?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = 141 + tas!(b"crop") + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, rff, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_fish(context: &mut Context, subject: Noun) -> Result {
|
||||
// axe must be Atom, though we use it as Noun
|
||||
let axe = slot(subject, 6)?.as_atom()?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = 141 + tas!(b"fish") + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, axe.as_noun(), bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_ut_fuse(context: &mut Context, subject: Noun) -> Result {
|
||||
let rff = slot(subject, 6)?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = 141 + tas!(b"fuse") + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, rff, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_ut_mint(context: &mut Context, subject: Noun) -> Result {
|
||||
let gol = slot(subject, 12)?;
|
||||
let gen = slot(subject, 13)?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let fun = 141 + tas!(b"mint");
|
||||
let vet = slot(van, 59).map_or(NONE, |x| x);
|
||||
let mut key = T(&mut context.stack, &[D(fun), vet, sut, gol, gen, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_ut_mull(context: &mut Context, subject: Noun) -> Result {
|
||||
let gol = slot(subject, 12)?;
|
||||
let dox = slot(subject, 26)?;
|
||||
let gen = slot(subject, 27)?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = 141 + tas!(b"mull") + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, gol, dox, gen, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_ut_nest(context: &mut Context, subject: Noun) -> Result {
|
||||
let nest_in_core = slot(subject, 3)?;
|
||||
|
||||
let seg = slot(nest_in_core, 12)?;
|
||||
let reg = slot(nest_in_core, 26)?;
|
||||
let nest_core = slot(nest_in_core, 7)?;
|
||||
|
||||
let rff = slot(nest_core, 13)?;
|
||||
let van = slot(nest_core, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = (141 + tas!(b"dext")) + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, rff, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
if unsafe { pro.raw_equals(YES) && reg.raw_equals(D(0)) }
|
||||
|| unsafe { pro.raw_equals(NO) && seg.raw_equals(D(0)) }
|
||||
{
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
}
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_ut_rest(context: &mut Context, subject: Noun) -> Result {
|
||||
let leg = slot(subject, 6)?;
|
||||
let van = slot(subject, 7)?;
|
||||
|
||||
let bat = slot(van, 2)?;
|
||||
let sut = slot(van, 6)?;
|
||||
|
||||
let flag = if let Ok(noun) = slot(van, 59) {
|
||||
if unsafe { noun.raw_equals(D(0)) } {
|
||||
0u64
|
||||
} else {
|
||||
1u64
|
||||
}
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let fun = 141 + tas!(b"rest") + (flag << 8);
|
||||
let mut key = T(&mut context.stack, &[D(fun), sut, leg, bat]);
|
||||
|
||||
match context.cache.lookup(&mut context.stack, &mut key) {
|
||||
Some(pro) => Ok(pro),
|
||||
None => {
|
||||
let pro = interpret(context, subject, slot(subject, 2)?)?;
|
||||
context.cache = context.cache.insert(&mut context.stack, &mut key, pro);
|
||||
Ok(pro)
|
||||
}
|
||||
}
|
||||
}
|
@ -51,18 +51,19 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
Err(error) => match error {
|
||||
Error::NonDeterministic(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryCrashed(trace) => {
|
||||
// When we enter a +mink call, we record what the scry handler stack looked like on
|
||||
// entry. Each scry pulls the scry handler off the top of the scry handler stack and
|
||||
// and calls interpret() with the remainder of the scry handler stack. When a scry
|
||||
// succeeds, it replaces the scry handler it used at the top of the stack. However,
|
||||
// it never does so when it fails. Therefore, we can tell which particular
|
||||
// virtualization instance failed if the scry handler stack at the time of failure
|
||||
// is identical to the scry handler stack on entry to the +mink call. Therefore,
|
||||
// when a virtual nock call returns ScryCrashed, mink compares the root of the scry
|
||||
// handler stack currently in the context object with the one that was on the stack
|
||||
// when the mink call was initiated. If they match, it's this mink call that crashed
|
||||
// so convert the Error::ScryCrashed into a Error::Deterministic. Otherwise, pass
|
||||
// the Error::ScryCrashed up to the senior virtualizer.
|
||||
// When we enter a +mink call, we record the state of the scry handler stack at the
|
||||
// time (i.e. the Noun representing (list scry)). Each scry will pop the head off of
|
||||
// this scry handler stack and calls interpret(), using the rest of the scry handler
|
||||
// stack in the event that it scries again recursively. When a scry succeeds, it
|
||||
// replaces the scry handler that it used by pushing it back onto the top of the
|
||||
// scry handler stack. However, it never does so when it fails. Therefore, we can
|
||||
// tell which particular virtualization instance failed by comparing the scry
|
||||
// handler stack at the time of failure (i.e. the scry handler stack in the context
|
||||
// after a failed scry) with the scry handler stack at the time of the virtualization
|
||||
// call. Thus, whenever a virtualized interpret() call fails with a
|
||||
// Error::ScryCrashed, jet_mink() compares the two scry handler stack Nouns> If they
|
||||
// are identical, jet_mink() bails with Error::Deterministic. Otherwise, it forwards
|
||||
// the Error::ScryCrashed to the senior virtualization call.
|
||||
if unsafe { context.scry_stack.raw_equals(old_scry_stack) } {
|
||||
Err(JetErr::Fail(Error::Deterministic(trace)))
|
||||
} else {
|
||||
|
@ -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};
|
||||
@ -39,6 +40,7 @@ const FORWARDING_MASK: u64 = CELL_MASK;
|
||||
/** Loobeans */
|
||||
pub const YES: Noun = D(0);
|
||||
pub const NO: Noun = D(1);
|
||||
pub const NONE: Noun = unsafe { DirectAtom::new_unchecked(tas!(b"MORMAGIC")).as_noun() };
|
||||
|
||||
#[cfg(feature = "check_acyclic")]
|
||||
#[macro_export]
|
||||
@ -916,6 +918,10 @@ pub union Noun {
|
||||
}
|
||||
|
||||
impl Noun {
|
||||
pub fn is_none(self) -> bool {
|
||||
unsafe { self.raw == u64::MAX }
|
||||
}
|
||||
|
||||
pub fn is_direct(&self) -> bool {
|
||||
unsafe { is_direct_atom(self.raw) }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user