on master help sign in
nock/Cargo.lock+141−5
since splitsnapshots
unifiedsplit
@@ -1,6 +1,6 @@
1# This file is automatically @generated by Cargo.
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
2# It is not intended for manual editing.
3−version = 3
3+version = 4
4
4
5[[package]]
5[[package]]
6name = "anstream"
6name = "anstream"
@@ -63,6 +63,12 @@ version = "0.8.0"
63source = "registry+https://github.com/rust-lang/crates.io-index"
63source = "registry+https://github.com/rust-lang/crates.io-index"
64checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
64checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
65
65
66+[[package]]
67+name = "bitflags"
68+version = "2.6.0"
69+source = "registry+https://github.com/rust-lang/crates.io-index"
70+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
71+
66[[package]]
72[[package]]
67name = "bitter"
73name = "bitter"
68version = "0.7.0"
74version = "0.7.0"
@@ -87,6 +93,12 @@ version = "3.16.0"
87source = "registry+https://github.com/rust-lang/crates.io-index"
93source = "registry+https://github.com/rust-lang/crates.io-index"
88checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
94checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
89
95
96+[[package]]
97+name = "bytecount"
98+version = "0.6.8"
99+source = "registry+https://github.com/rust-lang/crates.io-index"
100+checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
101+
90[[package]]
102[[package]]
91name = "cc"
103name = "cc"
92version = "1.1.31"
104version = "1.1.31"
@@ -102,6 +114,12 @@ version = "1.0.0"
102source = "registry+https://github.com/rust-lang/crates.io-index"
114source = "registry+https://github.com/rust-lang/crates.io-index"
103checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
115checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
104
116
117+[[package]]
118+name = "cfg_aliases"
119+version = "0.2.1"
120+source = "registry+https://github.com/rust-lang/crates.io-index"
121+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
122+
105[[package]]
123[[package]]
106name = "clap"
124name = "clap"
107version = "4.5.20"
125version = "4.5.20"
@@ -130,10 +148,10 @@ version = "4.5.18"
130source = "registry+https://github.com/rust-lang/crates.io-index"
148source = "registry+https://github.com/rust-lang/crates.io-index"
131checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
149checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
132dependencies = [
150dependencies = [
133− "heck",
151+ "heck 0.5.0",
134 "proc-macro2",
152 "proc-macro2",
135 "quote",
153 "quote",
136− "syn",
154+ "syn 2.0.85",
137]
155]
138
156
139[[package]]
157[[package]]
@@ -158,6 +176,22 @@ dependencies = [
158 "windows-sys 0.48.0",
176 "windows-sys 0.48.0",
159]
177]
160
178
179+[[package]]
180+name = "ctrlc"
181+version = "3.4.5"
182+source = "registry+https://github.com/rust-lang/crates.io-index"
183+checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3"
184+dependencies = [
185+ "nix",
186+ "windows-sys 0.59.0",
187+]
188+
189+[[package]]
190+name = "fnv"
191+version = "1.0.7"
192+source = "registry+https://github.com/rust-lang/crates.io-index"
193+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
194+
161[[package]]
195[[package]]
162name = "fplist"
196name = "fplist"
163version = "0.2.1"
197version = "0.2.1"
@@ -170,6 +204,12 @@ version = "2.0.0"
170source = "registry+https://github.com/rust-lang/crates.io-index"
204source = "registry+https://github.com/rust-lang/crates.io-index"
171checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
205checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
172
206
207+[[package]]
208+name = "heck"
209+version = "0.4.1"
210+source = "registry+https://github.com/rust-lang/crates.io-index"
211+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
212+
173[[package]]
213[[package]]
174name = "heck"
214name = "heck"
175version = "0.5.0"
215version = "0.5.0"
@@ -215,6 +255,18 @@ version = "0.5.2"
215source = "registry+https://github.com/rust-lang/crates.io-index"
255source = "registry+https://github.com/rust-lang/crates.io-index"
216checksum = "9252111cf132ba0929b6f8e030cac2a24b507f3a4d6db6fb2896f27b354c714b"
256checksum = "9252111cf132ba0929b6f8e030cac2a24b507f3a4d6db6fb2896f27b354c714b"
217
257
258+[[package]]
259+name = "nix"
260+version = "0.29.0"
261+source = "registry+https://github.com/rust-lang/crates.io-index"
262+checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
263+dependencies = [
264+ "bitflags",
265+ "cfg-if",
266+ "cfg_aliases",
267+ "libc",
268+]
269+
218[[package]]
270[[package]]
219name = "nock"
271name = "nock"
220version = "0.1.0"
272version = "0.1.0"
@@ -223,13 +275,16 @@ dependencies = [
223 "bitter",
275 "bitter",
224 "bitvec",
276 "bitvec",
225 "clap",
277 "clap",
278+ "ctrlc",
226 "fplist",
279 "fplist",
280+ "lazy_static",
227 "murmur3",
281 "murmur3",
228 "num-bigint",
282 "num-bigint",
229 "num-integer",
283 "num-integer",
230 "num-traits",
284 "num-traits",
231 "spinoff",
285 "spinoff",
232 "stacker",
286 "stacker",
287+ "tabled",
233 "web-sys",
288 "web-sys",
234 "xxhash-rust",
289 "xxhash-rust",
235]
290]
@@ -268,12 +323,47 @@ version = "1.20.2"
268source = "registry+https://github.com/rust-lang/crates.io-index"
323source = "registry+https://github.com/rust-lang/crates.io-index"
269checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
324checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
270
325
326+[[package]]
327+name = "papergrid"
328+version = "0.12.0"
329+source = "registry+https://github.com/rust-lang/crates.io-index"
330+checksum = "c7419ad52a7de9b60d33e11085a0fe3df1fbd5926aa3f93d3dd53afbc9e86725"
331+dependencies = [
332+ "bytecount",
333+ "fnv",
334+ "unicode-width",
335+]
336+
271[[package]]
337[[package]]
272name = "paste"
338name = "paste"
273version = "1.0.15"
339version = "1.0.15"
274source = "registry+https://github.com/rust-lang/crates.io-index"
340source = "registry+https://github.com/rust-lang/crates.io-index"
275checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
341checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
276
342
343+[[package]]
344+name = "proc-macro-error"
345+version = "1.0.4"
346+source = "registry+https://github.com/rust-lang/crates.io-index"
347+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
348+dependencies = [
349+ "proc-macro-error-attr",
350+ "proc-macro2",
351+ "quote",
352+ "syn 1.0.109",
353+ "version_check",
354+]
355+
356+[[package]]
357+name = "proc-macro-error-attr"
358+version = "1.0.4"
359+source = "registry+https://github.com/rust-lang/crates.io-index"
360+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
361+dependencies = [
362+ "proc-macro2",
363+ "quote",
364+ "version_check",
365+]
366+
277[[package]]
367[[package]]
278name = "proc-macro2"
368name = "proc-macro2"
279version = "1.0.89"
369version = "1.0.89"
@@ -343,6 +433,17 @@ version = "0.11.1"
343source = "registry+https://github.com/rust-lang/crates.io-index"
433source = "registry+https://github.com/rust-lang/crates.io-index"
344checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
434checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
345
435
436+[[package]]
437+name = "syn"
438+version = "1.0.109"
439+source = "registry+https://github.com/rust-lang/crates.io-index"
440+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
441+dependencies = [
442+ "proc-macro2",
443+ "quote",
444+ "unicode-ident",
445+]
446+
346[[package]]
447[[package]]
347name = "syn"
448name = "syn"
348version = "2.0.85"
449version = "2.0.85"
@@ -354,6 +455,29 @@ dependencies = [
354 "unicode-ident",
455 "unicode-ident",
355]
456]
356
457
458+[[package]]
459+name = "tabled"
460+version = "0.16.0"
461+source = "registry+https://github.com/rust-lang/crates.io-index"
462+checksum = "77c9303ee60b9bedf722012ea29ae3711ba13a67c9b9ae28993838b63057cb1b"
463+dependencies = [
464+ "papergrid",
465+ "tabled_derive",
466+]
467+
468+[[package]]
469+name = "tabled_derive"
470+version = "0.8.0"
471+source = "registry+https://github.com/rust-lang/crates.io-index"
472+checksum = "bf0fb8bfdc709786c154e24a66777493fb63ae97e3036d914c8666774c477069"
473+dependencies = [
474+ "heck 0.4.1",
475+ "proc-macro-error",
476+ "proc-macro2",
477+ "quote",
478+ "syn 1.0.109",
479+]
480+
357[[package]]
481[[package]]
358name = "tap"
482name = "tap"
359version = "1.0.1"
483version = "1.0.1"
@@ -366,12 +490,24 @@ version = "1.0.13"
366source = "registry+https://github.com/rust-lang/crates.io-index"
490source = "registry+https://github.com/rust-lang/crates.io-index"
367checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
491checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
368
492
493+[[package]]
494+name = "unicode-width"
495+version = "0.1.11"
496+source = "registry+https://github.com/rust-lang/crates.io-index"
497+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
498+
369[[package]]
499[[package]]
370name = "utf8parse"
500name = "utf8parse"
371version = "0.2.2"
501version = "0.2.2"
372source = "registry+https://github.com/rust-lang/crates.io-index"
502source = "registry+https://github.com/rust-lang/crates.io-index"
373checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
503checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
374
504
505+[[package]]
506+name = "version_check"
507+version = "0.9.5"
508+source = "registry+https://github.com/rust-lang/crates.io-index"
509+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
510+
375[[package]]
511[[package]]
376name = "wasm-bindgen"
512name = "wasm-bindgen"
377version = "0.2.95"
513version = "0.2.95"
@@ -394,7 +530,7 @@ dependencies = [
394 "once_cell",
530 "once_cell",
395 "proc-macro2",
531 "proc-macro2",
396 "quote",
532 "quote",
397− "syn",
533+ "syn 2.0.85",
398 "wasm-bindgen-shared",
534 "wasm-bindgen-shared",
399]
535]
400
536
@@ -416,7 +552,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
416dependencies = [
552dependencies = [
417 "proc-macro2",
553 "proc-macro2",
418 "quote",
554 "quote",
419− "syn",
555+ "syn 2.0.85",
420 "wasm-bindgen-backend",
556 "wasm-bindgen-backend",
421 "wasm-bindgen-shared",
557 "wasm-bindgen-shared",
422]
558]
nock/Cargo.toml+7
@@ -17,6 +17,9 @@ stacker = "0.1.17"
17murmur3 = "0.5.2"
17murmur3 = "0.5.2"
18web-sys = "0.3.70"
18web-sys = "0.3.70"
19fplist = "0.2.1"
19fplist = "0.2.1"
20+ctrlc = "3.4.5"
21+lazy_static = "1.5.0"
22+tabled = "0.16.0"
20
23
21[dependencies.xxhash-rust]
24[dependencies.xxhash-rust]
22version = "0.8.5"
25version = "0.8.5"
@@ -26,6 +29,9 @@ features = ["xxh3"]
26# Tell `rustc` to optimize for small code size.
29# Tell `rustc` to optimize for small code size.
27opt-level = 3
30opt-level = 3
28
31
32+[features]
33+count-jets = []
34+
29[[bin]]
35[[bin]]
30name = "nock"
36name = "nock"
31path = "src/main.rs"
37path = "src/main.rs"
@@ -33,3 +39,4 @@ path = "src/main.rs"
33[[bin]]
39[[bin]]
34name = "hash-gate"
40name = "hash-gate"
35path = "src/hash-gate.rs"
41path = "src/hash-gate.rs"
42+
nock/hello.hoon+2−1
@@ -1,5 +1,6 @@
1|= name=@t
1|= name=@t
2+~& name
2?+ name (crip (weld "Hello, " (trip name)))
3?+ name (crip (weld "Hello, " (trip name)))
3 'Curtis' 'Hello, daddy...'
4 'Curtis' 'Hello, daddy...'
4− '' 'Hello, world!'
5+ %'' 'Hello, world!'
5==
6==
nock/hello.nock

Binary file not shown.

