on master help sign in
Double hash
commitca45a0baf287d4d78ffbc97cabec585e38f85f10 authoriko <mail@iko.soy> dateFri 30 Aug 2024, 16:28 (2 years ago) parentd0b06e0
6 files changed+197−42
nock/Cargo.lock+7 nock/Cargo.toml+1 nock/src/interpreter.rs+11−1 nock/src/jets.rs+80−1 nock/src/main.rs+20−11 nock/src/noun.rs+78−29
nock/Cargo.lock+7
@@ -223,6 +223,12 @@ dependencies = [
223223 "walkdir",
224224]
225225
226+[[package]]
227+name = "murmur3"
228+version = "0.5.2"
229+source = "registry+https://github.com/rust-lang/crates.io-index"
230+checksum = "9252111cf132ba0929b6f8e030cac2a24b507f3a4d6db6fb2896f27b354c714b"
231+
226232[[package]]
227233name = "nock"
228234version = "0.1.0"
@@ -232,6 +238,7 @@ dependencies = [
232238 "bitvec",
233239 "clap",
234240 "console_error_panic_hook",
241+ "murmur3",
235242 "num-bigint",
236243 "num-integer",
237244 "num-traits",
nock/Cargo.toml+1
@@ -27,6 +27,7 @@ spinoff = "0.8.0"
2727bit-vec = "0.8.0"
2828bitvec = "1.0.1"
2929stacker = "0.1.17"
30+murmur3 = "0.5.2"
3031
3132[dependencies.xxhash-rust]
3233version = "0.8.5"
nock/src/interpreter.rs+11−1
@@ -27,12 +27,14 @@ pub struct BigUints {
2727
2828pub struct InterpreterContext {
2929 pub jets: Jets,
30+ pub double_jets: DoubleJets,
3031 pub nouns: Nouns,
3132 pub big_uints: BigUints,
3233}
3334
3435pub fn generate_interpreter_context() -> InterpreterContext {
3536 let jets = generate_jets();
37+ let double_jets = generate_double_jets();
3638 let big_uints = BigUints {
3739 zero: BigUint::ZERO,
3840 one: BigUint::new(vec![1]),
@@ -49,6 +51,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
4951 let two_three = cell(two.clone(), three.clone());
5052 InterpreterContext {
5153 jets,
54+ double_jets,
5255 nouns: Nouns {
5356 n: one.clone(),
5457 y: sig.clone(),
@@ -196,7 +199,13 @@ fn tar_u32(
196199
197200 match ctx.jets.get(&hash) {
198201 Some(f) => f(ctx, sample),
199− None => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
202+ None => {
203+ let (hash, sample_1, sample_2) = subj.hash_double_gate();
204+ match ctx.double_jets.get(&hash) {
205+ Some(f) => f(ctx, sample_1, sample_2),
206+ None => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
207+ }
208+ }
200209 }
201210 }
202211 _ => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
@@ -259,6 +268,7 @@ fn tar_u32(
259268 }
260269 11 => {
261270 let (b, d) = formula.as_cell()?;
271+ // println!("{b}");
262272 match (*b).clone() {
263273 Noun::Atom(_) => tar(ctx, subj, d),
264274 Noun::Cell { q: c, .. } => tar_u32(
nock/src/jets.rs+80−1
@@ -1,14 +1,16 @@
11use core::panic;
2+use murmur3::murmur3_32;
23use num_integer::Integer;
34use std::{
45 collections::BTreeMap,
6+ io::Read,
57 iter::{once, repeat_n, zip},
68 rc::Rc,
79};
810
911use crate::{
1012 interpreter::{eval_gate, slam, InterpreterContext},
11− noun::{self, cell, Atom, Hair, Noun},
13+ noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
1214};
1315
1416fn traverse_iter_option<T: Clone, I: Iterator<Item = Option<T>>>(xs: I) -> Option<Vec<T>> {
@@ -22,6 +24,11 @@ fn traverse_iter_option<T: Clone, I: Iterator<Item = Option<T>>>(xs: I) -> Optio
2224}
2325
2426pub type Jets = BTreeMap<noun::Hash, Jet>;
27+pub type DoubleJets = BTreeMap<noun::Hash, DoubleJet>;
28+
29+pub fn generate_double_jets() -> DoubleJets {
30+ BTreeMap::from([(210326504639957723220404138306543145797, JUST)])
31+}
2532
2633pub fn generate_jets() -> Jets {
2734 BTreeMap::from([
@@ -94,10 +101,12 @@ pub fn generate_jets() -> Jets {
94101 (39579736615539990724554083585557839000, NOT),
95102 (3482046397915506566435874021936376320, LAST),
96103 (124976064672625230427889101290245200507, TRIP),
104+ (4078279288073906183633157465551067635, MUK),
97105 ])
98106}
99107
100108pub type Jet = fn(ctx: &InterpreterContext, Rc<Noun>) -> Option<Rc<Noun>>;
109+pub type DoubleJet = fn(ctx: &InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>;
101110
102111static BINARY_ATOM: fn(Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
103112 |n: Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
@@ -915,3 +924,73 @@ static TRIP: Jet = |_ctx, n| {
915924 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
916925 ))
917926};
927+
928+static MUK: Jet = |_ctx, n| {
929+ let (seed, len) = n.as_cell()?;
930+ let (len, key) = len.as_cell()?;
931+ let seed = seed.as_u32()?;
932+ let len = len.as_u32()?;
933+ let key = key.as_atom()?;
934+
935+ let key: Vec<_> = key
936+ .to_bytes_le()
937+ .iter()
938+ .take(len as usize)
939+ .cloned()
940+ .collect();
941+
942+ Some(Rc::new(Noun::from_u32(
943+ murmur3_32(&mut &*key, seed).unwrap(),
944+ )))
945+};
946+
947+static JUST: DoubleJet = |ctx, n, m| {
948+ let char = n.as_atom()?;
949+ let nail = m.as_nail()?;
950+ if nail.rest == ctx.nouns.sig {
951+ Some(fail(nail).as_noun())
952+ } else {
953+ let (i, _) = nail.rest.as_cell()?;
954+ let i = i.as_atom()?;
955+ if i == char {
956+ Some(next(nail)?.as_noun())
957+ } else {
958+ Some(fail(nail).as_noun())
959+ }
960+ }
961+};
962+
963+fn next(nail: Nail) -> Option<Edge> {
964+ if *nail.rest == Noun::SIG {
965+ Some(fail(nail))
966+ } else {
967+ let (i, t) = nail.rest.as_cell()?;
968+ let zac = lust(i.as_atom()?.clone(), nail.hair);
969+ // cell(zac, cell(Rc::new(Noun::SIG), cell(i, cell(zac, t))))
970+ Some(Edge {
971+ hair: zac.clone(),
972+ result: Some((i, Nail { hair: zac, rest: t })),
973+ })
974+ }
975+}
976+
977+fn lust(char: Atom, hair: Hair) -> Hair {
978+ if char == Atom::from_slice(&vec![10]) {
979+ Hair {
980+ line: hair.line + 1,
981+ column: 1,
982+ }
983+ } else {
984+ Hair {
985+ line: hair.line,
986+ column: hair.column + 1,
987+ }
988+ }
989+}
990+
991+fn fail(nail: Nail) -> Edge {
992+ Edge {
993+ hair: nail.hair,
994+ result: None,
995+ }
996+}
nock/src/main.rs+20−11
@@ -42,6 +42,14 @@ enum NockCommand {
4242 #[arg(value_name = "FILE.nock")]
4343 gate: PathBuf,
4444 },
45+ HashDoubleGate {
46+ #[arg(value_name = "FILE.nock")]
47+ gate: PathBuf,
48+ },
49+ EvalGate {
50+ #[arg(value_name = "FILE.nock")]
51+ gate: PathBuf,
52+ },
4553}
4654
4755#[derive(Subcommand)]
@@ -75,21 +83,22 @@ fn main() -> Result<(), std::io::Error> {
7583
7684 println!("{hash}");
7785 }
78− }
79−
80− Ok(())
86+ NockCommand::HashDoubleGate { gate } => {
87+ let gate = read_nock(&gate)?;
88+ let (hash, _sample_1, _sample_2) = gate.hash_double_gate();
8189
82− // let mut jammed_input = Vec::new();
83− // match io::stdin().read_to_end(&mut jammed_input) {
84− // Err(err) => panic!("{err}"),
85− // Ok(_) => (),
86− // };
90+ println!("{hash}");
91+ }
92+ NockCommand::EvalGate { gate } => {
93+ let gate = read_nock(&gate).unwrap();
8794
88− // let gate = cue_bytes(&jammed_input);
95+ let result = eval_gate(&generate_interpreter_context(), gate).unwrap();
8996
90− // let result = eval_gate(&generate_interpreter_context(), gate);
97+ println!("{result}");
98+ }
99+ }
91100
92− // println!("{result}");
101+ Ok(())
93102}
94103
95104fn interact(gate_file: PathBuf) -> Result<(), std::io::Error> {
nock/src/noun.rs+78−29
@@ -1,29 +1,32 @@
1−use std::{
2− borrow::{Borrow, BorrowMut},
3− cell::Cell,
4− cmp::{self, Ordering},
5− rc::Rc,
6− str::FromStr,
7−};
1+use std::{cell::Cell, cmp::Ordering, rc::Rc, str::FromStr};
82
93use num_bigint::BigUint;
4+use num_traits::ToBytes;
105use std::fmt;
116use xxhash_rust::xxh3::xxh3_128;
127
8+use crate::interpreter::InterpreterContext;
9+
1310pub type Atom = BigUint;
1411
1512pub type Hash = u128;
1613
17−#[derive(Clone, Debug, Eq)]
14+#[derive(Clone, Debug)]
1815pub enum Noun {
1916 Atom(Atom),
2017 Cell {
2118 p: Rc<Noun>,
2219 q: Rc<Noun>,
2320 hash: Cell<Option<Hash>>,
21+ compiled_gate: Option<(
22+ Rc<Noun>,
23+ Rc<fn(&InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>>,
24+ )>,
2425 },
2526}
2627
28+impl Eq for Noun {}
29+
2730impl Ord for Noun {
2831 fn cmp(&self, other: &Self) -> Ordering {
2932 compare_nouns(self, other)
@@ -55,11 +58,13 @@ impl PartialEq for Noun {
5558 p: lhs_p,
5659 q: lhs_q,
5760 hash: lhs_hash,
61+ compiled_gate: _,
5862 },
5963 Noun::Cell {
6064 p: rhs_p,
6165 q: rhs_q,
6266 hash: rhs_hash,
67+ compiled_gate: _,
6368 },
6469 ) => lhs_hash == rhs_hash && lhs_p == rhs_p && lhs_q == rhs_q,
6570 _ => false,
@@ -153,7 +158,12 @@ impl Noun {
153158
154159 pub fn hash(self: &Self) -> Hash {
155160 match self {
156− Noun::Cell { hash, p, q } => match hash.get() {
161+ Noun::Cell {
162+ hash,
163+ p,
164+ q,
165+ compiled_gate: _,
166+ } => match hash.get() {
157167 Some(x) => x.clone(),
158168 None => {
159169 let hash_value = stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
@@ -169,24 +179,23 @@ impl Noun {
169179
170180 /// returns the hash and the current sample
171181 pub fn hash_gate(self: &Self) -> (Hash, Rc<Noun>) {
172− let Noun::Cell {
173− p: battery,
174− q: payload,
175− ..
176− } = self
177− else {
178− panic!()
179− };
180− let Noun::Cell {
181− p: sample,
182− q: context,
183− ..
184− } = (**payload).clone()
185− else {
186− panic!()
187− };
182+ let (battery, payload) = self.as_cell().unwrap();
183+ let (sample, context) = payload.as_cell().unwrap();
184+
185+ (hash_pair(battery.clone(), context), sample)
186+ }
188187
189− (hash_pair((*battery).clone(), context), sample)
188+ /// returns the hash and the current sample
189+ pub fn hash_double_gate(self: &Self) -> (Hash, Rc<Noun>, Rc<Noun>) {
190+ let (battery, payload) = self.as_cell().unwrap();
191+ let (sample_2, context) = payload.as_cell().unwrap();
192+ let (inner_hash, sample_1) = context.hash_gate();
193+
194+ (
195+ hash_tripple(battery.clone(), inner_hash),
196+ sample_1,
197+ sample_2,
198+ )
190199 }
191200
192201 pub fn as_bite(self: &Self) -> Bite {
@@ -233,7 +242,7 @@ impl Noun {
233242 let (hair, tape) = self.as_cell()?;
234243 Some(Nail {
235244 hair: hair.as_hair()?,
236− rest: tape.as_atom()?.clone(),
245+ rest: tape.clone(),
237246 })
238247 }
239248
@@ -251,6 +260,29 @@ impl Noun {
251260 };
252261 Some(Edge { hair, result })
253262 }
263+
264+ pub fn with_jet(
265+ self: &Self,
266+ jet: (
267+ Rc<Noun>,
268+ Rc<fn(&InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>>,
269+ ),
270+ ) -> Self {
271+ match self {
272+ Noun::Atom(_) => self.clone(),
273+ Noun::Cell {
274+ p,
275+ q,
276+ hash,
277+ compiled_gate: _,
278+ } => Noun::Cell {
279+ p: p.clone(),
280+ q: q.clone(),
281+ hash: hash.clone(),
282+ compiled_gate: Some(jet),
283+ },
284+ }
285+ }
254286}
255287
256288#[derive(Clone)]
@@ -259,6 +291,18 @@ pub struct Edge {
259291 pub result: Option<(Rc<Noun>, Nail)>,
260292}
261293
294+impl Edge {
295+ pub fn as_noun(self: &Self) -> Rc<Noun> {
296+ cell(
297+ self.hair.as_noun(),
298+ match self.result.clone() {
299+ None => Rc::new(Noun::SIG),
300+ Some((result, nail)) => cell(Rc::new(Noun::SIG), cell(result, nail.as_noun())),
301+ },
302+ )
303+ }
304+}
305+
262306#[derive(Clone)]
263307pub struct Hair {
264308 pub line: u32,
@@ -277,12 +321,12 @@ impl Hair {
277321#[derive(Clone)]
278322pub struct Nail {
279323 pub hair: Hair,
280− pub rest: Atom,
324+ pub rest: Rc<Noun>,
281325}
282326
283327impl Nail {
284328 pub fn as_noun(self: &Self) -> Rc<Noun> {
285− cell(self.hair.as_noun(), Rc::new(Noun::Atom(self.rest.clone())))
329+ cell(self.hair.as_noun(), self.rest.clone())
286330 }
287331}
288332
@@ -360,9 +404,14 @@ pub fn cell(p: Rc<Noun>, q: Rc<Noun>) -> Rc<Noun> {
360404 p: p.clone(),
361405 q: q.clone(),
362406 hash: Cell::new(None),
407+ compiled_gate: None,
363408 })
364409}
365410
366411fn hash_pair(p: Rc<Noun>, q: Rc<Noun>) -> Hash {
367412 xxh3_128(&[p.hash().to_le_bytes(), q.hash().to_le_bytes()].as_flattened())
368413}
414+
415+fn hash_tripple(p: Rc<Noun>, q: Hash) -> Hash {
416+ xxh3_128(&[p.hash().to_le_bytes(), q.to_le_bytes()].as_flattened())
417+}