on master help sign in
memo
commit862a57d70eb3cf621feea5cb8d8e8c84c429ae9f authoriko <mail@iko.soy> dateThu 5 Sep 2024, 20:45 (2 years ago) parent6d79aa0
6 files changed+133−69
nock/one.hoon+1−1 nock/one.nock+1−1 nock/src/interpreter.rs+63−44 nock/src/jets.rs+37−13 nock/src/main.rs+7−7 nock/src/noun.rs+24−3
nock/one.hoon+1−1
@@ -1 +1 @@
1−=> ~ |=(@ 'Hello')
1+=> ~ ~+ |=(@ 'Hello')
nock/one.nock+1−1
@@ -1 +1 @@
1−���� �����
1+�d �mem���pq x������
nock/src/interpreter.rs+63−44
@@ -1,4 +1,5 @@
11use std::borrow::Borrow;
2+use std::collections::BTreeMap;
23use std::rc::Rc;
34
45use num_bigint::BigUint;
@@ -16,6 +17,7 @@ pub struct Nouns {
1617 pub four: Rc<Noun>,
1718 pub sig_one: Rc<Noun>,
1819 pub two_three: Rc<Noun>,
20+ pub memo: Rc<Noun>,
1921}
2022
2123pub struct BigUints {
@@ -31,6 +33,7 @@ pub struct InterpreterContext {
3133 pub double_jets: DoubleJets,
3234 pub nouns: Nouns,
3335 pub big_uints: BigUints,
36+ pub memo: BTreeMap<Hash, Rc<Noun>>,
3437}
3538
3639pub fn generate_interpreter_context() -> InterpreterContext {
@@ -50,6 +53,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
5053 let four = Rc::new(Noun::Atom(big_uints.four.clone()));
5154 let sig_one = cell(&sig, &one);
5255 let two_three = cell(&two, &three);
56+ let memo = Rc::new(Noun::from_bytes(b"memo"));
5357 InterpreterContext {
5458 jets,
5559 double_jets,
@@ -63,8 +67,10 @@ pub fn generate_interpreter_context() -> InterpreterContext {
6367 four,
6468 sig_one,
6569 two_three,
70+ memo,
6671 },
6772 big_uints,
73+ memo: BTreeMap::new(),
6874 }
6975}
7076
@@ -172,15 +178,15 @@ fn hax(
172178}
173179
174180fn tar_u32<'a>(
175− ctx: &InterpreterContext,
176− subj: &'a Noun,
181+ ctx: &mut InterpreterContext,
182+ subj: Rc<Noun>,
177183 op: u32,
178184 formula: &'a Rc<Noun>,
179185) -> Option<Rc<Noun>> {
180186 match op {
181187 0 => {
182188 let b = formula.as_atom()?;
183− fas(ctx, b, subj)
189+ fas(ctx, b, &*subj)
184190 }
185191 1 => Some(formula.clone()),
186192 2 => {
@@ -196,16 +202,16 @@ fn tar_u32<'a>(
196202 match ctx.jets.get(&hash) {
197203 Some(f) => f(ctx, sample),
198204 None => {
199− let foo = tar(ctx, subj, &b)?;
205+ let foo = tar(ctx, subj.clone(), &b)?;
200206 let bar = tar(ctx, subj, &c)?;
201− tar(ctx, &foo, &bar)
207+ tar(ctx, foo, &bar)
202208 }
203209 }
204210 }
205211 _ => {
206− let foo = tar(ctx, &subj, &b)?;
207− let bar = tar(ctx, &subj, &c)?;
208− tar(ctx, &foo, &bar)
212+ let foo = tar(ctx, subj.clone(), &b)?;
213+ let bar = tar(ctx, subj, &c)?;
214+ tar(ctx, foo, &bar)
209215 }
210216 }
211217 }
@@ -219,7 +225,7 @@ fn tar_u32<'a>(
219225 }
220226 5 => {
221227 let (b, c) = formula.as_cell()?;
222− let foo = tar(ctx, &subj, &b)?;
228+ let foo = tar(ctx, subj.clone(), &b)?;
223229 let bar = tar(ctx, subj, &c)?;
224230 Some(tis(ctx, &foo, &bar).clone())
225231 }
@@ -227,36 +233,29 @@ fn tar_u32<'a>(
227233 let (b, c) = formula.as_cell()?;
228234 let (c, d) = c.as_cell()?;
229235
230− let foo = tar_u32(
231− ctx,
232− &cell(&c, &d),
233− 0,
234− &tar_u32(
235− ctx,
236− &ctx.nouns.two_three,
237− 0,
238− &tar_u32(ctx, subj, 4, &cell(&ctx.nouns.four, &b))?,
239− )?,
240− )?;
236+ let bar = tar_u32(ctx, subj.clone(), 4, &cell(&ctx.nouns.four.clone(), &b))?;
241237
242− tar(ctx, &subj, &foo)
238+ let foo = tar_u32(ctx, ctx.nouns.two_three.clone(), 0, &bar)?;
239+ let foo = tar_u32(ctx, cell(&c, &d), 0, &foo)?;
240+
241+ tar(ctx, subj, &foo)
243242 }
244243 7 => {
245244 let (b, c) = formula.as_cell()?;
246245 let foo = tar(ctx, subj, &b)?;
247− tar(ctx, &foo, &c)
246+ tar(ctx, foo, &c)
248247 }
249248 8 => {
250249 let (b, c) = formula.as_cell()?;
251− let foo = tar(ctx, &subj, &b)?;
252− tar(ctx, &cell(&foo, &Rc::new(subj.clone())), &c)
250+ let foo = tar(ctx, subj.clone(), &b)?;
251+ tar(ctx, cell(&foo, &subj), &c)
253252 }
254253 9 => {
255254 let (b, c) = formula.as_cell()?;
256− let foo = tar(ctx, &subj, &c)?;
255+ let foo = tar(ctx, subj, &c)?;
257256 tar_u32(
258257 ctx,
259− &foo,
258+ foo,
260259 2,
261260 &cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
262261 )
@@ -266,17 +265,33 @@ fn tar_u32<'a>(
266265 let (b, c) = b.as_cell()?;
267266 let b = b.as_atom()?;
268267
269− hax(ctx, b, &tar(ctx, subj, &c)?, &tar(ctx, subj, &d)?)
268+ let foo = tar(ctx, subj.clone(), &c)?;
269+ let bar = tar(ctx, subj, &d)?;
270+ hax(ctx, b, &foo, &bar)
270271 }
271272 11 => {
272273 let (b, d) = formula.as_cell()?;
273− // println!("{b}");
274274 match b.borrow() {
275275 Noun::Atom(_) => tar(ctx, subj, &d),
276− Noun::Cell { q: c, .. } => {
277− let foo = tar(ctx, subj, &c)?;
278− let bar = tar(ctx, subj, &d)?;
279− tar_u32(ctx, &cell(&foo, &bar), 0, &ctx.nouns.three)
276+ Noun::Cell { p, q, .. } => {
277+ if *p == ctx.nouns.memo {
278+ let hash = cell(&subj, formula).hash();
279+ match ctx.memo.get(&hash) {
280+ Some(target) => Some(target.clone()),
281+ None => {
282+ let foo = cell(
283+ &tar(ctx, subj.clone(), &q)?,
284+ &tar(ctx, subj.clone(), &d)?,
285+ );
286+ let target = tar_u32(ctx, foo, 0, &ctx.nouns.three.clone())?;
287+ ctx.memo.insert(hash, target.clone());
288+ Some(target)
289+ }
290+ }
291+ } else {
292+ let foo = cell(&tar(ctx, subj.clone(), &q)?, &tar(ctx, subj.clone(), &d)?);
293+ tar_u32(ctx, foo, 0, &ctx.nouns.three.clone())
294+ }
280295 }
281296 }
282297 }
@@ -284,11 +299,15 @@ fn tar_u32<'a>(
284299 }
285300}
286301
287−pub fn tar<'a>(ctx: &InterpreterContext, subj: &'a Noun, formula: &'a Noun) -> Option<Rc<Noun>> {
302+pub fn tar<'a>(
303+ ctx: &mut InterpreterContext,
304+ subj: Rc<Noun>,
305+ formula: &'a Noun,
306+) -> Option<Rc<Noun>> {
288307 let (op, formula) = formula.as_cell()?;
289308 match op.borrow() {
290309 Noun::Cell { .. } => {
291− let foo = tar(ctx, subj, &op)?;
310+ let foo = tar(ctx, subj.clone(), &op)?;
292311 let bar = tar(ctx, subj, &formula)?;
293312 Some(cell(&foo, &bar))
294313 }
@@ -305,27 +324,27 @@ pub fn tar<'a>(ctx: &InterpreterContext, subj: &'a Noun, formula: &'a Noun) -> O
305324 }
306325}
307326
308−pub fn eval_gate(ctx: &InterpreterContext, gate_factory: &Rc<Noun>) -> Option<Rc<Noun>> {
309− let pulled_gate = tar(ctx, &ctx.nouns.sig, &gate_factory)?;
310− eval_pulled_gate(ctx, &pulled_gate)
327+pub fn eval_gate(ctx: &mut InterpreterContext, gate_factory: &Rc<Noun>) -> Option<Rc<Noun>> {
328+ let pulled_gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
329+ eval_pulled_gate(ctx, pulled_gate)
311330}
312331
313332pub fn slam(
314− ctx: &InterpreterContext,
333+ ctx: &mut InterpreterContext,
315334 gate_factory: &Rc<Noun>,
316335 sample: &Rc<Noun>,
317336) -> Option<Rc<Noun>> {
318− let gate = tar(ctx, &ctx.nouns.sig, &gate_factory)?;
337+ let gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
319338
320− eval_pulled_gate(ctx, &replace_sample(&gate, sample)?)
339+ eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
321340}
322341
323342/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
324343/// Also for calling gates from within jets.
325−pub fn eval_pulled_gate(ctx: &InterpreterContext, gate: &Rc<Noun>) -> Option<Rc<Noun>> {
344+pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Option<Rc<Noun>> {
326345 tar(
327346 ctx,
328− &gate,
347+ gate,
329348 &cell(
330349 &Rc::new(Noun::Atom(BigUint::new(vec![9]))),
331350 &cell(&ctx.nouns.two, &cell(&ctx.nouns.sig, &ctx.nouns.one)),
@@ -336,11 +355,11 @@ pub fn eval_pulled_gate(ctx: &InterpreterContext, gate: &Rc<Noun>) -> Option<Rc<
336355/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
337356/// Also for calling gates from within jets.
338357pub fn slam_pulled_gate(
339− ctx: &InterpreterContext,
358+ ctx: &mut InterpreterContext,
340359 gate: &Rc<Noun>,
341360 sample: &Rc<Noun>,
342361) -> Option<Rc<Noun>> {
343− eval_pulled_gate(ctx, &replace_sample(gate, sample)?)
362+ eval_pulled_gate(ctx, replace_sample(gate, sample)?)
344363}
345364
346365pub fn replace_sample(gate: &Rc<Noun>, sample: &Rc<Noun>) -> Option<Rc<Noun>> {
nock/src/jets.rs+37−13
@@ -8,7 +8,7 @@ use std::{
88};
99
1010use crate::{
11− interpreter::{slam, slam_pulled_gate, InterpreterContext},
11+ interpreter::{slam_pulled_gate, InterpreterContext},
1212 noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
1313};
1414
@@ -104,11 +104,12 @@ pub fn generate_jets() -> Jets {
104104 (3482046397915506566435874021936376320, LAST),
105105 (124976064672625230427889101290245200507, TRIP),
106106 (4078279288073906183633157465551067635, MUK),
107+ (261900159748071234702685239353558471892, MUG),
107108 ])
108109}
109110
110−pub type Jet = fn(ctx: &InterpreterContext, &Rc<Noun>) -> Option<Rc<Noun>>;
111−pub type DoubleJet = fn(ctx: &InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
111+pub type Jet = fn(ctx: &mut InterpreterContext, &Rc<Noun>) -> Option<Rc<Noun>>;
112+pub type DoubleJet = fn(ctx: &mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
112113
113114static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
114115 |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
@@ -941,16 +942,7 @@ static MUK: Jet = |_ctx, n| {
941942 let len = len.as_u32()?;
942943 let key = key.as_atom()?;
943944
944− let key: Vec<_> = key
945− .to_bytes_le()
946− .iter()
947− .take(len as usize)
948− .cloned()
949− .collect();
950−
951− Some(Rc::new(Noun::from_u32(
952− murmur3_32(&mut &*key, seed).unwrap(),
953− )))
945+ Some(Rc::new(Noun::from_u32(muk(seed, len, key))))
954946};
955947
956948static JUST: DoubleJet = |ctx, n, m| {
@@ -1013,3 +1005,35 @@ fn fail(nail: Nail) -> Edge {
10131005 result: None,
10141006 }
10151007}
1008+
1009+const MUG: Jet = |__ctx, n| Some(Rc::new(Noun::from_u32(n.mug())));
1010+
1011+pub fn mum(syd: u32, fal: u32, key: &Atom) -> u32 {
1012+ let wyd = met(3, &key);
1013+ let mut i = 0;
1014+ loop {
1015+ if i == 8 {
1016+ break fal;
1017+ } else {
1018+ let haz = muk(syd, wyd, &key);
1019+ let ham = (haz >> 31) ^ (haz & !(1 << 31));
1020+ if ham == 0 {
1021+ i += 1;
1022+ continue;
1023+ } else {
1024+ break ham;
1025+ }
1026+ }
1027+ }
1028+}
1029+
1030+fn muk(seed: u32, len: u32, key: &Atom) -> u32 {
1031+ let key: Vec<_> = key
1032+ .to_bytes_le()
1033+ .iter()
1034+ .take(len as usize)
1035+ .cloned()
1036+ .collect();
1037+
1038+ murmur3_32(&mut &*key, seed).unwrap()
1039+}
nock/src/main.rs+7−7
@@ -1,5 +1,5 @@
11use clap::{command, error::Result, Parser, Subcommand};
2−use nock::interpreter::{eval_gate, eval_pulled_gate, slam_pulled_gate};
2+use nock::interpreter::{eval_pulled_gate, slam_pulled_gate};
33use nock::{
44 cue::cue_bytes,
55 interpreter::{generate_interpreter_context, slam},
@@ -90,15 +90,15 @@ fn main() -> Result<(), std::io::Error> {
9090 NockCommand::EvalGate { gate } => {
9191 let gate = read_nock(&gate).unwrap();
9292
93− let result = eval_pulled_gate(&generate_interpreter_context(), &gate).unwrap();
93+ let result = eval_pulled_gate(&mut generate_interpreter_context(), gate).unwrap();
9494
9595 println!("{result}");
9696 }
9797 NockCommand::Eval { nock } => {
9898 let nock = read_nock(&nock).unwrap();
9999
100− let ctx = generate_interpreter_context();
101− let result = eval_pulled_gate(&ctx, &nock).unwrap();
100+ let mut ctx = generate_interpreter_context();
101+ let result = eval_pulled_gate(&mut ctx, nock).unwrap();
102102
103103 println!("{result}");
104104 }
@@ -118,7 +118,7 @@ fn interact(gate_file: PathBuf) -> Result<(), std::io::Error> {
118118 let source = get_stdin().unwrap();
119119
120120 let mut spinner = new_spinner(String::from("Slamming gate..."));
121− let Some(slam) = slam(&generate_interpreter_context(), &gate, &source) else {
121+ let Some(slam) = slam(&mut generate_interpreter_context(), &gate, &source) else {
122122 spinner.fail("Gate execution failed");
123123 exit(1);
124124 };
@@ -163,7 +163,7 @@ fn compile(root: PathBuf, output: PathBuf) -> Result<(), std::io::Error> {
163163 let root_source = read_file(&root)?;
164164
165165 slam_pulled_gate(
166− &generate_interpreter_context(),
166+ &mut generate_interpreter_context(),
167167 &ream_gate,
168168 &Rc::new(Noun::Atom(Atom::from_bytes_le(&root_source))),
169169 )
@@ -185,7 +185,7 @@ fn compile(root: PathBuf, output: PathBuf) -> Result<(), std::io::Error> {
185185
186186 let mint_gate = cue_bytes(include_bytes!("../res/mint.nock"));
187187 let minted_ast =
188− slam_pulled_gate(&generate_interpreter_context(), &mint_gate, &root_ast).unwrap();
188+ slam_pulled_gate(&mut generate_interpreter_context(), &mint_gate, &ast).unwrap();
189189 let (_type, nock) = minted_ast.as_cell().unwrap();
190190
191191 let mut output_file = File::create(output)?;
nock/src/noun.rs+24−3
@@ -4,9 +4,12 @@ use num_bigint::BigUint;
44use std::fmt;
55use xxhash_rust::xxh3::xxh3_128;
66
7+use crate::jets::mum;
8+
79pub type Atom = BigUint;
810
911pub type Hash = u128;
12+pub type Mug = u32;
1013
1114#[derive(Clone, Debug, Eq)]
1215pub enum Noun {
@@ -15,6 +18,7 @@ pub enum Noun {
1518 p: Rc<Noun>,
1619 q: Rc<Noun>,
1720 hash: Cell<Option<Hash>>,
21+ mug: Cell<Option<Mug>>,
1822 },
1923}
2024
@@ -126,8 +130,8 @@ impl<'a> Noun {
126130
127131 pub fn hash(self: &Self) -> Hash {
128132 match self {
129− Noun::Cell { hash, p, q } => match hash.get() {
130− Some(x) => x.clone(),
133+ Noun::Cell { hash, p, q, .. } => match hash.get() {
134+ Some(x) => x,
131135 None => {
132136 let hash_value =
133137 stacker::maybe_grow(32 * 1024, 1024 * 1024, || hash_pair(p, q));
@@ -139,6 +143,22 @@ impl<'a> Noun {
139143 }
140144 }
141145
146+ pub fn mug(self: &Self) -> Mug {
147+ match self {
148+ Noun::Cell { mug, p, q, .. } => match mug.get() {
149+ Some(x) => x,
150+ None => {
151+ let mug_value = stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
152+ mum(0xDEADBEEF, 0xFFFE, &Atom::new(vec![p.mug(), q.mug()]))
153+ });
154+ mug.replace(Some(mug_value));
155+ mug_value
156+ }
157+ },
158+ Self::Atom(a) => mum(0xCAFEBABE, 0x7FFF, a),
159+ }
160+ }
161+
142162 /// returns the hash and the current sample
143163 pub fn hash_gate(self: &Self) -> (Hash, &Rc<Noun>) {
144164 let (battery, payload) = self.as_cell().unwrap();
@@ -323,7 +343,7 @@ fn write_noun(f: &mut fmt::Formatter, noun: &Noun, is_rhs: bool) -> fmt::Result
323343 }
324344 Noun::Atom(a) => {
325345 let atom_bytes = a.to_bytes_le();
326− if atom_bytes.len() > 1 && atom_bytes.into_iter().all(|c| (c > 33) && c < 126) {
346+ if atom_bytes.len() > 0 && atom_bytes.into_iter().all(|c| (c > 33) && c < 126) {
327347 f.write_char('%')?;
328348 let cord = unsafe { String::from_utf8_unchecked(a.to_bytes_le()) };
329349 f.write_str(&*cord)
@@ -355,6 +375,7 @@ pub fn naked_cell(p: &Rc<Noun>, q: &Rc<Noun>) -> Noun {
355375 p: p.clone(),
356376 q: q.clone(),
357377 hash: Cell::new(None),
378+ mug: Cell::new(None),
358379 }
359380}
360381