1#![no_std]
42#![forbid(unsafe_code)]
43#![warn(missing_docs)]
44
45extern crate alloc;
46#[cfg(feature = "std")]
47extern crate std;
48
49mod box_iter;
50pub mod error;
51mod filter;
52mod hir;
53mod into_iter;
54mod lir;
55mod mir;
56mod path;
57mod rc_iter;
58mod rc_lazy_list;
59mod rc_list;
60pub mod results;
61mod stack;
62mod val;
63
64#[allow(dead_code)]
65mod exn;
66
67pub use error::Error;
68pub use filter::{Args, FilterT, Native, Owned as Filter, RunPtr, UpdatePtr};
69pub use rc_iter::RcIter;
70pub use val::{Val, ValR, ValRs, ValT};
71
72use alloc::{string::String, vec::Vec};
73use jaq_syn::Arg as Bind;
74use rc_list::List as RcList;
75use stack::Stack;
76
77#[derive(Clone, Debug, PartialEq, Eq)]
79struct Vars<V>(RcList<Bind<V, (filter::Id, Self)>>);
80type Inputs<'i, V> = RcIter<dyn Iterator<Item = Result<V, String>> + 'i>;
81
82impl<V> Vars<V> {
83 fn get(&self, i: usize) -> Option<&Bind<V, (filter::Id, Self)>> {
84 self.0.get(i)
85 }
86}
87
88#[derive(Clone)]
90pub struct Ctx<'a, V = Val> {
91 vars: Vars<V>,
92 inputs: &'a Inputs<'a, V>,
93}
94
95impl<'a, V> Ctx<'a, V> {
96 pub fn new(vars: impl IntoIterator<Item = V>, inputs: &'a Inputs<'a, V>) -> Self {
98 let vars = Vars(RcList::new().extend(vars.into_iter().map(Bind::Var)));
99 Self { vars, inputs }
100 }
101
102 pub(crate) fn cons_var(mut self, x: V) -> Self {
104 self.vars.0 = self.vars.0.cons(Bind::Var(x));
105 self
106 }
107
108 pub(crate) fn cons_fun(mut self, (f, ctx): (filter::Id, Self)) -> Self {
110 self.vars.0 = self.vars.0.cons(Bind::Fun((f, ctx.vars)));
111 self
112 }
113
114 fn skip_vars(mut self, skip: usize) -> Self {
116 if skip > 0 {
117 self.vars.0 = self.vars.0.skip(skip).clone();
118 }
119 self
120 }
121
122 fn with_vars(&self, vars: Vars<V>) -> Self {
123 let inputs = self.inputs;
124 Self { vars, inputs }
125 }
126
127 pub fn inputs(&self) -> &'a Inputs<'a, V> {
129 self.inputs
130 }
131}
132
133pub struct ParseCtx {
137 pub errs: Vec<jaq_syn::Spanned<hir::Error>>,
140 native: Vec<((String, usize), filter::Native)>,
141 def: jaq_syn::Def,
142}
143
144impl ParseCtx {
145 pub fn new(vars: Vec<String>) -> Self {
150 use alloc::string::ToString;
151 let def = jaq_syn::Def {
152 lhs: jaq_syn::Call {
153 name: "$".to_string(),
154 args: vars.into_iter().map(Bind::Var).collect(),
155 },
156 rhs: jaq_syn::Main {
157 defs: Vec::new(),
158 body: (jaq_syn::filter::Filter::Id, 0..0),
159 },
160 };
161
162 Self {
163 errs: Vec::new(),
164 native: Vec::new(),
165 def,
166 }
167 }
168
169 pub fn insert_native(&mut self, name: String, arity: usize, f: filter::Native) {
171 self.native.push(((name, arity), f));
172 }
173
174 pub fn insert_natives<I>(&mut self, natives: I)
176 where
177 I: IntoIterator<Item = (String, usize, filter::Native)>,
178 {
179 let natives = natives
180 .into_iter()
181 .map(|(name, arity, f)| ((name, arity), f));
182 self.native.extend(natives);
183 }
184
185 pub fn insert_defs(&mut self, defs: impl IntoIterator<Item = jaq_syn::Def>) {
189 self.def.rhs.defs.extend(defs);
190 }
191
192 #[deprecated(since = "1.1.0", note = "use `insert_defs` instead")]
194 pub fn root_def(&mut self, def: jaq_syn::Def) {
195 self.def.rhs.defs.push(def);
196 }
197
198 #[deprecated(since = "1.1.0", note = "this call has no effect")]
200 pub fn root_filter(&mut self, filter: jaq_syn::Spanned<jaq_syn::filter::Filter>) {
201 self.def.rhs.body = filter;
202 }
203
204 pub fn compile(&mut self, main: jaq_syn::Main) -> Filter {
206 let mut hctx = hir::Ctx::default();
207 let native = self.native.iter().map(|(sig, _)| sig.clone());
208 hctx.native = native.collect();
209 self.def.rhs.defs.extend(main.defs);
210 self.def.rhs.body = main.body;
211 let def = hctx.def(self.def.clone());
212 self.errs = hctx.errs;
213
214 if !self.errs.is_empty() {
215 return Default::default();
216 }
217 let mut mctx = mir::Ctx::default();
218 let def = mctx.def(def, Default::default());
220
221 let mut lctx = lir::Ctx::default();
222 let id = lctx.def(def);
223 let native = self.native.iter().map(|(_sig, native)| native.clone());
224 filter::Owned::new(id, lctx.defs.into(), native.collect())
225 }
226
227 pub fn yields(&mut self, x: Val, f: jaq_syn::Main, ys: impl Iterator<Item = ValR>) {
231 let f = self.compile(f);
232 assert!(self.errs.is_empty());
233
234 let inputs = RcIter::new(core::iter::empty());
235 let out = f.run((Ctx::new([], &inputs), x));
236
237 assert!(out.eq(ys));
238 }
239}