on master help sign in
refs
commit284c591e6c888e50968f5c0a419d5a9f57ca7f25 authoriko <mail@iko.soy> dateSat 31 Aug 2024, 17:11 (2 years ago) parentc3509cf
4 files changed+163−202
nock/src/interpreter.rs+59−56 nock/src/jets.rs+53−64 nock/src/main.rs+6−6 nock/src/noun.rs+45−76
nock/src/interpreter.rs+59−56
@@ -1,3 +1,4 @@
1+use std::borrow::Borrow;
12use std::rc::Rc;
23
34use num_bigint::BigUint;
@@ -67,34 +68,34 @@ pub fn generate_interpreter_context() -> InterpreterContext {
6768 }
6869}
6970
70−fn wut(ctx: &InterpreterContext, noun: &Noun) -> Rc<Noun> {
71+fn wut<'a>(ctx: &'a InterpreterContext, noun: &Noun) -> &'a Rc<Noun> {
7172 match noun {
72− Noun::Cell { .. } => ctx.nouns.sig.clone(),
73− Noun::Atom(_) => ctx.nouns.one.clone(),
73+ Noun::Cell { .. } => &ctx.nouns.sig,
74+ Noun::Atom(_) => &ctx.nouns.one,
7475 }
7576}
7677
7778fn lus(noun: &Noun) -> Option<Noun> {
78− match (*noun).clone() {
79+ match noun {
7980 Noun::Cell { .. } => None,
8081 Noun::Atom(atm) => Some(Noun::Atom(atm + 1u32)),
8182 }
8283}
8384
84−fn tis(ctx: &InterpreterContext, lhs: &Noun, rhs: &Noun) -> Rc<Noun> {
85+fn tis<'a>(ctx: &'a InterpreterContext, lhs: &Noun, rhs: &Noun) -> &'a Rc<Noun> {
8586 if lhs == rhs {
86− ctx.nouns.sig.clone()
87+ &ctx.nouns.sig
8788 } else {
88− ctx.nouns.one.clone()
89+ &ctx.nouns.one
8990 }
9091}
9192
9293fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Option<Rc<Noun>> {
9394 let mut addr_iter = addr.iter_u32_digits();
9495
95− match addr_iter.len() {
96− 0 => None,
97− 1 => Some(fas_u32(addr_iter.next()?, noun)?),
96+ match (addr_iter.next(), addr_iter.next()) {
97+ (None, _) => None,
98+ (Some(x), None) => fas_u32(x, noun),
9899 _ => {
99100 let rest = fas(ctx, &(addr >> 1u8), noun)?;
100101 Some(fas_u32(
@@ -113,13 +114,13 @@ fn fas_u32(addr: u32, noun: &Noun) -> Option<Rc<Noun>> {
113114 match addr {
114115 0 => None,
115116 1 => Some(Rc::new(noun.clone())),
116− n => match noun {
117+ n => match noun.borrow() {
117118 Noun::Atom(_) => None,
118119 Noun::Cell { p, q, .. } => match n {
119120 2 => Some(p.clone()),
120121 3 => Some(q.clone()),
121122 _ => {
122− let rest = fas_u32(n >> 1, &naked_cell(&p, &q))?;
123+ let rest = fas_u32(n >> 1, &cell(p, q))?;
123124 fas_u32(if (n & 1) == 1 { 3 } else { 2 }, &rest)
124125 }
125126 },
@@ -127,65 +128,67 @@ fn fas_u32(addr: u32, noun: &Noun) -> Option<Rc<Noun>> {
127128 }
128129}
129130
130−fn hax_u32(addr: u32, new_value: Rc<Noun>, target: Rc<Noun>) -> Option<Rc<Noun>> {
131+fn hax_u32(addr: u32, new_value: &Rc<Noun>, target: &Rc<Noun>) -> Option<Rc<Noun>> {
131132 match addr {
132133 0 => None,
133− 1 => Some(new_value),
134− _ => hax_u32(
135− addr >> 1,
136− if (addr & 1) == 1 {
134+ 1 => Some(new_value.clone()),
135+ _ => {
136+ let new_value = if (addr & 1) == 1 {
137137 let foo = fas_u32(addr - 1, &target)?;
138− cell(&foo, &new_value)
138+ &cell(&foo, &new_value)
139139 } else {
140140 let foo = fas_u32(addr + 1, &target)?;
141− cell(&new_value, &foo)
142− },
143− target,
144− ),
141+ &cell(&new_value, &foo)
142+ };
143+ hax_u32(addr >> 1, new_value, target)
144+ }
145145 }
146146}
147147
148148fn hax(
149149 ctx: &InterpreterContext,
150− addr: Atom,
151− new_value: Rc<Noun>,
152− target: Rc<Noun>,
150+ addr: &Atom,
151+ new_value: &Rc<Noun>,
152+ target: &Rc<Noun>,
153153) -> Option<Rc<Noun>> {
154154 let mut addr_iter = addr.iter_u32_digits();
155155
156− match addr_iter.len() {
157− 0 => None,
158− 1 => hax_u32(addr_iter.next().expect("invariant"), new_value, target),
156+ match (addr_iter.next(), addr_iter.next()) {
157+ (None, _) => None,
158+ (Some(x), None) => hax_u32(x, new_value, target),
159159 _ => hax(
160160 ctx,
161− &addr >> 1u32,
162− if (&addr & &ctx.big_uints.one) == ctx.big_uints.one {
161+ &(addr >> 1u32),
162+ &(if (addr & &ctx.big_uints.one) == ctx.big_uints.one {
163163 let foo = fas(ctx, &(addr - &ctx.big_uints.one), &target)?;
164− cell(&foo, &new_value)
164+ cell(&foo, new_value)
165165 } else {
166166 let foo = fas(ctx, &(addr + &ctx.big_uints.one), &target)?;
167167 cell(&new_value, &foo)
168− },
168+ }),
169169 target,
170170 ),
171171 }
172172}
173173
174−fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) -> Option<Rc<Noun>> {
174+fn tar_u32<'a>(
175+ ctx: &InterpreterContext,
176+ subj: &'a Noun,
177+ op: u32,
178+ formula: &'a Rc<Noun>,
179+) -> Option<Rc<Noun>> {
175180 match op {
176181 0 => {
177− let b = formula.as_atom()?.clone();
178− fas(ctx, &b, subj)
182+ let b = formula.as_atom()?;
183+ fas(ctx, b, subj)
179184 }
180− 1 => Some(formula),
185+ 1 => Some(formula.clone()),
181186 2 => {
182187 let (b, c) = formula.as_cell()?;
183188
184− match (*c).clone() {
189+ match c.borrow() {
185190 Noun::Cell { p, q, .. }
186− if *p == Noun::SIG
187− && q == ctx.nouns.two
188− && b == cell(&Noun::SIG, &ctx.nouns.one) =>
191+ if **p == Noun::SIG && *q == ctx.nouns.two && *b == ctx.nouns.sig_one =>
189192 {
190193 // This means we are about the evaluate a gate at the head of the current subject.
191194 let (hash, sample) = subj.hash_gate();
@@ -214,7 +217,7 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
214217 }
215218 3 => {
216219 let foo = tar(ctx, subj, &formula)?;
217− Some(wut(ctx, &foo))
220+ Some(wut(ctx, &foo).clone())
218221 }
219222 4 => {
220223 let foo = tar(ctx, subj, &formula)?;
@@ -224,7 +227,7 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
224227 let (b, c) = formula.as_cell()?;
225228 let foo = tar(ctx, &subj, &b)?;
226229 let bar = tar(ctx, subj, &c)?;
227− Some(tis(ctx, &foo, &bar))
230+ Some(tis(ctx, &foo, &bar).clone())
228231 }
229232 6 => {
230233 let (b, c) = formula.as_cell()?;
@@ -234,11 +237,11 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
234237 ctx,
235238 &cell(&c, &d),
236239 0,
237− tar_u32(
240+ &tar_u32(
238241 ctx,
239242 &ctx.nouns.two_three,
240243 0,
241− tar_u32(ctx, subj, 4, cell(&ctx.nouns.four, &b))?,
244+ &tar_u32(ctx, subj, 4, &cell(&ctx.nouns.four, &b))?,
242245 )?,
243246 )?;
244247
@@ -252,7 +255,7 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
252255 8 => {
253256 let (b, c) = formula.as_cell()?;
254257 let foo = tar(ctx, &subj, &b)?;
255− tar(ctx, &cell(&foo, subj), &c)
258+ tar(ctx, &cell(&foo, &Rc::new(subj.clone())), &c)
256259 }
257260 9 => {
258261 let (b, c) = formula.as_cell()?;
@@ -261,7 +264,7 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
261264 ctx,
262265 &foo,
263266 2,
264− cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
267+ &cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
265268 )
266269 }
267270 10 => {
@@ -269,17 +272,17 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
269272 let (b, c) = b.as_cell()?;
270273 let b = b.as_atom()?;
271274
272− hax(ctx, b.clone(), tar(ctx, subj, &c)?, tar(ctx, subj, &d)?)
275+ hax(ctx, b, &tar(ctx, subj, &c)?, &tar(ctx, subj, &d)?)
273276 }
274277 11 => {
275278 let (b, d) = formula.as_cell()?;
276279 // println!("{b}");
277− match (*b).clone() {
280+ match b.borrow() {
278281 Noun::Atom(_) => tar(ctx, subj, &d),
279282 Noun::Cell { q: c, .. } => {
280283 let foo = tar(ctx, subj, &c)?;
281284 let bar = tar(ctx, subj, &d)?;
282− tar_u32(ctx, &cell(&foo, &bar), 0, ctx.nouns.three.clone())
285+ tar_u32(ctx, &cell(&foo, &bar), 0, &ctx.nouns.three)
283286 }
284287 }
285288 }
@@ -287,9 +290,9 @@ fn tar_u32(ctx: &InterpreterContext, subj: &Noun, op: u32, formula: Rc<Noun>) ->
287290 }
288291}
289292
290−pub fn tar(ctx: &InterpreterContext, subj: &Noun, formula: &Noun) -> Option<Rc<Noun>> {
293+pub fn tar<'a>(ctx: &InterpreterContext, subj: &'a Noun, formula: &'a Noun) -> Option<Rc<Noun>> {
291294 let (op, formula) = formula.as_cell()?;
292− match *op {
295+ match op.borrow() {
293296 Noun::Cell { .. } => {
294297 let foo = tar(ctx, subj, &op)?;
295298 let bar = tar(ctx, subj, &formula)?;
@@ -303,25 +306,25 @@ pub fn tar(ctx: &InterpreterContext, subj: &Noun, formula: &Noun) -> Option<Rc<N
303306 _ => None,
304307 };
305308 let op = op?;
306− stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, &subj, op, formula))
309+ stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, subj, op, formula))
307310 }
308311 }
309312}
310313
311−pub fn eval_gate(ctx: &InterpreterContext, gate: Rc<Noun>) -> Option<Rc<Noun>> {
314+pub fn eval_gate(ctx: &InterpreterContext, gate: &Rc<Noun>) -> Option<Rc<Noun>> {
312315 tar(
313316 ctx,
314317 &gate,
315318 &cell(
316− &Noun::Atom(BigUint::new(vec![9])),
319+ &Rc::new(Noun::Atom(BigUint::new(vec![9]))),
317320 &cell(&ctx.nouns.two, &cell(&ctx.nouns.sig, &ctx.nouns.one)),
318321 ),
319322 )
320323}
321324
322−pub fn slam(ctx: &InterpreterContext, gate: Rc<Noun>, sample: Rc<Noun>) -> Option<Rc<Noun>> {
325+pub fn slam(ctx: &InterpreterContext, gate: &Rc<Noun>, sample: &Rc<Noun>) -> Option<Rc<Noun>> {
323326 let (battery, payload) = gate.as_cell()?;
324327 let (_sample, context) = payload.as_cell()?;
325328
326− eval_gate(ctx, cell(&battery, &cell(&sample, &context)))
329+ eval_gate(ctx, &cell(battery, &cell(sample, context)))
327330}
nock/src/jets.rs+53−64
@@ -108,20 +108,20 @@ pub fn generate_jets() -> Jets {
108108 ])
109109}
110110
111−pub type Jet = fn(ctx: &InterpreterContext, Rc<Noun>) -> Option<Rc<Noun>>;
112−pub type DoubleJet = fn(ctx: &InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>;
111+pub type Jet = fn(ctx: &InterpreterContext, &Rc<Noun>) -> Option<Rc<Noun>>;
112+pub type DoubleJet = fn(ctx: &InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
113113
114−static BINARY_ATOM: fn(Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
115− |n: Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
114+static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
115+ |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
116116 let (p, q) = n.as_cell()?;
117117 Some(Rc::new(Noun::Atom(f(p.as_atom()?, q.as_atom()?))))
118118 };
119119
120120static BINARY_ATOM_LOOB: fn(
121121 &InterpreterContext,
122− Rc<Noun>,
122+ &Rc<Noun>,
123123 fn(&Atom, &Atom) -> bool,
124−) -> Option<Rc<Noun>> = |ctx: &InterpreterContext, n: Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
124+) -> Option<Rc<Noun>> = |ctx: &InterpreterContext, n: &Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
125125 let (p, q) = n.as_cell()?;
126126
127127 if f(p.as_atom()?, q.as_atom()?) {
@@ -131,12 +131,12 @@ static BINARY_ATOM_LOOB: fn(
131131 }
132132};
133133
134−static BINARY_ATOM_PAIR: fn(Rc<Noun>, fn(&Atom, &Atom) -> (Atom, Atom)) -> Option<Rc<Noun>> =
135− |n: Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
134+static BINARY_ATOM_PAIR: fn(&Rc<Noun>, fn(&Atom, &Atom) -> (Atom, Atom)) -> Option<Rc<Noun>> =
135+ |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
136136 let (p, q) = n.as_cell()?;
137137
138138 let (a, b) = f(p.as_atom()?, q.as_atom()?);
139− Some(cell(&Noun::Atom(a), &Noun::Atom(b)))
139+ Some(cell(&Rc::new(Noun::Atom(a)), &Rc::new(Noun::Atom(b))))
140140 };
141141
142142static ADD: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a + b);
@@ -231,7 +231,7 @@ static FAND: Jet = |ctx, n| {
231231 return Some(ctx.nouns.sig.clone());
232232 }
233233
234− let nedl: Vec<Rc<Noun>> = nedl.list_iter().collect();
234+ let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
235235
236236 let mut result: Vec<u32> = Vec::new();
237237
@@ -261,7 +261,7 @@ static FIND: Jet = |ctx, n| {
261261 return Some(ctx.nouns.sig.clone());
262262 }
263263
264− let nedl: Vec<Rc<Noun>> = nedl.list_iter().collect();
264+ let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
265265
266266 let mut iter = zip(0.., hstk.list_iter());
267267
@@ -328,7 +328,7 @@ static INTO: Jet = |_ctx, n| {
328328 .chain(l.skip(b))
329329 .collect::<Vec<_>>()
330330 .iter()
331− .map(|x| x.clone()),
331+ .map(|x| *x),
332332 ))
333333 }
334334 _ => Some(Noun::list_refs(
@@ -360,7 +360,7 @@ static LENT: Jet = |_ctx, n| {
360360
361361static LEVY: Jet = |ctx, n| {
362362 let (a, b) = n.as_cell()?;
363− if traverse_iter_option(a.list_iter().map(|n| slam(ctx, b.clone(), n)))?
363+ if traverse_iter_option(a.list_iter().map(|n| slam(ctx, b, n)))?
364364 .iter()
365365 .all(|x| x.is_y())
366366 {
@@ -372,7 +372,7 @@ static LEVY: Jet = |ctx, n| {
372372
373373static LIEN: Jet = |ctx, n| {
374374 let (a, b) = n.as_cell()?;
375− if traverse_iter_option(a.list_iter().map(|n| slam(ctx, b.clone(), n)))?
375+ if traverse_iter_option(a.list_iter().map(|n| slam(ctx, b, n)))?
376376 .iter()
377377 .any(|x| x.is_y())
378378 {
@@ -387,10 +387,9 @@ static MURN: Jet = |ctx, n| {
387387
388388 Some(Noun::list_refs(
389389 a.list_iter()
390− .filter_map(|n| slam(ctx, b.clone(), n)?.as_unit())
390+ .filter_map(|n| slam(ctx, b, n)?.as_unit().cloned())
391391 .collect::<Vec<_>>()
392− .iter()
393− .map(|x| x.clone()),
392+ .iter(),
394393 ))
395394};
396395
@@ -400,16 +399,16 @@ static REAP: Jet = |_ctx, n| {
400399 Some(Noun::list_refs(repeat_n(b, a.as_u32().unwrap() as usize)))
401400};
402401
403−static REAR: Jet = |_ctx, n| n.list_iter().last();
402+static REAR: Jet = |_ctx, n| n.list_iter().last().cloned();
404403
405404static REEL: Jet = |ctx, n| {
406405 let (list, gate) = n.as_cell()?;
407406
408407 list.list_iter().collect::<Vec<_>>().iter().rfold(
409− Some(gate.clone().gate_sample()?.as_cell()?.1),
408+ Some(gate.gate_sample()?.as_cell()?.1.clone()),
410409 |acc, next| {
411410 let acc = acc?;
412− slam(ctx, gate.clone(), cell(&next, &acc))
411+ slam(ctx, gate, &cell(&next, &acc))
413412 },
414413 )
415414};
@@ -418,10 +417,10 @@ static ROLL: Jet = |ctx, n| {
418417 let (list, gate) = n.as_cell()?;
419418
420419 list.list_iter().fold(
421− Some(gate.clone().gate_sample()?.as_cell()?.1),
420+ Some(gate.clone().gate_sample()?.as_cell()?.1.clone()),
422421 |acc, next| {
423422 let acc = acc?;
424− slam(ctx, gate.clone(), cell(&next, &acc))
423+ slam(ctx, gate, &cell(&next, &acc))
425424 },
426425 )
427426};
@@ -441,10 +440,7 @@ static SCAG: Jet = |_ctx, n| {
441440static SKID: Jet = |ctx, n| {
442441 let (list, gate) = n.as_cell()?;
443442
444− let slammed_n = traverse_iter_option(
445− list.list_iter()
446− .map(|n| Some((slam(ctx, gate.clone(), n.clone())?, n))),
447− )?;
443+ let slammed_n = traverse_iter_option(list.list_iter().map(|n| Some((slam(ctx, gate, n)?, n))))?;
448444 let (ys, ns): (Vec<_>, _) = slammed_n.iter().partition(|(l, _)| l.is_y());
449445
450446 Some(cell(
@@ -457,14 +453,10 @@ static SKIM: Jet = |ctx, n| {
457453 let (list, gate) = n.as_cell()?;
458454
459455 Some(Noun::list_refs(
460− traverse_iter_option(
461− list.list_iter()
462− .map(|n| Some((slam(ctx, gate.clone(), n.clone())?, n))),
463− )?
464− .iter()
465− .filter(|(l, _)| l.is_y())
466− .map(|(_, x)| x)
467− .cloned(),
456+ traverse_iter_option(list.list_iter().map(|n| Some((slam(ctx, gate, n)?, n))))?
457+ .iter()
458+ .filter(|(l, _)| l.is_y())
459+ .map(|(_, x)| *x),
468460 ))
469461};
470462
@@ -472,14 +464,11 @@ static SKIP: Jet = |ctx, n| {
472464 let (list, gate) = n.as_cell()?;
473465
474466 Some(Noun::list_refs(
475− traverse_iter_option(
476− list.list_iter()
477− .map(|n| Some((slam(ctx, gate.clone(), n.clone())?, n))),
478− )?
479− .iter()
480− .filter(|(l, _)| l.is_y())
481− .map(|(_, x)| x)
482− .cloned(),
467+ traverse_iter_option(list.list_iter().map(|n| Some((slam(ctx, gate, n)?, n))))?
468+ .iter()
469+ .filter(|(l, _)| l.is_y())
470+ .map(|(_, x)| x)
471+ .cloned(),
483472 ))
484473};
485474
@@ -489,7 +478,7 @@ static SLAG: Jet = |ctx, n| {
489478 let mut a_iter = a.as_atom()?.iter_u32_digits();
490479
491480 match a_iter.len() {
492− 0 => Some(list),
481+ 0 => Some(list.clone()),
493482 1 => Some(Noun::list_refs(
494483 list.list_iter()
495484 .skip(a_iter.next().unwrap() as usize)
@@ -504,7 +493,7 @@ static SLAG: Jet = |ctx, n| {
504493static SNAG: Jet = |_ctx, n| {
505494 let (a, list) = n.as_cell()?;
506495
507− list.list_iter().nth(a.as_u32().unwrap() as usize)
496+ list.list_iter().nth(a.as_u32().unwrap() as usize).cloned()
508497};
509498
510499static SNIP: Jet = |_ctx, n| {
@@ -551,40 +540,41 @@ static SNOC: Jet = |_ctx, n| {
551540
552541static SPIN: Jet = |ctx, n| {
553542 let (list, b) = n.as_cell()?;
554− let (mut acc, gate) = b.as_cell()?;
543+ let (acc, gate) = b.as_cell()?;
555544
556545 let mut res = Vec::new();
546+ let mut acc = acc.clone();
557547
558548 for n in list.list_iter() {
559− let (el, new_acc) = slam(ctx, gate.clone(), cell(&n, &acc))?.as_cell()?;
560− acc = new_acc;
561− res.push(el);
549+ let foo = slam(ctx, gate, &cell(&n, &acc))?;
550+ let (el, new_acc) = foo.as_cell()?;
551+ acc = new_acc.clone();
552+ res.push(el.clone());
562553 }
563554
564− Some(cell(&Noun::list_refs(res.iter().cloned()), &acc))
555+ Some(cell(&Noun::list_refs(res.iter()), &acc))
565556};
566557
567558static SPUN: Jet = |ctx, n| {
568559 let (list, gate) = n.as_cell()?;
569560
570561 let mut res = Vec::new();
571− let mut acc = gate.clone().gate_sample()?.as_cell()?.1;
562+ let mut acc = gate.gate_sample()?.as_cell()?.1.clone();
572563
573564 for n in list.list_iter() {
574− let (el, new_acc) = slam(ctx, gate.clone(), cell(&n, &acc))?.as_cell()?;
575− acc = new_acc;
576− res.push(el);
565+ let foo = slam(ctx, gate, &cell(&n, &acc))?;
566+ let (el, new_acc) = foo.as_cell()?;
567+ acc = new_acc.clone();
568+ res.push(el.clone());
577569 }
578570
579− Some(cell(&Noun::list_refs(res.iter().cloned()), &acc))
571+ Some(cell(&Noun::list_refs(res.iter()), &acc))
580572};
581573
582574static TURN: Jet = |ctx, n| {
583575 let (list, gate) = n.as_cell()?;
584576 Some(Noun::list_refs(
585− traverse_iter_option(list.list_iter().map(|x| slam(ctx, gate.clone(), x)))?
586− .iter()
587− .cloned(),
577+ traverse_iter_option(list.list_iter().map(|x| slam(ctx, gate, x)))?.iter(),
588578 ))
589579};
590580
@@ -791,7 +781,7 @@ static RIP: Jet = |ctx, n| {
791781 b = b >> bits;
792782 }
793783
794− Some(Noun::list_refs(target.iter().cloned()))
784+ Some(Noun::list_refs(target.iter()))
795785};
796786
797787static RUN: Jet = |ctx, n| {
@@ -808,7 +798,7 @@ static RUN: Jet = |ctx, n| {
808798
809799 while b > ctx.big_uints.zero {
810800 target = (target << bits)
811− | ((*slam(ctx, gate.clone(), Rc::new(Noun::Atom(&mask & &b)))?).as_atom()? & &mask);
801+ | ((*slam(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?).as_atom()? & &mask);
812802 b = b >> bits;
813803 }
814804
@@ -828,8 +818,7 @@ static RUT: Jet = |ctx, n| {
828818 let mut target = Vec::new();
829819
830820 while b > ctx.big_uints.zero {
831− target
832− .push((*slam(ctx, gate.clone(), Rc::new(Noun::Atom(&mask & &b)))?).as_atom()? & &mask);
821+ target.push((*slam(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?).as_atom()? & &mask);
833822 b = b >> bits;
834823 }
835824
@@ -956,7 +945,7 @@ static MUK: Jet = |_ctx, n| {
956945static JUST: DoubleJet = |ctx, n, m| {
957946 let char = n.as_atom()?;
958947 let nail = m.as_nail()?;
959− if nail.rest == ctx.nouns.sig {
948+ if *nail.rest == ctx.nouns.sig {
960949 Some(fail(nail).as_noun())
961950 } else {
962951 let (i, _) = nail.rest.as_cell()?;
@@ -979,8 +968,8 @@ static JUST: DoubleJet = |ctx, n, m| {
979968// if vex.
980969// };
981970
982−fn next(nail: Nail) -> Option<Edge> {
983− if *nail.rest == Noun::SIG {
971+fn next<'a>(nail: Nail<'a>) -> Option<Edge<'a>> {
972+ if **nail.rest == Noun::SIG {
984973 Some(fail(nail))
985974 } else {
986975 let (i, t) = nail.rest.as_cell()?;
nock/src/main.rs+6−6
@@ -92,7 +92,7 @@ fn main() -> Result<(), std::io::Error> {
9292 NockCommand::EvalGate { gate } => {
9393 let gate = read_nock(&gate).unwrap();
9494
95− let result = eval_gate(&generate_interpreter_context(), gate).unwrap();
95+ let result = eval_gate(&generate_interpreter_context(), &gate).unwrap();
9696
9797 println!("{result}");
9898 }
@@ -112,7 +112,7 @@ fn interact(gate_file: PathBuf) -> Result<(), std::io::Error> {
112112 let source = get_stdin().unwrap();
113113
114114 let mut spinner = new_spinner(String::from("Slamming gate..."));
115− let Some(slam) = slam(&generate_interpreter_context(), gate, source) else {
115+ let Some(slam) = slam(&generate_interpreter_context(), &gate, &source) else {
116116 spinner.fail("Gate execution failed");
117117 exit(1);
118118 };
@@ -158,8 +158,8 @@ fn build(root: PathBuf, output: PathBuf) -> Result<(), std::io::Error> {
158158
159159 slam(
160160 &generate_interpreter_context(),
161− ream_gate,
162− Rc::new(Noun::Atom(Atom::from_bytes_le(&root_source))),
161+ &ream_gate,
162+ &Rc::new(Noun::Atom(Atom::from_bytes_le(&root_source))),
163163 )
164164 .unwrap()
165165 };
@@ -170,7 +170,7 @@ fn build(root: PathBuf, output: PathBuf) -> Result<(), std::io::Error> {
170170 let hoon_hoon_ast_nock = include_bytes!("../res/hoon-hoon-ast.nock");
171171 let hoon_hoon_ast = cue_bytes(hoon_hoon_ast_nock);
172172 cell(
173− &Noun::Atom(Atom::from_bytes_le(b"tsgl")),
173+ &Rc::new(Noun::Atom(Atom::from_bytes_le(b"tsgl"))),
174174 &cell(&hoon_hoon_ast, &root_ast),
175175 )
176176 };
@@ -178,7 +178,7 @@ fn build(root: PathBuf, output: PathBuf) -> Result<(), std::io::Error> {
178178 println!("minting");
179179
180180 let mint_gate = cue_bytes(include_bytes!("../res/mint.nock"));
181− let slam_result = slam(&generate_interpreter_context(), mint_gate, ast).unwrap();
181+ let slam_result = slam(&generate_interpreter_context(), &mint_gate, &ast).unwrap();
182182
183183 // println!("{slam_result}");
184184
nock/src/noun.rs+45−76
@@ -1,7 +1,6 @@
11use std::{cell::Cell, cmp::Ordering, rc::Rc, str::FromStr};
22
33use num_bigint::BigUint;
4−use num_traits::ToBytes;
54use std::fmt;
65use xxhash_rust::xxh3::xxh3_128;
76
@@ -18,10 +17,6 @@ pub enum Noun {
1817 p: Rc<Noun>,
1918 q: Rc<Noun>,
2019 hash: Cell<Option<Hash>>,
21− compiled_gate: Option<(
22− Rc<Noun>,
23− Rc<fn(&InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>>,
24− )>,
2520 },
2621}
2722
@@ -58,13 +53,11 @@ impl PartialEq for Noun {
5853 p: lhs_p,
5954 q: lhs_q,
6055 hash: lhs_hash,
61− compiled_gate: _,
6256 },
6357 Noun::Cell {
6458 p: rhs_p,
6559 q: rhs_q,
6660 hash: rhs_hash,
67− compiled_gate: _,
6861 },
6962 ) => lhs_hash == rhs_hash && lhs_p == rhs_p && lhs_q == rhs_q,
7063 _ => false,
@@ -72,7 +65,7 @@ impl PartialEq for Noun {
7265 }
7366}
7467
75−impl Noun {
68+impl<'a> Noun {
7669 pub const SIG: Noun = Noun::Atom(BigUint::ZERO);
7770
7871 pub fn from_u32(a: u32) -> Noun {
@@ -80,15 +73,15 @@ impl Noun {
8073 }
8174
8275 pub fn list<I: Iterator<Item = Noun> + DoubleEndedIterator>(l: I) -> Rc<Noun> {
83− l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&head, &tail))
76+ l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&Rc::new(head), &tail))
8477 }
8578
86− pub fn list_refs<I: Iterator<Item = Rc<Noun>> + DoubleEndedIterator>(l: I) -> Rc<Noun> {
87− l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&head, &tail))
79+ pub fn list_refs<I: Iterator<Item = &'a Rc<Noun>> + DoubleEndedIterator>(l: I) -> Rc<Noun> {
80+ l.rfold(Rc::new(Noun::SIG), |tail, head| cell(head, &tail))
8881 }
8982
9083 pub fn unit(self: Rc<Self>) -> Rc<Noun> {
91− cell(&Noun::SIG, &self)
84+ cell(&Rc::new(Noun::SIG), &self)
9285 }
9386
9487 pub fn from_unit(unit: Option<Rc<Noun>>) -> Rc<Noun> {
@@ -115,15 +108,15 @@ impl Noun {
115108 }
116109 }
117110
118− pub fn gate_sample(self: Rc<Self>) -> Option<Rc<Self>> {
111+ pub fn gate_sample(self: &Rc<Self>) -> Option<&Rc<Self>> {
119112 let (_battery, payload) = self.as_cell()?;
120113 let (sample, _context) = payload.as_cell()?;
121114 Option::Some(sample)
122115 }
123116
124− pub fn as_cell(self: &Self) -> Option<(Rc<Noun>, Rc<Noun>)> {
117+ pub fn as_cell(self: &'a Self) -> Option<(&'a Rc<Noun>, &'a Rc<Noun>)> {
125118 match self {
126− Noun::Cell { p, q, .. } => Option::Some((p.clone(), q.clone())),
119+ Noun::Cell { p, q, .. } => Option::Some((p, q)),
127120 _ => Option::None,
128121 }
129122 }
@@ -143,12 +136,12 @@ impl Noun {
143136 !self.is_sig()
144137 }
145138
146− pub fn list_iter(self: Rc<Self>) -> NounListIterator {
147− NounListIterator { noun: self.clone() }
139+ pub fn list_iter(self: &'a Rc<Self>) -> NounListIterator<'a> {
140+ NounListIterator { noun: self }
148141 }
149142
150143 /// panics if malformed
151− pub fn as_unit(self: &Self) -> Option<Rc<Self>> {
144+ pub fn as_unit(self: &Self) -> Option<&Rc<Self>> {
152145 if self.is_sig() {
153146 Option::None
154147 } else {
@@ -158,17 +151,11 @@ impl Noun {
158151
159152 pub fn hash(self: &Self) -> Hash {
160153 match self {
161− Noun::Cell {
162− hash,
163− p,
164− q,
165− compiled_gate: _,
166− } => match hash.get() {
154+ Noun::Cell { hash, p, q } => match hash.get() {
167155 Some(x) => x.clone(),
168156 None => {
169− let hash_value = stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
170− hash_pair(p.clone(), q.clone())
171− });
157+ let hash_value =
158+ stacker::maybe_grow(32 * 1024, 1024 * 1024, || hash_pair(p, q));
172159 hash.replace(Some(hash_value));
173160 hash_value
174161 }
@@ -178,15 +165,15 @@ impl Noun {
178165 }
179166
180167 /// returns the hash and the current sample
181− pub fn hash_gate(self: &Self) -> (Hash, Rc<Noun>) {
168+ pub fn hash_gate(self: &Self) -> (Hash, &Rc<Noun>) {
182169 let (battery, payload) = self.as_cell().unwrap();
183170 let (sample, context) = payload.as_cell().unwrap();
184171
185− (hash_pair(battery.clone(), context), sample)
172+ (hash_pair(battery, context), sample)
186173 }
187174
188175 /// returns the hash and the current sample
189− pub fn hash_double_gate(self: &Self) -> (Hash, Rc<Noun>, Rc<Noun>) {
176+ pub fn hash_double_gate(self: &Self) -> (Hash, &Rc<Noun>, &Rc<Noun>) {
190177 let (battery, payload) = self.as_cell().unwrap();
191178 let (sample_2, context) = payload.as_cell().unwrap();
192179 let (inner_hash, sample_1) = context.hash_gate();
@@ -232,14 +219,17 @@ impl Noun {
232219 }
233220
234221 pub fn from_hair(hair: &Hair) -> Rc<Self> {
235− cell(&Noun::from_u32(hair.line), &Noun::from_u32(hair.column))
222+ cell(
223+ &Rc::new(Noun::from_u32(hair.line)),
224+ &Rc::new(Noun::from_u32(hair.column)),
225+ )
236226 }
237227
238228 pub fn as_nail(self: &Self) -> Option<Nail> {
239229 let (hair, tape) = self.as_cell()?;
240230 Some(Nail {
241231 hair: hair.as_hair()?,
242− rest: tape.clone(),
232+ rest: tape,
243233 })
244234 }
245235
@@ -257,44 +247,21 @@ impl Noun {
257247 };
258248 Some(Edge { hair, result })
259249 }
260−
261− pub fn with_jet(
262− self: &Self,
263− jet: (
264− Rc<Noun>,
265− Rc<fn(&InterpreterContext, Rc<Noun>, Rc<Noun>) -> Option<Rc<Noun>>>,
266− ),
267− ) -> Self {
268− match self {
269− Noun::Atom(_) => self.clone(),
270− Noun::Cell {
271− p,
272− q,
273− hash,
274− compiled_gate: _,
275− } => Noun::Cell {
276− p: p.clone(),
277− q: q.clone(),
278− hash: hash.clone(),
279− compiled_gate: Some(jet),
280− },
281− }
282− }
283250}
284251
285252#[derive(Clone)]
286−pub struct Edge {
253+pub struct Edge<'a> {
287254 pub hair: Hair,
288− pub result: Option<(Rc<Noun>, Nail)>,
255+ pub result: Option<(&'a Rc<Noun>, Nail<'a>)>,
289256}
290257
291−impl Edge {
258+impl<'a> Edge<'a> {
292259 pub fn as_noun(self: &Self) -> Rc<Noun> {
293− let foo = match self.result.clone() {
294− None => &Noun::SIG,
260+ let foo = match &self.result {
261+ None => &Rc::new(Noun::SIG),
295262 Some((result, nail)) => {
296263 let foo = cell(&result, &nail.as_noun());
297− &cell(&Noun::SIG, &foo)
264+ &cell(&Rc::new(Noun::SIG), &foo)
298265 }
299266 };
300267 cell(&self.hair.as_noun(), foo)
@@ -309,17 +276,20 @@ pub struct Hair {
309276
310277impl Hair {
311278 pub fn as_noun(self: &Self) -> Rc<Noun> {
312− cell(&Noun::from_u32(self.line), &Noun::from_u32(self.column))
279+ cell(
280+ &Rc::new(Noun::from_u32(self.line)),
281+ &Rc::new(Noun::from_u32(self.column)),
282+ )
313283 }
314284}
315285
316286#[derive(Clone)]
317−pub struct Nail {
287+pub struct Nail<'a> {
318288 pub hair: Hair,
319− pub rest: Rc<Noun>,
289+ pub rest: &'a Rc<Noun>,
320290}
321291
322−impl Nail {
292+impl<'a> Nail<'a> {
323293 pub fn as_noun(self: &Self) -> Rc<Noun> {
324294 cell(&self.hair.as_noun(), &self.rest)
325295 }
@@ -338,19 +308,19 @@ impl Bite {
338308}
339309
340310#[derive(Clone)]
341−pub struct NounListIterator {
342− noun: Rc<Noun>,
311+pub struct NounListIterator<'a> {
312+ noun: &'a Rc<Noun>,
343313}
344314
345−impl Iterator for NounListIterator {
346− type Item = Rc<Noun>;
315+impl<'a> Iterator for NounListIterator<'a> {
316+ type Item = &'a Rc<Noun>;
347317
348318 fn next(&mut self) -> Option<Self::Item> {
349319 if self.noun.is_sig() {
350320 Option::None
351321 } else {
352322 let (p, q) = self.noun.as_cell().unwrap();
353− self.noun = q.clone();
323+ self.noun = q;
354324 Option::Some(p)
355325 }
356326 }
@@ -394,20 +364,19 @@ fn print_noun(noun: Rc<Noun>, is_rhs: bool) -> String {
394364 }
395365}
396366
397−pub fn cell(p: &Noun, q: &Noun) -> Rc<Noun> {
367+pub fn cell(p: &Rc<Noun>, q: &Rc<Noun>) -> Rc<Noun> {
398368 Rc::new(naked_cell(p, q))
399369}
400370
401−pub fn naked_cell(p: &Noun, q: &Noun) -> Noun {
371+pub fn naked_cell(p: &Rc<Noun>, q: &Rc<Noun>) -> Noun {
402372 Noun::Cell {
403− p: Rc::new(p.clone()),
404− q: Rc::new(q.clone()),
373+ p: p.clone(),
374+ q: q.clone(),
405375 hash: Cell::new(None),
406− compiled_gate: None,
407376 }
408377}
409378
410−fn hash_pair(p: Rc<Noun>, q: Rc<Noun>) -> Hash {
379+fn hash_pair(p: &Rc<Noun>, q: &Rc<Noun>) -> Hash {
411380 xxh3_128(&[p.hash().to_le_bytes(), q.hash().to_le_bytes()].as_flattened())
412381}
413382