Merge pull request #166 from urbit/msl/more-parse-jets

more parse jets
This commit is contained in:
Edward Amsden 2024-01-31 18:04:45 -06:00 committed by GitHub
commit dd8f481824
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 413 additions and 66 deletions

View File

@ -349,6 +349,19 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_pfix,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"plug"),
],
1,
jet_plug,
),
//
(
&[
K_139,
@ -375,6 +388,34 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_sfix,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"cold"),
Left(b"fun"),
],
1,
jet_cold,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"cook"),
Left(b"fun"),
],
1,
jet_cook,
),
//
(
&[
K_139,
@ -431,6 +472,20 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_mask,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"shim"),
Left(b"fun"),
],
1,
jet_shim,
),
//
(
&[
K_139,
@ -445,6 +500,34 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
jet_stag,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"stew"),
Left(b"fun"),
],
1,
jet_stew,
),
//
(
&[
K_139,
Left(b"one"),
Left(b"two"),
Left(b"tri"),
Left(b"qua"),
Left(b"stir"),
Left(b"fun"),
],
1,
jet_stir,
),
//
(
&[
K_139,

View File

@ -15,7 +15,7 @@
use crate::interpreter::{Context, Error};
use crate::jets::util::*;
use crate::jets::{JetErr, Result};
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, T};
use either::{Left, Right};
use ibig::ops::DivRem;
use ibig::UBig;
@ -120,21 +120,7 @@ pub fn jet_gte(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
if a.data() >= b.data() {
YES
} else {
NO
}
} else if a.bit_size() > b.bit_size() {
YES
} else if a.bit_size() < b.bit_size() {
NO
} else if a.as_ubig(stack) >= b.as_ubig(stack) {
YES
} else {
NO
})
Ok(util::gte(stack, a, b))
}
pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
@ -143,21 +129,7 @@ pub fn jet_gth(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
if a.data() > b.data() {
YES
} else {
NO
}
} else if a.bit_size() > b.bit_size() {
YES
} else if a.bit_size() < b.bit_size() {
NO
} else if a.as_ubig(stack) > b.as_ubig(stack) {
YES
} else {
NO
})
Ok(util::gth(stack, a, b))
}
pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
@ -166,21 +138,7 @@ pub fn jet_lte(context: &mut Context, subject: Noun) -> Result {
let a = slot(arg, 2)?.as_atom()?;
let b = slot(arg, 3)?.as_atom()?;
Ok(if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
if a.data() <= b.data() {
YES
} else {
NO
}
} else if a.bit_size() < b.bit_size() {
YES
} else if a.bit_size() > b.bit_size() {
NO
} else if a.as_ubig(stack) <= b.as_ubig(stack) {
YES
} else {
NO
})
Ok(util::lte(stack, a, b))
}
pub fn jet_lth(context: &mut Context, subject: Noun) -> Result {
@ -307,19 +265,88 @@ pub mod util {
}
}
/// Greater than or equal to (boolean)
pub fn gte_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() >= b.data()
} else if a.bit_size() > b.bit_size() {
true
} else if a.bit_size() < b.bit_size() {
false
} else {
a.as_ubig(stack) >= b.as_ubig(stack)
}
}
/// Greater than or equal to
pub fn gte(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if gte_b(stack, a, b) {
YES
} else {
NO
}
}
/// Greater than (boolean)
pub fn gth_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() > b.data()
} else if a.bit_size() > b.bit_size() {
true
} else if a.bit_size() < b.bit_size() {
false
} else {
a.as_ubig(stack) > b.as_ubig(stack)
}
}
/// Greater than
pub fn gth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if gth_b(stack, a, b) {
YES
} else {
NO
}
}
/// Less than or equal to (boolean)
pub fn lte_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() <= b.data()
} else if a.bit_size() < b.bit_size() {
true
} else if a.bit_size() > b.bit_size() {
false
} else {
a.as_ubig(stack) <= b.as_ubig(stack)
}
}
/// Less than or equal to
pub fn lte(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if lte_b(stack, a, b) {
YES
} else {
NO
}
}
/// Less than (boolean)
pub fn lth_b(stack: &mut NockStack, a: Atom, b: Atom) -> bool {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
a.data() < b.data()
} else if a.bit_size() > b.bit_size() {
false
} else if a.bit_size() < b.bit_size() {
true
} else {
a.as_ubig(stack) < b.as_ubig(stack)
}
}
/// Less than
pub fn lth(stack: &mut NockStack, a: Atom, b: Atom) -> Noun {
if let (Ok(a), Ok(b)) = (a.as_direct(), b.as_direct()) {
if a.data() < b.data() {
YES
} else {
NO
}
} else if a.bit_size() < b.bit_size() {
YES
} else if a.bit_size() > b.bit_size() {
NO
} else if a.as_ubig(stack) < b.as_ubig(stack) {
if lth_b(stack, a, b) {
YES
} else {
NO

View File

@ -1,9 +1,11 @@
/** Parsing jets
*/
use crate::interpreter::Context;
use crate::interpreter::{Context, Error};
use crate::jets::math::util::{gte_b, lte_b, lth_b};
use crate::jets::util::{kick, slam, slot};
use crate::jets::Result;
use crate::jets::{JetErr, Result};
use crate::noun::{Noun, D, T};
use either::{Left, Right};
crate::gdb!();
@ -177,6 +179,38 @@ pub fn jet_pfix(context: &mut Context, subject: Noun) -> Result {
Ok(T(&mut context.stack, &[arg, q_yit]))
}
pub fn jet_plug(context: &mut Context, subject: Noun) -> Result {
let vex = slot(subject, 12)?.as_cell()?;
let sab = slot(subject, 13)?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let uq_vex = q_vex.as_cell()?.tail().as_cell()?;
let puq_vex = uq_vex.head();
let quq_vex = uq_vex.tail();
let yit = slam(context, sab, quq_vex)?.as_cell()?;
let p_yit = yit.head();
let q_yit = yit.tail();
let yur = util::last(p_vex, p_yit)?;
if unsafe { q_yit.raw_equals(D(0)) } {
Ok(T(&mut context.stack, &[yur, D(0)]))
} else {
let uq_yit = q_yit.as_cell()?.tail().as_cell()?;
let puq_yit = uq_yit.head();
let quq_yit = uq_yit.tail();
let inner = T(&mut context.stack, &[puq_vex, puq_yit]);
Ok(T(&mut context.stack, &[yur, D(0), inner, quq_yit]))
}
}
}
pub fn jet_pose(context: &mut Context, subject: Noun) -> Result {
let vex = slot(subject, 12)?.as_cell()?;
let sab = slot(subject, 13)?;
@ -229,6 +263,47 @@ pub fn jet_sfix(context: &mut Context, subject: Noun) -> Result {
// Rule Builders
//
pub fn jet_cold(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let cus = slot(van, 12)?;
let sef = slot(van, 13)?;
let vex = slam(context, sef, tub)?.as_cell()?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let quq_vex = q_vex.as_cell()?.tail().as_cell()?.tail();
Ok(T(&mut context.stack, &[p_vex, D(0), cus, quq_vex]))
}
}
pub fn jet_cook(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let poq = slot(van, 12)?;
let sef = slot(van, 13)?;
let vex = slam(context, sef, tub)?.as_cell()?;
let p_vex = vex.head();
let q_vex = vex.tail();
if unsafe { q_vex.raw_equals(D(0)) } {
Ok(vex.as_noun())
} else {
let uq_vex = q_vex.as_cell()?.tail().as_cell()?;
let puq_vex = uq_vex.head();
let quq_vex = uq_vex.tail();
let wag = slam(context, poq, puq_vex)?;
Ok(T(&mut context.stack, &[p_vex, D(0), wag, quq_vex]))
}
}
pub fn jet_easy(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
@ -307,6 +382,35 @@ pub fn jet_mask(context: &mut Context, subject: Noun) -> Result {
util::fail(context, p_tub)
}
pub fn jet_shim(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?.as_cell()?;
let van = slot(subject, 7)?;
let zep = slot(van, 6)?.as_cell()?;
let p_tub = tub.head();
let q_tub = tub.tail();
if unsafe { q_tub.raw_equals(D(0)) } {
util::fail(context, p_tub)
} else {
let p_zep = zep.head();
let q_zep = zep.tail();
let iq_tub = q_tub.as_cell()?.head();
if let (Some(p_zep_d), Some(q_zep_d), Some(iq_tub_d)) =
(p_zep.direct(), q_zep.direct(), iq_tub.direct())
{
if (iq_tub_d.data() >= p_zep_d.data()) && (iq_tub_d.data() <= q_zep_d.data()) {
util::next(context, tub.as_noun())
} else {
util::fail(context, p_tub)
}
} else {
Err(JetErr::Fail(Error::NonDeterministic(D(0))))
}
}
}
pub fn jet_stag(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
@ -329,6 +433,139 @@ pub fn jet_stag(context: &mut Context, subject: Noun) -> Result {
}
}
pub fn jet_stew(context: &mut Context, subject: Noun) -> Result {
let tub = slot(subject, 6)?.as_cell()?;
let con = slot(subject, 7)?;
let mut hel = slot(con, 2)?;
let p_tub = tub.head();
let q_tub = tub.tail();
if unsafe { q_tub.raw_equals(D(0)) } {
return util::fail(context, p_tub);
}
let iq_tub = q_tub.as_cell()?.head().as_atom()?;
if !iq_tub.is_direct() {
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
loop {
if unsafe { hel.raw_equals(D(0)) } {
return util::fail(context, p_tub);
} else {
let n_hel = slot(hel, 2)?.as_cell()?;
let l_hel = slot(hel, 6)?;
let r_hel = slot(hel, 7)?;
let pn_hel = n_hel.head();
let qn_hel = n_hel.tail();
let bit = match pn_hel.as_either_atom_cell() {
Left(atom) => match atom.as_either() {
Left(direct) => iq_tub.as_direct()?.data() == direct.data(),
Right(_) => {
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
},
Right(cell) => {
let hpn_hel = cell.head().as_atom()?;
let tpn_hel = cell.tail().as_atom()?;
match (hpn_hel.as_either(), tpn_hel.as_either()) {
(Left(_), Left(_)) => {
gte_b(&mut context.stack, iq_tub, hpn_hel)
&& lte_b(&mut context.stack, iq_tub, tpn_hel)
}
_ => {
// XX: Fixes jet mismatch in Vere
// Character cannot be encoded using 8 bytes = computibilty error
return Err(JetErr::Fail(Error::NonDeterministic(D(0))));
}
}
}
};
if bit {
return slam(context, qn_hel, tub.as_noun());
} else {
let wor = match pn_hel.as_either_atom_cell() {
Left(atom) => atom,
Right(cell) => cell.head().as_atom()?,
};
if lth_b(&mut context.stack, iq_tub, wor) {
hel = l_hel;
} else {
hel = r_hel;
}
}
}
}
}
// +$ edge [p=hair q=(unit [p=* q=nail])]
#[derive(Copy, Clone)]
struct StirPair {
pub har: Noun, // p.edge
pub res: Noun, // p.u.q.edge
}
pub fn jet_stir(context: &mut Context, subject: Noun) -> Result {
unsafe {
context.with_stack_frame(0, |context| {
let mut tub = slot(subject, 6)?;
let van = slot(subject, 7)?;
let rud = slot(van, 12)?;
let raq = slot(van, 26)?;
let fel = slot(van, 27)?;
// initial accumulator (deconstructed)
let mut p_wag: Noun;
let mut puq_wag: Noun;
let quq_wag: Noun;
// push incremental, succesful [fel] parse results onto stack
{
let vex = slam(context, fel, tub)?.as_cell()?;
let mut p_vex = vex.head();
let mut q_vex = vex.tail();
while !q_vex.raw_equals(D(0)) {
let puq_vex = slot(q_vex, 6)?;
let quq_vex = slot(q_vex, 7)?;
*(context.stack.push::<StirPair>()) = StirPair {
har: p_vex,
res: puq_vex,
};
tub = quq_vex;
let vex = slam(context, fel, tub)?.as_cell()?;
p_vex = vex.head();
q_vex = vex.tail();
}
p_wag = p_vex;
puq_wag = rud;
quq_wag = tub;
}
// unwind the stack, folding parse results into [wag] by way of [raq]
while !context.stack.stack_is_empty() {
let par_u = *(context.stack.top::<StirPair>());
p_wag = util::last(par_u.har, p_wag)?;
let sam = T(&mut context.stack, &[par_u.res, puq_wag]);
puq_wag = slam(context, raq, sam)?;
context.stack.pop::<StirPair>();
}
let res = T(&mut context.stack, &[p_wag, D(0), puq_wag, quq_wag]);
Ok(res)
})
}
}
pub mod util {
use crate::interpreter::{inc, Context};
use crate::jets::Result;
@ -339,14 +576,14 @@ pub mod util {
let zyl = zyc.as_cell()?;
let nal = naz.as_cell()?;
let zyll = zyl.head().as_direct()?.data();
let zylc = zyl.tail().as_direct()?.data();
let nall = nal.head().as_direct()?.data();
let nalc = nal.tail().as_direct()?.data();
let p_zyc = zyl.head().as_direct()?.data();
let q_zyc = zyl.tail().as_direct()?.data();
let p_naz = nal.head().as_direct()?.data();
let q_naz = nal.tail().as_direct()?.data();
match zyll.cmp(&nall) {
match p_zyc.cmp(&p_naz) {
Ordering::Equal => {
if zylc > nalc {
if q_zyc > q_naz {
Ok(zyc)
} else {
Ok(naz)

View File

@ -419,7 +419,7 @@ fn peek(context: &mut Context, ovo: Noun) -> Noun {
}
fn goof(context: &mut Context, traces: Noun) -> Noun {
let trace = zing(&mut context.nock_context.stack, traces).unwrap();
let trace = zing(&mut context.nock_context.stack, traces).expect("serf: goof: zing failed");
let tone = Cell::new(&mut context.nock_context.stack, D(2), trace);
let tang = mook(&mut context.nock_context, tone, false)
.expect("serf: goof: +mook crashed on bail")