diff --git a/DEVELOPERS.md b/DEVELOPERS.md index e82ac33..2fa954a 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -42,12 +42,12 @@ bazel-bin/pkg/vere/urbit -F zod #### Pills Ares development and testing, unlike regular development and ship operation, currently requires careful control over what pill is used to launch a ship. Currently, there are several pills available in `resources/pills/`: -* baby.pill: an extremely minimal Arvo-shaped core and Hoon standard library (`~wicdev-wisryt` [streamed a +- **baby.pill**: an extremely minimal Arvo-shaped core and Hoon standard library (`~wicdev-wisryt` [streamed a video of its development](https://youtu.be/fOVhCx1a-9A)) -* toddler.pill: a slightly more complex Arvo and Hoon than `baby`, which runs slow recursive operations for testing jets -* azimuth.pill: a pill that processes an Azimuth snapshot -* full.pill: the complete Urbit `v2.11` pill -* slim.pill: a slimmed down version of the Urbit `v2.11` pill that has had every desk and agent not necessary for booting to dojo removed +- **toddler.pill**: a slightly more complex Arvo and Hoon than `baby`, which runs slow recursive operations for testing jets +- **azimuth.pill**: a pill that processes an Azimuth snapshot +- **full.pill**: the complete Urbit `v2.11` pill +- **slim.pill**: a slimmed down version of the Urbit `v2.11` pill that has had every desk and agent not necessary for booting to dojo removed More information on the pills used by Ares can be found [here](https://github.com/urbit/ares/blob/status/docs/pills.md). diff --git a/docs/pills.md b/docs/pills.md index e4b149a..65b0b36 100644 --- a/docs/pills.md +++ b/docs/pills.md @@ -4,7 +4,7 @@ Ares development and testing, unlike regular development and ship operation, cur ## Example: `baby.pill` -`baby.pill` is an extremely minimal Arvo-shaped core and Hoon standard library equipped with `%sham` jets needed to run it. `~wicdev-wisryt`` [streamed a video](https://youtu.be/fOVhCx1a-9A) of its development. You can find the source Hoon for `baby.pill` in `resources/pills/src/baby/baby.hoon`, and the limited version of Hoon that it uses in `resources/pills/src/baby/cradle.hoon`. A pre-compiled `baby.pill` is already available at `resources/pills/baby.pill`. However, the steps to compile it yourself are documented below. +`baby.pill` is an extremely minimal Arvo-shaped core and Hoon standard library equipped with `%sham` jets needed to run it. `~wicdev-wisryt` [streamed a video](https://youtu.be/fOVhCx1a-9A) of its development. You can find the source Hoon for `baby.pill` in `resources/pills/src/baby/baby.hoon`, and the limited version of Hoon that it uses in `resources/pills/src/baby/cradle.hoon`. A pre-compiled `baby.pill` is already available at `resources/pills/baby.pill`. However, the steps to compile it yourself are documented below. 1. Boot a fake `zod` using an ordinary Urbit executable (not the one you created to run Ares as serf) diff --git a/rust/ares/Cargo.lock b/rust/ares/Cargo.lock index d9a3794..274c0b5 100644 --- a/rust/ares/Cargo.lock +++ b/rust/ares/Cargo.lock @@ -244,9 +244,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -255,15 +255,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -392,6 +392,12 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -526,9 +532,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "half" -version = "1.8.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hashbrown" @@ -618,9 +628,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -935,18 +945,18 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -955,9 +965,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -1103,9 +1113,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1113,9 +1123,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", @@ -1128,9 +1138,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1138,9 +1148,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", @@ -1151,15 +1161,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/rust/ares/benches/cue_pill.rs b/rust/ares/benches/cue_pill.rs index f7e9834..70a13dc 100644 --- a/rust/ares/benches/cue_pill.rs +++ b/rust/ares/benches/cue_pill.rs @@ -57,7 +57,7 @@ fn main() -> io::Result<()> { let f_out = OpenOptions::new() .read(true) .write(true) - .create(true) + .truncate(true) .open(output_filename)?; f_out.set_len((jammed_output.size() << 3) as u64)?; unsafe { diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index 8bdb04a..7555997 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -382,6 +382,7 @@ impl From for Error { pub type Result = result::Result; const BAIL_EXIT: Result = Err(Error::Deterministic(Mote::Exit, D(0))); +const BAIL_INTR: Result = Err(Error::NonDeterministic(Mote::Intr, D(0))); #[allow(unused_variables)] fn debug_assertions(stack: &mut NockStack, noun: Noun) { @@ -1300,7 +1301,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result { return BAIL_EXIT; } } else { - // Heah of argument to Nock 10 must be a cell + // Head of argument to Nock 10 must be a cell return BAIL_EXIT; }; } else { @@ -1670,7 +1671,7 @@ mod hint { tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => { let terminator = Arc::clone(&TERMINATOR); if (*terminator).load(Ordering::Relaxed) { - return Some(Err(Error::NonDeterministic(Mote::Intr, D(0)))); + return Some(BAIL_INTR); } let stack = &mut context.stack; diff --git a/rust/ares/src/jets/hot.rs b/rust/ares/src/jets/hot.rs index 2cd5387..97bf5c7 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, @@ -344,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, @@ -370,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, @@ -426,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, @@ -440,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, diff --git a/rust/ares/src/jets/list.rs b/rust/ares/src/jets/list.rs index bf40b8d..3a2d318 100644 --- a/rust/ares/src/jets/list.rs +++ b/rust/ares/src/jets/list.rs @@ -1,9 +1,11 @@ /** Text processing jets */ -use crate::interpreter::Context; -use crate::jets::util::slot; +use crate::interpreter::{interpret, Context}; +use crate::jets::util::{slot, BAIL_FAIL}; use crate::jets::Result; -use crate::noun::{Noun, D}; +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 = 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(BAIL_FAIL); + } + 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(BAIL_FAIL); + } + unsafe { + *dest = D(0); + }; + return Ok(res); + } + } + } +} + pub mod util { use crate::jets::util::BAIL_EXIT; use crate::jets::{JetErr, Result}; diff --git a/rust/ares/src/jets/lock/ed.rs b/rust/ares/src/jets/lock/ed.rs index 54f75db..0ff2d26 100644 --- a/rust/ares/src/jets/lock/ed.rs +++ b/rust/ares/src/jets/lock/ed.rs @@ -51,7 +51,7 @@ pub fn jet_shar(context: &mut Context, subject: Noun) -> Result { let sec_bytes = sec_key.as_bytes(); public[0..pub_bytes.len()].copy_from_slice(pub_bytes); - secret[0..pub_bytes.len()].copy_from_slice(sec_bytes); + secret[0..sec_bytes.len()].copy_from_slice(sec_bytes); let (mut shar_ida, shar) = IndirectAtom::new_raw_mut_bytearray::<32, NockStack>(stack); ac_ed_shar(public, secret, shar); diff --git a/rust/ares/src/jets/lock/sha.rs b/rust/ares/src/jets/lock/sha.rs index b368e28..63db027 100644 --- a/rust/ares/src/jets/lock/sha.rs +++ b/rust/ares/src/jets/lock/sha.rs @@ -13,18 +13,19 @@ pub fn jet_shas(context: &mut Context, subject: Noun) -> Result { let sal = slot(sam, 2)?.as_atom()?; let ruz = slot(sam, 3)?.as_atom()?; - let sal_bytes = &(sal.as_bytes())[0..met(3, sal)]; // drop trailing zeros - let (mut _salt_ida, salt) = unsafe { IndirectAtom::new_raw_mut_bytes(stack, sal_bytes.len()) }; - salt.copy_from_slice(sal_bytes); - unsafe { let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); + let sal_bytes = &(sal.as_bytes())[0..met(3, sal)]; // drop trailing zeros + let (mut _salt_ida, salt) = IndirectAtom::new_raw_mut_bytes(stack, sal_bytes.len()); + salt.copy_from_slice(sal_bytes); + let msg_len = met(3, ruz); if msg_len > 0 { - let (_msg_ida, message) = IndirectAtom::new_raw_mut_bytes(stack, msg_len); - message.copy_from_slice(&ruz.as_bytes()[0..msg_len]); - ac_shas(message, salt, out); + let msg_bytes = &(ruz.as_bytes())[0..msg_len]; + let (_msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len()); + msg.copy_from_slice(msg_bytes); + ac_shas(msg, salt, out); } else { ac_shas(&mut [], salt, out); } @@ -36,16 +37,17 @@ pub fn jet_shas(context: &mut Context, subject: Noun) -> Result { pub fn jet_shax(context: &mut Context, subject: Noun) -> Result { let stack = &mut context.stack; let sam = slot(subject, 6)?; - let msg = sam.as_atom()?; - let len = met(3, msg); + let ruz = sam.as_atom()?; + let msg_len = met(3, ruz); unsafe { let (mut ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); - if len > 0 { - let (mut _msg_ida, msg_copy) = IndirectAtom::new_raw_mut_bytes(stack, len); - msg_copy.copy_from_slice(&msg.as_bytes()[0..len]); - ac_shay(&mut (msg_copy)[0..len], out); + if msg_len > 0 { + let msg_bytes = &(ruz.as_bytes())[0..msg_len]; + let (_msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len()); + msg.copy_from_slice(msg_bytes); + ac_shay(msg, out); } else { ac_shay(&mut [], out); } @@ -57,23 +59,30 @@ pub fn jet_shax(context: &mut Context, subject: Noun) -> Result { pub fn jet_shay(context: &mut Context, subject: Noun) -> Result { let stack = &mut context.stack; let sam = slot(subject, 6)?; - let wid = slot(sam, 2)?.as_atom()?; - let dat = slot(sam, 3)?.as_atom()?; + let len = slot(sam, 2)?.as_atom()?; + let ruz = slot(sam, 3)?.as_atom()?; - let width = match wid.as_direct() { + let length = match len.as_direct() { Ok(direct) => direct.data() as usize, Err(_) => return Err(BAIL_FAIL), }; + let msg_len = met(3, ruz); unsafe { let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 32); - if width > 0 { - let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, width); - msg.copy_from_slice(&dat.as_bytes()[0..width]); + if length == 0 { + ac_shay(&mut [], out); + } else if msg_len >= length { + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg.copy_from_slice(&(ruz.as_bytes())[0..length]); ac_shay(msg, out); } else { - ac_shay(&mut [], out); + let msg_bytes = &(ruz.as_bytes())[0..msg_len]; + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg[0..msg_len].copy_from_slice(msg_bytes); + ac_shay(msg, out); } + Ok(out_ida.normalize_as_atom().as_noun()) } } @@ -81,47 +90,61 @@ pub fn jet_shay(context: &mut Context, subject: Noun) -> Result { pub fn jet_shal(context: &mut Context, subject: Noun) -> Result { let stack = &mut context.stack; let sam = slot(subject, 6)?; - let wid = slot(sam, 2)?.as_atom()?; - let dat = slot(sam, 3)?.as_atom()?; + let len = slot(sam, 2)?.as_atom()?; + let ruz = slot(sam, 3)?.as_atom()?; - let _width = match wid.as_direct() { + let length = match len.as_direct() { Ok(direct) => direct.data() as usize, Err(_) => return Err(BAIL_FAIL), }; - - let msg_len = met(3, dat); + let msg_len = met(3, ruz); unsafe { - let (mut ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 64); - if msg_len > 0 { - let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_len); - msg.copy_from_slice(&dat.as_bytes()[0..msg_len]); + let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 64); + if length == 0 { + ac_shal(&mut [], out); + } else if msg_len >= length { + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg.copy_from_slice(&(ruz.as_bytes())[0..length]); ac_shal(msg, out); } else { - ac_shal(&mut [], out); + let msg_bytes = &(ruz.as_bytes())[0..msg_len]; + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg[0..msg_len].copy_from_slice(msg_bytes); + ac_shal(msg, out); } - Ok(ida.normalize_as_atom().as_noun()) + + Ok(out_ida.normalize_as_atom().as_noun()) } } pub fn jet_sha1(context: &mut Context, subject: Noun) -> Result { let stack = &mut context.stack; let sam = slot(subject, 6)?; - let wid = slot(sam, 2)?.as_atom()?; - let dat = slot(sam, 3)?.as_atom()?; + let len = slot(sam, 2)?.as_atom()?; + let ruz = slot(sam, 3)?.as_atom()?; - let width = match wid.as_direct() { + let length = match len.as_direct() { Ok(direct) => direct.data() as usize, Err(_) => return Err(BAIL_FAIL), }; + let msg_len = met(3, ruz); unsafe { - let msg_bytes = &(dat.as_bytes())[0..width]; - let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, msg_bytes.len()); - msg.copy_from_slice(msg_bytes); - let (mut out_ida, out) = IndirectAtom::new_raw_mut_bytes(stack, 20); - ac_sha1(msg, out); + if length == 0 { + ac_sha1(&mut [], out); + } else if msg_len >= length { + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg.copy_from_slice(&(ruz.as_bytes())[0..length]); + ac_sha1(msg, out); + } else { + let msg_bytes = &(ruz.as_bytes())[0..msg_len]; + let (mut _msg_ida, msg) = IndirectAtom::new_raw_mut_bytes(stack, length); + msg[0..msg_len].copy_from_slice(msg_bytes); + ac_sha1(msg, out); + } + Ok(out_ida.normalize_as_atom().as_noun()) } } @@ -130,7 +153,6 @@ pub fn jet_sha1(context: &mut Context, subject: Noun) -> Result { mod tests { use super::*; use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, init_context, A}; - use crate::jets::JetErr; use crate::noun::{D, DIRECT_MAX, T}; use ibig::ubig; @@ -293,20 +315,20 @@ mod tests { ubig!(_0x3eda27f97a3238a5817a4147bd31b9632fec7e87d21883ffb0f2855d3cd1d047cee96cd321a9f483dc15570b05e420d607806dd6502854f1bdb8ef7e35e183cf) ); - let sam = T(&mut c.stack, &[D(1), D(1)]); + let sam = T(&mut c.stack, &[D(1), D(0)]); assert_jet_ubig( c, jet_shal, sam, - ubig!(_0x39e3d936c6e31eaac08fcfcfe7bb443460c61c0bd5b74408c8bcc35a6b8d6f5700bdcddeaa4b466ae65f8fb67f67ca62dc34149e1d44d213ddfbc13668b6547b) + ubig!(_0xee1069e3f03884c3e5d457253423844a323c29eb4cde70630b58c3712a804a70221d35d9506e242c9414ff192e283dd6caa4eff86a457baf93d68189024d24b8) ); - let sam = T(&mut c.stack, &[D(1), D(2)]); + let sam = T(&mut c.stack, &[D(0), D(1)]); assert_jet_ubig( c, jet_shal, sam, - ubig!(_0xcadc698fca01cf2935f760278554b4e61f35453975a5bb45389003159bc8485b7018dd8152d9cc23b6e9dd91b107380b9d14ddbf9cc037ee53a857b6c948b8fa) + ubig!(_0x3eda27f97a3238a5817a4147bd31b9632fec7e87d21883ffb0f2855d3cd1d047cee96cd321a9f483dc15570b05e420d607806dd6502854f1bdb8ef7e35e183cf) ); let wid = A( @@ -332,20 +354,28 @@ mod tests { fn test_sha1() { let c = &mut init_context(); - let sam = T(&mut c.stack, &[D(1), D(1)]); + let sam = T(&mut c.stack, &[D(0), D(0)]); assert_jet_ubig( c, jet_sha1, sam, - ubig!(_0xbf8b4530d8d246dd74ac53a13471bba17941dff7), + ubig!(_0xda39a3ee5e6b4b0d3255bfef95601890afd80709), ); - let sam = T(&mut c.stack, &[D(1), D(2)]); + let sam = T(&mut c.stack, &[D(1), D(0)]); assert_jet_ubig( c, jet_sha1, sam, - ubig!(_0xc4ea21bb365bbeeaf5f2c654883e56d11e43c44e), + ubig!(_0x5ba93c9db0cff93f52b521d7420e43f6eda2784f), + ); + + let sam = T(&mut c.stack, &[D(0), D(1)]); + assert_jet_ubig( + c, + jet_sha1, + sam, + ubig!(_0xda39a3ee5e6b4b0d3255bfef95601890afd80709), ); let wid = A( diff --git a/rust/ares/src/jets/math.rs b/rust/ares/src/jets/math.rs index e97d2e5..fd12dd4 100644 --- a/rust/ares/src/jets/math.rs +++ b/rust/ares/src/jets/math.rs @@ -15,7 +15,7 @@ use crate::interpreter::Context; use crate::jets::util::*; use crate::jets::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 @@ -356,9 +383,7 @@ pub mod util { #[cfg(test)] mod tests { use super::*; - use crate::interpreter::Error; use crate::jets::util::test::*; - use crate::jets::JetErr; use crate::mem::NockStack; use crate::noun::{Noun, D, NO, T, YES}; use ibig::ubig; diff --git a/rust/ares/src/jets/parse.rs b/rust/ares/src/jets/parse.rs index 0eb3c9b..01b452e 100644 --- a/rust/ares/src/jets/parse.rs +++ b/rust/ares/src/jets/parse.rs @@ -1,9 +1,11 @@ /** Parsing jets */ use crate::interpreter::Context; -use crate::jets::util::{kick, slam, slot}; +use crate::jets::math::util::{gte_b, lte_b, lth_b}; +use crate::jets::util::{kick, slam, slot, BAIL_FAIL}; use crate::jets::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(BAIL_FAIL) + } + } +} + 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(BAIL_FAIL); + } + + 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(BAIL_FAIL); + } + }, + 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(BAIL_FAIL); + } + } + } + }; + + 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 { + 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::()); + 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::(); + } + + 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) diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs index d448958..7e99d15 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -288,8 +288,14 @@ impl NockStack { if self.pc { panic!("Allocation during cleanup phase is prohibited."); } - self.alloc_pointer = self.alloc_pointer.sub(words); - self.alloc_pointer + + let alloc = self.alloc_pointer.sub(words); + if alloc < self.stack_pointer { + ptr::null_mut() + } else { + self.alloc_pointer = alloc; + alloc + } } /** Bump the alloc pointer for an east frame to make space for an allocation */ @@ -297,9 +303,15 @@ impl NockStack { if self.pc { panic!("Allocation during cleanup phase is prohibited."); } + let alloc = self.alloc_pointer; - self.alloc_pointer = self.alloc_pointer.add(words); - alloc + let new_ap = self.alloc_pointer.add(words); + if new_ap > self.stack_pointer { + ptr::null_mut() + } else { + self.alloc_pointer = new_ap; + alloc + } } /** Allocate space for an indirect pointer in a west frame */ @@ -343,14 +355,24 @@ impl NockStack { unsafe fn raw_alloc_in_previous_frame_west(&mut self, words: usize) -> *mut u64 { // note that the allocation is on the east frame, and thus resembles raw_alloc_east let alloc = *self.prev_alloc_pointer_pointer(); - *(self.prev_alloc_pointer_pointer()) = (*(self.prev_alloc_pointer_pointer())).add(words); - alloc + let new_prev_ap = (*(self.prev_alloc_pointer_pointer())).add(words); + if new_prev_ap > self.stack_pointer { + ptr::null_mut() + } else { + *(self.prev_alloc_pointer_pointer()) = new_prev_ap; + alloc + } } unsafe fn raw_alloc_in_previous_frame_east(&mut self, words: usize) -> *mut u64 { // note that the allocation is on the west frame, and thus resembles raw_alloc_west - *(self.prev_alloc_pointer_pointer()) = (*(self.prev_alloc_pointer_pointer())).sub(words); - *(self.prev_alloc_pointer_pointer()) + let alloc = (*(self.prev_alloc_pointer_pointer())).sub(words); + if alloc < self.stack_pointer { + ptr::null_mut() + } else { + *(self.prev_alloc_pointer_pointer()) = alloc; + alloc + } } /** Allocate space in the previous stack frame. This calls pre_copy() first to ensure that the @@ -415,17 +437,27 @@ impl NockStack { * or not pre_copy() has been called.*/ unsafe fn pre_copy(&mut self) { if !self.pc { - *(self.free_slot(FRAME)) = *(self.slot_pointer(FRAME)); - *(self.free_slot(STACK)) = *(self.slot_pointer(STACK)); - *(self.free_slot(ALLOC)) = *(self.slot_pointer(ALLOC)); + let old_stack_pointer = self.stack_pointer; - self.pc = true; // Change polarity of lightweight stack. if self.is_west() { self.stack_pointer = self.alloc_pointer.sub(RESERVED + 1); + if self.stack_pointer < old_stack_pointer { + // OOM + std::ptr::null::().read_volatile(); + } } else { self.stack_pointer = self.alloc_pointer.add(RESERVED); + if self.stack_pointer > old_stack_pointer { + // OOM + std::ptr::null::().read_volatile(); + } } + self.pc = true; + + *(self.free_slot(FRAME)) = *(self.slot_pointer(FRAME)); + *(self.free_slot(STACK)) = *(self.slot_pointer(STACK)); + *(self.free_slot(ALLOC)) = *(self.slot_pointer(ALLOC)); } } @@ -630,11 +662,19 @@ impl NockStack { let current_stack_pointer = self.stack_pointer; let current_alloc_pointer = self.alloc_pointer; unsafe { - self.frame_pointer = if self.is_west() { - current_alloc_pointer.sub(num_locals + RESERVED) + if self.is_west() { + self.frame_pointer = current_alloc_pointer.sub(num_locals + RESERVED); + if self.frame_pointer <= current_stack_pointer { + // OOM + std::ptr::null::().read_volatile(); + } } else { - current_alloc_pointer.add(num_locals + RESERVED) - }; + self.frame_pointer = current_alloc_pointer.add(num_locals + RESERVED); + if self.frame_pointer >= current_stack_pointer { + // OOM + std::ptr::null::().read_volatile(); + } + } self.alloc_pointer = current_stack_pointer; self.stack_pointer = self.frame_pointer; @@ -693,18 +733,37 @@ impl NockStack { } } - /** Push onto a west-oriented lightweight stack, moving the stack_pointer. - * */ + /** Push onto a west-oriented lightweight stack, moving the stack_pointer. */ unsafe fn push_west(&mut self) -> *mut T { + let ap = if self.pc { + *(self.prev_alloc_pointer_pointer()) + } else { + self.alloc_pointer + }; let alloc = self.stack_pointer; - self.stack_pointer = self.stack_pointer.add(word_size_of::()); - alloc as *mut T + let new_sp = self.stack_pointer.add(word_size_of::()); + if new_sp > ap { + ptr::null_mut() + } else { + self.stack_pointer = new_sp; + alloc as *mut T + } } /** Push onto an east-oriented ligthweight stack, moving the stack_pointer */ unsafe fn push_east(&mut self) -> *mut T { - self.stack_pointer = self.stack_pointer.sub(word_size_of::()); - self.stack_pointer as *mut T + let ap = if self.pc { + *(self.prev_alloc_pointer_pointer()) + } else { + self.alloc_pointer + }; + let alloc = self.stack_pointer.sub(word_size_of::()); + if alloc < ap { + ptr::null_mut() + } else { + self.stack_pointer = alloc; + alloc as *mut T + } } /** Pop a west-oriented lightweight stack, moving the stack pointer. */ diff --git a/rust/ares/src/noun.rs b/rust/ares/src/noun.rs index 68212a4..39066fa 100644 --- a/rust/ares/src/noun.rs +++ b/rust/ares/src/noun.rs @@ -440,7 +440,7 @@ impl IndirectAtom { pub unsafe fn new_raw_mut_bytearray<'a, const N: usize, A: NounAllocator>( allocator: &mut A, ) -> (Self, &'a mut [u8; N]) { - let word_size = (std::mem::size_of::<[u8; N]>() + 7) << 3; + let word_size = (std::mem::size_of::<[u8; N]>() + 7) >> 3; let (noun, ptr) = Self::new_raw_mut_zeroed(allocator, word_size); (noun, &mut *(ptr as *mut [u8; N])) } diff --git a/rust/ares/src/serf.rs b/rust/ares/src/serf.rs index a982fe0..3aa8031 100644 --- a/rust/ares/src/serf.rs +++ b/rust/ares/src/serf.rs @@ -143,7 +143,7 @@ impl Context { snapshot: Option, constant_hot_state: &[HotEntry], ) -> Self { - let mut stack = NockStack::new(64 << 10 << 10, 0); + let mut stack = NockStack::new(4096 << 10 << 10, 0); let newt = Newt::new(); let cache = Hamt::::new(&mut stack); @@ -419,7 +419,7 @@ fn peek(context: &mut Context, ovo: Noun) -> Noun { } fn goof(context: &mut Context, mote: Mote, 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") @@ -448,8 +448,8 @@ fn soft(context: &mut Context, ovo: Noun, trace_name: Option) -> Result< match slam_res { Ok(res) => Ok(res), Err(error) => match error { - Error::Deterministic(mote, trace) | Error::NonDeterministic(mote, trace) => { - Err(goof(context, mote, trace)) + Error::Deterministic(mote, traces) | Error::NonDeterministic(mote, traces) => { + Err(goof(context, mote, traces)) } Error::ScryBlocked(_) | Error::ScryCrashed(_) => { panic!("serf: soft: .^ invalid outside of virtual Nock") @@ -485,8 +485,8 @@ fn play_life(context: &mut Context, eve: Noun) { context.play_done(); } Err(error) => match error { - Error::Deterministic(mote, trace) | Error::NonDeterministic(mote, trace) => { - let goof = goof(context, mote, trace); + Error::Deterministic(mote, traces) | Error::NonDeterministic(mote, traces) => { + let goof = goof(context, mote, traces); context.play_bail(goof); } Error::ScryBlocked(_) | Error::ScryCrashed(_) => { diff --git a/rust/ares_crypto/src/ed25519.rs b/rust/ares_crypto/src/ed25519.rs index 635c19e..54b9083 100644 --- a/rust/ares_crypto/src/ed25519.rs +++ b/rust/ares_crypto/src/ed25519.rs @@ -71,19 +71,6 @@ mod tests { #[test] fn test_ed_sign() { // from https://datatracker.ietf.org/doc/html/rfc8032#section-7.1 - // let msg: [u8; 0] = []; - // let seed_src = &ubig!(_0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60) - // .to_le_bytes(); - // let mut seed: [u8; 32] = [0; 32]; - // seed.copy_from_slice(seed_src); - // let mut signature: [u8; 64] = [0; 64]; - // ac_ed_sign(&msg, &seed, &mut signature); - // let signature_src = &ubig!(_0xe5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b).to_le_bytes(); - // let mut test_signature: [u8; 64] = [0; 64]; - // test_signature.copy_from_slice(signature_src); - // assert_eq!(signature, test_signature); - - // let msg = b"Ares has long exerted a pull on the human imagination."; let seed_src = &ubig!(_0x4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb) .to_le_bytes(); diff --git a/rust/flake.nix b/rust/flake.nix index aefd21a..f311b0c 100644 --- a/rust/flake.nix +++ b/rust/flake.nix @@ -35,7 +35,6 @@ pkgs.llvmPackages.clang pkgs.pkg-config pkgs.urcrypt - pkgs.glibc.static ] ++ (nixpkgs.lib.lists.optional (parsedSystem.kernel.name != "darwin") pkgs.gdb); # nixpkgs won't build gdb for darwin };