nock/src/interpreter.rs+225−54
@@ -1,14 +1,23 @@
1+use core::str;
1use std::borrow::Borrow;
2use std::borrow::Borrow;
2use std::collections::BTreeMap;
3use std::collections::BTreeMap;
4+use std::collections::HashMap;
3use std::rc::Rc;
5use std::rc::Rc;
6+use std::sync::Mutex;
4
7
5use fplist::cons;
8use fplist::cons;
6use fplist::PersistentList;
9use fplist::PersistentList;
10+use lazy_static::lazy_static;
7use num_bigint::BigUint;
11use num_bigint::BigUint;
8
12
9use crate::jets::*;
13use crate::jets::*;
10use crate::noun::*;
14use crate::noun::*;
11
15
16+// #[cfg(feature = "count-jets")]
17+lazy_static! {
18+ pub static ref JET_COUNTER: Mutex<HashMap<Atom, u32>> = Mutex::new(HashMap::new());
19+}
20+
12#[derive(Clone)]
21#[derive(Clone)]
13pub struct Nouns {
22pub struct Nouns {
14 pub y: Rc<Noun>,
23 pub y: Rc<Noun>,
@@ -22,6 +31,8 @@ pub struct Nouns {
22 pub two_three: Rc<Noun>,
31 pub two_three: Rc<Noun>,
23 pub memo: Rc<Noun>,
32 pub memo: Rc<Noun>,
24 pub mean: Rc<Noun>,
33 pub mean: Rc<Noun>,
34+ pub slog: Rc<Noun>,
35+ pub fast: Rc<Noun>,
25}
36}
26
37
27#[derive(Clone)]
38#[derive(Clone)]
@@ -40,6 +51,7 @@ pub struct InterpreterContext {
40 pub nouns: Nouns,
51 pub nouns: Nouns,
41 pub big_uints: BigUints,
52 pub big_uints: BigUints,
42 pub memo: BTreeMap<Hash, Rc<Noun>>,
53 pub memo: BTreeMap<Hash, Rc<Noun>>,
54+ pub slog: fn(&String) -> (),
43}
55}
44
56
45pub fn generate_interpreter_context() -> InterpreterContext {
57pub fn generate_interpreter_context() -> InterpreterContext {
@@ -61,6 +73,8 @@ pub fn generate_interpreter_context() -> InterpreterContext {
61 let two_three = cell(&two, &three);
73 let two_three = cell(&two, &three);
62 let memo = Rc::new(Noun::from_bytes(b"memo"));
74 let memo = Rc::new(Noun::from_bytes(b"memo"));
63 let mean = Rc::new(Noun::from_bytes(b"mean"));
75 let mean = Rc::new(Noun::from_bytes(b"mean"));
76+ let slog = Rc::new(Noun::from_bytes(b"slog"));
77+ let fast = Rc::new(Noun::from_bytes(b"fast"));
64 InterpreterContext {
78 InterpreterContext {
65 jets,
79 jets,
66 double_jets,
80 double_jets,
@@ -76,9 +90,12 @@ pub fn generate_interpreter_context() -> InterpreterContext {
76 two_three,
90 two_three,
77 memo,
91 memo,
78 mean,
92 mean,
93+ slog,
94+ fast,
79 },
95 },
80 big_uints,
96 big_uints,
81 memo: BTreeMap::new(),
97 memo: BTreeMap::new(),
98+ slog: |str: &String| eprintln!("{}", str),
82 }
99 }
83}
100}
84
101
@@ -89,7 +106,7 @@ fn wut<'a>(ctx: &'a InterpreterContext, noun: &Noun) -> &'a Rc<Noun> {
89 }
106 }
90}
107}
91
108
92−fn lus(noun: &Noun) -> Result<Noun, Tanks> {
109+fn lus(noun: &Noun) -> Result<Noun, TTanks> {
93 match noun {
110 match noun {
94 Noun::Cell { .. } => Err(PersistentList::new()),
111 Noun::Cell { .. } => Err(PersistentList::new()),
95 Noun::Atom(atm) => Ok(Noun::Atom(atm + 1u32)),
112 Noun::Atom(atm) => Ok(Noun::Atom(atm + 1u32)),
@@ -104,7 +121,7 @@ fn tis<'a>(ctx: &'a InterpreterContext, lhs: &Noun, rhs: &Noun) -> &'a Rc<Noun>
104 }
121 }
105}
122}
106
123
107−fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Result<Rc<Noun>, Tanks> {
124+fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Result<Rc<Noun>, TTanks> {
108 let mut addr_iter = addr.iter_u32_digits();
125 let mut addr_iter = addr.iter_u32_digits();
109
126
110 match (addr_iter.next(), addr_iter.next()) {
127 match (addr_iter.next(), addr_iter.next()) {
@@ -124,7 +141,7 @@ fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Result<Rc<Noun>, T
124 }
141 }
125}
142}
126
143
127−fn fas_u32(addr: u32, noun: &Noun) -> Result<Rc<Noun>, Tanks> {
144+fn fas_u32(addr: u32, noun: &Noun) -> Result<Rc<Noun>, TTanks> {
128 match addr {
145 match addr {
129 0 => Err(PersistentList::new()),
146 0 => Err(PersistentList::new()),
130 1 => Ok(Rc::new(noun.clone())),
147 1 => Ok(Rc::new(noun.clone())),
@@ -142,7 +159,7 @@ fn fas_u32(addr: u32, noun: &Noun) -> Result<Rc<Noun>, Tanks> {
142 }
159 }
143}
160}
144
161
145−fn hax_u32(addr: u32, new_value: &Rc<Noun>, target: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
162+fn hax_u32(addr: u32, new_value: &Rc<Noun>, target: &Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
146 match addr {
163 match addr {
147 0 => Err(PersistentList::new()),
164 0 => Err(PersistentList::new()),
148 1 => Ok(new_value.clone()),
165 1 => Ok(new_value.clone()),
@@ -164,11 +181,11 @@ fn hax(
164 addr: &Atom,
181 addr: &Atom,
165 new_value: &Rc<Noun>,
182 new_value: &Rc<Noun>,
166 target: &Rc<Noun>,
183 target: &Rc<Noun>,
167−) -> Result<Rc<Noun>, Tanks> {
184+) -> Result<Rc<Noun>, TTanks> {
168 let mut addr_iter = addr.iter_u32_digits();
185 let mut addr_iter = addr.iter_u32_digits();
169
186
170 match (addr_iter.next(), addr_iter.next()) {
187 match (addr_iter.next(), addr_iter.next()) {
171− (None, _) => Err(Tanks::new()),
188+ (None, _) => Err(TTanks::new()),
172 (Some(x), None) => hax_u32(x, new_value, target),
189 (Some(x), None) => hax_u32(x, new_value, target),
173 _ => hax(
190 _ => hax(
174 ctx,
191 ctx,
@@ -187,18 +204,18 @@ fn hax(
187
204
188fn tar_u32<'a>(
205fn tar_u32<'a>(
189 ctx: &mut InterpreterContext,
206 ctx: &mut InterpreterContext,
190− subj: Rc<Noun>,
207+ subj: &'a Rc<Noun>,
191 op: u32,
208 op: u32,
192 formula: &'a Rc<Noun>,
209 formula: &'a Rc<Noun>,
193−) -> Result<Rc<Noun>, Tanks> {
210+) -> Result<Rc<Noun>, TTanks> {
194 match op {
211 match op {
195 0 => {
212 0 => {
196− let b = formula.as_atom().ok_or(Tanks::new())?;
213+ let b = formula.as_atom().ok_or(TTanks::new())?;
197 fas(ctx, b, &*subj)
214 fas(ctx, b, &*subj)
198 }
215 }
199 1 => Ok(formula.clone()),
216 1 => Ok(formula.clone()),
200 2 => {
217 2 => {
201− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
218+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
202
219
203 match c.borrow() {
220 match c.borrow() {
204 Noun::Cell { p, q, .. }
221 Noun::Cell { p, q, .. }
@@ -210,16 +227,16 @@ fn tar_u32<'a>(
210 match ctx.jets.get(&hash) {
227 match ctx.jets.get(&hash) {
211 Some(f) => f(ctx, sample),
228 Some(f) => f(ctx, sample),
212 None => {
229 None => {
213− let foo = tar(ctx, subj.clone(), &b)?;
230+ let foo = tar(ctx, subj, &b)?;
214 let bar = tar(ctx, subj, &c)?;
231 let bar = tar(ctx, subj, &c)?;
215− tar(ctx, foo, &bar)
232+ tar(ctx, &foo, &bar)
216 }
233 }
217 }
234 }
218 }
235 }
219 _ => {
236 _ => {
220− let foo = tar(ctx, subj.clone(), &b)?;
237+ let foo = tar(ctx, subj, &b)?;
221 let bar = tar(ctx, subj, &c)?;
238 let bar = tar(ctx, subj, &c)?;
222− tar(ctx, foo, &bar)
239+ tar(ctx, &foo, &bar)
223 }
240 }
224 }
241 }
225 }
242 }
@@ -229,57 +246,57 @@ fn tar_u32<'a>(
229 }
246 }
230 4 => Ok(Rc::new(lus(&*tar(ctx, subj, &formula)?)?)),
247 4 => Ok(Rc::new(lus(&*tar(ctx, subj, &formula)?)?)),
231 5 => {
248 5 => {
232− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
249+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
233− let foo = tar(ctx, subj.clone(), &b)?;
250+ let foo = tar(ctx, subj, &b)?;
234 let bar = tar(ctx, subj, &c)?;
251 let bar = tar(ctx, subj, &c)?;
235 Ok(tis(ctx, &foo, &bar).clone())
252 Ok(tis(ctx, &foo, &bar).clone())
236 }
253 }
237 6 => {
254 6 => {
238− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
255+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
239− let (c, d) = c.as_cell().ok_or(Tanks::new())?;
256+ let (c, d) = c.as_cell().ok_or(TTanks::new())?;
240
257
241− 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))?;
242
259
243− let foo = tar_u32(ctx, ctx.nouns.two_three.clone(), 0, &bar)?;
260+ let foo = tar_u32(ctx, &ctx.nouns.two_three.clone(), 0, &bar)?;
244− let foo = tar_u32(ctx, cell(&c, &d), 0, &foo)?;
261+ let foo = tar_u32(ctx, &cell(&c, &d), 0, &foo)?;
245
262
246 tar(ctx, subj, &foo)
263 tar(ctx, subj, &foo)
247 }
264 }
248 7 => {
265 7 => {
249− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
266+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
250 let foo = tar(ctx, subj, &b)?;
267 let foo = tar(ctx, subj, &b)?;
251− tar(ctx, foo, &c)
268+ tar(ctx, &foo, &c)
252 }
269 }
253 8 => {
270 8 => {
254− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
271+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
255− let foo = tar(ctx, subj.clone(), &b)?;
272+ let foo = tar(ctx, subj, &b)?;
256− tar(ctx, cell(&foo, &subj), &c)
273+ tar(ctx, &cell(&foo, &subj), &c)
257 }
274 }
258 9 => {
275 9 => {
259− let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
276+ let (b, c) = formula.as_cell().ok_or(TTanks::new())?;
260 let foo = tar(ctx, subj, &c)?;
277 let foo = tar(ctx, subj, &c)?;
261 tar_u32(
278 tar_u32(
262 ctx,
279 ctx,
263− foo,
280+ &foo,
264 2,
281 2,
265 &cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
282 &cell(&ctx.nouns.sig_one, &cell(&ctx.nouns.sig, &b)),
266 )
283 )
267 }
284 }
268 10 => {
285 10 => {
269− let (b, d) = formula.as_cell().ok_or(Tanks::new())?;
286+ let (b, d) = formula.as_cell().ok_or(TTanks::new())?;
270− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
287+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
271− let b = b.as_atom().ok_or(Tanks::new())?;
288+ let b = b.as_atom().ok_or(TTanks::new())?;
272
289
273− let foo = tar(ctx, subj.clone(), &c)?;
290+ let foo = tar(ctx, subj, &c)?;
274 let bar = tar(ctx, subj, &d)?;
291 let bar = tar(ctx, subj, &d)?;
275 hax(ctx, b, &foo, &bar)
292 hax(ctx, b, &foo, &bar)
276 }
293 }
277 11 => {
294 11 => {
278− let (b, d) = formula.as_cell().ok_or(Tanks::new())?;
295+ let (b, d) = formula.as_cell().ok_or(TTanks::new())?;
279 match b.borrow() {
296 match b.borrow() {
280 Noun::Atom(_) => tar(ctx, subj, &d),
297 Noun::Atom(_) => tar(ctx, subj, &d),
281 Noun::Cell { p, q, .. } => {
298 Noun::Cell { p, q, .. } => {
282− let eval = |ctx: &mut InterpreterContext| tar(ctx, subj.clone(), &d);
299+ let eval = |ctx: &mut InterpreterContext| tar(ctx, subj, &d);
283 if *p == ctx.nouns.memo {
300 if *p == ctx.nouns.memo {
284 let hash = cell(&subj, &d).hash();
301 let hash = cell(&subj, &d).hash();
285 match ctx.memo.get(&hash) {
302 match ctx.memo.get(&hash) {
@@ -292,37 +309,188 @@ fn tar_u32<'a>(
292 }
309 }
293 } else if *p == ctx.nouns.mean {
310 } else if *p == ctx.nouns.mean {
294 with_trace((subj.clone(), q.clone()), eval(ctx))
311 with_trace((subj.clone(), q.clone()), eval(ctx))
312+ } else if *p == ctx.nouns.slog {
313+ let noun = tar(ctx, subj, &q)?;
314+ let (_prio, tank) = noun.as_cell().ok_or(TTanks::new())?;
315+
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+ }
339+ eval(ctx)
295 } else {
340 } else {
296 eval(ctx)
341 eval(ctx)
297 }
342 }
298 }
343 }
299 }
344 }
300 }
345 }
301− _ => Err(Tanks::new()),
346+ _ => Err(TTanks::new()),
302 }
347 }
303}
348}
304
349
350+fn ram(ctx: &mut InterpreterContext, tank: Rc<Noun>) -> Option<String> {
351+ match tank.borrow() {
352+ Noun::Atom(str) => {
353+ let mut bytes = str.to_bytes_le();
354+ Some(String::from(str::from_utf8_mut(&mut bytes).ok()?))
355+ }
356+ Noun::Cell { p, q, .. } => {
357+ let tag = p.as_atom()?.to_bytes_le();
358+ if tag == b"leaf" {
359+ let mut bytes = crip(ctx, q.clone()).ok()?.as_bytes()?;
360+ Some(String::from(str::from_utf8_mut(&mut bytes).ok()?))
361+ } else if tag == b"palm" {
362+ let (spacers, tanks) = q.as_cell()?;
363+ let (mid, open, flat_open, close) = spacers.tuple_4()?;
364+
365+ let mut mid = crip(ctx, mid.clone()).ok()?.as_bytes()?;
366+ let mid = String::from(str::from_utf8_mut(&mut mid).ok()?);
367+
368+ let mut open = crip(ctx, open.clone()).ok()?.as_bytes()?;
369+ let open = String::from(str::from_utf8_mut(&mut open).ok()?);
370+
371+ let mut flat_open = crip(ctx, flat_open.clone()).ok()?.as_bytes()?;
372+ let flat_open = String::from(str::from_utf8_mut(&mut flat_open).ok()?);
373+
374+ let mut close = crip(ctx, close.clone()).ok()?.as_bytes()?;
375+ let close = String::from(str::from_utf8_mut(&mut close).ok()?);
376+
377+ let mut target = String::new();
378+
379+ target.push_str(&*open);
380+ target.push_str(&*flat_open);
381+
382+ let mut is_first = true;
383+ for tank in tanks.list_iter() {
384+ if !is_first {
385+ target.push_str(&*mid);
386+ }
387+
388+ target.push_str(&*(ram(ctx, tank.clone())?));
389+
390+ is_first = false;
391+ }
392+
393+ target.push_str(&*close);
394+
395+ Some(target)
396+ } else if tag == b"rose" {
397+ let (spacers, tanks) = q.as_cell()?;
398+ let (mid, open, close) = spacers.tuple_3()?;
399+
400+ let mut mid = crip(ctx, mid.clone()).ok()?.as_bytes()?;
401+ let mid = String::from(str::from_utf8_mut(&mut mid).ok()?);
402+
403+ let mut open = crip(ctx, open.clone()).ok()?.as_bytes()?;
404+ let open = String::from(str::from_utf8_mut(&mut open).ok()?);
405+
406+ let mut close = crip(ctx, close.clone()).ok()?.as_bytes()?;
407+ let close = String::from(str::from_utf8_mut(&mut close).ok()?);
408+
409+ let mut target = String::new();
410+
411+ target.push_str(&*open);
412+
413+ let mut is_first = true;
414+ for tank in tanks.list_iter() {
415+ if !is_first {
416+ target.push_str(&*mid);
417+ }
418+
419+ target.push_str(&*(ram(ctx, tank.clone())?));
420+
421+ is_first = false;
422+ }
423+
424+ target.push_str(&*close);
425+
426+ Some(target)
427+ } else {
428+ None
429+ }
430+ }
431+ }
432+}
433+
434+pub fn ram_ttanks(ctx: &mut InterpreterContext, tanks: TTanks) -> String {
435+ let mut target = String::new();
436+
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+
443+ target.push_str(&*ram_ttank(ctx, tank.clone()));
444+
445+ first = false;
446+ }
447+
448+ target
449+}
450+
451+pub fn ram_ttank(ctx: &mut InterpreterContext, ttank: TTank) -> String {
452+ let (subj, q) = ttank;
453+
454+ let tank = match tar(ctx, &subj, &q) {
455+ Ok(gate) => match eval_pulled_gate(ctx, gate) {
456+ Ok(tank) => tank,
457+ Err(_) => {
458+ return String::new();
459+ }
460+ },
461+ Err(_) => {
462+ return String::new();
463+ }
464+ };
465+ ram(ctx, tank).unwrap_or(String::new())
466+}
467+
468+pub fn crip(ctx: &mut InterpreterContext, tape: Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
469+ RAP(ctx, &cell(&Rc::new(Noun::from_u32(3)), &tape))
470+}
471+
305−fn with_trace<T>(tank: (Rc<Noun>, Rc<Noun>), src: Result<T, Tanks>) -> Result<T, Tanks> {
472+fn with_trace<T>(tank: (Rc<Noun>, Rc<Noun>), src: Result<T, TTanks>) -> Result<T, TTanks> {
306 match src {
473 match src {
307 Ok(a) => Ok(a),
474 Ok(a) => Ok(a),
308 Err(tanks) => Err(cons(tank, tanks)),
475 Err(tanks) => Err(cons(tank, tanks)),
309 }
476 }
310}
477}
311
478
479+/// Not actually a tank, but rather a thunk (subject, formula) which calculates the tank.
312−pub type Tank = Rc<Noun>;
480+pub type TTank = (Rc<Noun>, Rc<Noun>);
313−pub type Tanks = PersistentList<(Rc<Noun>, Rc<Noun>)>;
481+pub type TTanks = PersistentList<TTank>;
314
482
315−pub const EMPTY_TANKS: Tanks = Tanks::new();
483+pub const EMPTY_TANKS: TTanks = TTanks::new();
316
484
317pub fn tar<'a>(
485pub fn tar<'a>(
318 ctx: &mut InterpreterContext,
486 ctx: &mut InterpreterContext,
319− subj: Rc<Noun>,
487+ subj: &'a Rc<Noun>,
320 formula: &'a Noun,
488 formula: &'a Noun,
321−) -> Result<Rc<Noun>, Tanks> {
489+) -> Result<Rc<Noun>, TTanks> {
322− let (op, formula) = formula.as_cell().ok_or(Tanks::new())?;
490+ let (op, formula) = formula.as_cell().ok_or(TTanks::new())?;
323 match op.borrow() {
491 match op.borrow() {
324 Noun::Cell { .. } => {
492 Noun::Cell { .. } => {
325− let foo = tar(ctx, subj.clone(), &op)?;
493+ let foo = tar(ctx, subj, &op)?;
326 let bar = tar(ctx, subj, &formula)?;
494 let bar = tar(ctx, subj, &formula)?;
327 Ok(cell(&foo, &bar))
495 Ok(cell(&foo, &bar))
328 }
496 }
@@ -333,14 +501,17 @@ pub fn tar<'a>(
333 1 => Some(op_iter.next().unwrap()),
501 1 => Some(op_iter.next().unwrap()),
334 _ => None,
502 _ => None,
335 };
503 };
336− let op = op.ok_or(Tanks::new())?;
504+ let op = op.ok_or(TTanks::new())?;
337 stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, subj, op, formula))
505 stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, subj, op, formula))
338 }
506 }
339 }
507 }
340}
508}
341
509
510+pub fn eval_gate(
342−pub fn eval_gate(ctx: &mut InterpreterContext, gate_factory: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
511+ ctx: &mut InterpreterContext,
512+ gate_factory: &Rc<Noun>,
513+) -> Result<Rc<Noun>, TTanks> {
343− let pulled_gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
514+ let pulled_gate = tar(ctx, &ctx.nouns.sig.clone(), &gate_factory)?;
344 eval_pulled_gate(ctx, pulled_gate)
515 eval_pulled_gate(ctx, pulled_gate)
345}
516}
346
517
@@ -348,18 +519,18 @@ pub fn slam(
348 ctx: &mut InterpreterContext,
519 ctx: &mut InterpreterContext,
349 gate_factory: &Rc<Noun>,
520 gate_factory: &Rc<Noun>,
350 sample: &Rc<Noun>,
521 sample: &Rc<Noun>,
351−) -> Result<Rc<Noun>, Tanks> {
522+) -> Result<Rc<Noun>, TTanks> {
352− let gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
523+ let gate = tar(ctx, &ctx.nouns.sig.clone(), &gate_factory)?;
353
524
354 eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
525 eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
355}
526}
356
527
357/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
528/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
358/// Also for calling gates from within jets.
529/// Also for calling gates from within jets.
359−pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
530+pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
360 tar(
531 tar(
361 ctx,
532 ctx,
362− gate,
533+ &gate,
363 &cell(
534 &cell(
364 &Rc::new(Noun::Atom(BigUint::new(vec![9]))),
535 &Rc::new(Noun::Atom(BigUint::new(vec![9]))),
365 &cell(&ctx.nouns.two, &cell(&ctx.nouns.sig, &ctx.nouns.one)),
536 &cell(&ctx.nouns.two, &cell(&ctx.nouns.sig, &ctx.nouns.one)),
@@ -373,13 +544,13 @@ pub fn slam_pulled_gate(
373 ctx: &mut InterpreterContext,
544 ctx: &mut InterpreterContext,
374 gate: &Rc<Noun>,
545 gate: &Rc<Noun>,
375 sample: &Rc<Noun>,
546 sample: &Rc<Noun>,
376−) -> Result<Rc<Noun>, Tanks> {
547+) -> Result<Rc<Noun>, TTanks> {
377 eval_pulled_gate(ctx, replace_sample(gate, sample)?)
548 eval_pulled_gate(ctx, replace_sample(gate, sample)?)
378}
549}
379
550
380−pub fn replace_sample(gate: &Rc<Noun>, sample: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
551+pub fn replace_sample(gate: &Rc<Noun>, sample: &Rc<Noun>) -> Result<Rc<Noun>, TTanks> {
381− let (battery, payload) = gate.as_cell().ok_or(Tanks::new())?;
552+ let (battery, payload) = gate.as_cell().ok_or(TTanks::new())?;
382− let (_sample, context) = payload.as_cell().ok_or(Tanks::new())?;
553+ let (_sample, context) = payload.as_cell().ok_or(TTanks::new())?;
383
554
384 Ok(cell(battery, &cell(sample, context)))
555 Ok(cell(battery, &cell(sample, context)))
385}
556}
nock/src/jets.rs+304−129
@@ -2,14 +2,15 @@ use core::panic;
2use murmur3::murmur3_32;
2use murmur3::murmur3_32;
3use num_integer::Integer;
3use num_integer::Integer;
4use std::{
4use std::{
5+ borrow::Borrow,
5 collections::BTreeMap,
6 collections::BTreeMap,
6 iter::{once, repeat_n, zip},
7 iter::{once, repeat_n, zip},
7 rc::Rc,
8 rc::Rc,
8};
9};
9
10
10use crate::{
11use crate::{
11− interpreter::{slam_pulled_gate, InterpreterContext, Tanks},
12+ interpreter::{slam_pulled_gate, InterpreterContext, TTanks, EMPTY_TANKS},
12− noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
13+ noun::{self, cell, AsNoun, Atom, Edge, Hair, Nail, Noun},
13};
14};
14
15
15fn traverse_iter_result<E: Clone, T: Clone, I: Iterator<Item = Result<T, E>>>(
16fn traverse_iter_result<E: Clone, T: Clone, I: Iterator<Item = Result<T, E>>>(
@@ -107,18 +108,23 @@ pub fn generate_jets() -> Jets {
107 (124976064672625230427889101290245200507, TRIP),
108 (124976064672625230427889101290245200507, TRIP),
108 (4078279288073906183633157465551067635, MUK),
109 (4078279288073906183633157465551067635, MUK),
109 (261900159748071234702685239353558471892, MUG),
110 (261900159748071234702685239353558471892, MUG),
111+ (198191257620924788695943358402651905954, AOR),
112+ (299422828284010240628877806738195667652, DOR),
113+ (166326796552601297695313176538120818632, GOR),
114+ (7942398240152905363972500667649380756, MOR),
115+ (315687984998079865981003916817293521765, LOOK),
110 ])
116 ])
111}
117}
112
118
113−pub type Jet = fn(ctx: &mut InterpreterContext, &Rc<Noun>) -> Result<Rc<Noun>, Tanks>;
119+pub type Jet = fn(ctx: &mut InterpreterContext, &Rc<Noun>) -> Result<Rc<Noun>, TTanks>;
114pub type DoubleJet = fn(ctx: &mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
120pub type DoubleJet = fn(ctx: &mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
115
121
116−static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Result<Rc<Noun>, Tanks> =
122+static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Result<Rc<Noun>, TTanks> =
117 |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
123 |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
118− let (p, q) = n.as_cell().ok_or(Tanks::new())?;
124+ let (p, q) = n.as_cell().ok_or(TTanks::new())?;
119 Ok(Rc::new(Noun::Atom(f(
125 Ok(Rc::new(Noun::Atom(f(
120− p.as_atom().ok_or(Tanks::new())?,
126+ p.as_atom().ok_or(TTanks::new())?,
121− q.as_atom().ok_or(Tanks::new())?,
127+ q.as_atom().ok_or(TTanks::new())?,
122 ))))
128 ))))
123 };
129 };
124
130
@@ -126,13 +132,13 @@ static BINARY_ATOM_LOOB: fn(
126 &InterpreterContext,
132 &InterpreterContext,
127 &Rc<Noun>,
133 &Rc<Noun>,
128 fn(&Atom, &Atom) -> bool,
134 fn(&Atom, &Atom) -> bool,
129−) -> Result<Rc<Noun>, Tanks> =
135+) -> Result<Rc<Noun>, TTanks> =
130 |ctx: &InterpreterContext, n: &Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
136 |ctx: &InterpreterContext, n: &Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
131− let (p, q) = n.as_cell().ok_or(Tanks::new())?;
137+ let (p, q) = n.as_cell().ok_or(TTanks::new())?;
132
138
133 if f(
139 if f(
134− p.as_atom().ok_or(Tanks::new())?,
140+ p.as_atom().ok_or(TTanks::new())?,
135− q.as_atom().ok_or(Tanks::new())?,
141+ q.as_atom().ok_or(TTanks::new())?,
136 ) {
142 ) {
137 Ok(ctx.nouns.sig.clone())
143 Ok(ctx.nouns.sig.clone())
138 } else {
144 } else {
@@ -143,18 +149,22 @@ static BINARY_ATOM_LOOB: fn(
143static BINARY_ATOM_PAIR: fn(
149static BINARY_ATOM_PAIR: fn(
144 &Rc<Noun>,
150 &Rc<Noun>,
145 fn(&Atom, &Atom) -> (Atom, Atom),
151 fn(&Atom, &Atom) -> (Atom, Atom),
146−) -> Result<Rc<Noun>, Tanks> = |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
152+) -> Result<Rc<Noun>, TTanks> = |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
147− let (p, q) = n.as_cell().ok_or(Tanks::new())?;
153+ let (p, q) = n.as_cell().ok_or(TTanks::new())?;
148
154
149 let (a, b) = f(
155 let (a, b) = f(
150− p.as_atom().ok_or(Tanks::new())?,
156+ p.as_atom().ok_or(TTanks::new())?,
151− q.as_atom().ok_or(Tanks::new())?,
157+ q.as_atom().ok_or(TTanks::new())?,
152 );
158 );
153 Ok(cell(&Rc::new(Noun::Atom(a)), &Rc::new(Noun::Atom(b))))
159 Ok(cell(&Rc::new(Noun::Atom(a)), &Rc::new(Noun::Atom(b))))
154};
160};
155
161
156static ADD: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a + b);
162static ADD: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a + b);
163+static DEC: Jet = |_ctx, n| {
164+ Ok(Rc::new(Noun::Atom(
157−static DEC: Jet = |_ctx, n| Ok(Rc::new(Noun::Atom(n.as_atom().ok_or(Tanks::new())? - 1u32)));
165+ n.as_atom().ok_or(TTanks::new())? - 1u32,
166+ )))
167+};
158static DVR: Jet = |_ctx, n| BINARY_ATOM_PAIR(n, |a, b| a.div_rem(&b));
168static DVR: Jet = |_ctx, n| BINARY_ATOM_PAIR(n, |a, b| a.div_rem(&b));
159static DIV: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a / b);
169static DIV: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a / b);
160static GTE: Jet = |ctx, n| BINARY_ATOM_LOOB(ctx, n, |a, b| a >= b);
170static GTE: Jet = |ctx, n| BINARY_ATOM_LOOB(ctx, n, |a, b| a >= b);
@@ -168,30 +178,30 @@ static MUL: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a * b);
168static SUB: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a - b);
178static SUB: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a - b);
169
179
170static CAP: Jet = |ctx, n| {
180static CAP: Jet = |ctx, n| {
171− let n = n.as_atom().ok_or(Tanks::new())?;
181+ let n = n.as_atom().ok_or(TTanks::new())?;
172 CAP_ATOM(ctx, n.clone())
182 CAP_ATOM(ctx, n.clone())
173};
183};
174
184
175−static CAP_ATOM: fn(&InterpreterContext, Atom) -> Result<Rc<Noun>, Tanks> = |ctx, n: Atom| {
185+static CAP_ATOM: fn(&InterpreterContext, Atom) -> Result<Rc<Noun>, TTanks> = |ctx, n: Atom| {
176 let mut n_iter = n.iter_u32_digits();
186 let mut n_iter = n.iter_u32_digits();
177
187
178 match n_iter.len() {
188 match n_iter.len() {
179− 0 => Err(Tanks::new()),
189+ 0 => Err(TTanks::new()),
180 1 => CAP_U32(ctx, n_iter.next().unwrap()),
190 1 => CAP_U32(ctx, n_iter.next().unwrap()),
181 _ => CAP_ATOM(ctx, n >> 1),
191 _ => CAP_ATOM(ctx, n >> 1),
182 }
192 }
183};
193};
184−static CAP_U32: fn(ctx: &InterpreterContext, u32) -> Result<Rc<Noun>, Tanks> = |ctx, n| match n {
194+static CAP_U32: fn(ctx: &InterpreterContext, u32) -> Result<Rc<Noun>, TTanks> = |ctx, n| match n {
185− 0 | 1 => Err(Tanks::new()),
195+ 0 | 1 => Err(TTanks::new()),
186 2 => Ok(ctx.nouns.two.clone()),
196 2 => Ok(ctx.nouns.two.clone()),
187 3 => Ok(ctx.nouns.three.clone()),
197 3 => Ok(ctx.nouns.three.clone()),
188 n => CAP_U32(ctx, n >> 1),
198 n => CAP_U32(ctx, n >> 1),
189};
199};
190
200
191static MAS: Jet = |ctx, n| {
201static MAS: Jet = |ctx, n| {
192− let n = n.as_atom().ok_or(Tanks::new())?;
202+ let n = n.as_atom().ok_or(TTanks::new())?;
193 Ok(Rc::new(Noun::Atom(
203 Ok(Rc::new(Noun::Atom(
194− MAS_ATOM(ctx, n.clone()).ok_or(Tanks::new())?,
204+ MAS_ATOM(ctx, n.clone()).ok_or(TTanks::new())?,
195 )))
205 )))
196};
206};
197static MAS_ATOM: fn(&InterpreterContext, Atom) -> Option<Atom> = |ctx, n| {
207static MAS_ATOM: fn(&InterpreterContext, Atom) -> Option<Atom> = |ctx, n| {
@@ -213,22 +223,22 @@ static MAS_U32: fn(u32) -> u32 = |n| match n {
213};
223};
214
224
215static PEG: Jet = |ctx, n| {
225static PEG: Jet = |ctx, n| {
216− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
226+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
217
227
218− let a = a.as_atom().ok_or(Tanks::new())?;
228+ let a = a.as_atom().ok_or(TTanks::new())?;
219− let b = b.as_atom().ok_or(Tanks::new())?;
229+ let b = b.as_atom().ok_or(TTanks::new())?;
220
230
221 if *a == Atom::ZERO {
231 if *a == Atom::ZERO {
222− return Err(Tanks::new());
232+ return Err(TTanks::new());
223 };
233 };
224
234
225 Ok(Rc::new(Noun::Atom(PEG_ATOM(ctx, a, b.clone())?)))
235 Ok(Rc::new(Noun::Atom(PEG_ATOM(ctx, a, b.clone())?)))
226};
236};
227−static PEG_ATOM: fn(&InterpreterContext, &Atom, Atom) -> Result<Atom, Tanks> = |ctx, a, b| {
237+static PEG_ATOM: fn(&InterpreterContext, &Atom, Atom) -> Result<Atom, TTanks> = |ctx, a, b| {
228 let mut b_iter = b.iter_u32_digits();
238 let mut b_iter = b.iter_u32_digits();
229
239
230 match b_iter.len() {
240 match b_iter.len() {
231− 0 => Err(Tanks::new()),
241+ 0 => Err(TTanks::new()),
232 1 => Ok(PEG_U32(a, b_iter.next().unwrap())),
242 1 => Ok(PEG_U32(a, b_iter.next().unwrap())),
233 _ => Ok((&b & &ctx.big_uints.one) + (PEG_ATOM(ctx, a, b >> 1)? << 1)),
243 _ => Ok((&b & &ctx.big_uints.one) + (PEG_ATOM(ctx, a, b >> 1)? << 1)),
234 }
244 }
@@ -242,7 +252,7 @@ static PEG_U32: fn(&Atom, u32) -> Atom = |a, b| match b {
242};
252};
243
253
244static FAND: Jet = |ctx, n| {
254static FAND: Jet = |ctx, n| {
245− let (nedl, hstk) = n.as_cell().ok_or(Tanks::new())?;
255+ let (nedl, hstk) = n.as_cell().ok_or(TTanks::new())?;
246 if nedl.is_sig() || hstk.is_sig() {
256 if nedl.is_sig() || hstk.is_sig() {
247 return Ok(ctx.nouns.sig.clone());
257 return Ok(ctx.nouns.sig.clone());
248 }
258 }
@@ -272,7 +282,7 @@ static FAND: Jet = |ctx, n| {
272};
282};
273
283
274static FIND: Jet = |ctx, n| {
284static FIND: Jet = |ctx, n| {
275− let (nedl, hstk) = n.as_cell().ok_or(Tanks::new())?;
285+ let (nedl, hstk) = n.as_cell().ok_or(TTanks::new())?;
276 if nedl.is_sig() || hstk.is_sig() {
286 if nedl.is_sig() || hstk.is_sig() {
277 return Ok(ctx.nouns.sig.clone());
287 return Ok(ctx.nouns.sig.clone());
278 }
288 }
@@ -305,13 +315,13 @@ static FLOP: Jet = |ctx, n| {
305};
315};
306
316
307static GULF: Jet = |_ctx, n| {
317static GULF: Jet = |_ctx, n| {
308− let (from, to) = n.as_cell().ok_or(Tanks::new())?;
318+ let (from, to) = n.as_cell().ok_or(TTanks::new())?;
309
319
310− let mut from = (*from.as_atom().ok_or(Tanks::new())?).clone();
320+ let mut from = (*from.as_atom().ok_or(TTanks::new())?).clone();
311− let to = to.as_atom().ok_or(Tanks::new())?.clone();
321+ let to = to.as_atom().ok_or(TTanks::new())?.clone();
312
322
313 if from > to {
323 if from > to {
314− return Err(Tanks::new());
324+ return Err(TTanks::new());
315 }
325 }
316
326
317 let mut tmp = Vec::new();
327 let mut tmp = Vec::new();
@@ -325,10 +335,10 @@ static GULF: Jet = |_ctx, n| {
325};
335};
326
336
327static INTO: Jet = |_ctx, n| {
337static INTO: Jet = |_ctx, n| {
328− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
338+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
329− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
339+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
330
340
331− let mut b_iter = b.as_atom().ok_or(Tanks::new())?.iter_u32_digits();
341+ let mut b_iter = b.as_atom().ok_or(TTanks::new())?.iter_u32_digits();
332
342
333 match b_iter.len() {
343 match b_iter.len() {
334 0 => Ok(cell(&c, &a)),
344 0 => Ok(cell(&c, &a)),
@@ -358,7 +368,7 @@ static INTO: Jet = |_ctx, n| {
358};
368};
359
369
360static JOIN: Jet = |_ctx, n| {
370static JOIN: Jet = |_ctx, n| {
361− let (sep, list) = n.as_cell().ok_or(Tanks::new())?;
371+ let (sep, list) = n.as_cell().ok_or(TTanks::new())?;
362 Ok(Noun::list_refs(
372 Ok(Noun::list_refs(
363 list.list_iter()
373 list.list_iter()
364 .intersperse(sep)
374 .intersperse(sep)
@@ -376,7 +386,7 @@ static LENT: Jet = |_ctx, n| {
376};
386};
377
387
378static LEVY: Jet = |ctx, n| {
388static LEVY: Jet = |ctx, n| {
379− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
389+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
380 if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
390 if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
381 .iter()
391 .iter()
382 .all(|x| x.is_y())
392 .all(|x| x.is_y())
@@ -388,7 +398,7 @@ static LEVY: Jet = |ctx, n| {
388};
398};
389
399
390static LIEN: Jet = |ctx, n| {
400static LIEN: Jet = |ctx, n| {
391− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
401+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
392 if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
402 if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
393 .iter()
403 .iter()
394 .any(|x| x.is_y())
404 .any(|x| x.is_y())
@@ -400,7 +410,7 @@ static LIEN: Jet = |ctx, n| {
400};
410};
401
411
402static MURN: Jet = |ctx, n| {
412static MURN: Jet = |ctx, n| {
403− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
413+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
404
414
405 Ok(Noun::list_refs(
415 Ok(Noun::list_refs(
406 traverse_iter_result(
416 traverse_iter_result(
@@ -413,7 +423,7 @@ static MURN: Jet = |ctx, n| {
413};
423};
414
424
415static REAP: Jet = |_ctx, n| {
425static REAP: Jet = |_ctx, n| {
416− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
426+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
417
427
418 Ok(Noun::list_refs(repeat_n(
428 Ok(Noun::list_refs(repeat_n(
419 b.clone(),
429 b.clone(),
@@ -421,17 +431,17 @@ static REAP: Jet = |_ctx, n| {
421 )))
431 )))
422};
432};
423
433
424−static REAR: Jet = |_ctx, n| n.list_iter().last().ok_or(Tanks::new()).cloned();
434+static REAR: Jet = |_ctx, n| n.list_iter().last().ok_or(TTanks::new()).cloned();
425
435
426static REEL: Jet = |ctx, n| {
436static REEL: Jet = |ctx, n| {
427− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
437+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
428
438
429 list.list_iter().collect::<Vec<_>>().iter().rfold(
439 list.list_iter().collect::<Vec<_>>().iter().rfold(
430 Ok(gate
440 Ok(gate
431 .gate_sample()
441 .gate_sample()
432− .ok_or(Tanks::new())?
442+ .ok_or(TTanks::new())?
433 .as_cell()
443 .as_cell()
434− .ok_or(Tanks::new())?
444+ .ok_or(TTanks::new())?
435 .1
445 .1
436 .clone()),
446 .clone()),
437 |acc, next| {
447 |acc, next| {
@@ -442,15 +452,15 @@ static REEL: Jet = |ctx, n| {
442};
452};
443
453
444static ROLL: Jet = |ctx, n| {
454static ROLL: Jet = |ctx, n| {
445− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
455+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
446
456
447 list.list_iter().fold(
457 list.list_iter().fold(
448 Ok(gate
458 Ok(gate
449 .clone()
459 .clone()
450 .gate_sample()
460 .gate_sample()
451− .ok_or(Tanks::new())?
461+ .ok_or(TTanks::new())?
452 .as_cell()
462 .as_cell()
453− .ok_or(Tanks::new())?
463+ .ok_or(TTanks::new())?
454 .1
464 .1
455 .clone()),
465 .clone()),
456 |acc, next| {
466 |acc, next| {
@@ -461,7 +471,7 @@ static ROLL: Jet = |ctx, n| {
461};
471};
462
472
463static SCAG: Jet = |_ctx, n| {
473static SCAG: Jet = |_ctx, n| {
464− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
474+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
465
475
466 Ok(Noun::list_refs(
476 Ok(Noun::list_refs(
467 b.list_iter()
477 b.list_iter()
@@ -474,7 +484,7 @@ static SCAG: Jet = |_ctx, n| {
474};
484};
475
485
476static SKID: Jet = |ctx, n| {
486static SKID: Jet = |ctx, n| {
477− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
487+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
478
488
479 let slammed_n = traverse_iter_result(
489 let slammed_n = traverse_iter_result(
480 list.list_iter()
490 list.list_iter()
@@ -489,7 +499,7 @@ static SKID: Jet = |ctx, n| {
489};
499};
490
500
491static SKIM: Jet = |ctx, n| {
501static SKIM: Jet = |ctx, n| {
492− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
502+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
493
503
494 Ok(Noun::list_refs(
504 Ok(Noun::list_refs(
495 traverse_iter_result(
505 traverse_iter_result(
@@ -503,7 +513,7 @@ static SKIM: Jet = |ctx, n| {
503};
513};
504
514
505static SKIP: Jet = |ctx, n| {
515static SKIP: Jet = |ctx, n| {
506− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
516+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
507
517
508 Ok(Noun::list_refs(
518 Ok(Noun::list_refs(
509 traverse_iter_result(
519 traverse_iter_result(
@@ -517,9 +527,9 @@ static SKIP: Jet = |ctx, n| {
517};
527};
518
528
519static SLAG: Jet = |ctx, n| {
529static SLAG: Jet = |ctx, n| {
520− let (a, list) = n.as_cell().ok_or(Tanks::new())?;
530+ let (a, list) = n.as_cell().ok_or(TTanks::new())?;
521
531
522− let mut a_iter = a.as_atom().ok_or(Tanks::new())?.iter_u32_digits();
532+ let mut a_iter = a.as_atom().ok_or(TTanks::new())?.iter_u32_digits();
523
533
524 match a_iter.len() {
534 match a_iter.len() {
525 0 => Ok(list.clone()),
535 0 => Ok(list.clone()),
@@ -536,12 +546,12 @@ static SLAG: Jet = |ctx, n| {
536};
546};
537
547
538static SNAG: Jet = |_ctx, n| {
548static SNAG: Jet = |_ctx, n| {
539− let (a, list) = n.as_cell().ok_or(Tanks::new())?;
549+ let (a, list) = n.as_cell().ok_or(TTanks::new())?;
540
550
541 list.list_iter()
551 list.list_iter()
542 .nth(a.as_u32().unwrap() as usize)
552 .nth(a.as_u32().unwrap() as usize)
543 .cloned()
553 .cloned()
544− .ok_or(Tanks::new())
554+ .ok_or(TTanks::new())
545};
555};
546
556
547static SNIP: Jet = |_ctx, n| {
557static SNIP: Jet = |_ctx, n| {
@@ -558,7 +568,7 @@ static SNIP: Jet = |_ctx, n| {
558};
568};
559
569
560static SNOC: Jet = |_ctx, n| {
570static SNOC: Jet = |_ctx, n| {
561− let (list, b) = n.as_cell().ok_or(Tanks::new())?;
571+ let (list, b) = n.as_cell().ok_or(TTanks::new())?;
562
572
563 Ok(Noun::list_refs(
573 Ok(Noun::list_refs(
564 list.list_iter()
574 list.list_iter()
@@ -589,15 +599,15 @@ static SNOC: Jet = |_ctx, n| {
589// };
599// };
590
600
591static SPIN: Jet = |ctx, n| {
601static SPIN: Jet = |ctx, n| {
592− let (list, b) = n.as_cell().ok_or(Tanks::new())?;
602+ let (list, b) = n.as_cell().ok_or(TTanks::new())?;
593− let (acc, gate) = b.as_cell().ok_or(Tanks::new())?;
603+ let (acc, gate) = b.as_cell().ok_or(TTanks::new())?;
594
604
595 let mut res = Vec::new();
605 let mut res = Vec::new();
596 let mut acc = acc.clone();
606 let mut acc = acc.clone();
597
607
598 for n in list.list_iter() {
608 for n in list.list_iter() {
599 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
609 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
600− let (el, new_acc) = foo.as_cell().ok_or(Tanks::new())?;
610+ let (el, new_acc) = foo.as_cell().ok_or(TTanks::new())?;
601 acc = new_acc.clone();
611 acc = new_acc.clone();
602 res.push(el.clone());
612 res.push(el.clone());
603 }
613 }
@@ -606,20 +616,20 @@ static SPIN: Jet = |ctx, n| {
606};
616};
607
617
608static SPUN: Jet = |ctx, n| {
618static SPUN: Jet = |ctx, n| {
609− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
619+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
610
620
611 let mut res = Vec::new();
621 let mut res = Vec::new();
612 let mut acc = gate
622 let mut acc = gate
613 .gate_sample()
623 .gate_sample()
614− .ok_or(Tanks::new())?
624+ .ok_or(TTanks::new())?
615 .as_cell()
625 .as_cell()
616− .ok_or(Tanks::new())?
626+ .ok_or(TTanks::new())?
617 .1
627 .1
618 .clone();
628 .clone();
619
629
620 for n in list.list_iter() {
630 for n in list.list_iter() {
621 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
631 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
622− let (el, new_acc) = foo.as_cell().ok_or(Tanks::new())?;
632+ let (el, new_acc) = foo.as_cell().ok_or(TTanks::new())?;
623 acc = new_acc.clone();
633 acc = new_acc.clone();
624 res.push(el.clone());
634 res.push(el.clone());
625 }
635 }
@@ -628,7 +638,7 @@ static SPUN: Jet = |ctx, n| {
628};
638};
629
639
630static TURN: Jet = |ctx, n| {
640static TURN: Jet = |ctx, n| {
631− let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
641+ let (list, gate) = n.as_cell().ok_or(TTanks::new())?;
632 Ok(Noun::list_refs(
642 Ok(Noun::list_refs(
633 traverse_iter_result(list.list_iter().map(|x| slam_pulled_gate(ctx, gate, x)))?
643 traverse_iter_result(list.list_iter().map(|x| slam_pulled_gate(ctx, gate, x)))?
634 .iter()
644 .iter()
@@ -637,7 +647,7 @@ static TURN: Jet = |ctx, n| {
637};
647};
638
648
639static WELD: Jet = |_ctx, n| {
649static WELD: Jet = |_ctx, n| {
640− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
650+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
641
651
642 Ok(Noun::list_refs(
652 Ok(Noun::list_refs(
643 a.list_iter()
653 a.list_iter()
@@ -670,18 +680,20 @@ static BEX: Jet = |ctx, n| {
670};
680};
671
681
672static END: Jet = |ctx, n| {
682static END: Jet = |ctx, n| {
673− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
683+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
674 let bite = a.as_bite();
684 let bite = a.as_bite();
675
685
676 let bits = bite.bits();
686 let bits = bite.bits();
677
687
678 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
688 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
679
689
690+ Ok(Rc::new(Noun::Atom(
680− Ok(Rc::new(Noun::Atom(mask & b.as_atom().ok_or(Tanks::new())?)))
691+ mask & b.as_atom().ok_or(TTanks::new())?,
692+ )))
681};
693};
682
694
683static CAN: Jet = |ctx, n| {
695static CAN: Jet = |ctx, n| {
684− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
696+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
685 let bloq = a.as_u32().unwrap();
697 let bloq = a.as_u32().unwrap();
686 let bloq_ = 2u32.pow(bloq);
698 let bloq_ = 2u32.pow(bloq);
687
699
@@ -696,16 +708,16 @@ static CAN: Jet = |ctx, n| {
696 Some((acc? << bits) | (mask & q.as_atom()?))
708 Some((acc? << bits) | (mask & q.as_atom()?))
697 },
709 },
698 );
710 );
699− Ok(Rc::new(Noun::Atom(atom.ok_or(Tanks::new())?)))
711+ Ok(Rc::new(Noun::Atom(atom.ok_or(TTanks::new())?)))
700};
712};
701
713
702static CAT: Jet = |_ctx, n| {
714static CAT: Jet = |_ctx, n| {
703− let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
715+ let (bloq, b) = n.as_cell().ok_or(TTanks::new())?;
704− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
716+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
705
717
706− let bloq = bloq.as_u32().ok_or(Tanks::new())?;
718+ let bloq = bloq.as_u32().ok_or(TTanks::new())?;
707− let b = b.as_atom().ok_or(Tanks::new())?;
719+ let b = b.as_atom().ok_or(TTanks::new())?;
708− let c = c.as_atom().ok_or(Tanks::new())?;
720+ let c = c.as_atom().ok_or(TTanks::new())?;
709
721
710 Ok(Rc::new(Noun::Atom(
722 Ok(Rc::new(Noun::Atom(
711 (c << (met(bloq, &b) * 2u32.pow(bloq))) | b,
723 (c << (met(bloq, &b) * 2u32.pow(bloq))) | b,
@@ -713,8 +725,8 @@ static CAT: Jet = |_ctx, n| {
713};
725};
714
726
715static MET: Jet = |_ctx, n| {
727static MET: Jet = |_ctx, n| {
716− let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
728+ let (bloq, b) = n.as_cell().ok_or(TTanks::new())?;
717− let b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
729+ let b: Atom = b.as_atom().ok_or(TTanks::new())?.clone();
718 let bloq = bloq.as_u32().unwrap();
730 let bloq = bloq.as_u32().unwrap();
719
731
720 Ok(Rc::new(Noun::from_u32(met(bloq, &b))))
732 Ok(Rc::new(Noun::from_u32(met(bloq, &b))))
@@ -725,28 +737,28 @@ fn met(bloq: u32, a: &Atom) -> u32 {
725}
737}
726
738
727static CUT: Jet = |ctx, n| {
739static CUT: Jet = |ctx, n| {
728− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
740+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
729− let (b, d) = b.as_cell().ok_or(Tanks::new())?;
741+ let (b, d) = b.as_cell().ok_or(TTanks::new())?;
730− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
742+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
731
743
732 let bits = 2u32.pow(a.as_u32().unwrap());
744 let bits = 2u32.pow(a.as_u32().unwrap());
733
745
734 let mask = (&ctx.big_uints.one << (bits * c.as_u32().unwrap())) - &ctx.big_uints.one;
746 let mask = (&ctx.big_uints.one << (bits * c.as_u32().unwrap())) - &ctx.big_uints.one;
735
747
736 Ok(Rc::new(Noun::Atom(
748 Ok(Rc::new(Noun::Atom(
737− (d.as_atom().ok_or(Tanks::new())? >> (bits * b.as_u32().unwrap())) & mask,
749+ (d.as_atom().ok_or(TTanks::new())? >> (bits * b.as_u32().unwrap())) & mask,
738 )))
750 )))
739};
751};
740
752
741static FIL: Jet = |ctx, n| {
753static FIL: Jet = |ctx, n| {
742− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
754+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
743− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
755+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
744
756
745 let bits = 2u32.pow(a.as_u32().unwrap());
757 let bits = 2u32.pow(a.as_u32().unwrap());
746
758
747 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
759 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
748
760
749− let src = c.as_atom().ok_or(Tanks::new())? & mask;
761+ let src = c.as_atom().ok_or(TTanks::new())? & mask;
750
762
751 let mut target = ctx.big_uints.zero.clone();
763 let mut target = ctx.big_uints.zero.clone();
752
764
@@ -758,30 +770,30 @@ static FIL: Jet = |ctx, n| {
758};
770};
759
771
760static LSH: Jet = |_ctx, n| {
772static LSH: Jet = |_ctx, n| {
761− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
773+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
762 let a = a.as_bite();
774 let a = a.as_bite();
763− let b = b.as_atom().ok_or(Tanks::new())?;
775+ let b = b.as_atom().ok_or(TTanks::new())?;
764
776
765 Ok(Rc::new(Noun::Atom(b << a.bits())))
777 Ok(Rc::new(Noun::Atom(b << a.bits())))
766};
778};
767
779
768static RSH: Jet = |_ctx, n| {
780static RSH: Jet = |_ctx, n| {
769− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
781+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
770 let a = a.as_bite();
782 let a = a.as_bite();
771− let b = b.as_atom().ok_or(Tanks::new())?;
783+ let b = b.as_atom().ok_or(TTanks::new())?;
772
784
773 Ok(Rc::new(Noun::Atom(b >> a.bits())))
785 Ok(Rc::new(Noun::Atom(b >> a.bits())))
774};
786};
775
787
776−static RAP: Jet = |ctx, n| {
788+pub static RAP: Jet = |ctx, n| {
777− let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
789+ let (bloq, b) = n.as_cell().ok_or(TTanks::new())?;
778 let bloq = bloq.as_u32().unwrap();
790 let bloq = bloq.as_u32().unwrap();
779 let bits = 2u32.pow(bloq);
791 let bits = 2u32.pow(bloq);
780
792
781 let mut target = ctx.big_uints.zero.clone();
793 let mut target = ctx.big_uints.zero.clone();
782
794
783 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
795 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
784− let el = el.as_atom().ok_or(Tanks::new())?;
796+ let el = el.as_atom().ok_or(TTanks::new())?;
785 if el != &ctx.big_uints.zero {
797 if el != &ctx.big_uints.zero {
786 target = (target << (bits * met(bloq, &el))) | el;
798 target = (target << (bits * met(bloq, &el))) | el;
787 }
799 }
@@ -791,7 +803,7 @@ static RAP: Jet = |ctx, n| {
791};
803};
792
804
793static REP: Jet = |ctx, n| {
805static REP: Jet = |ctx, n| {
794− let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
806+ let (bite, b) = n.as_cell().ok_or(TTanks::new())?;
795 let bite = bite.as_bite();
807 let bite = bite.as_bite();
796
808
797 let bits = bite.bits();
809 let bits = bite.bits();
@@ -800,18 +812,18 @@ static REP: Jet = |ctx, n| {
800 let mut target = ctx.big_uints.zero.clone();
812 let mut target = ctx.big_uints.zero.clone();
801
813
802 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
814 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
803− target = (target << bits) | (el.as_atom().ok_or(Tanks::new())? & &mask);
815+ target = (target << bits) | (el.as_atom().ok_or(TTanks::new())? & &mask);
804 }
816 }
805
817
806 Ok(Rc::new(Noun::Atom(target)))
818 Ok(Rc::new(Noun::Atom(target)))
807};
819};
808
820
809static REV: Jet = |ctx, n| {
821static REV: Jet = |ctx, n| {
810− let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
822+ let (bloq, b) = n.as_cell().ok_or(TTanks::new())?;
811− let (len, dat) = b.as_cell().ok_or(Tanks::new())?;
823+ let (len, dat) = b.as_cell().ok_or(TTanks::new())?;
812 let bloq = bloq.as_u32().unwrap();
824 let bloq = bloq.as_u32().unwrap();
813 let len = len.as_u32().unwrap();
825 let len = len.as_u32().unwrap();
814− let mut dat: Atom = dat.as_atom().ok_or(Tanks::new())?.clone();
826+ let mut dat: Atom = dat.as_atom().ok_or(TTanks::new())?.clone();
815
827
816 let bits = 2u32.pow(bloq);
828 let bits = 2u32.pow(bloq);
817 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
829 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -827,9 +839,9 @@ static REV: Jet = |ctx, n| {
827};
839};
828
840
829static RIP: Jet = |ctx, n| {
841static RIP: Jet = |ctx, n| {
830− let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
842+ let (bite, b) = n.as_cell().ok_or(TTanks::new())?;
831 let bite = bite.as_bite();
843 let bite = bite.as_bite();
832− let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
844+ let mut b: Atom = b.as_atom().ok_or(TTanks::new())?.clone();
833
845
834 let bits = bite.bits();
846 let bits = bite.bits();
835 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
847 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -845,11 +857,11 @@ static RIP: Jet = |ctx, n| {
845};
857};
846
858
847static RUN: Jet = |ctx, n| {
859static RUN: Jet = |ctx, n| {
848− let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
860+ let (bite, b) = n.as_cell().ok_or(TTanks::new())?;
849− let (b, gate) = b.as_cell().ok_or(Tanks::new())?;
861+ let (b, gate) = b.as_cell().ok_or(TTanks::new())?;
850
862
851 let bite = bite.as_bite();
863 let bite = bite.as_bite();
852− let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
864+ let mut b: Atom = b.as_atom().ok_or(TTanks::new())?.clone();
853
865
854 let bits = bite.bits();
866 let bits = bite.bits();
855 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
867 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -860,7 +872,7 @@ static RUN: Jet = |ctx, n| {
860 target = (target << bits)
872 target = (target << bits)
861 | ((*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
873 | ((*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
862 .as_atom()
874 .as_atom()
863− .ok_or(Tanks::new())?
875+ .ok_or(TTanks::new())?
864 & &mask);
876 & &mask);
865 b = b >> bits;
877 b = b >> bits;
866 }
878 }
@@ -869,11 +881,11 @@ static RUN: Jet = |ctx, n| {
869};
881};
870
882
871static RUT: Jet = |ctx, n| {
883static RUT: Jet = |ctx, n| {
872− let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
884+ let (bite, b) = n.as_cell().ok_or(TTanks::new())?;
873− let (b, gate) = b.as_cell().ok_or(Tanks::new())?;
885+ let (b, gate) = b.as_cell().ok_or(TTanks::new())?;
874
886
875 let bite = bite.as_bite();
887 let bite = bite.as_bite();
876− let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
888+ let mut b: Atom = b.as_atom().ok_or(TTanks::new())?.clone();
877
889
878 let bits = bite.bits();
890 let bits = bite.bits();
879 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
891 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -884,7 +896,7 @@ static RUT: Jet = |ctx, n| {
884 target.push(
896 target.push(
885 (*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
897 (*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
886 .as_atom()
898 .as_atom()
887− .ok_or(Tanks::new())?
899+ .ok_or(TTanks::new())?
888 & &mask,
900 & &mask,
889 );
901 );
890 b = b >> bits;
902 b = b >> bits;
@@ -894,12 +906,12 @@ static RUT: Jet = |ctx, n| {
894};
906};
895
907
896static SEW: Jet = |ctx, n| {
908static SEW: Jet = |ctx, n| {
897− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
909+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
898− let (b, recipient) = b.as_cell().ok_or(Tanks::new())?;
910+ let (b, recipient) = b.as_cell().ok_or(TTanks::new())?;
899− let (sew_start, c) = b.as_cell().ok_or(Tanks::new())?;
911+ let (sew_start, c) = b.as_cell().ok_or(TTanks::new())?;
900− let (number_of_blocks, donor) = c.as_cell().ok_or(Tanks::new())?;
912+ let (number_of_blocks, donor) = c.as_cell().ok_or(TTanks::new())?;
901− let recipient = recipient.as_atom().ok_or(Tanks::new())?;
913+ let recipient = recipient.as_atom().ok_or(TTanks::new())?;
902− let donor = donor.as_atom().ok_or(Tanks::new())?;
914+ let donor = donor.as_atom().ok_or(TTanks::new())?;
903
915
904 let bloq = a.as_u32().unwrap();
916 let bloq = a.as_u32().unwrap();
905 let bits = 2u32.pow(bloq);
917 let bits = 2u32.pow(bloq);
@@ -915,12 +927,12 @@ static SEW: Jet = |ctx, n| {
915};
927};
916
928
917static SWP: Jet = |ctx, n| {
929static SWP: Jet = |ctx, n| {
918− let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
930+ let (bloq, b) = n.as_cell().ok_or(TTanks::new())?;
919 let bloq = bloq.as_u32().unwrap();
931 let bloq = bloq.as_u32().unwrap();
920 let bits = 2u32.pow(bloq);
932 let bits = 2u32.pow(bloq);
921 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
933 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
922
934
923− let mut source = b.as_atom().ok_or(Tanks::new())?.clone();
935+ let mut source = b.as_atom().ok_or(TTanks::new())?.clone();
924 let mut target = ctx.big_uints.zero.clone();
936 let mut target = ctx.big_uints.zero.clone();
925
937
926 while source > ctx.big_uints.zero {
938 while source > ctx.big_uints.zero {
@@ -932,7 +944,7 @@ static SWP: Jet = |ctx, n| {
932};
944};
933
945
934static XEB: Jet = |_ctx, n| {
946static XEB: Jet = |_ctx, n| {
935− let mut a = n.as_atom().ok_or(Tanks::new())?.clone();
947+ let mut a = n.as_atom().ok_or(TTanks::new())?.clone();
936
948
937 let mut c = 0;
949 let mut c = 0;
938
950
@@ -949,22 +961,22 @@ static DIS: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a & b);
949static MIX: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a ^ b);
961static MIX: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a ^ b);
950
962
951static NOT: Jet = |ctx, n| {
963static NOT: Jet = |ctx, n| {
952− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
964+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
953− let (b, c) = b.as_cell().ok_or(Tanks::new())?;
965+ let (b, c) = b.as_cell().ok_or(TTanks::new())?;
954
966
955 let bloq = a.as_u32().unwrap();
967 let bloq = a.as_u32().unwrap();
956 let bits = 2u32.pow(bloq);
968 let bits = 2u32.pow(bloq);
957 let mask = (&ctx.big_uints.one << (bits * b.as_u32().unwrap())) - &ctx.big_uints.one;
969 let mask = (&ctx.big_uints.one << (bits * b.as_u32().unwrap())) - &ctx.big_uints.one;
958
970
959− let target = c.as_atom().ok_or(Tanks::new())? ^ &mask;
971+ let target = c.as_atom().ok_or(TTanks::new())? ^ &mask;
960
972
961 Ok(Rc::new(Noun::Atom(target)))
973 Ok(Rc::new(Noun::Atom(target)))
962};
974};
963
975
964static LAST: Jet = |_ctx, n| {
976static LAST: Jet = |_ctx, n| {
965− let (a, b) = n.as_cell().ok_or(Tanks::new())?;
977+ let (a, b) = n.as_cell().ok_or(TTanks::new())?;
966− let a = a.as_hair().ok_or(Tanks::new())?;
978+ let a = a.as_hair().ok_or(TTanks::new())?;
967− let b = b.as_hair().ok_or(Tanks::new())?;
979+ let b = b.as_hair().ok_or(TTanks::new())?;
968 Ok(Noun::from_hair(last(&a, &b)))
980 Ok(Noun::from_hair(last(&a, &b)))
969};
981};
970
982
@@ -985,22 +997,185 @@ fn last<'a>(a: &'a Hair, b: &'a Hair) -> &'a Hair {
985}
997}
986
998
987static TRIP: Jet = |_ctx, n| {
999static TRIP: Jet = |_ctx, n| {
988− let a = n.as_atom().ok_or(Tanks::new())?;
1000+ let a = n.as_atom().ok_or(TTanks::new())?;
989 Ok(Noun::list(
1001 Ok(Noun::list(
990 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
1002 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
991 ))
1003 ))
992};
1004};
993
1005
994static MUK: Jet = |_ctx, n| {
1006static MUK: Jet = |_ctx, n| {
995− let (seed, len) = n.as_cell().ok_or(Tanks::new())?;
1007+ let (seed, len) = n.as_cell().ok_or(TTanks::new())?;
996− let (len, key) = len.as_cell().ok_or(Tanks::new())?;
1008+ let (len, key) = len.as_cell().ok_or(TTanks::new())?;
997− let seed = seed.as_u32().ok_or(Tanks::new())?;
1009+ let seed = seed.as_u32().ok_or(TTanks::new())?;
998− let len = len.as_u32().ok_or(Tanks::new())?;
1010+ let len = len.as_u32().ok_or(TTanks::new())?;
999− let key = key.as_atom().ok_or(Tanks::new())?;
1011+ let key = key.as_atom().ok_or(TTanks::new())?;
1000
1012
1001 Ok(Rc::new(Noun::from_u32(muk(seed, len, key))))
1013 Ok(Rc::new(Noun::from_u32(muk(seed, len, key))))
1002};
1014};
1003
1015
1016+static AOR: Jet = |ctx, n| {
1017+ let (a, b) = n.as_cell().ok_or(EMPTY_TANKS)?;
1018+
1019+ if a == b {
1020+ Ok(ctx.nouns.y.clone())
1021+ } else {
1022+ match (a.borrow(), b.borrow()) {
1023+ (Noun::Cell { .. }, Noun::Atom(_)) => Ok(ctx.nouns.n.clone()),
1024+ (Noun::Cell { p: a_p, q: a_q, .. }, Noun::Cell { p: b_p, q: b_q, .. }) => {
1025+ if a_p == b_p {
1026+ AOR(ctx, &cell(a_q, b_q))
1027+ } else {
1028+ AOR(ctx, &cell(a_p, b_p))
1029+ }
1030+ }
1031+ (Noun::Atom(_), Noun::Cell { .. }) => Ok(ctx.nouns.y.clone()),
1032+ (Noun::Atom(a), Noun::Atom(b)) => {
1033+ let a = a.to_bytes_le();
1034+ let b = b.to_bytes_le();
1035+
1036+ let mut i = 0;
1037+ loop {
1038+ let c = a.get(i).unwrap_or(&0);
1039+ let d = b.get(i).unwrap_or(&0);
1040+
1041+ if a[0] == b[0] {
1042+ i += 1;
1043+ } else {
1044+ if c < d {
1045+ return Ok(ctx.nouns.y.clone());
1046+ } else {
1047+ return Ok(ctx.nouns.n.clone());
1048+ }
1049+ }
1050+ }
1051+ }
1052+ }
1053+ }
1054+};
1055+
1056+static DOR: Jet = |ctx, n| {
1057+ let (a, b) = n.as_cell().ok_or(EMPTY_TANKS)?;
1058+
1059+ if a == b {
1060+ Ok(ctx.nouns.y.clone())
1061+ } else {
1062+ match (a.borrow(), b.borrow()) {
1063+ (Noun::Cell { .. }, Noun::Atom(_)) => Ok(ctx.nouns.n.clone()),
1064+ (Noun::Cell { p: a_p, q: a_q, .. }, Noun::Cell { p: b_p, q: b_q, .. }) => {
1065+ if a_p == b_p {
1066+ DOR(ctx, &cell(a_q, b_q))
1067+ } else {
1068+ DOR(ctx, &cell(a_p, b_p))
1069+ }
1070+ }
1071+ (Noun::Atom(_), Noun::Cell { .. }) => Ok(ctx.nouns.y.clone()),
1072+ (Noun::Atom(a), Noun::Atom(b)) => {
1073+ if a < b {
1074+ Ok(ctx.nouns.y.clone())
1075+ } else {
1076+ Ok(ctx.nouns.n.clone())
1077+ }
1078+ }
1079+ }
1080+ }
1081+};
1082+
1083+static GOR: Jet = |ctx, n| {
1084+ let (a, b) = n.as_cell().ok_or(EMPTY_TANKS)?;
1085+ let c = a.mug();
1086+ let d = b.mug();
1087+
1088+ if c == d {
1089+ DOR(ctx, n)
1090+ } else {
1091+ if c < d {
1092+ Ok(ctx.nouns.y.clone())
1093+ } else {
1094+ Ok(ctx.nouns.n.clone())
1095+ }
1096+ }
1097+};
1098+
1099+static GOR_PAIR: fn(&mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Result<bool, TTanks> =
1100+ |ctx, a, b| {
1101+ let c = a.mug();
1102+ let d = b.mug();
1103+
1104+ if c == d {
1105+ Ok(DOR(ctx, &(a.clone(), b.clone()).as_noun())? == ctx.nouns.y)
1106+ } else {
1107+ Ok(c < d)
1108+ }
1109+ };
1110+
1111+static MOR: Jet = |ctx, n| {
1112+ let (a, b) = n.as_cell().ok_or(EMPTY_TANKS)?;
1113+ let c = Noun::from_u32(a.mug()).mug();
1114+ let d = Noun::from_u32(b.mug()).mug();
1115+
1116+ if c == d {
1117+ DOR(ctx, n)
1118+ } else {
1119+ if c < d {
1120+ Ok(ctx.nouns.y.clone())
1121+ } else {
1122+ Ok(ctx.nouns.n.clone())
1123+ }
1124+ }
1125+};
1126+
1127+static LOOK: Jet = |ctx, n| {
1128+ let (cog, dab) = n.as_cell().ok_or(EMPTY_TANKS)?;
1129+ LOOK_PAIR(ctx, Atom::new(vec![1]), cog, dab)
1130+};
1131+
1132+static LOOK_PAIR: fn(
1133+ &mut InterpreterContext,
1134+ Atom,
1135+ &Rc<Noun>,
1136+ &Rc<Noun>,
1137+) -> Result<Rc<Noun>, TTanks> = |ctx, axe, cog, dab| {
1138+ if dab.is_sig() {
1139+ Ok(ctx.nouns.sig.clone())
1140+ } else {
1141+ let (node, b, c) = dab.tuple_3().ok_or(EMPTY_TANKS)?;
1142+ let l = b;
1143+ let r = c;
1144+ let (p, q) = node.as_cell().ok_or(EMPTY_TANKS)?;
1145+ if b.is_sig() && c.is_sig() {
1146+ if cog == p {
1147+ Ok((ctx.nouns.sig.clone(), Noun::Atom(axe), q.clone()).as_noun())
1148+ } else {
1149+ Ok(ctx.nouns.sig.clone())
1150+ }
1151+ } else if b.is_sig() {
1152+ if cog == p {
1153+ Ok((ctx.nouns.sig.clone(), PEG_U32(&axe, 2), q.clone()).as_noun())
1154+ } else if GOR_PAIR(ctx, cog, p)? {
1155+ Ok(ctx.nouns.sig.clone())
1156+ } else {
1157+ LOOK_PAIR(ctx, PEG_U32(&axe, 3), cog, r)
1158+ }
1159+ } else if c.is_sig() {
1160+ if cog == p {
1161+ Ok((ctx.nouns.sig.clone(), PEG_U32(&axe, 2), q.clone()).as_noun())
1162+ } else if GOR_PAIR(ctx, cog, p)? {
1163+ LOOK_PAIR(ctx, PEG_U32(&axe, 3), cog, l)
1164+ } else {
1165+ Ok(ctx.nouns.sig.clone())
1166+ }
1167+ } else {
1168+ if cog == p {
1169+ Ok((ctx.nouns.sig.clone(), PEG_U32(&axe, 2), q.clone()).as_noun())
1170+ } else if GOR_PAIR(ctx, cog, p)? {
1171+ LOOK_PAIR(ctx, PEG_U32(&axe, 6), cog, l)
1172+ } else {
1173+ LOOK_PAIR(ctx, PEG_U32(&axe, 7), cog, r)
1174+ }
1175+ }
1176+ }
1177+};
1178+
1004static JUST: DoubleJet = |ctx, n, m| {
1179static JUST: DoubleJet = |ctx, n, m| {
1005 let char = n.as_atom()?;
1180 let char = n.as_atom()?;
1006 let nail = m.as_nail()?;
1181 let nail = m.as_nail()?;
nock/src/lib.rs+2−37
@@ -1,11 +1,9 @@
1#![feature(iter_intersperse)]
1#![feature(iter_intersperse)]
2#![feature(let_chains)]
2#![feature(let_chains)]
3
3
4−use core::str;
5−use std::{borrow::Borrow, rc::Rc};
4+use std::rc::Rc;
6
5
7−use interpreter::{eval_pulled_gate, slam_pulled_gate, tar, InterpreterContext, Tanks};
8−use noun::{cell, Noun};
6+use noun::Noun;
9pub mod cue;
7pub mod cue;
10pub mod interpreter;
8pub mod interpreter;
11pub mod jam;
9pub mod jam;
@@ -13,36 +11,3 @@ mod jets;
13pub mod noun;
11pub mod noun;
14
12
15pub type Vase = (Rc<Noun>, Rc<Noun>);
13pub type Vase = (Rc<Noun>, Rc<Noun>);
16−
17−pub fn wash(ctx: &mut InterpreterContext, urbit: &Rc<Noun>, tanks: Tanks) -> String {
18− let mut target = String::new();
19− for (subj, q) in tanks.iter() {
20− match tar(ctx, subj.clone(), q).unwrap().borrow() {
21− Noun::Atom(a) => {
22− target.push_str(str::from_utf8_mut(&mut *a.to_bytes_le()).unwrap());
23− }
24− gate @ Noun::Cell { .. } => {
25− let tank = eval_pulled_gate(ctx, Rc::new(gate.clone())).unwrap();
26− let mut str = slam_pulled_gate(
27− ctx,
28− &urbit,
29− &cell(
30− &Rc::new(Noun::from_bytes(b"wash")),
31− &cell(
32− &cell(&Rc::new(Noun::from_u32(0)), &Rc::new(Noun::from_u32(80))),
33− &tank,
34− ),
35− ),
36− )
37− .unwrap()
38− .as_atom()
39− .unwrap()
40− .to_bytes_le();
41−
42− target.push_str(str::from_utf8_mut(&mut *str).unwrap())
43− }
44− }
45− }
46−
47− target
48−}
nock/src/main.rs+44−18
@@ -1,7 +1,8 @@
1use clap::{command, error::Result, Parser, Subcommand};
1use clap::{command, error::Result, Parser, Subcommand};
2use core::str;
2use core::str;
3+use nock::interpreter::{
3−use nock::interpreter::{eval_pulled_gate, slam_pulled_gate, tar, InterpreterContext, Tanks};
4+ ram_ttanks, slam_pulled_gate, tar, InterpreterContext, TTanks, JET_COUNTER,
4−use nock::wash;
5+};
5use nock::{
6use nock::{
6 cue::cue_bytes,
7 cue::cue_bytes,
7 interpreter::{generate_interpreter_context, slam},
8 interpreter::{generate_interpreter_context, slam},
@@ -9,7 +10,6 @@ use nock::{
9 noun::{cell, Atom, Noun},
10 noun::{cell, Atom, Noun},
10};
11};
11use spinoff::Spinner;
12use spinoff::Spinner;
12−use std::borrow::Borrow;
13use std::cell::LazyCell;
13use std::cell::LazyCell;
14use std::{
14use std::{
15 fs::File,
15 fs::File,
@@ -67,9 +67,38 @@ enum RunCommand {
67 },
67 },
68}
68}
69
69
70+fn print_jet_counter() {
71+ let counter = JET_COUNTER.lock().unwrap();
72+ let mut builder = tabled::builder::Builder::new();
73+ builder.push_record(vec!["jet", "number of calls"]);
74+ let mut counters = counter.iter().collect::<Vec<_>>();
75+ counters.sort_unstable_by_key(|x| x.1);
76+ for (key, count) in counters {
77+ let key = String::from_utf8(key.to_bytes_le()).unwrap();
78+ builder.push_record(vec![key, count.to_string()]);
79+ }
80+ println!(
81+ "\n{}",
82+ builder
83+ .build()
84+ .with(tabled::settings::style::Style::rounded())
85+ );
86+}
87+
70fn main() -> Result<(), std::io::Error> {
88fn main() -> Result<(), std::io::Error> {
89+ if cfg!(feature = "count-jets") {
90+ ctrlc::set_handler(|| {
91+ print_jet_counter();
92+ exit(1);
93+ })
94+ .unwrap();
95+ }
96+
71 let urbit = LazyCell::new(GENERATE_URBIT);
97 let urbit = LazyCell::new(GENERATE_URBIT);
98+ let mut ctx = InterpreterContext {
99+ // slog: |_| {},
72− let mut ctx = generate_interpreter_context();
100+ ..generate_interpreter_context()
101+ };
73
102
74 let cli = Cli::parse();
103 let cli = Cli::parse();
75
104
@@ -91,7 +120,7 @@ fn main() -> Result<(), std::io::Error> {
91 spinner.fail("Gate execution failed");
120 spinner.fail("Gate execution failed");
92
121
93 let mut spinner = new_spinner(String::from("Building trace"));
122 let mut spinner = new_spinner(String::from("Building trace"));
94− let trace = wash(&mut ctx, &urbit, tanks);
123+ let trace = ram_ttanks(&mut ctx, tanks);
95 spinner.success("Trace built");
124 spinner.success("Trace built");
96 println!("{trace}");
125 println!("{trace}");
97 exit(1);
126 exit(1);
@@ -138,12 +167,16 @@ fn main() -> Result<(), std::io::Error> {
138 let (_typ, nok) = read_nock_or_compile(&mut spinner, &mut ctx, &urbit, &nock)?;
167 let (_typ, nok) = read_nock_or_compile(&mut spinner, &mut ctx, &urbit, &nock)?;
139
168
140 let sig = ctx.nouns.sig.clone();
169 let sig = ctx.nouns.sig.clone();
141− let result = tar(&mut ctx, sig, &nok).unwrap();
170+ let result = tar(&mut ctx, &sig, &nok).unwrap();
142
171
143 println!("{result}");
172 println!("{result}");
144 }
173 }
145 }
174 }
146
175
176+ if cfg!(feature = "count-jets") {
177+ print_jet_counter()
178+ }
179+
147 Ok(())
180 Ok(())
148}
181}
149
182
@@ -182,13 +215,7 @@ fn compile_to_nock(
182 &urbit,
215 &urbit,
183 &cell(&Rc::new(Noun::from_bytes(b"hoon")), &ctx.nouns.sig),
216 &cell(&Rc::new(Noun::from_bytes(b"hoon")), &ctx.nouns.sig),
184 );
217 );
185− let hoon = or_wash_fail(
186− ctx,
187− urbit,
188− hoon,
189− spinner,
190− "Failed to read Hoon standard library",
218+ let hoon = or_wash_fail(ctx, hoon, spinner, "Failed to read Hoon standard library");
191− );
192 let (hoon_type, hoon) = hoon.as_cell().unwrap();
219 let (hoon_type, hoon) = hoon.as_cell().unwrap();
193
220
194 spinner.update_text(format!("Compiling {root:#?}"));
221 spinner.update_text(format!("Compiling {root:#?}"));
@@ -206,7 +233,7 @@ fn compile_to_nock(
206 ),
233 ),
207 ),
234 ),
208 );
235 );
209− let target = or_wash_fail(ctx, urbit, target, spinner, "Compilation failed");
236+ let target = or_wash_fail(ctx, target, spinner, "Compilation failed");
210
237
211 let (target_type, target_nock) = target.as_cell().unwrap();
238 let (target_type, target_nock) = target.as_cell().unwrap();
212
239
@@ -222,7 +249,7 @@ fn compile_to_nock(
222 );
249 );
223 let combined_nock = cell(
250 let combined_nock = cell(
224 target_type,
251 target_type,
225− &or_wash_fail(ctx, urbit, combined_nock, spinner, "Failed to combine Nock"),
252+ &or_wash_fail(ctx, combined_nock, spinner, "Failed to combine Nock"),
226 );
253 );
227 Ok(combined_nock)
254 Ok(combined_nock)
228}
255}
@@ -244,8 +271,7 @@ fn read_nock_or_compile(
244
271
245fn or_wash_fail(
272fn or_wash_fail(
246 ctx: &mut InterpreterContext,
273 ctx: &mut InterpreterContext,
247− urbit: &Rc<Noun>,
248− source: Result<Rc<Noun>, Tanks>,
274+ source: Result<Rc<Noun>, TTanks>,
249 spinner: &mut Spinner,
275 spinner: &mut Spinner,
250 fail_err: &str,
276 fail_err: &str,
251) -> Rc<Noun> {
277) -> Rc<Noun> {
@@ -253,7 +279,7 @@ fn or_wash_fail(
253 Ok(source) => source,
279 Ok(source) => source,
254 Err(tanks) => {
280 Err(tanks) => {
255 spinner.fail(fail_err);
281 spinner.fail(fail_err);
256− let washed_tanks = wash(ctx, urbit, tanks);
282+ let washed_tanks = ram_ttanks(ctx, tanks);
257 eprintln!("{}", washed_tanks);
283 eprintln!("{}", washed_tanks);
258 exit(1)
284 exit(1)
259 }
285 }
nock/src/noun.rs+313
@@ -47,6 +47,10 @@ impl PartialEq for Noun {
47impl<'a> Noun {
47impl<'a> Noun {
48 pub const SIG: Noun = Noun::Atom(BigUint::ZERO);
48 pub const SIG: Noun = Noun::Atom(BigUint::ZERO);
49
49
50+ pub fn rc(self: Self) -> Rc<Self> {
51+ Rc::new(self)
52+ }
53+
50 pub fn from_u32(a: u32) -> Noun {
54 pub fn from_u32(a: u32) -> Noun {
51 Noun::Atom(Atom::new(vec![a]))
55 Noun::Atom(Atom::new(vec![a]))
52 }
56 }
@@ -100,6 +104,59 @@ impl<'a> Noun {
100 }
104 }
101 }
105 }
102
106
107+ pub fn as_cell_cloned(self: &'a Self) -> Option<(Rc<Noun>, Rc<Noun>)> {
108+ match self {
109+ Noun::Cell { p, q, .. } => Option::Some((p.clone(), q.clone())),
110+ _ => Option::None,
111+ }
112+ }
113+
114+ pub fn tuple_2(self: &Self) -> Option<(&Rc<Noun>, &Rc<Noun>)> {
115+ self.as_cell()
116+ }
117+
118+ pub fn tuple_3(self: &Self) -> Option<(&Rc<Noun>, &Rc<Noun>, &Rc<Noun>)> {
119+ let (a, b) = self.as_cell()?;
120+ let (b, c) = b.as_cell()?;
121+
122+ Some((a, b, c))
123+ }
124+ pub fn tuple_4(self: &Self) -> Option<(&Rc<Noun>, &Rc<Noun>, &Rc<Noun>, &Rc<Noun>)> {
125+ let (a, b) = self.as_cell()?;
126+ let (b, c) = b.as_cell()?;
127+ let (c, d) = c.as_cell()?;
128+
129+ Some((a, b, c, d))
130+ }
131+
132+ pub fn tuple_5(self: &Self) -> Option<(&Rc<Noun>, &Rc<Noun>, &Rc<Noun>, &Rc<Noun>, &Rc<Noun>)> {
133+ let (a, b) = self.as_cell()?;
134+ let (b, c) = b.as_cell()?;
135+ let (c, d) = c.as_cell()?;
136+ let (d, e) = d.as_cell()?;
137+
138+ Some((a, b, c, d, e))
139+ }
140+
141+ pub fn tuple_6(
142+ self: &Self,
143+ ) -> Option<(
144+ &Rc<Noun>,
145+ &Rc<Noun>,
146+ &Rc<Noun>,
147+ &Rc<Noun>,
148+ &Rc<Noun>,
149+ &Rc<Noun>,
150+ )> {
151+ let (a, b) = self.as_cell()?;
152+ let (b, c) = b.as_cell()?;
153+ let (c, d) = c.as_cell()?;
154+ let (d, e) = d.as_cell()?;
155+ let (e, f) = e.as_cell()?;
156+
157+ Some((a, b, c, d, e, f))
158+ }
159+
103 pub fn is_sig(self: &Self) -> bool {
160 pub fn is_sig(self: &Self) -> bool {
104 match self {
161 match self {
105 Noun::Atom(n) if *n == Atom::ZERO => true,
162 Noun::Atom(n) if *n == Atom::ZERO => true,
@@ -244,6 +301,262 @@ impl<'a> Noun {
244 }
301 }
245}
302}
246
303
304+pub trait AsNoun {
305+ fn as_noun(self: &Self) -> Rc<Noun>;
306+}
307+
308+impl AsNoun for Atom {
309+ fn as_noun(self: &Self) -> Rc<Noun> {
310+ Rc::new(Noun::Atom(self.clone()))
311+ }
312+}
313+
314+impl AsNoun for Noun {
315+ fn as_noun(self: &Self) -> Rc<Noun> {
316+ Rc::new(self.clone())
317+ }
318+}
319+
320+impl AsNoun for Rc<Noun> {
321+ fn as_noun(self: &Self) -> Rc<Noun> {
322+ self.clone()
323+ }
324+}
325+
326+impl<A, B> AsNoun for (A, B)
327+where
328+ A: AsNoun,
329+ B: AsNoun,
330+{
331+ fn as_noun(self: &Self) -> Rc<Noun> {
332+ let (a, b) = self;
333+
334+ cell(&a.as_noun(), &b.as_noun())
335+ }
336+}
337+
338+impl<A, B, C> AsNoun for (A, B, C)
339+where
340+ A: AsNoun,
341+ B: AsNoun,
342+ C: AsNoun,
343+{
344+ fn as_noun(self: &Self) -> Rc<Noun> {
345+ let (a, b, c) = self;
346+
347+ cell(&a.as_noun(), &cell(&b.as_noun(), &c.as_noun()))
348+ }
349+}
350+
351+impl<A, B, C, D> AsNoun for (A, B, C, D)
352+where
353+ A: AsNoun,
354+ B: AsNoun,
355+ C: AsNoun,
356+ D: AsNoun,
357+{
358+ fn as_noun(self: &Self) -> Rc<Noun> {
359+ let (a, b, c, d) = self;
360+
361+ cell(
362+ &a.as_noun(),
363+ &cell(&b.as_noun(), &cell(&c.as_noun(), &d.as_noun())),
364+ )
365+ }
366+}
367+
368+impl<A, B, C, D, E> AsNoun for (A, B, C, D, E)
369+where
370+ A: AsNoun,
371+ B: AsNoun,
372+ C: AsNoun,
373+ D: AsNoun,
374+ E: AsNoun,
375+{
376+ fn as_noun(self: &Self) -> Rc<Noun> {
377+ let (a, b, c, d, e) = self;
378+
379+ cell(
380+ &a.as_noun(),
381+ &cell(
382+ &b.as_noun(),
383+ &cell(&c.as_noun(), &cell(&d.as_noun(), &e.as_noun())),
384+ ),
385+ )
386+ }
387+}
388+
389+impl<A, B, C, D, E, F> AsNoun for (A, B, C, D, E, F)
390+where
391+ A: AsNoun,
392+ B: AsNoun,
393+ C: AsNoun,
394+ D: AsNoun,
395+ E: AsNoun,
396+ F: AsNoun,
397+{
398+ fn as_noun(self: &Self) -> Rc<Noun> {
399+ let (a, b, c, d, e, f) = self;
400+
401+ cell(
402+ &a.as_noun(),
403+ &cell(
404+ &b.as_noun(),
405+ &cell(
406+ &c.as_noun(),
407+ &cell(&d.as_noun(), &cell(&e.as_noun(), &f.as_noun())),
408+ ),
409+ ),
410+ )
411+ }
412+}
413+
414+impl From<(Rc<Noun>, Rc<Noun>)> for Noun {
415+ fn from(value: (Rc<Noun>, Rc<Noun>)) -> Self {
416+ naked_cell(&value.0, &value.1)
417+ }
418+}
419+
420+impl From<(Rc<Noun>, Rc<Noun>, Rc<Noun>)> for Noun {
421+ fn from(value: (Rc<Noun>, Rc<Noun>, Rc<Noun>)) -> Self {
422+ naked_cell(&value.0, &cell(&value.1, &value.2))
423+ }
424+}
425+
426+impl From<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> for Noun {
427+ fn from(value: (Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)) -> Self {
428+ naked_cell(&value.0, &cell(&value.1, &cell(&value.2, &value.3)))
429+ }
430+}
431+
432+impl From<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> for Noun {
433+ fn from(value: (Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)) -> Self {
434+ naked_cell(
435+ &value.0,
436+ &cell(&value.1, &cell(&value.2, &cell(&value.3, &value.4))),
437+ )
438+ }
439+}
440+
441+impl From<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> for Noun {
442+ fn from(value: (Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)) -> Self {
443+ naked_cell(
444+ &value.0,
445+ &cell(
446+ &value.1,
447+ &cell(&value.2, &cell(&value.3, &cell(&value.4, &value.5))),
448+ ),
449+ )
450+ }
451+}
452+
453+impl
454+ From<(
455+ Rc<Noun>,
456+ Rc<Noun>,
457+ Rc<Noun>,
458+ Rc<Noun>,
459+ Rc<Noun>,
460+ Rc<Noun>,
461+ Rc<Noun>,
462+ )> for Noun
463+{
464+ fn from(
465+ value: (
466+ Rc<Noun>,
467+ Rc<Noun>,
468+ Rc<Noun>,
469+ Rc<Noun>,
470+ Rc<Noun>,
471+ Rc<Noun>,
472+ Rc<Noun>,
473+ ),
474+ ) -> Self {
475+ naked_cell(
476+ &value.0,
477+ &cell(
478+ &value.1,
479+ &cell(
480+ &value.2,
481+ &cell(&value.3, &cell(&value.4, &cell(&value.5, &value.6))),
482+ ),
483+ ),
484+ )
485+ }
486+}
487+
488+impl From<Noun> for Option<(Rc<Noun>, Rc<Noun>)> {
489+ fn from(value: Noun) -> Self {
490+ value.as_cell_cloned()
491+ }
492+}
493+
494+impl From<Noun> for Option<(Rc<Noun>, Rc<Noun>, Rc<Noun>)> {
495+ fn from(value: Noun) -> Self {
496+ let (a, b) = value.as_cell_cloned()?;
497+ let (b, c) = b.as_cell_cloned()?;
498+ Some((a, b, c))
499+ }
500+}
501+
502+impl From<Noun> for Option<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> {
503+ fn from(value: Noun) -> Self {
504+ let (a, b) = value.as_cell_cloned()?;
505+ let (b, c) = b.as_cell_cloned()?;
506+ let (c, d) = c.as_cell_cloned()?;
507+ Some((a, b, c, d))
508+ }
509+}
510+
511+impl From<Noun> for Option<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> {
512+ fn from(value: Noun) -> Self {
513+ let (a, b) = value.as_cell_cloned()?;
514+ let (b, c) = b.as_cell_cloned()?;
515+ let (c, d) = c.as_cell_cloned()?;
516+ let (d, e) = d.as_cell_cloned()?;
517+ Some((a, b, c, d, e))
518+ }
519+}
520+
521+impl From<Noun> for Option<(Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>, Rc<Noun>)> {
522+ fn from(value: Noun) -> Self {
523+ let (a, b) = value.as_cell_cloned()?;
524+ let (b, c) = b.as_cell_cloned()?;
525+ let (c, d) = c.as_cell_cloned()?;
526+ let (d, e) = d.as_cell_cloned()?;
527+ let (e, f) = e.as_cell_cloned()?;
528+ Some((a, b, c, d, e, f))
529+ }
530+}
531+
532+impl From<Noun>
533+ for Option<(
534+ Rc<Noun>,
535+ Rc<Noun>,
536+ Rc<Noun>,
537+ Rc<Noun>,
538+ Rc<Noun>,
539+ Rc<Noun>,
540+ Rc<Noun>,
541+ )>
542+{
543+ fn from(value: Noun) -> Self {
544+ let (a, b) = value.as_cell_cloned()?;
545+ let (b, c) = b.as_cell_cloned()?;
546+ let (c, d) = c.as_cell_cloned()?;
547+ let (d, e) = d.as_cell_cloned()?;
548+ let (e, f) = e.as_cell_cloned()?;
549+ let (f, g) = f.as_cell_cloned()?;
550+ Some((a, b, c, d, e, f, g))
551+ }
552+}
553+
554+impl From<&[u8]> for Noun {
555+ fn from(value: &[u8]) -> Self {
556+ Noun::from_bytes(value)
557+ }
558+}
559+
247#[derive(Clone)]
560#[derive(Clone)]
248pub struct Edge<'a> {
561pub struct Edge<'a> {
249 pub hair: Hair,
562 pub hair: Hair,
nock/test.hoonnew file+3
@@ -0,0 +1,3 @@
1+|= *
2+=/ target (gor 'd' 'c')
3+(crip "{<target>}")
nock/wock.hoon+198−10
@@ -1,16 +1,204 @@
1=>
1=>
2|%
2|%
3+++ http ^?
4+ |%
5+ :: +header-list: an ordered list of http headers
6+ ::
7+ +$ header-list
8+ (list [key=@t value=@t])
9+ :: +method: exhaustive list of http verbs
10+ ::
11+ +$ method
12+ $? %'CONNECT'
13+ %'DELETE'
14+ %'GET'
15+ %'HEAD'
16+ %'OPTIONS'
17+ %'PATCH'
18+ %'POST'
19+ %'PUT'
20+ %'TRACE'
21+ ==
22+ :: +request: a single http request
23+ ::
24+ +$ request
25+ $: :: method: http method
26+ ::
27+ method=method
28+ :: url: the url requested
29+ ::
30+ :: The url is not escaped. There is no escape.
31+ ::
32+ url=@t
33+ :: header-list: headers to pass with this request
34+ ::
35+ =header-list
36+ :: body: optionally, data to send with this request
37+ ::
38+ body=(unit octs)
39+ ==
40+ :: +response-header: the status code and header list on an http request
41+ ::
42+ :: We separate these away from the body data because we may not wait for
43+ :: the entire body before we send a %progress to the caller.
44+ ::
45+ +$ response-header
46+ $: :: status: http status code
47+ ::
48+ status-code=@ud
49+ :: headers: http headers
50+ ::
51+ headers=header-list
52+ ==
53+ :: +http-event: packetized http
54+ ::
55+ :: Urbit treats Earth's HTTP servers as pipes, where Urbit sends or
56+ :: receives one or more %http-events. The first of these will always be a
57+ :: %start or an %error, and the last will always be %cancel or will have
58+ :: :complete set to %.y to finish the connection.
59+ ::
60+ :: Calculation of control headers such as 'Content-Length' or
61+ :: 'Transfer-Encoding' should be performed at a higher level; this structure
62+ :: is merely for what gets sent to or received from Earth.
63+ ::
64+ +$ http-event
65+ $% :: %start: the first packet in a response
66+ ::
67+ $: %start
68+ :: response-header: first event information
69+ ::
70+ =response-header
71+ :: data: data to pass to the pipe
72+ ::
73+ data=(unit octs)
74+ :: whether this completes the request
75+ ::
76+ complete=?
77+ ==
78+ :: %continue: every subsequent packet
79+ ::
80+ $: %continue
81+ :: data: data to pass to the pipe
82+ ::
83+ data=(unit octs)
84+ :: complete: whether this completes the request
85+ ::
86+ complete=?
87+ ==
88+ :: %cancel: represents unsuccessful termination
89+ ::
90+ [%cancel ~]
91+ ==
92+ :: +get-header: returns the value for :header, if it exists in :header-list
93+ ::
94+ ++ get-header
95+ |= [header=@t =header-list]
96+ ^- (unit @t)
97+ ::
98+ ?~ header-list
99+ ~
100+ ::
101+ ?: =(key.i.header-list header)
102+ `value.i.header-list
103+ ::
104+ $(header-list t.header-list)
105+ :: +set-header: sets the value of an item in the header list
106+ ::
107+ :: This adds to the end if it doesn't exist.
108+ ::
109+ ++ set-header
110+ |= [header=@t value=@t =header-list]
111+ ^- ^header-list
112+ ::
113+ ?~ header-list
114+ :: we didn't encounter the value, add it to the end
115+ ::
116+ [[header value] ~]
117+ ::
118+ ?: =(key.i.header-list header)
119+ [[header value] t.header-list]
120+ ::
121+ [i.header-list $(header-list t.header-list)]
122+ :: +delete-header: removes the first instance of a header from the list
123+ ::
124+ ++ delete-header
125+ |= [header=@t =header-list]
126+ ^- ^header-list
127+ ::
128+ ?~ header-list
129+ ~
130+ :: if we see it in the list, remove it
131+ ::
132+ ?: =(key.i.header-list header)
133+ t.header-list
134+ ::
135+ [i.header-list $(header-list t.header-list)]
136+ :: +unpack-header: parse header field values
137+ ::
138+ ++ unpack-header
139+ |^ |= value=@t
140+ ^- (unit (list (map @t @t)))
141+ (rust (cass (trip value)) values)
142+ ::
143+ ++ values
144+ %+ more
145+ (ifix [. .]:(star ;~(pose ace (just '\09'))) com)
146+ pairs
147+ ::
148+ ++ pairs
149+ %+ cook
150+ ~(gas by *(map @t @t))
151+ %+ most (ifix [. .]:(star ace) mic)
152+ ;~(plug token ;~(pose ;~(pfix tis value) (easy '')))
153+ ::
154+ ++ value
155+ ;~(pose token quoted-string)
156+ ::
157+ ++ token :: 7230 token
158+ %+ cook crip
159+ ::NOTE this is ptok:de-purl:html, but can't access that here
160+ %- plus
161+ ;~ pose
162+ aln zap hax buc cen pam soq tar lus
163+ hep dot ket cab tic bar sig
164+ ==
165+ ::
166+ ++ quoted-string :: 7230 quoted string
167+ %+ cook crip
168+ %+ ifix [. .]:;~(less (jest '\\"') doq)
169+ %- star
170+ ;~ pose
171+ ;~(pfix bas ;~(pose (just '\09') ace prn))
172+ ;~(pose (just '\09') ;~(less (mask "\22\5c\7f") (shim 0x20 0xff)))
173+ ==
174+ --
175+ :: +simple-payload: a simple, one event response used for generators
176+ ::
177+ +$ simple-payload
178+ $: :: response-header: status code, etc
179+ ::
180+ =response-header
181+ :: data: the data returned as the body
182+ ::
183+ data=(unit octs)
184+ ==
185+ --
186+++ hop
187+ |$ step
188+ $%
189+ [%fetch request:http]
190+ ==
3++ wock-app
191++ wock-app
4− |$ [model event]
192+ |$ [model step]
5 $_ ^?
193 $_ ^?
6 |%
194 |%
7 ++ init *model
195 ++ init *model
8 ++ view |~ model *manx
196 ++ view |~ model *manx
9− ++ move |~ [model event] *model
197+ ++ move |~ [model step] *model
10 --
198 --
11++ app
199++ app
12− |* [model=mold event=mold]
200+ |* [model=mold step=mold]
13− |= app=(wock-app model event)
201+ |= app=(wock-app model step)
14 |= [cmd=@tas args=*]
202 |= [cmd=@tas args=*]
15 ?+ cmd !!
203 ?+ cmd !!
16 %init
204 %init
@@ -18,19 +206,19 @@
18 %view
206 %view
19 (view.app (model args))
207 (view.app (model args))
20 %move
208 %move
21− =/ [=model event-tape=tape payload=*] (,[model tape *] args)
209+ =/ [=model step-tape=tape payload=*] (,[model tape *] args)
22− (move.app [model (event [(crip event-tape) payload])])
210+ (move.app [model (step [(crip step-tape) payload])])
23 ==
211 ==
24--
212--
25=>
213=>
26|%
214|%
27−+$ event
215++$ step
28 $%
216 $%
29 [%inc ~]
217 [%inc ~]
30 [%dec ~]
218 [%dec ~]
31 ==
219 ==
32--
220--
33−%- (app @ud event)
221+%- (app @ud step)
34|%
222|%
35++ view
223++ view
36 |= count=@ud
224 |= count=@ud
@@ -40,9 +228,9 @@
40 ;button(on-click "inc"): +
228 ;button(on-click "inc"): +
41 ;button(on-click "dec"): -
229 ;button(on-click "dec"): -
42 ==
230 ==
43−++ init 8
231+++ init 11
44++ move
232++ move
45− |= [model=@ud step=event]
233+ |= [model=@ud step=step]
46 ^- @ud
234 ^- @ud
47 ?- -.step
235 ?- -.step
48 %inc +(model)
236 %inc +(model)
wock-web/src/lib.rs+31−74
@@ -8,15 +8,17 @@ use dodrio::{
8 bumpalo::{self, Bump},
8 bumpalo::{self, Bump},
9 Attribute, Listener, Node, NodeKey, Render, RenderContext, RootRender, VdomWeak,
9 Attribute, Listener, Node, NodeKey, Render, RenderContext, RootRender, VdomWeak,
10};
10};
11+use gloo::net::{self, http::Request};
11use nock::{
12use nock::{
12 cue::cue_bytes,
13 cue::cue_bytes,
13− interpreter::{generate_interpreter_context, slam, InterpreterContext},
14+ interpreter::{generate_interpreter_context, ram_ttanks, slam, InterpreterContext},
14 noun::{cell, Noun},
15 noun::{cell, Noun},
15− wash,
16};
16};
17use wasm_bindgen::prelude::*;
17use wasm_bindgen::prelude::*;
18−use wasm_bindgen_futures::{spawn_local, JsFuture};
18+use web_sys::{
19−use web_sys::{console::error_1, Element};
19+ console::{error_1, log_1},
20+ Element,
21+};
20
22
21#[wasm_bindgen]
23#[wasm_bindgen]
22extern "C" {
24extern "C" {
@@ -29,41 +31,11 @@ extern "C" {
29 fn error(s: &str);
31 fn error(s: &str);
30}
32}
31
33
32−#[derive(Clone)]
33−struct Urbit {
34− urbit: RefCell<Option<Rc<Noun>>>,
35−}
36−
37−impl Urbit {
38− fn new() -> Urbit {
39− Urbit {
40− urbit: RefCell::new(None),
41− }
42− }
43−
44− async fn get(self: &Self) -> Rc<Noun> {
45− match self.urbit.borrow().clone() {
46− Some(urbit) => urbit,
47− None => {
48− let urbit = load_nock("/urbit.nock").await.unwrap_or_else(|err| {
49− error_1(&err);
50− panic!("Could not load urbit.")
51− });
52−
53− self.urbit.replace(Some(urbit.clone()));
54−
55− urbit
56− }
57− }
58− }
59−}
60−
61#[derive(Clone)]
34#[derive(Clone)]
62struct WockApp {
35struct WockApp {
63 nock: Rc<Noun>,
36 nock: Rc<Noun>,
64 ctx: RefCell<InterpreterContext>,
37 ctx: RefCell<InterpreterContext>,
65 model: Rc<Noun>,
38 model: Rc<Noun>,
66− urbit: Rc<Urbit>,
67}
39}
68
40
69impl<'a> Render<'a> for WockApp {
41impl<'a> Render<'a> for WockApp {
@@ -75,13 +47,9 @@ impl<'a> Render<'a> for WockApp {
75 ) {
47 ) {
76 Ok(sail) => render_sail(cx, sail),
48 Ok(sail) => render_sail(cx, sail),
77 Err(tanks) => {
49 Err(tanks) => {
78− let wock_app = self.clone();
50+ let str = ram_ttanks(&mut (*self).ctx.borrow_mut(), tanks);
79− let mut ctx = (*self.ctx.borrow()).clone();
80− spawn_local(async move {
81− let urbit = wock_app.urbit.get().await;
82− let str = wash(&mut ctx, &urbit, tanks);
83− error_1(&JsValue::from_str(&str));
51+ error_1(&JsValue::from_str(&str));
84− });
52+
85 panic!("Could not render");
53 panic!("Could not render");
86 }
54 }
87 }
55 }
@@ -124,17 +92,20 @@ fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: Rc<Noun>) -> Node<'a> {
124
92
125 let binding = app.ctx.clone();
93 let binding = app.ctx.clone();
126 let mut ctx = binding.borrow_mut();
94 let mut ctx = binding.borrow_mut();
127−
128 let sig = ctx.nouns.sig.clone();
95 let sig = ctx.nouns.sig.clone();
129
96
130− let event = cell(&value, &sig);
97+ let step: Rc<Noun> = Rc::new((value.clone(), sig).into());
131
98
132 match slam(
99 match slam(
133 &mut ctx,
100 &mut ctx,
134 &app.nock,
101 &app.nock,
135− &cell(
102+ &Rc::new(
103+ (
136− &Rc::new(Noun::from_bytes(b"move")),
104+ Noun::from_bytes(b"move").rc(),
137− &cell(&app.model, &event),
105+ app.model.clone(),
106+ step.clone(),
107+ )
108+ .into(),
138 ),
109 ),
139 ) {
110 ) {
140 Ok(new_model) => {
111 Ok(new_model) => {
@@ -142,16 +113,14 @@ fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: Rc<Noun>) -> Node<'a> {
142 vdom.schedule_render();
113 vdom.schedule_render();
143 }
114 }
144 Err(tanks) => {
115 Err(tanks) => {
145− let urbit = app.urbit.clone();
146 let mut ctx = ctx.borrow_mut().clone();
116 let mut ctx = ctx.borrow_mut().clone();
147− spawn_local(async move {
117+
148− let urbit = urbit.get().await;
149− let str = wash(&mut ctx, &urbit, tanks);
118+ let str = ram_ttanks(&mut ctx, tanks);
150− error_1(&JsValue::from_str(&str));
119+ error_1(&JsValue::from_str(&str));
151− });
120+
152 error(&*format!(
121 error(&*format!(
153 "Application failed to process event: {}",
122 "Application failed to process event: {}",
154− event
123+ step
155 ))
124 ))
156 }
125 }
157 };
126 };
@@ -199,14 +168,17 @@ fn tape_to_bump_str<'a>(bump: &'a Bump, non: &Rc<Noun>) -> &'a str {
199#[wasm_bindgen]
168#[wasm_bindgen]
200pub async fn main(path: &str) {
169pub async fn main(path: &str) {
201 let nock = load_nock(path).await.unwrap_or_else(|err| {
170 let nock = load_nock(path).await.unwrap_or_else(|err| {
202− error_1(&err);
171+ error(&*err.to_string());
203 panic!("Could not load nock.")
172 panic!("Could not load nock.")
204 });
173 });
205
174
206 let document = gloo::utils::document();
175 let document = gloo::utils::document();
207 let output_el: Element = document.get_element_by_id("output").unwrap();
176 let output_el: Element = document.get_element_by_id("output").unwrap();
208
177
178+ let mut ctx = InterpreterContext {
179+ slog: |str: &String| log_1(&JsValue::from_str(&*str)),
209− let mut ctx = generate_interpreter_context();
180+ ..generate_interpreter_context()
181+ };
210
182
211 let model = slam(
183 let model = slam(
212 &mut ctx,
184 &mut ctx,
@@ -216,12 +188,7 @@ pub async fn main(path: &str) {
216 let model = match model {
188 let model = match model {
217 Ok(model) => model,
189 Ok(model) => model,
218 Err(tanks) => {
190 Err(tanks) => {
219− let urbit = load_nock("/urbit.nock").await.unwrap_or_else(|err| {
220− error_1(&err);
221− panic!("Could not load urbit.")
222− });
223−
224− let str = wash(&mut ctx, &urbit, tanks);
191+ let str = ram_ttanks(&mut ctx, tanks);
225 error_1(&JsValue::from_str(&str));
192 error_1(&JsValue::from_str(&str));
226 panic!("Could not load initial model.");
193 panic!("Could not load initial model.");
227 }
194 }
@@ -233,25 +200,15 @@ pub async fn main(path: &str) {
233 nock,
200 nock,
234 model,
201 model,
235 ctx: RefCell::new(ctx),
202 ctx: RefCell::new(ctx),
236− urbit: Rc::new(Urbit::new()),
237 },
203 },
238 )
204 )
239 .forget();
205 .forget();
240}
206}
241
207
242−pub async fn load_nock(path: &str) -> Result<Rc<Noun>, JsValue> {
208+pub async fn load_nock(path: &str) -> Result<Rc<Noun>, net::Error> {
243− let window = web_sys::window().unwrap();
209+ let blob = Request::get(path).send().await?.binary().await?;
244−
245− let resp = JsFuture::from(window.fetch_with_str(path)).await?;
246− assert!(resp.is_instance_of::<web_sys::Response>());
247− let resp: web_sys::Response = resp.dyn_into()?;
248− let blob = JsFuture::from(resp.blob()?).await?;
249− assert!(blob.is_instance_of::<web_sys::Blob>());
250− let blob: web_sys::Blob = blob.dyn_into()?;
251−
252− let nock = js_sys::Uint8Array::new(&JsFuture::from(blob.array_buffer()).await?).to_vec();
253
210
254− let nock = cue_bytes(&*nock);
211+ let nock = cue_bytes(&*blob);
255 let (_typ, nok) = nock.as_cell().unwrap();
212 let (_typ, nok) = nock.as_cell().unwrap();
256
213
257 Ok(nok.clone())
214 Ok(nok.clone())
wock.nock

Binary file not shown.