From 7b2684aa26e1d6e6a627d0a74a17d12b5531e41f Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Mon, 18 Dec 2023 10:46:34 -0600 Subject: [PATCH 1/3] jets: jet +turn --- rust/ares/src/jets/hot.rs | 5 +++ rust/ares/src/jets/list.rs | 72 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/rust/ares/src/jets/hot.rs b/rust/ares/src/jets/hot.rs index 2cd5387..7dc5596 100644 --- a/rust/ares/src/jets/hot.rs +++ b/rust/ares/src/jets/hot.rs @@ -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, diff --git a/rust/ares/src/jets/list.rs b/rust/ares/src/jets/list.rs index c281d35..577937c 100644 --- a/rust/ares/src/jets/list.rs +++ b/rust/ares/src/jets/list.rs @@ -1,9 +1,9 @@ /** 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}; crate::gdb!(); @@ -24,6 +24,72 @@ 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) + { + 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}; From b884cb31306979b8ed914b9dbdbdb8c61124ca2e Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Wed, 17 Jan 2024 18:54:39 -0600 Subject: [PATCH 2/3] jets: add safety check to jet cache in jet_turn --- rust/ares/src/jets/list.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/rust/ares/src/jets/list.rs b/rust/ares/src/jets/list.rs index 577937c..1327ae0 100644 --- a/rust/ares/src/jets/list.rs +++ b/rust/ares/src/jets/list.rs @@ -4,6 +4,8 @@ use crate::interpreter::{interpret, Context, Error}; use crate::jets::util::slot; use crate::jets::{JetErr, Result}; use crate::noun::{Cell, Noun, D, T}; +use bitvec::slice::BitSlice; +use bitvec::order::Lsb0; crate::gdb!(); @@ -24,6 +26,7 @@ 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)?; @@ -39,6 +42,32 @@ pub fn jet_turn(context: &mut Context, subject: Noun) -> Result { 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 = 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() { From 2706cb5834674fbe2a22b2eaa57370342af5a299 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Wed, 17 Jan 2024 19:37:19 -0600 Subject: [PATCH 3/3] jets: format --- rust/ares/src/jets/list.rs | 54 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/rust/ares/src/jets/list.rs b/rust/ares/src/jets/list.rs index 1327ae0..bca2402 100644 --- a/rust/ares/src/jets/list.rs +++ b/rust/ares/src/jets/list.rs @@ -4,8 +4,8 @@ use crate::interpreter::{interpret, Context, Error}; use crate::jets::util::slot; use crate::jets::{JetErr, Result}; use crate::noun::{Cell, Noun, D, T}; -use bitvec::slice::BitSlice; use bitvec::order::Lsb0; +use bitvec::slice::BitSlice; crate::gdb!(); @@ -26,7 +26,6 @@ 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)?; @@ -38,36 +37,35 @@ pub fn jet_turn(context: &mut Context, subject: Noun) -> Result { // 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 = 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; - } + 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 = 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; } - }; - ret - }) + } else { + ret = false; + break; + } + } + ret + }) { loop { if let Ok(list_cell) = list.as_cell() {