on master help sign in
Double hash
ca45a0biko
nock/Cargo.lock+7
@@ -223,6 +223,12 @@ dependencies = [
223 "walkdir",
223 "walkdir",
224]
224]
225
225
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+
226[[package]]
232[[package]]
227name = "nock"
233name = "nock"
228version = "0.1.0"
234version = "0.1.0"
@@ -232,6 +238,7 @@ dependencies = [
232 "bitvec",
238 "bitvec",
233 "clap",
239 "clap",
234 "console_error_panic_hook",
240 "console_error_panic_hook",
241+ "murmur3",
235 "num-bigint",
242 "num-bigint",
236 "num-integer",
243 "num-integer",
237 "num-traits",
244 "num-traits",
nock/Cargo.toml+1
@@ -27,6 +27,7 @@ spinoff = "0.8.0"
27bit-vec = "0.8.0"
27bit-vec = "0.8.0"
28bitvec = "1.0.1"
28bitvec = "1.0.1"
29stacker = "0.1.17"
29stacker = "0.1.17"
30+murmur3 = "0.5.2"
30
31
31[dependencies.xxhash-rust]
32[dependencies.xxhash-rust]
32version = "0.8.5"
33version = "0.8.5"
nock/src/interpreter.rs+11−1
@@ -27,12 +27,14 @@ pub struct BigUints {
27
27
28pub struct InterpreterContext {
28pub struct InterpreterContext {
29 pub jets: Jets,
29 pub jets: Jets,
30+ pub double_jets: DoubleJets,
30 pub nouns: Nouns,
31 pub nouns: Nouns,
31 pub big_uints: BigUints,
32 pub big_uints: BigUints,
32}
33}
33
34
34pub fn generate_interpreter_context() -> InterpreterContext {
35pub fn generate_interpreter_context() -> InterpreterContext {
35 let jets = generate_jets();
36 let jets = generate_jets();
37+ let double_jets = generate_double_jets();
36 let big_uints = BigUints {
38 let big_uints = BigUints {
37 zero: BigUint::ZERO,
39 zero: BigUint::ZERO,
38 one: BigUint::new(vec![1]),
40 one: BigUint::new(vec![1]),
@@ -49,6 +51,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
49 let two_three = cell(two.clone(), three.clone());
51 let two_three = cell(two.clone(), three.clone());
50 InterpreterContext {
52 InterpreterContext {
51 jets,
53 jets,
54+ double_jets,
52 nouns: Nouns {
55 nouns: Nouns {
53 n: one.clone(),
56 n: one.clone(),
54 y: sig.clone(),
57 y: sig.clone(),
@@ -196,7 +199,13 @@ fn tar_u32(
196
199
197 match ctx.jets.get(&hash) {
200 match ctx.jets.get(&hash) {
198 Some(f) => f(ctx, sample),
201 Some(f) => f(ctx, sample),
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),
199− None => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
206+ None => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
207+ }
208+ }
200 }
209 }
201 }
210 }
202 _ => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
211 _ => tar(ctx, tar(ctx, subj.clone(), b)?, tar(ctx, subj, c)?),
@@ -259,6 +268,7 @@ fn tar_u32(
259 }
268 }
260 11 => {
269 11 => {
261 let (b, d) = formula.as_cell()?;
270 let (b, d) = formula.as_cell()?;
271+ // println!("{b}");
262 match (*b).clone() {
272 match (*b).clone() {
263 Noun::Atom(_) => tar(ctx, subj, d),
273 Noun::Atom(_) => tar(ctx, subj, d),
264 Noun::Cell { q: c, .. } => tar_u32(
274 Noun::Cell { q: c, .. } => tar_u32(
nock/src/jets.rs+80−1
@@ -1,14 +1,16 @@
1use core::panic;
1use core::panic;
2+use murmur3::murmur3_32;
2use num_integer::Integer;
3use num_integer::Integer;
3use std::{
4use std::{
4 collections::BTreeMap,
5 collections::BTreeMap,
6+ io::Read,
5 iter::{once, repeat_n, zip},
7 iter::{once, repeat_n, zip},
6 rc::Rc,
8 rc::Rc,
7};
9};
8
10
9use crate::{
11use crate::{
10 interpreter::{eval_gate, slam, InterpreterContext},
12 interpreter::{eval_gate, slam, InterpreterContext},
11− noun::{self, cell, Atom, Hair, Noun},
13+ noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
12};
14};
13
15
14fn traverse_iter_option<T: Clone, I: Iterator<Item = Option<T>>>(xs: I) -> Option<Vec<T>> {
16fn 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
22}
24}
23
25
24pub type Jets = BTreeMap<noun::Hash, Jet>;
26pub 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+}
25
32
26pub fn generate_jets() -> Jets {
33pub fn generate_jets() -> Jets {
27 BTreeMap::from([
34 BTreeMap::from([
@@ -94,10 +101,12 @@ pub fn generate_jets() -> Jets {
94 (39579736615539990724554083585557839000, NOT),
101 (39579736615539990724554083585557839000, NOT),
95 (3482046397915506566435874021936376320, LAST),
102 (3482046397915506566435874021936376320, LAST),
96 (124976064672625230427889101290245200507, TRIP),
103 (124976064672625230427889101290245200507, TRIP),
104+ (4078279288073906183633157465551067635, MUK),
97 ])
105 ])
98}
106}
99
107
100pub type Jet = fn(ctx: &InterpreterContext, Rc<Noun>) -> Option<Rc<Noun>>;
108pub type Jet = fn(ctx: &InterpreterContext, Rc<Noun>) -> Option<Rc<Noun>>;
109+pub type DoubleJet = fn(ctx: &InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>;
101
110
102static BINARY_ATOM: fn(Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
111static BINARY_ATOM: fn(Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
103 |n: Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
112 |n: Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
@@ -915,3 +924,73 @@ static TRIP: Jet = |_ctx, n| {
915 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
924 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
916 ))
925 ))
917};
926};
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 {
42 #[arg(value_name = "FILE.nock")]
42 #[arg(value_name = "FILE.nock")]
43 gate: PathBuf,
43 gate: PathBuf,
44 },
44 },
45+ HashDoubleGate {
46+ #[arg(value_name = "FILE.nock")]
47+ gate: PathBuf,
48+ },
49+ EvalGate {
50+ #[arg(value_name = "FILE.nock")]
51+ gate: PathBuf,
52+ },
45}
53}
46
54
47#[derive(Subcommand)]
55#[derive(Subcommand)]
@@ -75,21 +83,22 @@ fn main() -> Result<(), std::io::Error> {
75
83
76 println!("{hash}");
84 println!("{hash}");
77 }
85 }
78− }
86+ NockCommand::HashDoubleGate { gate } => {
79−
87+ let gate = read_nock(&gate)?;
80− Ok(())
88+ let (hash, _sample_1, _sample_2) = gate.hash_double_gate();
81
89
82− // let mut jammed_input = Vec::new();
90+ println!("{hash}");
83− // match io::stdin().read_to_end(&mut jammed_input) {
91+ }
84− // Err(err) => panic!("{err}"),
92+ NockCommand::EvalGate { gate } => {
85− // Ok(_) => (),
93+ let gate = read_nock(&gate).unwrap();
86− // };
87
94
88− // let gate = cue_bytes(&jammed_input);
95+ let result = eval_gate(&generate_interpreter_context(), gate).unwrap();
89
96
90− // let result = eval_gate(&generate_interpreter_context(), gate);
97+ println!("{result}");
98+ }
99+ }
91
100
92− // println!("{result}");
101+ Ok(())
93}
102}
94
103
95fn interact(gate_file: PathBuf) -> Result<(), std::io::Error> {
104fn 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},
1+use std::{cell::Cell, cmp::Ordering, rc::Rc, str::FromStr};
5− rc::Rc,
6− str::FromStr,
7−};
8
2
9use num_bigint::BigUint;
3use num_bigint::BigUint;
4+use num_traits::ToBytes;
10use std::fmt;
5use std::fmt;
11use xxhash_rust::xxh3::xxh3_128;
6use xxhash_rust::xxh3::xxh3_128;
12
7
8+use crate::interpreter::InterpreterContext;
9+
13pub type Atom = BigUint;
10pub type Atom = BigUint;
14
11
15pub type Hash = u128;
12pub type Hash = u128;
16
13
17−#[derive(Clone, Debug, Eq)]
14+#[derive(Clone, Debug)]
18pub enum Noun {
15pub enum Noun {
19 Atom(Atom),
16 Atom(Atom),
20 Cell {
17 Cell {
21 p: Rc<Noun>,
18 p: Rc<Noun>,
22 q: Rc<Noun>,
19 q: Rc<Noun>,
23 hash: Cell<Option<Hash>>,
20 hash: Cell<Option<Hash>>,
21+ compiled_gate: Option<(
22+ Rc<Noun>,
23+ Rc<fn(&InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>>,
24+ )>,
24 },
25 },
25}
26}
26
27
28+impl Eq for Noun {}
29+
27impl Ord for Noun {
30impl Ord for Noun {
28 fn cmp(&self, other: &Self) -> Ordering {
31 fn cmp(&self, other: &Self) -> Ordering {
29 compare_nouns(self, other)
32 compare_nouns(self, other)
@@ -55,11 +58,13 @@ impl PartialEq for Noun {
55 p: lhs_p,
58 p: lhs_p,
56 q: lhs_q,
59 q: lhs_q,
57 hash: lhs_hash,
60 hash: lhs_hash,
61+ compiled_gate: _,
58 },
62 },
59 Noun::Cell {
63 Noun::Cell {
60 p: rhs_p,
64 p: rhs_p,
61 q: rhs_q,
65 q: rhs_q,
62 hash: rhs_hash,
66 hash: rhs_hash,
67+ compiled_gate: _,
63 },
68 },
64 ) => lhs_hash == rhs_hash && lhs_p == rhs_p && lhs_q == rhs_q,
69 ) => lhs_hash == rhs_hash && lhs_p == rhs_p && lhs_q == rhs_q,
65 _ => false,
70 _ => false,
@@ -153,7 +158,12 @@ impl Noun {
153
158
154 pub fn hash(self: &Self) -> Hash {
159 pub fn hash(self: &Self) -> Hash {
155 match self {
160 match self {
161+ Noun::Cell {
162+ hash,
163+ p,
164+ q,
165+ compiled_gate: _,
156− Noun::Cell { hash, p, q } => match hash.get() {
166+ } => match hash.get() {
157 Some(x) => x.clone(),
167 Some(x) => x.clone(),
158 None => {
168 None => {
159 let hash_value = stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
169 let hash_value = stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
@@ -169,24 +179,23 @@ impl Noun {
169
179
170 /// returns the hash and the current sample
180 /// returns the hash and the current sample
171 pub fn hash_gate(self: &Self) -> (Hash, Rc<Noun>) {
181 pub fn hash_gate(self: &Self) -> (Hash, Rc<Noun>) {
172− let Noun::Cell {
182+ let (battery, payload) = self.as_cell().unwrap();
173− p: battery,
183+ let (sample, context) = payload.as_cell().unwrap();
174− q: payload,
184+
175− ..
185+ (hash_pair(battery.clone(), context), sample)
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− };
186+ }
188
187
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+ )
190 }
199 }
191
200
192 pub fn as_bite(self: &Self) -> Bite {
201 pub fn as_bite(self: &Self) -> Bite {
@@ -233,7 +242,7 @@ impl Noun {
233 let (hair, tape) = self.as_cell()?;
242 let (hair, tape) = self.as_cell()?;
234 Some(Nail {
243 Some(Nail {
235 hair: hair.as_hair()?,
244 hair: hair.as_hair()?,
236− rest: tape.as_atom()?.clone(),
245+ rest: tape.clone(),
237 })
246 })
238 }
247 }
239
248
@@ -251,6 +260,29 @@ impl Noun {
251 };
260 };
252 Some(Edge { hair, result })
261 Some(Edge { hair, result })
253 }
262 }
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+ }
254}
286}
255
287
256#[derive(Clone)]
288#[derive(Clone)]
@@ -259,6 +291,18 @@ pub struct Edge {
259 pub result: Option<(Rc<Noun>, Nail)>,
291 pub result: Option<(Rc<Noun>, Nail)>,
260}
292}
261
293
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+
262#[derive(Clone)]
306#[derive(Clone)]
263pub struct Hair {
307pub struct Hair {
264 pub line: u32,
308 pub line: u32,
@@ -277,12 +321,12 @@ impl Hair {
277#[derive(Clone)]
321#[derive(Clone)]
278pub struct Nail {
322pub struct Nail {
279 pub hair: Hair,
323 pub hair: Hair,
280− pub rest: Atom,
324+ pub rest: Rc<Noun>,
281}
325}
282
326
283impl Nail {
327impl Nail {
284 pub fn as_noun(self: &Self) -> Rc<Noun> {
328 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())
286 }
330 }
287}
331}
288
332
@@ -360,9 +404,14 @@ pub fn cell(p: Rc<Noun>, q: Rc<Noun>) -> Rc<Noun> {
360 p: p.clone(),
404 p: p.clone(),
361 q: q.clone(),
405 q: q.clone(),
362 hash: Cell::new(None),
406 hash: Cell::new(None),
407+ compiled_gate: None,
363 })
408 })
364}
409}
365
410
366fn hash_pair(p: Rc<Noun>, q: Rc<Noun>) -> Hash {
411fn hash_pair(p: Rc<Noun>, q: Rc<Noun>) -> Hash {
367 xxh3_128(&[p.hash().to_le_bytes(), q.hash().to_le_bytes()].as_flattened())
412 xxh3_128(&[p.hash().to_le_bytes(), q.hash().to_le_bytes()].as_flattened())
368}
413}
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+}