1use crate::box_iter::{box_once, flat_map_with, map_with, BoxIter};
2use crate::results::{fold, recurse, then, Fold, Results};
3use crate::val::{Val, ValR2, ValR2s, ValT};
4use crate::{rc_lazy_list, Bind, Ctx, Error};
5use alloc::{boxed::Box, string::String, vec::Vec};
6use core::ops::ControlFlow;
7use dyn_clone::DynClone;
8use jaq_syn::filter::FoldType;
9use jaq_syn::{MathOp, OrdOp};
10
11#[derive(Debug, Clone)]
13pub struct Owned<V = Val>(Id, Lut<V>);
14
15#[derive(Clone, Debug)]
17struct Lut<V = Val> {
18 defs: Box<[Ast]>,
19 natives: Box<[Native<V>]>,
20}
21
22impl<V> Default for Owned<V> {
23 fn default() -> Self {
24 Self::new(Id(0), [Ast::Id].into(), [].into())
25 }
26}
27
28#[derive(Debug)]
29pub struct Ref<'a, V = Val>(Id, &'a Lut<V>);
30
31impl<'a, V> Clone for Ref<'a, V> {
32 fn clone(&self) -> Self {
33 *self
34 }
35}
36
37impl<'a, V> Copy for Ref<'a, V> {}
38
39#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
40pub struct Id(pub usize);
41
42#[derive(Clone, Debug)]
43pub enum CallTyp {
44 Normal,
46 Catch,
48 Throw,
50}
51
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub struct TailCall<V>(Id, crate::Vars<V>, V);
54
55#[derive(Clone, Debug)]
56pub(crate) struct Call {
57 pub id: Id,
58 pub typ: CallTyp,
59 pub skip: usize,
60 pub args: Box<[Bind<Id, Id>]>,
61}
62
63impl<V> Owned<V> {
64 pub(crate) fn new(main: Id, defs: Box<[Ast]>, natives: Box<[Native<V>]>) -> Self {
65 Self(main, Lut { defs, natives })
66 }
67}
68
69#[derive(Clone, Debug)]
71pub(crate) enum Ast {
72 Id,
73 ToString,
74
75 Int(isize),
76 Num(String),
77 Str(String),
78 Array(Id),
79 ObjEmpty,
80 ObjSingle(Id, Id),
81
82 Try(Id, Id),
83 Neg(Id),
84 Pipe(Id, bool, Id),
85 Comma(Id, Id),
86 Alt(Id, Id),
87 Ite(Id, Id, Id),
88 Fold(FoldType, Id, Id, Id),
112
113 Path(Id, crate::path::Path<Id>),
114
115 Update(Id, Id),
116 UpdateMath(Id, MathOp, Id),
117 Assign(Id, Id),
118
119 Logic(Id, bool, Id),
120 Math(Id, MathOp, Id),
121 Ord(Id, OrdOp, Id),
122
123 Var(usize),
124 Call(Call),
125
126 Native(usize, Box<[Id]>),
127}
128
129pub trait Update<'a, V = Val>: Fn(V) -> ValR2s<'a, V> + DynClone {}
132
133impl<'a, V, T: Fn(V) -> ValR2s<'a, V> + Clone> Update<'a, V> for T {}
134
135dyn_clone::clone_trait_object!(<'a, V> Update<'a, V>);
136
137fn bind_vars<'a, V: ValT>(
142 mut args: impl Iterator<Item = Bind<Ref<'a, V>, Ref<'a, V>>> + Clone + 'a,
143 ctx: Ctx<'a, V>,
144 cv: Cv<'a, V>,
145) -> Results<'a, Cv<'a, V>, Error<V>> {
146 match args.next() {
147 Some(Bind::Var(arg)) => flat_map_with(
148 arg.run(cv.clone()),
149 (ctx, cv, args),
150 |y, (ctx, cv, args)| then(y, |y| bind_vars(args, ctx.cons_var(y), cv)),
151 ),
152 Some(Bind::Fun(Ref(arg, _defs))) => bind_vars(args, ctx.cons_fun((arg, cv.0.clone())), cv),
153 None => box_once(Ok((ctx, cv.1))),
154 }
155}
156
157fn run_cvs<'a, V: ValT>(f: Ref<'a, V>, cvs: Results<'a, Cv<'a, V>, Error<V>>) -> ValR2s<'a, V> {
158 Box::new(cvs.flat_map(move |cv| then(cv, |cv| f.run(cv))))
159}
160
161fn reduce<'a, T, V, F>(xs: Results<'a, T, Error<V>>, init: V, f: F) -> ValR2s<V>
162where
163 T: Clone + 'a,
164 V: Clone + 'a,
165 F: Fn(T, V) -> ValR2s<'a, V> + 'a,
166{
167 let xs = rc_lazy_list::List::from_iter(xs);
168 Box::new(fold(false, xs, Fold::Input(init), f))
169}
170
171type Cv<'c, V = Val> = (Ctx<'c, V>, V);
172
173#[derive(Clone)]
175pub struct Native<V = Val> {
176 run: RunPtr<V>,
177 update: UpdatePtr<V>,
178}
179
180pub type RunPtr<V = Val> = for<'a> fn(Args<'a, V>, Cv<'a, V>) -> ValR2s<'a, V>;
182pub type UpdatePtr<V = Val> =
184 for<'a> fn(Args<'a, V>, Cv<'a, V>, Box<dyn Update<'a, V> + 'a>) -> ValR2s<'a, V>;
185
186impl<V> Native<V> {
187 pub const fn new(run: RunPtr<V>) -> Self {
189 Self::with_update(run, |_, _, _| box_once(Err(Error::PathExp)))
190 }
191
192 pub const fn with_update(run: RunPtr<V>, update: UpdatePtr<V>) -> Self {
195 Self { run, update }
196 }
197}
198
199impl<V> core::fmt::Debug for Native<V> {
201 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
202 f.debug_struct("Native").finish()
203 }
204}
205
206pub struct Args<'a, V = Val>(&'a [Id], &'a Lut<V>);
208
209impl<'a, V> Clone for Args<'a, V> {
210 fn clone(&self) -> Self {
211 *self
212 }
213}
214
215impl<'a, V> Copy for Args<'a, V> {}
216
217impl<'a, V: ValT> Args<'a, V> {
218 pub fn get(self, i: usize) -> impl FilterT<'a, V> {
225 Ref(self.0[i], self.1)
226 }
227}
228
229impl<'a, V: ValT> FilterT<'a, V> for &'a Owned<V> {
230 fn run(self, cv: Cv<'a, V>) -> ValR2s<'a, V> {
231 Ref(self.0, &self.1).run(cv)
232 }
233
234 fn update(self, cv: Cv<'a, V>, f: Box<dyn Update<'a, V> + 'a>) -> ValR2s<'a, V> {
235 Ref(self.0, &self.1).update(cv, f)
236 }
237}
238
239impl<'a, V: ValT> FilterT<'a, V> for Ref<'a, V> {
240 fn run(self, cv: Cv<'a, V>) -> ValR2s<'a, V> {
241 use alloc::string::ToString;
242 use core::iter::{once, once_with};
243 let w = move |id: &Id| Ref(*id, self.1);
245 match &self.1.defs[self.0 .0] {
246 Ast::Id => box_once(Ok(cv.1)),
247 Ast::ToString => Box::new(once_with(move || match cv.1.as_str() {
248 Some(_) => Ok(cv.1),
249 None => Ok(V::from(cv.1.to_string())),
250 })),
251 Ast::Int(n) => box_once(Ok(V::from(*n))),
252 Ast::Num(x) => box_once(V::from_num(x)),
253 Ast::Str(s) => Box::new(once_with(move || Ok(V::from(s.clone())))),
254 Ast::Array(f) => Box::new(once_with(move || w(f).run(cv).collect::<Result<_, _>>())),
255 Ast::ObjEmpty => box_once(V::from_map([])),
256 Ast::ObjSingle(k, v) => {
257 Box::new(Self::cartesian(w(k), w(v), cv).map(|(k, v)| V::from_map([(k?, v?)])))
258 }
259 Ast::Try(f, c) => Box::new(w(f).run((cv.0.clone(), cv.1)).flat_map(move |y| {
260 y.map_or_else(
261 |e| w(c).run((cv.0.clone(), e.as_val())),
262 |v| box_once(Ok(v)),
263 )
264 })),
265 Ast::Neg(f) => Box::new(w(f).run(cv).map(|v| -v?)),
266
267 Ast::Pipe(l, false, r) => {
269 let l = w(l).run((cv.0.clone(), cv.1));
270 flat_map_with(l, cv.0, move |y, ctx| then(y, |y| w(r).run((ctx, y))))
271 }
272 Ast::Pipe(l, true, r) => w(l).pipe(cv, move |cv, y| w(r).run((cv.0.cons_var(y), cv.1))),
274
275 Ast::Comma(l, r) => Box::new(w(l).run(cv.clone()).chain(w(r).run(cv))),
276 Ast::Alt(l, r) => {
277 let mut l = w(l)
278 .run(cv.clone())
279 .filter(|v| v.as_ref().map_or(true, |v| v.as_bool()));
280 match l.next() {
281 Some(head) => Box::new(once(head).chain(l)),
282 None => w(r).run(cv),
283 }
284 }
285 Ast::Ite(if_, then_, else_) => w(if_).pipe(cv, move |cv, v| {
286 w(if v.as_bool() { then_ } else { else_ }).run(cv)
287 }),
288 Ast::Path(f, path) => {
289 let path = path.map_ref(|i| {
290 let cv = cv.clone();
291 crate::into_iter::collect_if_once(move || w(i).run(cv))
292 });
293 flat_map_with(w(f).run(cv), path, |y, path| {
294 then(y, |y| {
295 flat_map_with(path.explode(), y, |path, y| then(path, |path| path.run(y)))
296 })
297 })
298 }
299
300 Ast::Update(path, f) => w(path).update(
301 (cv.0.clone(), cv.1),
302 Box::new(move |v| w(f).run((cv.0.clone(), v))),
303 ),
304 Ast::UpdateMath(path, op, f) => w(f).pipe(cv, move |cv, y| {
305 w(path).update(cv, Box::new(move |x| box_once(op.run(x, y.clone()))))
306 }),
307 Ast::Assign(path, f) => w(f).pipe(cv, move |cv, y| {
308 w(path).update(cv, Box::new(move |_| box_once(Ok(y.clone()))))
309 }),
310
311 Ast::Logic(l, stop, r) => w(l).pipe(cv, move |cv, l| {
312 if l.as_bool() == *stop {
313 box_once(Ok(V::from(*stop)))
314 } else {
315 Box::new(w(r).run(cv).map(|r| Ok(V::from(r?.as_bool()))))
316 }
317 }),
318 Ast::Math(l, op, r) => {
319 Box::new(Self::cartesian(w(l), w(r), cv).map(|(x, y)| op.run(x?, y?)))
320 }
321 Ast::Ord(l, op, r) => Box::new(
322 Self::cartesian(w(l), w(r), cv).map(|(x, y)| Ok(V::from(op.run(&x?, &y?)))),
323 ),
324
325 Ast::Fold(typ, xs, init, f) => {
326 let xs = rc_lazy_list::List::from_iter(w(xs).run(cv.clone()));
327 let init = w(init).run(cv.clone());
328 let f = move |x, v| w(f).run((cv.0.clone().cons_var(x), v));
329 use Fold::{Input, Output};
330 match typ {
331 FoldType::Reduce => Box::new(fold(false, xs, Output(init), f)),
332 FoldType::For => Box::new(fold(true, xs, Output(init), f)),
333 FoldType::Foreach => flat_map_with(init, xs, move |i, xs| {
334 then(i, |i| Box::new(fold(true, xs, Input(i), f.clone())))
335 }),
336 }
337 }
338
339 Ast::Var(v) => match cv.0.vars.get(*v).unwrap() {
340 Bind::Var(v) => box_once(Ok(v.clone())),
341 Bind::Fun(f) => w(&f.0).run((cv.0.with_vars(f.1.clone()), cv.1)),
342 },
343 Ast::Call(call) => {
344 let def = w(&call.id);
345 let ctx = cv.0.clone().skip_vars(call.skip);
346 let inputs = cv.0.inputs;
347 let cvs = bind_vars(call.args.iter().map(move |a| a.as_ref().map(w)), ctx, cv);
348 match call.typ {
349 CallTyp::Normal => run_cvs(def, cvs),
350 CallTyp::Catch => Box::new(crate::Stack::new(
351 Vec::from([run_cvs(def, cvs)]),
352 move |r| match r {
353 Err(Error::TailCall(TailCall(id, vars, v))) if id == call.id => {
354 ControlFlow::Continue(def.run((Ctx { inputs, vars }, v)))
355 }
356 Ok(_) | Err(_) => ControlFlow::Break(r),
357 },
358 )),
359 CallTyp::Throw => Box::new(cvs.map(move |cv| {
360 cv.and_then(|cv| Err(Error::TailCall(TailCall(call.id, cv.0.vars, cv.1))))
361 })),
362 }
363 }
364
365 Ast::Native(id, args) => (self.1.natives[*id].run)(Args(args, self.1), cv),
366 }
367 }
368
369 fn update(self, cv: Cv<'a, V>, f: Box<dyn Update<'a, V> + 'a>) -> ValR2s<'a, V> {
370 let err = box_once(Err(Error::PathExp));
371 let w = move |id: &Id| Ref(*id, self.1);
372 match &self.1.defs[self.0 .0] {
373 Ast::ToString => err,
374 Ast::Int(_) | Ast::Num(_) | Ast::Str(_) => err,
375 Ast::Array(_) | Ast::ObjEmpty | Ast::ObjSingle(..) => err,
376 Ast::Neg(_) | Ast::Logic(..) | Ast::Math(..) | Ast::Ord(..) => err,
377 Ast::Update(..) | Ast::UpdateMath(..) | Ast::Assign(..) => err,
378
379 Ast::Try(..) | Ast::Alt(..) | Ast::Fold(..) => {
381 unimplemented!("updating with this operator is not supported yet")
382 }
383
384 Ast::Id => f(cv.1),
385 Ast::Path(l, path) => {
386 let path = path.map_ref(|i| {
387 let cv = cv.clone();
388 crate::into_iter::collect_if_once(move || w(i).run(cv))
389 });
390 let f = move |v| {
391 let mut paths = path.clone().explode();
392 box_once(paths.try_fold(v, |acc, path| path?.update(acc, &f)))
393 };
394 w(l).update(cv, Box::new(f))
395 }
396 Ast::Pipe(l, false, r) => w(l).update(
397 (cv.0.clone(), cv.1),
398 Box::new(move |v| w(r).update((cv.0.clone(), v), f.clone())),
399 ),
400 Ast::Pipe(l, true, r) => reduce(w(l).run(cv.clone()), cv.1, move |x, v| {
401 w(r).update((cv.0.clone().cons_var(x), v), f.clone())
402 }),
403 Ast::Comma(l, r) => {
404 let l = w(l).update((cv.0.clone(), cv.1), f.clone());
405 Box::new(
406 l.flat_map(move |v| then(v, |v| w(r).update((cv.0.clone(), v), f.clone()))),
407 )
408 }
409 Ast::Ite(if_, then_, else_) => reduce(w(if_).run(cv.clone()), cv.1, move |x, v| {
410 w(if x.as_bool() { then_ } else { else_ }).update((cv.0.clone(), v), f.clone())
411 }),
412
413 Ast::Var(v) => match cv.0.vars.get(*v).unwrap() {
414 Bind::Var(_) => err,
415 Bind::Fun(l) => w(&l.0).update((cv.0.with_vars(l.1.clone()), cv.1), f),
416 },
417 Ast::Call(call) => {
418 let def = w(&call.id);
419 let init = cv.1.clone();
420 let ctx = cv.0.clone().skip_vars(call.skip);
421 let cvs = bind_vars(call.args.iter().map(move |a| a.as_ref().map(w)), ctx, cv);
422 reduce(cvs, init, move |cv, v| def.update((cv.0, v), f.clone()))
423 }
424
425 Ast::Native(id, args) => (self.1.natives[*id].update)(Args(args, self.1), cv, f),
426 }
427 }
428}
429
430type Triple<T> = (T, T, T);
431
432pub trait FilterT<'a, V: ValT = Val>: Clone + 'a {
436 fn run(self, cv: Cv<'a, V>) -> ValR2s<'a, V>;
438
439 fn update(self, cv: Cv<'a, V>, f: Box<dyn Update<'a, V> + 'a>) -> ValR2s<'a, V>;
441
442 fn pipe<T: 'a, F>(self, cv: Cv<'a, V>, f: F) -> Results<'a, T, Error<V>>
447 where
448 F: Fn(Cv<'a, V>, V) -> Results<'a, T, Error<V>> + 'a,
449 {
450 flat_map_with(self.run(cv.clone()), cv, move |y, cv| then(y, |y| f(cv, y)))
451 }
452
453 fn cartesian(self, r: Self, cv: Cv<'a, V>) -> BoxIter<'a, (ValR2<V>, ValR2<V>)> {
455 flat_map_with(self.run(cv.clone()), cv, move |l, cv| {
456 map_with(r.clone().run(cv), l, |r, l| (l, r))
457 })
458 }
459
460 fn cartesian3(self, m: Self, r: Self, cv: Cv<'a, V>) -> BoxIter<'a, Triple<ValR2<V>>> {
462 flat_map_with(self.run(cv.clone()), cv, move |l, cv| {
463 let r = r.clone();
464 flat_map_with(m.clone().run(cv.clone()), (l, cv), move |m, (l, cv)| {
465 map_with(r.clone().run(cv), (l, m), |r, (l, m)| (l, m, r))
466 })
467 })
468 }
469
470 #[deprecated(since = "1.2.0")]
477 fn recurse(self, inner: bool, outer: bool, cv: Cv<'a, V>) -> ValR2s<V> {
478 let f = move |v| self.clone().run((cv.0.clone(), v));
479 Box::new(recurse(inner, outer, box_once(Ok(cv.1)), f))
480 }
481
482 #[deprecated(since = "1.2.0")]
484 fn recurse_update(self, cv: Cv<'a, V>, f: Box<dyn Update<'a, V> + 'a>) -> ValR2s<'a, V> {
485 Box::new(f(cv.1).flat_map(move |v| {
487 then(v, |v| {
488 let (c, f) = (cv.0.clone(), f.clone());
489 let slf = self.clone();
490 let rec = move |v| slf.clone().recurse_update((c.clone(), v), f.clone());
491 (self.clone()).update((cv.0.clone(), v), Box::new(rec))
492 })
493 }))
494 }
495}