on master help sign in
fff3a22iko
flake.lock+56
@@ -1,5 +1,26 @@
1{
1{
2 "nodes": {
2 "nodes": {
3+ "fenix": {
4+ "inputs": {
5+ "nixpkgs": [
6+ "nixpkgs"
7+ ],
8+ "rust-analyzer-src": "rust-analyzer-src"
9+ },
10+ "locked": {
11+ "lastModified": 1725863722,
12+ "narHash": "sha256-YBcCMVp9RrN2rgqhsMhpu/iw7L8z17N4fp4A129IZ3w=",
13+ "owner": "nix-community",
14+ "repo": "fenix",
15+ "rev": "c30b094741641eef4a7200a5d52a8a16f0f345c6",
16+ "type": "github"
17+ },
18+ "original": {
19+ "owner": "nix-community",
20+ "repo": "fenix",
21+ "type": "github"
22+ }
23+ },
3 "flake-utils": {
24 "flake-utils": {
4 "inputs": {
25 "inputs": {
5 "systems": "systems"
26 "systems": "systems"
@@ -66,6 +87,22 @@
66 "type": "github"
87 "type": "github"
67 }
88 }
68 },
89 },
90+ "nockapp": {
91+ "flake": false,
92+ "locked": {
93+ "lastModified": 1725567177,
94+ "narHash": "sha256-2HvzgctPBXBXZEZi9fF3RKST4i6WtKaTx/v1/3t5sVo=",
95+ "owner": "zorp-corp",
96+ "repo": "nockapp",
97+ "rev": "cbe14c452106dd929a0dee013389049888e838df",
98+ "type": "github"
99+ },
100+ "original": {
101+ "owner": "zorp-corp",
102+ "repo": "nockapp",
103+ "type": "github"
104+ }
105+ },
69 "pdjson": {
106 "pdjson": {
70 "flake": false,
107 "flake": false,
71 "locked": {
108 "locked": {
@@ -84,10 +121,12 @@
84 },
121 },
85 "root": {
122 "root": {
86 "inputs": {
123 "inputs": {
124+ "fenix": "fenix",
87 "flake-utils": "flake-utils",
125 "flake-utils": "flake-utils",
88 "libaes_siv": "libaes_siv",
126 "libaes_siv": "libaes_siv",
89 "murmur3": "murmur3",
127 "murmur3": "murmur3",
90 "nixpkgs": "nixpkgs",
128 "nixpkgs": "nixpkgs",
129+ "nockapp": "nockapp",
91 "pdjson": "pdjson",
130 "pdjson": "pdjson",
92 "sha256": "sha256",
131 "sha256": "sha256",
93 "softfloat": "softfloat",
132 "softfloat": "softfloat",
@@ -95,6 +134,23 @@
95 "vere": "vere"
134 "vere": "vere"
96 }
135 }
97 },
136 },
137+ "rust-analyzer-src": {
138+ "flake": false,
139+ "locked": {
140+ "lastModified": 1725630423,
141+ "narHash": "sha256-gNCLk3Zg7JlAwmWbVHTH6f3+iqdeQ4fheOotCZy8x5M=",
142+ "owner": "rust-lang",
143+ "repo": "rust-analyzer",
144+ "rev": "08c7bbc2dbe4dcc8968484f1a0e1e6fe7a1d4f6d",
145+ "type": "github"
146+ },
147+ "original": {
148+ "owner": "rust-lang",
149+ "ref": "nightly",
150+ "repo": "rust-analyzer",
151+ "type": "github"
152+ }
153+ },
98 "sha256": {
154 "sha256": {
99 "flake": false,
155 "flake": false,
100 "locked": {
156 "locked": {
flake.nix+35−2
@@ -31,9 +31,17 @@
31 url = "github:dfoxfranke/libaes_siv";
31 url = "github:dfoxfranke/libaes_siv";
32 flake = false;
32 flake = false;
33 };
33 };
34+ nockapp = {
35+ url = "github:zorp-corp/nockapp";
36+ flake = false;
37+ };
38+ fenix = {
39+ url = "github:nix-community/fenix";
40+ inputs.nixpkgs.follows = "nixpkgs";
41+ };
34 };
42 };
35− outputs =
36− inputs@{ self, nixpkgs, flake-utils, vere, murmur3, pdjson, sha256, ... }:
43+ outputs = inputs@{ self, nixpkgs, flake-utils, vere, murmur3, pdjson, sha256
44+ , fenix, ... }:
37 flake-utils.lib.eachDefaultSystem (system:
45 flake-utils.lib.eachDefaultSystem (system:
38 let
46 let
39 pkgs = import nixpkgs {
47 pkgs = import nixpkgs {
@@ -42,6 +50,31 @@
42 };
50 };
43 in {
51 in {
44 packages = rec {
52 packages = rec {
53+ nockapp = (let toolchain = fenix.packages.${system}.minimal.toolchain;
54+ in pkgs.makeRustPlatform {
55+ rustc = toolchain;
56+ cargo = toolchain;
57+ }).buildRustPackage {
58+ doCheck = false;
59+ name = "nockapp";
60+ src = inputs.nockapp;
61+
62+ cargoLock = {
63+ lockFile = "${inputs.nockapp}/Cargo.lock";
64+ allowBuiltinFetchGit = true;
65+ };
66+ LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
67+ BINDGEN_EXTRA_CLANG_ARGS = [
68+ "-I${pkgs.glibc.dev}/include"
69+ "-I${pkgs.libclang.lib}/lib/clang/17/include"
70+ ];
71+ };
72+ urbit-nock = pkgs.runCommand "urbit.nock" { } ''
73+ mkdir -p source
74+ cp ${./urbit.hoon} source/urbit.hoon
75+ ${nockapp}/bin/choo source/urbit.hoon source
76+ cp out.jam $out
77+ '';
45 gmp = pkgs.runCommand "gmp" {
78 gmp = pkgs.runCommand "gmp" {
46 buildInputs = with pkgs; [ gnutar emscripten gcc ];
79 buildInputs = with pkgs; [ gnutar emscripten gcc ];
47 } ''
80 } ''
nock/Cargo.lock+7
@@ -168,6 +168,12 @@ dependencies = [
168 "wasm-bindgen",
168 "wasm-bindgen",
169]
169]
170
170
171+[[package]]
172+name = "fplist"
173+version = "0.2.1"
174+source = "registry+https://github.com/rust-lang/crates.io-index"
175+checksum = "1cadb436ce55a7716dd5b977b93a79a819a9b9bbc5746ba9e607cd389836aa8f"
176+
171[[package]]
177[[package]]
172name = "funty"
178name = "funty"
173version = "2.0.0"
179version = "2.0.0"
@@ -238,6 +244,7 @@ dependencies = [
238 "bitvec",
244 "bitvec",
239 "clap",
245 "clap",
240 "console_error_panic_hook",
246 "console_error_panic_hook",
247+ "fplist",
241 "murmur3",
248 "murmur3",
242 "num-bigint",
249 "num-bigint",
243 "num-integer",
250 "num-integer",
nock/Cargo.toml+1
@@ -29,6 +29,7 @@ bitvec = "1.0.1"
29stacker = "0.1.17"
29stacker = "0.1.17"
30murmur3 = "0.5.2"
30murmur3 = "0.5.2"
31web-sys = "0.3.70"
31web-sys = "0.3.70"
32+fplist = "0.2.1"
32
33
33[dependencies.xxhash-rust]
34[dependencies.xxhash-rust]
34version = "0.8.5"
35version = "0.8.5"
nock/res/wash.nocknew file

Binary file not shown.

nock/src/interpreter.rs+76−57
@@ -2,6 +2,9 @@ use std::borrow::Borrow;
2use std::collections::BTreeMap;
2use std::collections::BTreeMap;
3use std::rc::Rc;
3use std::rc::Rc;
4
4
5+use bitvec::prelude;
6+use fplist::cons;
7+use fplist::PersistentList;
5use num_bigint::BigUint;
8use num_bigint::BigUint;
6
9
7use crate::jets::*;
10use crate::jets::*;
@@ -18,6 +21,7 @@ pub struct Nouns {
18 pub sig_one: Rc<Noun>,
21 pub sig_one: Rc<Noun>,
19 pub two_three: Rc<Noun>,
22 pub two_three: Rc<Noun>,
20 pub memo: Rc<Noun>,
23 pub memo: Rc<Noun>,
24+ pub mean: Rc<Noun>,
21}
25}
22
26
23pub struct BigUints {
27pub struct BigUints {
@@ -54,6 +58,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
54 let sig_one = cell(&sig, &one);
58 let sig_one = cell(&sig, &one);
55 let two_three = cell(&two, &three);
59 let two_three = cell(&two, &three);
56 let memo = Rc::new(Noun::from_bytes(b"memo"));
60 let memo = Rc::new(Noun::from_bytes(b"memo"));
61+ let mean = Rc::new(Noun::from_bytes(b"mean"));
57 InterpreterContext {
62 InterpreterContext {
58 jets,
63 jets,
59 double_jets,
64 double_jets,
@@ -68,6 +73,7 @@ pub fn generate_interpreter_context() -> InterpreterContext {
68 sig_one,
73 sig_one,
69 two_three,
74 two_three,
70 memo,
75 memo,
76+ mean,
71 },
77 },
72 big_uints,
78 big_uints,
73 memo: BTreeMap::new(),
79 memo: BTreeMap::new(),
@@ -81,10 +87,10 @@ fn wut<'a>(ctx: &'a InterpreterContext, noun: &Noun) -> &'a Rc<Noun> {
81 }
87 }
82}
88}
83
89
84−fn lus(noun: &Noun) -> Option<Noun> {
90+fn lus(noun: &Noun) -> Result<Noun, Tanks> {
85 match noun {
91 match noun {
86− Noun::Cell { .. } => None,
92+ Noun::Cell { .. } => Err(PersistentList::new()),
87− Noun::Atom(atm) => Some(Noun::Atom(atm + 1u32)),
93+ Noun::Atom(atm) => Ok(Noun::Atom(atm + 1u32)),
88 }
94 }
89}
95}
90
96
@@ -96,15 +102,15 @@ fn tis<'a>(ctx: &'a InterpreterContext, lhs: &Noun, rhs: &Noun) -> &'a Rc<Noun>
96 }
102 }
97}
103}
98
104
99−fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Option<Rc<Noun>> {
105+fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Result<Rc<Noun>, Tanks> {
100 let mut addr_iter = addr.iter_u32_digits();
106 let mut addr_iter = addr.iter_u32_digits();
101
107
102 match (addr_iter.next(), addr_iter.next()) {
108 match (addr_iter.next(), addr_iter.next()) {
103− (None, _) => None,
109+ (None, _) => Err(PersistentList::new()),
104 (Some(x), None) => fas_u32(x, noun),
110 (Some(x), None) => fas_u32(x, noun),
105 _ => {
111 _ => {
106 let rest = fas(ctx, &(addr >> 1u8), noun)?;
112 let rest = fas(ctx, &(addr >> 1u8), noun)?;
107− Some(fas_u32(
113+ Ok(fas_u32(
108 if (addr & &ctx.big_uints.one) == ctx.big_uints.one {
114 if (addr & &ctx.big_uints.one) == ctx.big_uints.one {
109 3
115 3
110 } else {
116 } else {
@@ -116,15 +122,15 @@ fn fas(ctx: &InterpreterContext, addr: &Atom, noun: &Noun) -> Option<Rc<Noun>> {
116 }
122 }
117}
123}
118
124
119−fn fas_u32(addr: u32, noun: &Noun) -> Option<Rc<Noun>> {
125+fn fas_u32(addr: u32, noun: &Noun) -> Result<Rc<Noun>, Tanks> {
120 match addr {
126 match addr {
121− 0 => None,
127+ 0 => Err(PersistentList::new()),
122− 1 => Some(Rc::new(noun.clone())),
128+ 1 => Ok(Rc::new(noun.clone())),
123 n => match noun {
129 n => match noun {
124− Noun::Atom(_) => None,
130+ Noun::Atom(_) => Err(PersistentList::new()),
125 Noun::Cell { p, q, .. } => match n {
131 Noun::Cell { p, q, .. } => match n {
126− 2 => Some(p.clone()),
132+ 2 => Ok(p.clone()),
127− 3 => Some(q.clone()),
133+ 3 => Ok(q.clone()),
128 _ => {
134 _ => {
129 let rest = fas_u32(n >> 1, &cell(p, q))?;
135 let rest = fas_u32(n >> 1, &cell(p, q))?;
130 fas_u32(if (n & 1) == 1 { 3 } else { 2 }, &rest)
136 fas_u32(if (n & 1) == 1 { 3 } else { 2 }, &rest)
@@ -134,10 +140,10 @@ fn fas_u32(addr: u32, noun: &Noun) -> Option<Rc<Noun>> {
134 }
140 }
135}
141}
136
142
137−fn hax_u32(addr: u32, new_value: &Rc<Noun>, target: &Rc<Noun>) -> Option<Rc<Noun>> {
143+fn hax_u32(addr: u32, new_value: &Rc<Noun>, target: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
138 match addr {
144 match addr {
139− 0 => None,
145+ 0 => Err(PersistentList::new()),
140− 1 => Some(new_value.clone()),
146+ 1 => Ok(new_value.clone()),
141 _ => {
147 _ => {
142 let new_value = if (addr & 1) == 1 {
148 let new_value = if (addr & 1) == 1 {
143 let foo = fas_u32(addr - 1, &target)?;
149 let foo = fas_u32(addr - 1, &target)?;
@@ -156,11 +162,11 @@ fn hax(
156 addr: &Atom,
162 addr: &Atom,
157 new_value: &Rc<Noun>,
163 new_value: &Rc<Noun>,
158 target: &Rc<Noun>,
164 target: &Rc<Noun>,
159−) -> Option<Rc<Noun>> {
165+) -> Result<Rc<Noun>, Tanks> {
160 let mut addr_iter = addr.iter_u32_digits();
166 let mut addr_iter = addr.iter_u32_digits();
161
167
162 match (addr_iter.next(), addr_iter.next()) {
168 match (addr_iter.next(), addr_iter.next()) {
163− (None, _) => None,
169+ (None, _) => Err(Tanks::new()),
164 (Some(x), None) => hax_u32(x, new_value, target),
170 (Some(x), None) => hax_u32(x, new_value, target),
165 _ => hax(
171 _ => hax(
166 ctx,
172 ctx,
@@ -182,15 +188,15 @@ fn tar_u32<'a>(
182 subj: Rc<Noun>,
188 subj: Rc<Noun>,
183 op: u32,
189 op: u32,
184 formula: &'a Rc<Noun>,
190 formula: &'a Rc<Noun>,
185−) -> Option<Rc<Noun>> {
191+) -> Result<Rc<Noun>, Tanks> {
186 match op {
192 match op {
187 0 => {
193 0 => {
188− let b = formula.as_atom()?;
194+ let b = formula.as_atom().ok_or(Tanks::new())?;
189 fas(ctx, b, &*subj)
195 fas(ctx, b, &*subj)
190 }
196 }
191− 1 => Some(formula.clone()),
197+ 1 => Ok(formula.clone()),
192 2 => {
198 2 => {
193− let (b, c) = formula.as_cell()?;
199+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
194
200
195 match c.borrow() {
201 match c.borrow() {
196 Noun::Cell { p, q, .. }
202 Noun::Cell { p, q, .. }
@@ -217,21 +223,21 @@ fn tar_u32<'a>(
217 }
223 }
218 3 => {
224 3 => {
219 let foo = tar(ctx, subj, &formula)?;
225 let foo = tar(ctx, subj, &formula)?;
220− Some(wut(ctx, &foo).clone())
226+ Ok(wut(ctx, &foo).clone())
221 }
227 }
222 4 => {
228 4 => {
223 let foo = tar(ctx, subj, &formula)?;
229 let foo = tar(ctx, subj, &formula)?;
224− Some(Rc::new(lus(&foo)?))
230+ Ok(Rc::new(lus(&foo)?))
225 }
231 }
226 5 => {
232 5 => {
227− let (b, c) = formula.as_cell()?;
233+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
228 let foo = tar(ctx, subj.clone(), &b)?;
234 let foo = tar(ctx, subj.clone(), &b)?;
229 let bar = tar(ctx, subj, &c)?;
235 let bar = tar(ctx, subj, &c)?;
230− Some(tis(ctx, &foo, &bar).clone())
236+ Ok(tis(ctx, &foo, &bar).clone())
231 }
237 }
232 6 => {
238 6 => {
233− let (b, c) = formula.as_cell()?;
239+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
234− let (c, d) = c.as_cell()?;
240+ let (c, d) = c.as_cell().ok_or(Tanks::new())?;
235
241
236 let bar = tar_u32(ctx, subj.clone(), 4, &cell(&ctx.nouns.four.clone(), &b))?;
242 let bar = tar_u32(ctx, subj.clone(), 4, &cell(&ctx.nouns.four.clone(), &b))?;
237
243
@@ -241,17 +247,17 @@ fn tar_u32<'a>(
241 tar(ctx, subj, &foo)
247 tar(ctx, subj, &foo)
242 }
248 }
243 7 => {
249 7 => {
244− let (b, c) = formula.as_cell()?;
250+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
245 let foo = tar(ctx, subj, &b)?;
251 let foo = tar(ctx, subj, &b)?;
246 tar(ctx, foo, &c)
252 tar(ctx, foo, &c)
247 }
253 }
248 8 => {
254 8 => {
249− let (b, c) = formula.as_cell()?;
255+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
250 let foo = tar(ctx, subj.clone(), &b)?;
256 let foo = tar(ctx, subj.clone(), &b)?;
251 tar(ctx, cell(&foo, &subj), &c)
257 tar(ctx, cell(&foo, &subj), &c)
252 }
258 }
253 9 => {
259 9 => {
254− let (b, c) = formula.as_cell()?;
260+ let (b, c) = formula.as_cell().ok_or(Tanks::new())?;
255 let foo = tar(ctx, subj, &c)?;
261 let foo = tar(ctx, subj, &c)?;
256 tar_u32(
262 tar_u32(
257 ctx,
263 ctx,
@@ -261,55 +267,68 @@ fn tar_u32<'a>(
261 )
267 )
262 }
268 }
263 10 => {
269 10 => {
264− let (b, d) = formula.as_cell()?;
270+ let (b, d) = formula.as_cell().ok_or(Tanks::new())?;
265− let (b, c) = b.as_cell()?;
271+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
266− let b = b.as_atom()?;
272+ let b = b.as_atom().ok_or(Tanks::new())?;
267
273
268 let foo = tar(ctx, subj.clone(), &c)?;
274 let foo = tar(ctx, subj.clone(), &c)?;
269 let bar = tar(ctx, subj, &d)?;
275 let bar = tar(ctx, subj, &d)?;
270 hax(ctx, b, &foo, &bar)
276 hax(ctx, b, &foo, &bar)
271 }
277 }
272 11 => {
278 11 => {
273− let (b, d) = formula.as_cell()?;
279+ let (b, d) = formula.as_cell().ok_or(Tanks::new())?;
274 match b.borrow() {
280 match b.borrow() {
275 Noun::Atom(_) => tar(ctx, subj, &d),
281 Noun::Atom(_) => tar(ctx, subj, &d),
276 Noun::Cell { p, q, .. } => {
282 Noun::Cell { p, q, .. } => {
283+ let eval = |ctx: &mut InterpreterContext| tar(ctx, subj.clone(), &d);
277 if *p == ctx.nouns.memo {
284 if *p == ctx.nouns.memo {
278− let hash = cell(&subj, formula).hash();
285+ let hash = cell(&subj, &d).hash();
279 match ctx.memo.get(&hash) {
286 match ctx.memo.get(&hash) {
280− Some(target) => Some(target.clone()),
287+ Some(target) => Ok(target.clone()),
281 None => {
288 None => {
282− let foo = cell(
289+ let target = eval(ctx)?;
283− &tar(ctx, subj.clone(), &q)?,
284− &tar(ctx, subj.clone(), &d)?,
285− );
286− let target = tar_u32(ctx, foo, 0, &ctx.nouns.three.clone())?;
287 ctx.memo.insert(hash, target.clone());
290 ctx.memo.insert(hash, target.clone());
288− Some(target)
291+ Ok(target)
289 }
292 }
290 }
293 }
294+ } else if *p == ctx.nouns.mean {
295+ let gate = tar(ctx, subj.clone(), q)?;
296+ let trace = eval_pulled_gate(ctx, gate)?;
297+ with_trace(trace, eval(ctx))
291 } else {
298 } else {
292− let foo = cell(&tar(ctx, subj.clone(), &q)?, &tar(ctx, subj.clone(), &d)?);
299+ eval(ctx)
293− tar_u32(ctx, foo, 0, &ctx.nouns.three.clone())
294 }
300 }
295 }
301 }
296 }
302 }
297 }
303 }
298− _ => None,
304+ _ => Err(Tanks::new()),
299 }
305 }
300}
306}
301
307
308+fn with_trace<T>(tank: Tank, src: Result<T, Tanks>) -> Result<T, Tanks> {
309+ println!("{tank}");
310+ match src {
311+ Ok(a) => Ok(a),
312+ Err(tanks) => Err(cons(tank, tanks)),
313+ }
314+}
315+
316+pub type Tank = Rc<Noun>;
317+pub type Tanks = PersistentList<Tank>;
318+
319+pub const EMPTY_TANKS: Tanks = Tanks::new();
320+
302pub fn tar<'a>(
321pub fn tar<'a>(
303 ctx: &mut InterpreterContext,
322 ctx: &mut InterpreterContext,
304 subj: Rc<Noun>,
323 subj: Rc<Noun>,
305 formula: &'a Noun,
324 formula: &'a Noun,
306−) -> Option<Rc<Noun>> {
325+) -> Result<Rc<Noun>, Tanks> {
307− let (op, formula) = formula.as_cell()?;
326+ let (op, formula) = formula.as_cell().ok_or(Tanks::new())?;
308 match op.borrow() {
327 match op.borrow() {
309 Noun::Cell { .. } => {
328 Noun::Cell { .. } => {
310 let foo = tar(ctx, subj.clone(), &op)?;
329 let foo = tar(ctx, subj.clone(), &op)?;
311 let bar = tar(ctx, subj, &formula)?;
330 let bar = tar(ctx, subj, &formula)?;
312− Some(cell(&foo, &bar))
331+ Ok(cell(&foo, &bar))
313 }
332 }
314 Noun::Atom(ref op) => {
333 Noun::Atom(ref op) => {
315 let mut op_iter = op.iter_u32_digits();
334 let mut op_iter = op.iter_u32_digits();
@@ -318,13 +337,13 @@ pub fn tar<'a>(
318 1 => Some(op_iter.next().unwrap()),
337 1 => Some(op_iter.next().unwrap()),
319 _ => None,
338 _ => None,
320 };
339 };
321− let op = op?;
340+ let op = op.ok_or(Tanks::new())?;
322 stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, subj, op, formula))
341 stacker::maybe_grow(32 * 1024, 1024 * 1024, || tar_u32(ctx, subj, op, formula))
323 }
342 }
324 }
343 }
325}
344}
326
345
327−pub fn eval_gate(ctx: &mut InterpreterContext, gate_factory: &Rc<Noun>) -> Option<Rc<Noun>> {
346+pub fn eval_gate(ctx: &mut InterpreterContext, gate_factory: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
328 let pulled_gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
347 let pulled_gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
329 eval_pulled_gate(ctx, pulled_gate)
348 eval_pulled_gate(ctx, pulled_gate)
330}
349}
@@ -333,7 +352,7 @@ pub fn slam(
333 ctx: &mut InterpreterContext,
352 ctx: &mut InterpreterContext,
334 gate_factory: &Rc<Noun>,
353 gate_factory: &Rc<Noun>,
335 sample: &Rc<Noun>,
354 sample: &Rc<Noun>,
336−) -> Option<Rc<Noun>> {
355+) -> Result<Rc<Noun>, Tanks> {
337 let gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
356 let gate = tar(ctx, ctx.nouns.sig.clone(), &gate_factory)?;
338
357
339 eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
358 eval_pulled_gate(ctx, replace_sample(&gate, sample)?)
@@ -341,7 +360,7 @@ pub fn slam(
341
360
342/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
361/// This is useful for evaluaing gates produced by running `.foo/nock gate-name` in the dojo.
343/// Also for calling gates from within jets.
362/// Also for calling gates from within jets.
344−pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Option<Rc<Noun>> {
363+pub fn eval_pulled_gate(ctx: &mut InterpreterContext, gate: Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
345 tar(
364 tar(
346 ctx,
365 ctx,
347 gate,
366 gate,
@@ -358,13 +377,13 @@ pub fn slam_pulled_gate(
358 ctx: &mut InterpreterContext,
377 ctx: &mut InterpreterContext,
359 gate: &Rc<Noun>,
378 gate: &Rc<Noun>,
360 sample: &Rc<Noun>,
379 sample: &Rc<Noun>,
361−) -> Option<Rc<Noun>> {
380+) -> Result<Rc<Noun>, Tanks> {
362 eval_pulled_gate(ctx, replace_sample(gate, sample)?)
381 eval_pulled_gate(ctx, replace_sample(gate, sample)?)
363}
382}
364
383
365−pub fn replace_sample(gate: &Rc<Noun>, sample: &Rc<Noun>) -> Option<Rc<Noun>> {
384+pub fn replace_sample(gate: &Rc<Noun>, sample: &Rc<Noun>) -> Result<Rc<Noun>, Tanks> {
366− let (battery, payload) = gate.as_cell()?;
385+ let (battery, payload) = gate.as_cell().ok_or(Tanks::new())?;
367− let (_sample, context) = payload.as_cell()?;
386+ let (_sample, context) = payload.as_cell().ok_or(Tanks::new())?;
368
387
369− Some(cell(battery, &cell(sample, context)))
388+ Ok(cell(battery, &cell(sample, context)))
370}
389}
nock/src/jets.rs+268−212
@@ -8,18 +8,20 @@ use std::{
8};
8};
9
9
10use crate::{
10use crate::{
11− interpreter::{slam_pulled_gate, InterpreterContext},
11+ interpreter::{slam_pulled_gate, InterpreterContext, Tanks},
12 noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
12 noun::{self, cell, Atom, Edge, Hair, Nail, Noun},
13};
13};
14
14
15−fn traverse_iter_option<T: Clone, I: Iterator<Item = Option<T>>>(xs: I) -> Option<Vec<T>> {
15+fn traverse_iter_result<E: Clone, T: Clone, I: Iterator<Item = Result<T, E>>>(
16+ xs: I,
17+) -> Result<Vec<T>, E> {
16 let mut target: Vec<T> = Vec::new();
18 let mut target: Vec<T> = Vec::new();
17
19
18 for x in xs {
20 for x in xs {
19 target.push(x.clone()?)
21 target.push(x.clone()?)
20 }
22 }
21
23
22− Some(target)
24+ Ok(target)
23}
25}
24
26
25pub type Jets = BTreeMap<noun::Hash, Jet>;
27pub type Jets = BTreeMap<noun::Hash, Jet>;
@@ -108,39 +110,51 @@ pub fn generate_jets() -> Jets {
108 ])
110 ])
109}
111}
110
112
111−pub type Jet = fn(ctx: &mut InterpreterContext, &Rc<Noun>) -> Option<Rc<Noun>>;
113+pub type Jet = fn(ctx: &mut InterpreterContext, &Rc<Noun>) -> Result<Rc<Noun>, Tanks>;
112pub type DoubleJet = fn(ctx: &mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
114pub type DoubleJet = fn(ctx: &mut InterpreterContext, &Rc<Noun>, &Rc<Noun>) -> Option<Rc<Noun>>;
113
115
114−static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Option<Rc<Noun>> =
116+static BINARY_ATOM: fn(&Rc<Noun>, fn(&Atom, &Atom) -> Atom) -> Result<Rc<Noun>, Tanks> =
115 |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
117 |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> Atom| {
116− let (p, q) = n.as_cell()?;
118+ let (p, q) = n.as_cell().ok_or(Tanks::new())?;
117− Some(Rc::new(Noun::Atom(f(p.as_atom()?, q.as_atom()?))))
119+ Ok(Rc::new(Noun::Atom(f(
120+ p.as_atom().ok_or(Tanks::new())?,
121+ q.as_atom().ok_or(Tanks::new())?,
122+ ))))
118 };
123 };
119
124
120static BINARY_ATOM_LOOB: fn(
125static BINARY_ATOM_LOOB: fn(
121 &InterpreterContext,
126 &InterpreterContext,
122 &Rc<Noun>,
127 &Rc<Noun>,
123 fn(&Atom, &Atom) -> bool,
128 fn(&Atom, &Atom) -> bool,
129+) -> Result<Rc<Noun>, Tanks> =
124−) -> Option<Rc<Noun>> = |ctx: &InterpreterContext, n: &Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
130+ |ctx: &InterpreterContext, n: &Rc<Noun>, f: fn(&Atom, &Atom) -> bool| {
125− let (p, q) = n.as_cell()?;
131+ let (p, q) = n.as_cell().ok_or(Tanks::new())?;
126−
132+
133+ if f(
127− if f(p.as_atom()?, q.as_atom()?) {
134+ p.as_atom().ok_or(Tanks::new())?,
135+ q.as_atom().ok_or(Tanks::new())?,
136+ ) {
128− Some(ctx.nouns.sig.clone())
137+ Ok(ctx.nouns.sig.clone())
129− } else {
138+ } else {
130− Some(ctx.nouns.one.clone())
139+ Ok(ctx.nouns.one.clone())
131− }
140+ }
132−};
141+ };
133
142
134−static BINARY_ATOM_PAIR: fn(&Rc<Noun>, fn(&Atom, &Atom) -> (Atom, Atom)) -> Option<Rc<Noun>> =
143+static BINARY_ATOM_PAIR: fn(
144+ &Rc<Noun>,
145+ fn(&Atom, &Atom) -> (Atom, Atom),
135− |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
146+) -> Result<Rc<Noun>, Tanks> = |n: &Rc<Noun>, f: fn(&Atom, &Atom) -> (Atom, Atom)| {
136− let (p, q) = n.as_cell()?;
147+ let (p, q) = n.as_cell().ok_or(Tanks::new())?;
137
148
138− let (a, b) = f(p.as_atom()?, q.as_atom()?);
149+ let (a, b) = f(
150+ p.as_atom().ok_or(Tanks::new())?,
151+ q.as_atom().ok_or(Tanks::new())?,
152+ );
139− Some(cell(&Rc::new(Noun::Atom(a)), &Rc::new(Noun::Atom(b))))
153+ Ok(cell(&Rc::new(Noun::Atom(a)), &Rc::new(Noun::Atom(b))))
140− };
154+};
141
155
142static ADD: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a + b);
156static ADD: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a + b);
143−static DEC: Jet = |_ctx, n| Some(Rc::new(Noun::Atom(n.as_atom()? - 1u32)));
157+static DEC: Jet = |_ctx, n| Ok(Rc::new(Noun::Atom(n.as_atom().ok_or(Tanks::new())? - 1u32)));
144static DVR: Jet = |_ctx, n| BINARY_ATOM_PAIR(n, |a, b| a.div_rem(&b));
158static DVR: Jet = |_ctx, n| BINARY_ATOM_PAIR(n, |a, b| a.div_rem(&b));
145static DIV: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a / b);
159static DIV: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a / b);
146static GTE: Jet = |ctx, n| BINARY_ATOM_LOOB(ctx, n, |a, b| a >= b);
160static GTE: Jet = |ctx, n| BINARY_ATOM_LOOB(ctx, n, |a, b| a >= b);
@@ -154,29 +168,31 @@ static MUL: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a * b);
154static SUB: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a - b);
168static SUB: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a - b);
155
169
156static CAP: Jet = |ctx, n| {
170static CAP: Jet = |ctx, n| {
157− let n = n.as_atom()?;
171+ let n = n.as_atom().ok_or(Tanks::new())?;
158 CAP_ATOM(ctx, n.clone())
172 CAP_ATOM(ctx, n.clone())
159};
173};
160
174
161−static CAP_ATOM: fn(&InterpreterContext, Atom) -> Option<Rc<Noun>> = |ctx, n: Atom| {
175+static CAP_ATOM: fn(&InterpreterContext, Atom) -> Result<Rc<Noun>, Tanks> = |ctx, n: Atom| {
162 let mut n_iter = n.iter_u32_digits();
176 let mut n_iter = n.iter_u32_digits();
163
177
164 match n_iter.len() {
178 match n_iter.len() {
165− 0 => None,
179+ 0 => Err(Tanks::new()),
166 1 => CAP_U32(ctx, n_iter.next().unwrap()),
180 1 => CAP_U32(ctx, n_iter.next().unwrap()),
167 _ => CAP_ATOM(ctx, n >> 1),
181 _ => CAP_ATOM(ctx, n >> 1),
168 }
182 }
169};
183};
170−static CAP_U32: fn(ctx: &InterpreterContext, u32) -> Option<Rc<Noun>> = |ctx, n| match n {
184+static CAP_U32: fn(ctx: &InterpreterContext, u32) -> Result<Rc<Noun>, Tanks> = |ctx, n| match n {
171− 0 | 1 => None,
185+ 0 | 1 => Err(Tanks::new()),
172− 2 => Some(ctx.nouns.two.clone()),
186+ 2 => Ok(ctx.nouns.two.clone()),
173− 3 => Some(ctx.nouns.three.clone()),
187+ 3 => Ok(ctx.nouns.three.clone()),
174 n => CAP_U32(ctx, n >> 1),
188 n => CAP_U32(ctx, n >> 1),
175};
189};
176
190
177static MAS: Jet = |ctx, n| {
191static MAS: Jet = |ctx, n| {
178− let n = n.as_atom()?;
192+ let n = n.as_atom().ok_or(Tanks::new())?;
179− Some(Rc::new(Noun::Atom(MAS_ATOM(ctx, n.clone())?)))
193+ Ok(Rc::new(Noun::Atom(
194+ MAS_ATOM(ctx, n.clone()).ok_or(Tanks::new())?,
195+ )))
180};
196};
181static MAS_ATOM: fn(&InterpreterContext, Atom) -> Option<Atom> = |ctx, n| {
197static MAS_ATOM: fn(&InterpreterContext, Atom) -> Option<Atom> = |ctx, n| {
182 let mut n_iter = n.iter_u32_digits();
198 let mut n_iter = n.iter_u32_digits();
@@ -197,24 +213,24 @@ static MAS_U32: fn(u32) -> u32 = |n| match n {
197};
213};
198
214
199static PEG: Jet = |ctx, n| {
215static PEG: Jet = |ctx, n| {
200− let (a, b) = n.as_cell()?;
216+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
201
217
202− let a = a.as_atom()?;
218+ let a = a.as_atom().ok_or(Tanks::new())?;
203− let b = b.as_atom()?;
219+ let b = b.as_atom().ok_or(Tanks::new())?;
204
220
205 if *a == Atom::ZERO {
221 if *a == Atom::ZERO {
206− return None;
222+ return Err(Tanks::new());
207 };
223 };
208
224
209− Some(Rc::new(Noun::Atom(PEG_ATOM(ctx, a, b.clone())?)))
225+ Ok(Rc::new(Noun::Atom(PEG_ATOM(ctx, a, b.clone())?)))
210};
226};
211−static PEG_ATOM: fn(&InterpreterContext, &Atom, Atom) -> Option<Atom> = |ctx, a, b| {
227+static PEG_ATOM: fn(&InterpreterContext, &Atom, Atom) -> Result<Atom, Tanks> = |ctx, a, b| {
212 let mut b_iter = b.iter_u32_digits();
228 let mut b_iter = b.iter_u32_digits();
213
229
214 match b_iter.len() {
230 match b_iter.len() {
215− 0 => None,
231+ 0 => Err(Tanks::new()),
216− 1 => Some(PEG_U32(a, b_iter.next().unwrap())),
232+ 1 => Ok(PEG_U32(a, b_iter.next().unwrap())),
217− _ => Some((&b & &ctx.big_uints.one) + (PEG_ATOM(ctx, a, b >> 1)? << 1)),
233+ _ => Ok((&b & &ctx.big_uints.one) + (PEG_ATOM(ctx, a, b >> 1)? << 1)),
218 }
234 }
219};
235};
220static PEG_U32: fn(&Atom, u32) -> Atom = |a, b| match b {
236static PEG_U32: fn(&Atom, u32) -> Atom = |a, b| match b {
@@ -226,9 +242,9 @@ static PEG_U32: fn(&Atom, u32) -> Atom = |a, b| match b {
226};
242};
227
243
228static FAND: Jet = |ctx, n| {
244static FAND: Jet = |ctx, n| {
229− let (nedl, hstk) = n.as_cell()?;
245+ let (nedl, hstk) = n.as_cell().ok_or(Tanks::new())?;
230 if nedl.is_sig() || hstk.is_sig() {
246 if nedl.is_sig() || hstk.is_sig() {
231− return Some(ctx.nouns.sig.clone());
247+ return Ok(ctx.nouns.sig.clone());
232 }
248 }
233
249
234 let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
250 let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
@@ -252,13 +268,13 @@ static FAND: Jet = |ctx, n| {
252 inner_iter = iter.clone();
268 inner_iter = iter.clone();
253 }
269 }
254
270
255− Some(Noun::list(result.iter().map(|a| Noun::from_u32(*a))))
271+ Ok(Noun::list(result.iter().map(|a| Noun::from_u32(*a))))
256};
272};
257
273
258static FIND: Jet = |ctx, n| {
274static FIND: Jet = |ctx, n| {
259− let (nedl, hstk) = n.as_cell()?;
275+ let (nedl, hstk) = n.as_cell().ok_or(Tanks::new())?;
260 if nedl.is_sig() || hstk.is_sig() {
276 if nedl.is_sig() || hstk.is_sig() {
261− return Some(ctx.nouns.sig.clone());
277+ return Ok(ctx.nouns.sig.clone());
262 }
278 }
263
279
264 let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
280 let nedl: Vec<&Rc<Noun>> = nedl.list_iter().collect();
@@ -274,30 +290,28 @@ static FIND: Jet = |ctx, n| {
274 .collect::<Vec<_>>()
290 .collect::<Vec<_>>()
275 == nedl
291 == nedl
276 {
292 {
277− return Some(Rc::new(Noun::from_u32(i)).unit());
293+ return Ok(Rc::new(Noun::from_u32(i)).unit());
278 }
294 }
279
295
280 inner_iter = iter.clone();
296 inner_iter = iter.clone();
281 }
297 }
282
298
283− return Some(ctx.nouns.sig.clone());
299+ return Ok(ctx.nouns.sig.clone());
284};
300};
285
301
286static FLOP: Jet = |ctx, n| {
302static FLOP: Jet = |ctx, n| {
287− Some(
288− n.list_iter()
303+ Ok(n.list_iter()
289− .fold(ctx.nouns.sig.clone(), |tail, head| cell(&head, &tail)),
304+ .fold(ctx.nouns.sig.clone(), |tail, head| cell(&head, &tail)))
290− )
291};
305};
292
306
293static GULF: Jet = |_ctx, n| {
307static GULF: Jet = |_ctx, n| {
294− let (from, to) = n.as_cell()?;
308+ let (from, to) = n.as_cell().ok_or(Tanks::new())?;
295
309
296− let mut from = (*from.as_atom()?).clone();
310+ let mut from = (*from.as_atom().ok_or(Tanks::new())?).clone();
297− let to = to.as_atom()?.clone();
311+ let to = to.as_atom().ok_or(Tanks::new())?.clone();
298
312
299 if from > to {
313 if from > to {
300− return None;
314+ return Err(Tanks::new());
301 }
315 }
302
316
303 let mut tmp = Vec::new();
317 let mut tmp = Vec::new();
@@ -307,105 +321,119 @@ static GULF: Jet = |_ctx, n| {
307 from += 1u32;
321 from += 1u32;
308 }
322 }
309
323
310− Some(Noun::list(tmp.iter().rev().map(|a| Noun::Atom(a.clone()))))
324+ Ok(Noun::list(tmp.iter().rev().map(|a| Noun::Atom(a.clone()))))
311};
325};
312
326
313static INTO: Jet = |_ctx, n| {
327static INTO: Jet = |_ctx, n| {
314− let (a, b) = n.as_cell()?;
328+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
315− let (b, c) = b.as_cell()?;
329+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
316
330
317− let mut b_iter = b.as_atom()?.iter_u32_digits();
331+ let mut b_iter = b.as_atom().ok_or(Tanks::new())?.iter_u32_digits();
318
332
319 match b_iter.len() {
333 match b_iter.len() {
320− 0 => Some(cell(&c, &a)),
334+ 0 => Ok(cell(&c, &a)),
321 1 => {
335 1 => {
322 let l = a.list_iter();
336 let l = a.list_iter();
323 let b = b_iter.next().unwrap() as usize;
337 let b = b_iter.next().unwrap() as usize;
324− Some(Noun::list_refs(
338+ Ok(Noun::list_refs(
325 l.clone()
339 l.clone()
326 .take(b)
340 .take(b)
327 .chain(once(c))
341 .chain(once(c))
328 .chain(l.skip(b))
342 .chain(l.skip(b))
329 .collect::<Vec<_>>()
343 .collect::<Vec<_>>()
330 .iter()
344 .iter()
331− .map(|x| *x),
345+ .cloned()
346+ .cloned(),
332 ))
347 ))
333 }
348 }
334− _ => Some(Noun::list_refs(
349+ _ => Ok(Noun::list_refs(
335 a.list_iter()
350 a.list_iter()
336 .chain(once(c))
351 .chain(once(c))
337 .collect::<Vec<_>>()
352 .collect::<Vec<_>>()
338 .iter()
353 .iter()
354+ .cloned()
339 .cloned(),
355 .cloned(),
340 )),
356 )),
341 }
357 }
342};
358};
343
359
344static JOIN: Jet = |_ctx, n| {
360static JOIN: Jet = |_ctx, n| {
345− let (sep, list) = n.as_cell()?;
361+ let (sep, list) = n.as_cell().ok_or(Tanks::new())?;
346− Some(Noun::list_refs(
362+ Ok(Noun::list_refs(
347 list.list_iter()
363 list.list_iter()
348 .intersperse(sep)
364 .intersperse(sep)
349 .collect::<Vec<_>>()
365 .collect::<Vec<_>>()
350 .iter()
366 .iter()
367+ .cloned()
351 .cloned(),
368 .cloned(),
352 ))
369 ))
353};
370};
354
371
355static LENT: Jet = |_ctx, n| {
372static LENT: Jet = |_ctx, n| {
356− Some(Rc::new(Noun::from_u32(
373+ Ok(Rc::new(Noun::from_u32(
357 n.list_iter().fold(0u32, |l, _| l + 1),
374 n.list_iter().fold(0u32, |l, _| l + 1),
358 )))
375 )))
359};
376};
360
377
361static LEVY: Jet = |ctx, n| {
378static LEVY: Jet = |ctx, n| {
362− let (a, b) = n.as_cell()?;
379+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
363− if traverse_iter_option(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
380+ if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
364 .iter()
381 .iter()
365 .all(|x| x.is_y())
382 .all(|x| x.is_y())
366 {
383 {
367− Some(ctx.nouns.y.clone())
384+ Ok(ctx.nouns.y.clone())
368 } else {
385 } else {
369− Some(ctx.nouns.n.clone())
386+ Ok(ctx.nouns.n.clone())
370 }
387 }
371};
388};
372
389
373static LIEN: Jet = |ctx, n| {
390static LIEN: Jet = |ctx, n| {
374− let (a, b) = n.as_cell()?;
391+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
375− if traverse_iter_option(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
392+ if traverse_iter_result(a.list_iter().map(|n| slam_pulled_gate(ctx, b, n)))?
376 .iter()
393 .iter()
377 .any(|x| x.is_y())
394 .any(|x| x.is_y())
378 {
395 {
379− Some(ctx.nouns.y.clone())
396+ Ok(ctx.nouns.y.clone())
380 } else {
397 } else {
381− Some(ctx.nouns.n.clone())
398+ Ok(ctx.nouns.n.clone())
382 }
399 }
383};
400};
384
401
385static MURN: Jet = |ctx, n| {
402static MURN: Jet = |ctx, n| {
386− let (a, b) = n.as_cell()?;
403+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
387
404
388− Some(Noun::list_refs(
405+ Ok(Noun::list_refs(
406+ traverse_iter_result(
389− a.list_iter()
407+ a.list_iter()
390− .filter_map(|n| slam_pulled_gate(ctx, b, n)?.as_unit().cloned())
408+ .map(|n| Ok(slam_pulled_gate(ctx, b, n)?.as_unit().cloned())),
391− .collect::<Vec<_>>()
409+ )?
392− .iter(),
410+ .iter()
411+ .filter_map(|x| x.clone()),
393 ))
412 ))
394};
413};
395
414
396static REAP: Jet = |_ctx, n| {
415static REAP: Jet = |_ctx, n| {
397− let (a, b) = n.as_cell()?;
416+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
398
417
399− Some(Noun::list_refs(repeat_n(b, a.as_u32().unwrap() as usize)))
418+ Ok(Noun::list_refs(repeat_n(
419+ b.clone(),
420+ a.as_u32().unwrap() as usize,
421+ )))
400};
422};
401
423
402−static REAR: Jet = |_ctx, n| n.list_iter().last().cloned();
424+static REAR: Jet = |_ctx, n| n.list_iter().last().ok_or(Tanks::new()).cloned();
403
425
404static REEL: Jet = |ctx, n| {
426static REEL: Jet = |ctx, n| {
405− let (list, gate) = n.as_cell()?;
427+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
406
428
407 list.list_iter().collect::<Vec<_>>().iter().rfold(
429 list.list_iter().collect::<Vec<_>>().iter().rfold(
430+ Ok(gate
408− Some(gate.gate_sample()?.as_cell()?.1.clone()),
431+ .gate_sample()
432+ .ok_or(Tanks::new())?
433+ .as_cell()
434+ .ok_or(Tanks::new())?
435+ .1
436+ .clone()),
409 |acc, next| {
437 |acc, next| {
410 let acc = acc?;
438 let acc = acc?;
411 slam_pulled_gate(ctx, gate, &cell(&next, &acc))
439 slam_pulled_gate(ctx, gate, &cell(&next, &acc))
@@ -414,10 +442,17 @@ static REEL: Jet = |ctx, n| {
414};
442};
415
443
416static ROLL: Jet = |ctx, n| {
444static ROLL: Jet = |ctx, n| {
417− let (list, gate) = n.as_cell()?;
445+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
418
446
419 list.list_iter().fold(
447 list.list_iter().fold(
448+ Ok(gate
449+ .clone()
420− Some(gate.clone().gate_sample()?.as_cell()?.1.clone()),
450+ .gate_sample()
451+ .ok_or(Tanks::new())?
452+ .as_cell()
453+ .ok_or(Tanks::new())?
454+ .1
455+ .clone()),
421 |acc, next| {
456 |acc, next| {
422 let acc = acc?;
457 let acc = acc?;
423 slam_pulled_gate(ctx, gate, &cell(&next, &acc))
458 slam_pulled_gate(ctx, gate, &cell(&next, &acc))
@@ -426,105 +461,111 @@ static ROLL: Jet = |ctx, n| {
426};
461};
427
462
428static SCAG: Jet = |_ctx, n| {
463static SCAG: Jet = |_ctx, n| {
429− let (a, b) = n.as_cell()?;
464+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
430
465
431− Some(Noun::list_refs(
466+ Ok(Noun::list_refs(
432 b.list_iter()
467 b.list_iter()
433 .take(a.as_u32().unwrap() as usize)
468 .take(a.as_u32().unwrap() as usize)
434 .collect::<Vec<_>>()
469 .collect::<Vec<_>>()
435 .iter()
470 .iter()
471+ .cloned()
436 .cloned(),
472 .cloned(),
437 ))
473 ))
438};
474};
439
475
440static SKID: Jet = |ctx, n| {
476static SKID: Jet = |ctx, n| {
441− let (list, gate) = n.as_cell()?;
477+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
442
478
443− let slammed_n = traverse_iter_option(
479+ let slammed_n = traverse_iter_result(
444 list.list_iter()
480 list.list_iter()
445− .map(|n| Some((slam_pulled_gate(ctx, gate, n)?, n))),
481+ .map(|n| Ok((slam_pulled_gate(ctx, gate, n)?, n))),
446 )?;
482 )?;
447 let (ys, ns): (Vec<_>, _) = slammed_n.iter().partition(|(l, _)| l.is_y());
483 let (ys, ns): (Vec<_>, _) = slammed_n.iter().partition(|(l, _)| l.is_y());
448
484
449− Some(cell(
485+ Ok(cell(
450− &Noun::list_refs(ys.iter().map(|(_, x)| *x)),
486+ &Noun::list_refs(ys.iter().map(|(_, x)| (*x).clone())),
451− &Noun::list_refs(ns.iter().map(|(_, x)| *x)),
487+ &Noun::list_refs(ns.iter().map(|(_, x)| (*x).clone())),
452 ))
488 ))
453};
489};
454
490
455static SKIM: Jet = |ctx, n| {
491static SKIM: Jet = |ctx, n| {
456− let (list, gate) = n.as_cell()?;
492+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
457
493
458− Some(Noun::list_refs(
494+ Ok(Noun::list_refs(
459− traverse_iter_option(
495+ traverse_iter_result(
460 list.list_iter()
496 list.list_iter()
461− .map(|n| Some((slam_pulled_gate(ctx, gate, n)?, n))),
497+ .map(|n| Ok((slam_pulled_gate(ctx, gate, n)?, n))),
462 )?
498 )?
463 .iter()
499 .iter()
464 .filter(|(l, _)| l.is_y())
500 .filter(|(l, _)| l.is_y())
465− .map(|(_, x)| *x),
501+ .map(|(_, x)| (*x).clone()),
466 ))
502 ))
467};
503};
468
504
469static SKIP: Jet = |ctx, n| {
505static SKIP: Jet = |ctx, n| {
470− let (list, gate) = n.as_cell()?;
506+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
471
507
472− Some(Noun::list_refs(
508+ Ok(Noun::list_refs(
473− traverse_iter_option(
509+ traverse_iter_result(
474 list.list_iter()
510 list.list_iter()
475− .map(|n| Some((slam_pulled_gate(ctx, gate, n)?, n))),
511+ .map(|n| Ok((slam_pulled_gate(ctx, gate, n)?, n))),
476 )?
512 )?
477 .iter()
513 .iter()
478 .filter(|(l, _)| l.is_y())
514 .filter(|(l, _)| l.is_y())
479− .map(|(_, x)| x)
515+ .map(|(_, x)| (*x).clone()),
480− .cloned(),
481 ))
516 ))
482};
517};
483
518
484static SLAG: Jet = |ctx, n| {
519static SLAG: Jet = |ctx, n| {
485− let (a, list) = n.as_cell()?;
520+ let (a, list) = n.as_cell().ok_or(Tanks::new())?;
486
521
487− let mut a_iter = a.as_atom()?.iter_u32_digits();
522+ let mut a_iter = a.as_atom().ok_or(Tanks::new())?.iter_u32_digits();
488
523
489 match a_iter.len() {
524 match a_iter.len() {
490− 0 => Some(list.clone()),
525+ 0 => Ok(list.clone()),
491− 1 => Some(Noun::list_refs(
526+ 1 => Ok(Noun::list_refs(
492 list.list_iter()
527 list.list_iter()
493 .skip(a_iter.next().unwrap() as usize)
528 .skip(a_iter.next().unwrap() as usize)
494 .collect::<Vec<_>>()
529 .collect::<Vec<_>>()
495 .iter()
530 .iter()
531+ .cloned()
496 .cloned(),
532 .cloned(),
497 )),
533 )),
498− _ => Some(ctx.nouns.sig.clone()),
534+ _ => Ok(ctx.nouns.sig.clone()),
499 }
535 }
500};
536};
501
537
502static SNAG: Jet = |_ctx, n| {
538static SNAG: Jet = |_ctx, n| {
503− let (a, list) = n.as_cell()?;
539+ let (a, list) = n.as_cell().ok_or(Tanks::new())?;
504
540
541+ list.list_iter()
505− list.list_iter().nth(a.as_u32().unwrap() as usize).cloned()
542+ .nth(a.as_u32().unwrap() as usize)
543+ .cloned()
544+ .ok_or(Tanks::new())
506};
545};
507
546
508static SNIP: Jet = |_ctx, n| {
547static SNIP: Jet = |_ctx, n| {
509− Some(Noun::list_refs(
548+ Ok(Noun::list_refs(
510 n.list_iter()
549 n.list_iter()
511 .collect::<Vec<_>>()
550 .collect::<Vec<_>>()
512 .iter()
551 .iter()
513 .rev()
552 .rev()
514 .skip(1)
553 .skip(1)
515 .rev()
554 .rev()
555+ .cloned()
516 .cloned(),
556 .cloned(),
517 ))
557 ))
518};
558};
519
559
520static SNOC: Jet = |_ctx, n| {
560static SNOC: Jet = |_ctx, n| {
521− let (list, b) = n.as_cell()?;
561+ let (list, b) = n.as_cell().ok_or(Tanks::new())?;
522
562
523− Some(Noun::list_refs(
563+ Ok(Noun::list_refs(
524 list.list_iter()
564 list.list_iter()
525 .chain(once(b))
565 .chain(once(b))
526 .collect::<Vec<_>>()
566 .collect::<Vec<_>>()
527 .iter()
567 .iter()
568+ .cloned()
528 .cloned(),
569 .cloned(),
529 ))
570 ))
530};
571};
@@ -548,53 +589,62 @@ static SNOC: Jet = |_ctx, n| {
548// };
589// };
549
590
550static SPIN: Jet = |ctx, n| {
591static SPIN: Jet = |ctx, n| {
551− let (list, b) = n.as_cell()?;
592+ let (list, b) = n.as_cell().ok_or(Tanks::new())?;
552− let (acc, gate) = b.as_cell()?;
593+ let (acc, gate) = b.as_cell().ok_or(Tanks::new())?;
553
594
554 let mut res = Vec::new();
595 let mut res = Vec::new();
555 let mut acc = acc.clone();
596 let mut acc = acc.clone();
556
597
557 for n in list.list_iter() {
598 for n in list.list_iter() {
558 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
599 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
559− let (el, new_acc) = foo.as_cell()?;
600+ let (el, new_acc) = foo.as_cell().ok_or(Tanks::new())?;
560 acc = new_acc.clone();
601 acc = new_acc.clone();
561 res.push(el.clone());
602 res.push(el.clone());
562 }
603 }
563
604
564− Some(cell(&Noun::list_refs(res.iter()), &acc))
605+ Ok(cell(&Noun::list_refs(res.iter().cloned()), &acc))
565};
606};
566
607
567static SPUN: Jet = |ctx, n| {
608static SPUN: Jet = |ctx, n| {
568− let (list, gate) = n.as_cell()?;
609+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
569
610
570 let mut res = Vec::new();
611 let mut res = Vec::new();
571− let mut acc = gate.gate_sample()?.as_cell()?.1.clone();
612+ let mut acc = gate
613+ .gate_sample()
614+ .ok_or(Tanks::new())?
615+ .as_cell()
616+ .ok_or(Tanks::new())?
617+ .1
618+ .clone();
572
619
573 for n in list.list_iter() {
620 for n in list.list_iter() {
574 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
621 let foo = slam_pulled_gate(ctx, gate, &cell(&n, &acc))?;
575− let (el, new_acc) = foo.as_cell()?;
622+ let (el, new_acc) = foo.as_cell().ok_or(Tanks::new())?;
576 acc = new_acc.clone();
623 acc = new_acc.clone();
577 res.push(el.clone());
624 res.push(el.clone());
578 }
625 }
579
626
580− Some(cell(&Noun::list_refs(res.iter()), &acc))
627+ Ok(cell(&Noun::list_refs(res.iter().cloned()), &acc))
581};
628};
582
629
583static TURN: Jet = |ctx, n| {
630static TURN: Jet = |ctx, n| {
584− let (list, gate) = n.as_cell()?;
631+ let (list, gate) = n.as_cell().ok_or(Tanks::new())?;
585− Some(Noun::list_refs(
632+ Ok(Noun::list_refs(
586− traverse_iter_option(list.list_iter().map(|x| slam_pulled_gate(ctx, gate, x)))?.iter(),
633+ traverse_iter_result(list.list_iter().map(|x| slam_pulled_gate(ctx, gate, x)))?
634+ .iter()
635+ .cloned(),
587 ))
636 ))
588};
637};
589
638
590static WELD: Jet = |_ctx, n| {
639static WELD: Jet = |_ctx, n| {
591− let (a, b) = n.as_cell()?;
640+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
592
641
593− Some(Noun::list_refs(
642+ Ok(Noun::list_refs(
594 a.list_iter()
643 a.list_iter()
595 .chain(b.list_iter())
644 .chain(b.list_iter())
596 .collect::<Vec<_>>()
645 .collect::<Vec<_>>()
597 .iter()
646 .iter()
647+ .cloned()
598 .cloned(),
648 .cloned(),
599 ))
649 ))
600};
650};
@@ -602,35 +652,36 @@ static WELD: Jet = |_ctx, n| {
602static WELP: Jet = WELD;
652static WELP: Jet = WELD;
603
653
604static ZING: Jet = |_ctx, n| {
654static ZING: Jet = |_ctx, n| {
605− Some(Noun::list_refs(
655+ Ok(Noun::list_refs(
606 n.list_iter()
656 n.list_iter()
607 .map(|l| l.list_iter())
657 .map(|l| l.list_iter())
608 .flatten()
658 .flatten()
609 .collect::<Vec<_>>()
659 .collect::<Vec<_>>()
610 .iter()
660 .iter()
661+ .cloned()
611 .cloned(),
662 .cloned(),
612 ))
663 ))
613};
664};
614
665
615static BEX: Jet = |ctx, n| {
666static BEX: Jet = |ctx, n| {
616− Some(Rc::new(Noun::Atom(
667+ Ok(Rc::new(Noun::Atom(
617 &ctx.big_uints.one << n.as_u32().unwrap(),
668 &ctx.big_uints.one << n.as_u32().unwrap(),
618 )))
669 )))
619};
670};
620
671
621static END: Jet = |ctx, n| {
672static END: Jet = |ctx, n| {
622− let (a, b) = n.as_cell()?;
673+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
623 let bite = a.as_bite();
674 let bite = a.as_bite();
624
675
625 let bits = bite.bits();
676 let bits = bite.bits();
626
677
627 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
678 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
628
679
629− Some(Rc::new(Noun::Atom(mask & b.as_atom()?)))
680+ Ok(Rc::new(Noun::Atom(mask & b.as_atom().ok_or(Tanks::new())?)))
630};
681};
631
682
632static CAN: Jet = |ctx, n| {
683static CAN: Jet = |ctx, n| {
633− let (a, b) = n.as_cell()?;
684+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
634 let bloq = a.as_u32().unwrap();
685 let bloq = a.as_u32().unwrap();
635 let bloq_ = 2u32.pow(bloq);
686 let bloq_ = 2u32.pow(bloq);
636
687
@@ -645,28 +696,28 @@ static CAN: Jet = |ctx, n| {
645 Some((acc? << bits) | (mask & q.as_atom()?))
696 Some((acc? << bits) | (mask & q.as_atom()?))
646 },
697 },
647 );
698 );
648− Some(Rc::new(Noun::Atom(atom?)))
699+ Ok(Rc::new(Noun::Atom(atom.ok_or(Tanks::new())?)))
649};
700};
650
701
651static CAT: Jet = |_ctx, n| {
702static CAT: Jet = |_ctx, n| {
652− let (bloq, b) = n.as_cell()?;
703+ let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
653− let (b, c) = b.as_cell()?;
704+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
654
705
655− let bloq = bloq.as_u32()?;
706+ let bloq = bloq.as_u32().ok_or(Tanks::new())?;
656− let b = b.as_atom()?;
707+ let b = b.as_atom().ok_or(Tanks::new())?;
657− let c = c.as_atom()?;
708+ let c = c.as_atom().ok_or(Tanks::new())?;
658
709
659− Some(Rc::new(Noun::Atom(
710+ Ok(Rc::new(Noun::Atom(
660 (c << (met(bloq, &b) * 2u32.pow(bloq))) | b,
711 (c << (met(bloq, &b) * 2u32.pow(bloq))) | b,
661 )))
712 )))
662};
713};
663
714
664static MET: Jet = |_ctx, n| {
715static MET: Jet = |_ctx, n| {
665− let (bloq, b) = n.as_cell()?;
716+ let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
666− let b: Atom = b.as_atom()?.clone();
717+ let b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
667 let bloq = bloq.as_u32().unwrap();
718 let bloq = bloq.as_u32().unwrap();
668
719
669− Some(Rc::new(Noun::from_u32(met(bloq, &b))))
720+ Ok(Rc::new(Noun::from_u32(met(bloq, &b))))
670};
721};
671
722
672fn met(bloq: u32, a: &Atom) -> u32 {
723fn met(bloq: u32, a: &Atom) -> u32 {
@@ -674,28 +725,28 @@ fn met(bloq: u32, a: &Atom) -> u32 {
674}
725}
675
726
676static CUT: Jet = |ctx, n| {
727static CUT: Jet = |ctx, n| {
677− let (a, b) = n.as_cell()?;
728+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
678− let (b, d) = b.as_cell()?;
729+ let (b, d) = b.as_cell().ok_or(Tanks::new())?;
679− let (b, c) = b.as_cell()?;
730+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
680
731
681 let bits = 2u32.pow(a.as_u32().unwrap());
732 let bits = 2u32.pow(a.as_u32().unwrap());
682
733
683 let mask = (&ctx.big_uints.one << (bits * c.as_u32().unwrap())) - &ctx.big_uints.one;
734 let mask = (&ctx.big_uints.one << (bits * c.as_u32().unwrap())) - &ctx.big_uints.one;
684
735
685− Some(Rc::new(Noun::Atom(
736+ Ok(Rc::new(Noun::Atom(
686− (d.as_atom()? >> (bits * b.as_u32().unwrap())) & mask,
737+ (d.as_atom().ok_or(Tanks::new())? >> (bits * b.as_u32().unwrap())) & mask,
687 )))
738 )))
688};
739};
689
740
690static FIL: Jet = |ctx, n| {
741static FIL: Jet = |ctx, n| {
691− let (a, b) = n.as_cell()?;
742+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
692− let (b, c) = b.as_cell()?;
743+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
693
744
694 let bits = 2u32.pow(a.as_u32().unwrap());
745 let bits = 2u32.pow(a.as_u32().unwrap());
695
746
696 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
747 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
697
748
698− let src = c.as_atom()? & mask;
749+ let src = c.as_atom().ok_or(Tanks::new())? & mask;
699
750
700 let mut target = ctx.big_uints.zero.clone();
751 let mut target = ctx.big_uints.zero.clone();
701
752
@@ -703,44 +754,44 @@ static FIL: Jet = |ctx, n| {
703 target = (target << bits) | &src;
754 target = (target << bits) | &src;
704 }
755 }
705
756
706− Some(Rc::new(Noun::Atom(target)))
757+ Ok(Rc::new(Noun::Atom(target)))
707};
758};
708
759
709static LSH: Jet = |_ctx, n| {
760static LSH: Jet = |_ctx, n| {
710− let (a, b) = n.as_cell()?;
761+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
711 let a = a.as_bite();
762 let a = a.as_bite();
712− let b = b.as_atom()?;
763+ let b = b.as_atom().ok_or(Tanks::new())?;
713
764
714− Some(Rc::new(Noun::Atom(b << a.bits())))
765+ Ok(Rc::new(Noun::Atom(b << a.bits())))
715};
766};
716
767
717static RSH: Jet = |_ctx, n| {
768static RSH: Jet = |_ctx, n| {
718− let (a, b) = n.as_cell()?;
769+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
719 let a = a.as_bite();
770 let a = a.as_bite();
720− let b = b.as_atom()?;
771+ let b = b.as_atom().ok_or(Tanks::new())?;
721
772
722− Some(Rc::new(Noun::Atom(b >> a.bits())))
773+ Ok(Rc::new(Noun::Atom(b >> a.bits())))
723};
774};
724
775
725static RAP: Jet = |ctx, n| {
776static RAP: Jet = |ctx, n| {
726− let (bloq, b) = n.as_cell()?;
777+ let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
727 let bloq = bloq.as_u32().unwrap();
778 let bloq = bloq.as_u32().unwrap();
728 let bits = 2u32.pow(bloq);
779 let bits = 2u32.pow(bloq);
729
780
730 let mut target = ctx.big_uints.zero.clone();
781 let mut target = ctx.big_uints.zero.clone();
731
782
732 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
783 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
733− let el = el.as_atom()?;
784+ let el = el.as_atom().ok_or(Tanks::new())?;
734 if el != &ctx.big_uints.zero {
785 if el != &ctx.big_uints.zero {
735 target = (target << (bits * met(bloq, &el))) | el;
786 target = (target << (bits * met(bloq, &el))) | el;
736 }
787 }
737 }
788 }
738
789
739− Some(Rc::new(Noun::Atom(target)))
790+ Ok(Rc::new(Noun::Atom(target)))
740};
791};
741
792
742static REP: Jet = |ctx, n| {
793static REP: Jet = |ctx, n| {
743− let (bite, b) = n.as_cell()?;
794+ let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
744 let bite = bite.as_bite();
795 let bite = bite.as_bite();
745
796
746 let bits = bite.bits();
797 let bits = bite.bits();
@@ -749,18 +800,18 @@ static REP: Jet = |ctx, n| {
749 let mut target = ctx.big_uints.zero.clone();
800 let mut target = ctx.big_uints.zero.clone();
750
801
751 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
802 for el in b.list_iter().collect::<Vec<_>>().iter().rev() {
752− target = (target << bits) | (el.as_atom()? & &mask);
803+ target = (target << bits) | (el.as_atom().ok_or(Tanks::new())? & &mask);
753 }
804 }
754
805
755− Some(Rc::new(Noun::Atom(target)))
806+ Ok(Rc::new(Noun::Atom(target)))
756};
807};
757
808
758static REV: Jet = |ctx, n| {
809static REV: Jet = |ctx, n| {
759− let (bloq, b) = n.as_cell()?;
810+ let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
760− let (len, dat) = b.as_cell()?;
811+ let (len, dat) = b.as_cell().ok_or(Tanks::new())?;
761 let bloq = bloq.as_u32().unwrap();
812 let bloq = bloq.as_u32().unwrap();
762 let len = len.as_u32().unwrap();
813 let len = len.as_u32().unwrap();
763− let mut dat: Atom = dat.as_atom()?.clone();
814+ let mut dat: Atom = dat.as_atom().ok_or(Tanks::new())?.clone();
764
815
765 let bits = 2u32.pow(bloq);
816 let bits = 2u32.pow(bloq);
766 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
817 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -772,13 +823,13 @@ static REV: Jet = |ctx, n| {
772 dat = dat >> bits;
823 dat = dat >> bits;
773 }
824 }
774
825
775− Some(Rc::new(Noun::Atom(target)))
826+ Ok(Rc::new(Noun::Atom(target)))
776};
827};
777
828
778static RIP: Jet = |ctx, n| {
829static RIP: Jet = |ctx, n| {
779− let (bite, b) = n.as_cell()?;
830+ let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
780 let bite = bite.as_bite();
831 let bite = bite.as_bite();
781− let mut b: Atom = b.as_atom()?.clone();
832+ let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
782
833
783 let bits = bite.bits();
834 let bits = bite.bits();
784 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
835 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -790,15 +841,15 @@ static RIP: Jet = |ctx, n| {
790 b = b >> bits;
841 b = b >> bits;
791 }
842 }
792
843
793− Some(Noun::list_refs(target.iter()))
844+ Ok(Noun::list_refs(target.iter().cloned()))
794};
845};
795
846
796static RUN: Jet = |ctx, n| {
847static RUN: Jet = |ctx, n| {
797− let (bite, b) = n.as_cell()?;
848+ let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
798− let (b, gate) = b.as_cell()?;
849+ let (b, gate) = b.as_cell().ok_or(Tanks::new())?;
799
850
800 let bite = bite.as_bite();
851 let bite = bite.as_bite();
801− let mut b: Atom = b.as_atom()?.clone();
852+ let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
802
853
803 let bits = bite.bits();
854 let bits = bite.bits();
804 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
855 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -807,20 +858,22 @@ static RUN: Jet = |ctx, n| {
807
858
808 while b > ctx.big_uints.zero {
859 while b > ctx.big_uints.zero {
809 target = (target << bits)
860 target = (target << bits)
810− | ((*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?).as_atom()?
861+ | ((*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
862+ .as_atom()
863+ .ok_or(Tanks::new())?
811 & &mask);
864 & &mask);
812 b = b >> bits;
865 b = b >> bits;
813 }
866 }
814
867
815− Some(Rc::new(Noun::Atom(target)))
868+ Ok(Rc::new(Noun::Atom(target)))
816};
869};
817
870
818static RUT: Jet = |ctx, n| {
871static RUT: Jet = |ctx, n| {
819− let (bite, b) = n.as_cell()?;
872+ let (bite, b) = n.as_cell().ok_or(Tanks::new())?;
820− let (b, gate) = b.as_cell()?;
873+ let (b, gate) = b.as_cell().ok_or(Tanks::new())?;
821
874
822 let bite = bite.as_bite();
875 let bite = bite.as_bite();
823− let mut b: Atom = b.as_atom()?.clone();
876+ let mut b: Atom = b.as_atom().ok_or(Tanks::new())?.clone();
824
877
825 let bits = bite.bits();
878 let bits = bite.bits();
826 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
879 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
@@ -829,21 +882,24 @@ static RUT: Jet = |ctx, n| {
829
882
830 while b > ctx.big_uints.zero {
883 while b > ctx.big_uints.zero {
831 target.push(
884 target.push(
832− (*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?).as_atom()? & &mask,
885+ (*slam_pulled_gate(ctx, gate, &Rc::new(Noun::Atom(&mask & &b)))?)
886+ .as_atom()
887+ .ok_or(Tanks::new())?
888+ & &mask,
833 );
889 );
834 b = b >> bits;
890 b = b >> bits;
835 }
891 }
836
892
837− Some(Noun::list(target.iter().cloned().map(Noun::Atom)))
893+ Ok(Noun::list(target.iter().cloned().map(Noun::Atom)))
838};
894};
839
895
840static SEW: Jet = |ctx, n| {
896static SEW: Jet = |ctx, n| {
841− let (a, b) = n.as_cell()?;
897+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
842− let (b, recipient) = b.as_cell()?;
898+ let (b, recipient) = b.as_cell().ok_or(Tanks::new())?;
843− let (sew_start, c) = b.as_cell()?;
899+ let (sew_start, c) = b.as_cell().ok_or(Tanks::new())?;
844− let (number_of_blocks, donor) = c.as_cell()?;
900+ let (number_of_blocks, donor) = c.as_cell().ok_or(Tanks::new())?;
845− let recipient = recipient.as_atom()?;
901+ let recipient = recipient.as_atom().ok_or(Tanks::new())?;
846− let donor = donor.as_atom()?;
902+ let donor = donor.as_atom().ok_or(Tanks::new())?;
847
903
848 let bloq = a.as_u32().unwrap();
904 let bloq = a.as_u32().unwrap();
849 let bits = 2u32.pow(bloq);
905 let bits = 2u32.pow(bloq);
@@ -855,16 +911,16 @@ static SEW: Jet = |ctx, n| {
855
911
856 let target = (recipient ^ apendix) | (donor & mask);
912 let target = (recipient ^ apendix) | (donor & mask);
857
913
858− Some(Rc::new(Noun::Atom(target)))
914+ Ok(Rc::new(Noun::Atom(target)))
859};
915};
860
916
861static SWP: Jet = |ctx, n| {
917static SWP: Jet = |ctx, n| {
862− let (bloq, b) = n.as_cell()?;
918+ let (bloq, b) = n.as_cell().ok_or(Tanks::new())?;
863 let bloq = bloq.as_u32().unwrap();
919 let bloq = bloq.as_u32().unwrap();
864 let bits = 2u32.pow(bloq);
920 let bits = 2u32.pow(bloq);
865 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
921 let mask = (&ctx.big_uints.one << bits) - &ctx.big_uints.one;
866
922
867− let mut source = b.as_atom()?.clone();
923+ let mut source = b.as_atom().ok_or(Tanks::new())?.clone();
868 let mut target = ctx.big_uints.zero.clone();
924 let mut target = ctx.big_uints.zero.clone();
869
925
870 while source > ctx.big_uints.zero {
926 while source > ctx.big_uints.zero {
@@ -872,11 +928,11 @@ static SWP: Jet = |ctx, n| {
872 source = source >> bits;
928 source = source >> bits;
873 }
929 }
874
930
875− Some(Rc::new(Noun::Atom(target)))
931+ Ok(Rc::new(Noun::Atom(target)))
876};
932};
877
933
878static XEB: Jet = |_ctx, n| {
934static XEB: Jet = |_ctx, n| {
879− let mut a = n.as_atom()?.clone();
935+ let mut a = n.as_atom().ok_or(Tanks::new())?.clone();
880
936
881 let mut c = 0;
937 let mut c = 0;
882
938
@@ -885,7 +941,7 @@ static XEB: Jet = |_ctx, n| {
885 c += 1;
941 c += 1;
886 }
942 }
887
943
888− Some(Rc::new(Noun::from_u32(c)))
944+ Ok(Rc::new(Noun::from_u32(c)))
889};
945};
890
946
891static CON: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a | b);
947static CON: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a | b);
@@ -893,23 +949,23 @@ static DIS: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a & b);
893static MIX: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a ^ b);
949static MIX: Jet = |_ctx, n| BINARY_ATOM(n, |a, b| a ^ b);
894
950
895static NOT: Jet = |ctx, n| {
951static NOT: Jet = |ctx, n| {
896− let (a, b) = n.as_cell()?;
952+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
897− let (b, c) = b.as_cell()?;
953+ let (b, c) = b.as_cell().ok_or(Tanks::new())?;
898
954
899 let bloq = a.as_u32().unwrap();
955 let bloq = a.as_u32().unwrap();
900 let bits = 2u32.pow(bloq);
956 let bits = 2u32.pow(bloq);
901 let mask = (&ctx.big_uints.one << (bits * b.as_u32().unwrap())) - &ctx.big_uints.one;
957 let mask = (&ctx.big_uints.one << (bits * b.as_u32().unwrap())) - &ctx.big_uints.one;
902
958
903− let target = c.as_atom()? ^ &mask;
959+ let target = c.as_atom().ok_or(Tanks::new())? ^ &mask;
904
960
905− Some(Rc::new(Noun::Atom(target)))
961+ Ok(Rc::new(Noun::Atom(target)))
906};
962};
907
963
908static LAST: Jet = |_ctx, n| {
964static LAST: Jet = |_ctx, n| {
909− let (a, b) = n.as_cell()?;
965+ let (a, b) = n.as_cell().ok_or(Tanks::new())?;
910− let a = a.as_hair()?;
966+ let a = a.as_hair().ok_or(Tanks::new())?;
911− let b = b.as_hair()?;
967+ let b = b.as_hair().ok_or(Tanks::new())?;
912− Some(Noun::from_hair(last(&a, &b)))
968+ Ok(Noun::from_hair(last(&a, &b)))
913};
969};
914
970
915fn last<'a>(a: &'a Hair, b: &'a Hair) -> &'a Hair {
971fn last<'a>(a: &'a Hair, b: &'a Hair) -> &'a Hair {
@@ -929,20 +985,20 @@ fn last<'a>(a: &'a Hair, b: &'a Hair) -> &'a Hair {
929}
985}
930
986
931static TRIP: Jet = |_ctx, n| {
987static TRIP: Jet = |_ctx, n| {
932− let a = n.as_atom()?;
988+ let a = n.as_atom().ok_or(Tanks::new())?;
933− Some(Noun::list(
989+ Ok(Noun::list(
934 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
990 a.to_bytes_le().iter().map(|b| Noun::from_u32(*b as u32)),
935 ))
991 ))
936};
992};
937
993
938static MUK: Jet = |_ctx, n| {
994static MUK: Jet = |_ctx, n| {
939− let (seed, len) = n.as_cell()?;
995+ let (seed, len) = n.as_cell().ok_or(Tanks::new())?;
940− let (len, key) = len.as_cell()?;
996+ let (len, key) = len.as_cell().ok_or(Tanks::new())?;
941− let seed = seed.as_u32()?;
997+ let seed = seed.as_u32().ok_or(Tanks::new())?;
942− let len = len.as_u32()?;
998+ let len = len.as_u32().ok_or(Tanks::new())?;
943− let key = key.as_atom()?;
999+ let key = key.as_atom().ok_or(Tanks::new())?;
944
1000
945− Some(Rc::new(Noun::from_u32(muk(seed, len, key))))
1001+ Ok(Rc::new(Noun::from_u32(muk(seed, len, key))))
946};
1002};
947
1003
948static JUST: DoubleJet = |ctx, n, m| {
1004static JUST: DoubleJet = |ctx, n, m| {
@@ -1006,7 +1062,7 @@ fn fail(nail: Nail) -> Edge {
1006 }
1062 }
1007}
1063}
1008
1064
1009−const MUG: Jet = |__ctx, n| Some(Rc::new(Noun::from_u32(n.mug())));
1065+const MUG: Jet = |__ctx, n| Ok(Rc::new(Noun::from_u32(n.mug())));
1010
1066
1011pub fn mum(syd: u32, fal: u32, key: &Atom) -> u32 {
1067pub fn mum(syd: u32, fal: u32, key: &Atom) -> u32 {
1012 let wyd = met(3, &key);
1068 let wyd = met(3, &key);
nock/src/main.rs+28−4
@@ -1,5 +1,6 @@
1use clap::{command, error::Result, Parser, Subcommand};
1use clap::{command, error::Result, Parser, Subcommand};
2+use core::str;
2−use nock::interpreter::{eval_pulled_gate, slam_pulled_gate, tar, InterpreterContext};
3+use nock::interpreter::{eval_pulled_gate, slam_pulled_gate, tar, InterpreterContext, Tanks};
3use nock::{
4use nock::{
4 cue::cue_bytes,
5 cue::cue_bytes,
5 interpreter::{generate_interpreter_context, slam},
6 interpreter::{generate_interpreter_context, slam},
@@ -110,9 +111,15 @@ fn interact(gate_file: PathBuf) -> Result<(), std::io::Error> {
110 let source = get_stdin().unwrap();
111 let source = get_stdin().unwrap();
111
112
112 let mut spinner = new_spinner(String::from("Slamming gate..."));
113 let mut spinner = new_spinner(String::from("Slamming gate..."));
113− let Some(slam) = slam(&mut generate_interpreter_context(), &gate, &source) else {
114+ let slam = match slam(&mut generate_interpreter_context(), &gate, &source) {
115+ Ok(slam) => slam,
116+ Err(tanks) => {
114− spinner.fail("Gate execution failed");
117+ spinner.fail("Gate execution failed");
118+ let mut ctx = generate_interpreter_context();
119+ let trace = wash(&mut ctx, tanks);
120+ println!("{trace}");
115− exit(1);
121+ exit(1);
122+ }
116 };
123 };
117 let Some(target) = slam.as_bytes() else {
124 let Some(target) = slam.as_bytes() else {
118 spinner.fail("The gate did not produce a valid atom");
125 spinner.fail("The gate did not produce a valid atom");
@@ -207,3 +214,20 @@ fn read_nock_or_compile(
207 read_nock(&path)
214 read_nock(&path)
208 }
215 }
209}
216}
217+
218+fn wash(ctx: &mut InterpreterContext, tanks: Tanks) -> String {
219+ let wash = cue_bytes(include_bytes!("../res/wash.nock"));
220+
221+ let mut target = String::new();
222+ for tank in tanks.iter() {
223+ let mut str = slam_pulled_gate(ctx, &wash, &tank)
224+ .unwrap()
225+ .as_atom()
226+ .unwrap()
227+ .to_bytes_le();
228+
229+ target.push_str(str::from_utf8_mut(&mut *str).unwrap())
230+ }
231+
232+ target
233+}
nock/src/noun.rs+2−2
@@ -55,8 +55,8 @@ impl<'a> Noun {
55 l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&Rc::new(head), &tail))
55 l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&Rc::new(head), &tail))
56 }
56 }
57
57
58− pub fn list_refs<I: Iterator<Item = &'a Rc<Noun>> + DoubleEndedIterator>(l: I) -> Rc<Noun> {
58+ pub fn list_refs<I: Iterator<Item = Rc<Noun>> + DoubleEndedIterator>(l: I) -> Rc<Noun> {
59− l.rfold(Rc::new(Noun::SIG), |tail, head| cell(head, &tail))
59+ l.rfold(Rc::new(Noun::SIG), |tail, head| cell(&head, &tail))
60 }
60 }
61
61
62 pub fn unit(self: Rc<Self>) -> Rc<Noun> {
62 pub fn unit(self: Rc<Self>) -> Rc<Noun> {
urbit.hoonnew file+7
@@ -0,0 +1,7 @@
1+|= [tag=@tas args=*]
2+?+ tag !!
3+ :: %ride (ride (,[type @] args))
4+ :: %comb (comb (,[nock nock] args))
5+ :: %hoon ..ride
6+ %wash (wash (,[[@ @] tank] args))
7+==