@@ -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+}