Merge pull request #190 from urbit/eamsden/jet-turn

jets: jet +turn
This commit is contained in:
Edward Amsden 2024-01-22 13:21:15 -06:00 committed by GitHub
commit 8e45025228
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 101 additions and 3 deletions

View File

@ -94,6 +94,11 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
1,
jet_lent,
),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"turn")],
1,
jet_turn,
),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"zing")],
1,

View File

@ -1,9 +1,11 @@
/** Text processing jets
*/
use crate::interpreter::Context;
use crate::interpreter::{interpret, Context, Error};
use crate::jets::util::slot;
use crate::jets::Result;
use crate::noun::{Noun, D};
use crate::jets::{JetErr, Result};
use crate::noun::{Cell, Noun, D, T};
use bitvec::order::Lsb0;
use bitvec::slice::BitSlice;
crate::gdb!();
@ -24,6 +26,97 @@ pub fn jet_zing(context: &mut Context, subject: Noun) -> Result {
util::zing(stack, list)
}
pub fn jet_turn(context: &mut Context, subject: Noun) -> Result {
let sample = slot(subject, 6)?;
let mut list = slot(sample, 2)?;
let mut gate = slot(sample, 3)?;
let mut gate_battery = slot(gate, 2)?;
let gate_context = slot(gate, 7)?;
let mut res = D(0);
let mut dest: *mut Noun = &mut res; // Mutable pointer because we cannot guarantee initialized
// Since the gate doesn't change, we can do a single jet check and use that through the whole
// loop
if let Some((jet, _path)) = context
.warm
.find_jet(&mut context.stack, &mut gate, &mut gate_battery)
.filter(|(_jet, mut path)| {
// check that 7 is a prefix of the parent battery axis,
// to ensure that the sample (axis 6) is not part of the jet match.
//
// XX TODO this check is pessimized since there could be multiple ways to match the
// jet and we only actually match one of them, but we check all of them and run
// unjetted if any have an axis outside 7.
let axis_7_bits: &BitSlice<u64, Lsb0> = BitSlice::from_element(&7u64);
let batteries_list = context.cold.find(&mut context.stack, &mut path);
let mut ret = true;
for mut batteries in batteries_list {
if let Some((_battery, parent_axis)) = batteries.next() {
let parent_axis_prefix_bits = &parent_axis.as_bitslice()[0..3];
if parent_axis_prefix_bits == axis_7_bits {
continue;
} else {
ret = false;
break;
}
} else {
ret = false;
break;
}
}
ret
})
{
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = jet(context, element_subject)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
}
} else {
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = interpret(context, element_subject, gate_battery)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(JetErr::Fail(Error::Deterministic(D(0))));
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
}
}
}
pub mod util {
use crate::interpreter::Error;
use crate::jets::{JetErr, Result};