@@ -1,15 +1,23 @@
11use core::str;
22use std::borrow::Borrow;
33use std::collections::BTreeMap;
4+use std::collections::HashMap;
45use std::rc::Rc;
6+use std::sync::Mutex;
57
68use fplist::cons;
79use fplist::PersistentList;
10+use lazy_static::lazy_static;
811use num_bigint::BigUint;
912
1013use crate::jets::*;
1114use crate::noun::*;
1215
16+// #[cfg(feature = "count-jets")]
17+lazy_static! {
18+ pub static ref JET_COUNTER: Mutex<HashMap<Atom, u32>> = Mutex::new(HashMap::new());
19+}
20+
1321#[derive(Clone)]
1422pub struct Nouns {
1523 pub y: Rc<Noun>,
@@ -24,6 +32,7 @@ pub struct Nouns {
2432 pub memo: Rc<Noun>,
2533 pub mean: Rc<Noun>,
2634 pub slog: Rc<Noun>,
35+ pub fast: Rc<Noun>,
2736}
2837
2938#[derive(Clone)]
@@ -42,6 +51,7 @@ pub struct InterpreterContext {
4251 pub nouns: Nouns,
4352 pub big_uints: BigUints,
4453 pub memo: BTreeMap<Hash, Rc<Noun>>,
54+ pub slog: fn(&String) -> (),
4555}
4656
4757pub fn generate_interpreter_context() -> InterpreterContext {
@@ -64,6 +74,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
6474 let memo = Rc::new(Noun::from_bytes(b"memo"));
6575 let mean = Rc::new(Noun::from_bytes(b"mean"));
6676 let slog = Rc::new(Noun::from_bytes(b"slog"));
77+ let fast = Rc::new(Noun::from_bytes(b"fast"));
6778 InterpreterContext {
6879 jets,
6980 double_jets,
@@ -80,9 +91,11 @@ pub fn generate_interpreter_context() -> InterpreterContext {
8091 memo,
8192 mean,
8293 slog,
94+ fast,
8395 },
8496 big_uints,
8597 memo: BTreeMap::new(),
98+ slog: |str: &String| eprintln!("{}", str),
8699 }
87100}
88101
@@ -191,7 +204,7 @@ fn hax(
191204
192205fn tar_u32<'a>(
193206 ctx: &mut InterpreterContext,
194− subj: Rc<Noun>,
207+ subj: &'a Rc<Noun>,
195208 op: u32,
196209 formula: &'a Rc<Noun>,
197210) -> Result<Rc<Noun>, TTanks> {
@@ -214,16 +227,16 @@ fn tar_u32<'a>(
214227 match ctx.jets.get(&hash) {
215228 Some(f) => f(ctx, sample),
216229 None => {
217− let foo = tar(ctx, subj.clone(), &b)?;
230+ let foo = tar(ctx, subj, &b)?;
218231 let bar = tar(ctx, subj, &c)?;
219− tar(ctx, foo, &bar)
232+ tar(ctx, &foo, &bar)
220233 }
221234 }
222235 }
223236 _ => {
224− let foo = tar(ctx, subj.clone(), &b)?;
237+ let foo = tar(ctx, subj, &b)?;
225238 let bar = tar(ctx, subj, &c)?;
226− tar(ctx, foo, &bar)
239+ tar(ctx, &foo, &bar)
227240 }
228241 }
229242 }
@@ -234,7 +247,7 @@ fn tar_u32<'a>(
234247 4 => Ok(Rc::new(lus(&*tar(ctx, subj, &formula)?)?)),
235248 5 => {
236249 let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
237− let foo = tar(ctx, subj.clone(), &b)?;
250+ let foo = tar(ctx, subj, &b)?;
238251 let bar = tar(ctx, subj, &c)?;
239252 Ok(tis(ctx, &foo, &bar).clone())
240253 }
@@ -242,29 +255,29 @@ fn tar_u32<'a>(
242255 let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
243256 let (c, d) = c.as_cell().ok_or(TTanks::new())?;
244257
245− let bar = tar_u32(ctx, subj.clone(), 4, &cell(&ctx.nouns.four.clone(), &b))?;
258+ let bar = tar_u32(ctx, subj, 4, &cell(&ctx.nouns.four.clone(), &b))?;
246259
247− let foo = tar_u32(ctx, ctx.nouns.two_three.clone(), 0, &bar)?;
248− let foo = tar_u32(ctx, cell(&c, &d), 0, &foo)?;
260+ let foo = tar_u32(ctx, &ctx.nouns.two_three.clone(), 0, &bar)?;
261+ let foo = tar_u32(ctx, &cell(&c, &d), 0, &foo)?;
249262
250263 tar(ctx, subj, &foo)
251264 }
252265 7 => {
253266 let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
254267 let foo = tar(ctx, subj, &b)?;
255− tar(ctx, foo, &c)
268+ tar(ctx, &foo, &c)
256269 }
257270 8 => {
258271 let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
259− let foo = tar(ctx, subj.clone(), &b)?;
260− tar(ctx, cell(&foo, &subj), &c)
272+ let foo = tar(ctx, subj, &b)?;
273+ tar(ctx, &cell(&foo, &subj), &c)
261274 }
262275 9 => {
263276 let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
264277 let foo = tar(ctx, subj, &c)?;
265278 tar_u32(
266279 ctx,
267− foo,
280+ &foo,
268281 2,
269282 &cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
270283 )
@@ -274,7 +287,7 @@ fn tar_u32<'a>(
274287 let (b, c) = b.as_cell().ok_or(TTanks::new())?;
275288 let b = b.as_atom().ok_or(TTanks::new())?;
276289
277− let foo = tar(ctx, subj.clone(), &c)?;
290+ let foo = tar(ctx, subj, &c)?;
278291 let bar = tar(ctx, subj, &d)?;
279292 hax(ctx, b, &foo, &bar)
280293 }
@@ -283,7 +296,7 @@ fn tar_u32<'a>(
283296 match b.borrow() {
284297 Noun::Atom(_) => tar(ctx, subj, &d),
285298 Noun::Cell { p, q, .. } => {
286− let eval = |ctx: &mut InterpreterContext| tar(ctx, subj.clone(), &d);
299+ let eval = |ctx: &mut InterpreterContext| tar(ctx, subj, &d);
287300 if *p == ctx.nouns.memo {
288301 let hash = cell(&subj, &d).hash();
289302 match ctx.memo.get(&hash) {
@@ -297,10 +310,32 @@ fn tar_u32<'a>(
297310 } else if *p == ctx.nouns.mean {
298311 with_trace((subj.clone(), q.clone()), eval(ctx))
299312 } else if *p == ctx.nouns.slog {
300− let noun = tar(ctx, subj.clone(), &q)?;
313+ let noun = tar(ctx, subj, &q)?;
301314 let (_prio, tank) = noun.as_cell().ok_or(TTanks::new())?;
302315
303− eprintln!("{}", ram(ctx, tank.clone()).unwrap_or(String::new()));
316+ (ctx.slog)(&ram(ctx, tank.clone()).unwrap_or(String::new()));
317+ eval(ctx)
318+ } else if *p == ctx.nouns.fast {
319+ if cfg!(feature = "count-jets") {
320+ let tag = q.as_cell().unwrap().1.as_cell().unwrap().0.as_atom();
321+ match tag {
322+ None => (),
323+ Some(tag) => {
324+ let mut counter = JET_COUNTER.lock().unwrap();
325+ match counter.get(tag) {
326+ None => {
327+ counter.insert(tag.clone(), 1);
328+ ()
329+ }
330+ Some(v) => {
331+ let v = *v;
332+ counter.insert(tag.clone(), v + 1);
333+ ()
334+ }
335+ }
336+ }
337+ }
338+ }
304339 eval(ctx)
305340 } else {
306341 eval(ctx)
@@ -321,24 +356,22 @@ fn ram(ctx: &mut InterpreterContext, tank: Rc<Noun>) -> Option<String> {
321356 Noun::Cell { p, q, .. } => {
322357 let tag = p.as_atom()?.to_bytes_le();
323358 if tag == b"leaf" {
324− let mut bytes = crip(ctx, q.clone()).ok()?.as_atom()?.to_bytes_le();
359+ let mut bytes = crip(ctx, q.clone()).ok()?.as_bytes()?;
325360 Some(String::from(str::from_utf8_mut(&mut bytes).ok()?))
326361 } else if tag == b"palm" {
327− let (mid, foo) = q.as_cell()?;
328− let (open, foo) = foo.as_cell()?;
329− let (flat_open, foo) = foo.as_cell()?;
330− let (close, tanks) = foo.as_cell()?;
362+ let (spacers, tanks) = q.as_cell()?;
363+ let (mid, open, flat_open, close) = spacers.tuple_4()?;
331364
332− let mut mid = mid.as_bytes()?;
365+ let mut mid = crip(ctx, mid.clone()).ok()?.as_bytes()?;
333366 let mid = String::from(str::from_utf8_mut(&mut mid).ok()?);
334367
335− let mut open = open.as_bytes()?;
368+ let mut open = crip(ctx, open.clone()).ok()?.as_bytes()?;
336369 let open = String::from(str::from_utf8_mut(&mut open).ok()?);
337370
338− let mut flat_open = flat_open.as_bytes()?;
371+ let mut flat_open = crip(ctx, flat_open.clone()).ok()?.as_bytes()?;
339372 let flat_open = String::from(str::from_utf8_mut(&mut flat_open).ok()?);
340373
341− let mut close = close.as_bytes()?;
374+ let mut close = crip(ctx, close.clone()).ok()?.as_bytes()?;
342375 let close = String::from(str::from_utf8_mut(&mut close).ok()?);
343376
344377 let mut target = String::new();
@@ -361,17 +394,16 @@ fn ram(ctx: &mut InterpreterContext, tank: Rc<Noun>) -> Option<String> {
361394
362395 Some(target)
363396 } else if tag == b"rose" {
364− let (mid, foo) = q.as_cell()?;
365− let (open, foo) = foo.as_cell()?;
366− let (close, tanks) = foo.as_cell()?;
397+ let (spacers, tanks) = q.as_cell()?;
398+ let (mid, open, close) = spacers.tuple_3()?;
367399
368− let mut mid = mid.as_bytes()?;
400+ let mut mid = crip(ctx, mid.clone()).ok()?.as_bytes()?;
369401 let mid = String::from(str::from_utf8_mut(&mut mid).ok()?);
370402
371− let mut open = open.as_bytes()?;
403+ let mut open = crip(ctx, open.clone()).ok()?.as_bytes()?;
372404 let open = String::from(str::from_utf8_mut(&mut open).ok()?);
373405
374− let mut close = close.as_bytes()?;
406+ let mut close = crip(ctx, close.clone()).ok()?.as_bytes()?;
375407 let close = String::from(str::from_utf8_mut(&mut close).ok()?);
376408
377409 let mut target = String::new();
@@ -402,8 +434,15 @@ fn ram(ctx: &mut InterpreterContext, tank: Rc<Noun>) -> Option<String> {
402434pub fn ram_ttanks(ctx: &mut InterpreterContext, tanks: TTanks) -> String {
403435 let mut target = String::new();
404436
405− for tank in tanks.iter() {
437+ let mut first = true;
438+ for tank in tanks.iter().collect::<Vec<_>>().iter().cloned().rev() {
439+ if !first {
440+ target.push('\n');
441+ }
442+
406443 target.push_str(&*ram_ttank(ctx, tank.clone()));
444+
445+ first = false;
407446 }
408447
409448 target
@@ -412,17 +451,21 @@ pub fn ram_ttanks(ctx: &mut InterpreterContext, tanks: TTanks) -> String {
412451pub fn ram_ttank(ctx: &mut InterpreterContext, ttank: TTank) -> String {
413452 let (subj, q) = ttank;
414453
415− let tank = match tar(ctx, subj.clone(), &q) {
454+ let tank = match tar(ctx, &subj, &q) {
416455 Ok(gate) => match eval_pulled_gate(ctx, gate) {
417456 Ok(tank) => tank,
418− Err(_) => return String::new(),
457+ Err(_) => {
458+ return String::new();
459+ }
419460 },
420− Err(_) => return String::new(),
461+ Err(_) => {
462+ return String::new();
463+ }
421464 };
422465 ram(ctx, tank).unwrap_or(String::new())
423466}
424467
425−fn crip(ctx: &mut InterpreterContext, tape: Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
468+pub fn crip(ctx: &mut InterpreterContext, tape: Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
426469 RAP(ctx, &cell(&Rc::new(Noun::from_u32(3)), &tape))
427470}
428471
@@ -441,13 +484,13 @@ pub const EMPTY_TANKS: TTanks = TTanks::new();
441484
442485pub fn tar<'a>(
443486 ctx: &mut InterpreterContext,
444− subj: Rc<Noun>,
487+ subj: &'a Rc<Noun>,
445488 formula: &'a Noun,
446489) -> Result<Rc<Noun>, TTanks> {
447490 let (op, formula) = formula.as_cell().ok_or(TTanks::new())?;
448491 match op.borrow() {
449492 Noun::Cell { .. } => {
450− let foo = tar(ctx, subj.clone(), &op)?;
493+ let foo = tar(ctx, subj, &op)?;
451494 let bar = tar(ctx, subj, &formula)?;
452495 Ok(cell(&foo, &bar))
453496 }
@@ -468,7 +511,7 @@ pub fn eval_gate(
468511 ctx: &mut InterpreterContext,
469512 gate_factory: &Rc<Noun>,
470513) -> Result<Rc<Noun>, TTanks> {
471− let pulled_gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
514+ let pulled_gate = tar(ctx, &ctx.nouns.sig.clone(), &gate_factory)?;
472515 eval_pulled_gate(ctx, pulled_gate)
473516}
474517
@@ -477,7 +520,7 @@ pub fn slam(
477520 gate_factory: &Rc<Noun>,
478521 sample: &Rc<Noun>,
479522) -> Result<Rc<Noun>, TTanks> {
480− let gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
523+ let gate = tar(ctx, &ctx.nouns.sig.clone(), &gate_factory)?;
481524
482525 eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
483526}
@@ -487,7 +530,7 @@ pub fn slam(
487530pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
488531 tar(
489532 ctx,
490− gate,
533+ &gate,
491534 &cell(
492535 &Rc::new(Noun::Atom(BigUint::new(vec![9]))),
493536 &cell(&ctx.nouns.two, &cell(&ctx.nouns.sig, &ctx.nouns.one)),