1use core::fmt::{self, Display};
4use core::iter::FusedIterator;
5
6use alloc::collections::linked_list::{self, LinkedList};
7use alloc::vec::Vec;
8
9use module::Merge;
10use module::merge::error::Trace;
11
12use crate::Result;
13
14trait LinkedListExt<T> {
17 fn append_front(&mut self, other: &mut Self);
18}
19
20impl<T> LinkedListExt<T> for LinkedList<T> {
21 fn append_front(&mut self, other: &mut Self) {
22 other.append(self);
23 self.append(other);
24 }
25}
26
27#[derive(Debug, Clone)]
30enum Instruction<T> {
31 Enter(T),
32 Exit,
33 Eval(T),
34}
35
36impl<T> Instruction<T> {
37 fn as_eval(&self) -> Option<&T> {
38 if let Self::Eval(v) = self {
39 Some(v)
40 } else {
41 None
42 }
43 }
44
45 fn as_eval_mut(&mut self) -> Option<&mut T> {
46 if let Self::Eval(v) = self {
47 Some(v)
48 } else {
49 None
50 }
51 }
52
53 fn into_eval(self) -> Option<T> {
54 if let Self::Eval(v) = self {
55 Some(v)
56 } else {
57 None
58 }
59 }
60}
61
62#[derive(Clone)]
72pub struct Imports<T>(LinkedList<Instruction<T>>);
73
74impl<T> fmt::Debug for Imports<T>
75where
76 T: fmt::Debug,
77{
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.debug_list()
80 .entries(self.0.iter().map(|x| {
81 x.as_eval()
82 .expect("Imports should only have Eval instructions")
83 }))
84 .finish()
85 }
86}
87
88impl<T> FromIterator<T> for Imports<T> {
89 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
90 let inner = iter.into_iter().map(Instruction::Eval).collect();
91 Self(inner)
92 }
93}
94
95impl<T> From<T> for Imports<T> {
96 fn from(value: T) -> Self {
97 [value].into_iter().collect()
98 }
99}
100
101impl<T> Default for Imports<T> {
102 fn default() -> Self {
103 Self::empty()
104 }
105}
106
107impl<T> Imports<T> {
108 pub const fn empty() -> Self {
110 Self(LinkedList::new())
111 }
112
113 pub fn len(&self) -> usize {
115 self.0.len()
116 }
117
118 pub fn is_empty(&self) -> bool {
120 self.0.is_empty()
121 }
122
123 pub fn push(&mut self, import: T) {
125 self.0.push_back(Instruction::Eval(import));
126 }
127
128 pub fn append(&mut self, imports: &mut Self) {
135 self.0.append(&mut imports.0);
136 }
137
138 pub fn iter(&self) -> Iter<'_, T> {
140 Iter(self.0.iter())
141 }
142
143 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
145 IterMut(self.0.iter_mut())
146 }
147}
148
149impl<'a, T> IntoIterator for &'a Imports<T> {
150 type Item = &'a T;
151 type IntoIter = Iter<'a, T>;
152
153 fn into_iter(self) -> Self::IntoIter {
154 self.iter()
155 }
156}
157
158impl<'a, T> IntoIterator for &'a mut Imports<T> {
159 type Item = &'a mut T;
160 type IntoIter = IterMut<'a, T>;
161
162 fn into_iter(self) -> Self::IntoIter {
163 self.iter_mut()
164 }
165}
166
167impl<T> IntoIterator for Imports<T> {
168 type Item = T;
169 type IntoIter = IntoIter<T>;
170
171 fn into_iter(self) -> Self::IntoIter {
172 IntoIter(self.0.into_iter())
173 }
174}
175
176#[expect(missing_debug_implementations)]
180pub struct Iter<'a, T>(linked_list::Iter<'a, Instruction<T>>);
181
182impl<'a, T> Iterator for Iter<'a, T> {
183 type Item = &'a T;
184
185 fn next(&mut self) -> Option<Self::Item> {
186 self.0.next().map(|x| {
187 x.as_eval()
188 .expect("Imports should only have Eval instructions")
189 })
190 }
191
192 fn size_hint(&self) -> (usize, Option<usize>) {
193 self.0.size_hint()
194 }
195}
196
197impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
198 fn next_back(&mut self) -> Option<Self::Item> {
199 self.0.next_back().map(|x| {
200 x.as_eval()
201 .expect("Imports should only have Eval instructions")
202 })
203 }
204}
205
206impl<'a, T> ExactSizeIterator for Iter<'a, T> {
207 fn len(&self) -> usize {
208 self.0.len()
209 }
210}
211
212impl<'a, T> FusedIterator for Iter<'a, T> {}
213
214#[expect(missing_debug_implementations)]
218pub struct IterMut<'a, T>(linked_list::IterMut<'a, Instruction<T>>);
219
220impl<'a, T> Iterator for IterMut<'a, T> {
221 type Item = &'a mut T;
222
223 fn next(&mut self) -> Option<Self::Item> {
224 self.0.next().map(|x| {
225 x.as_eval_mut()
226 .expect("Imports should only have Eval instructions")
227 })
228 }
229
230 fn size_hint(&self) -> (usize, Option<usize>) {
231 self.0.size_hint()
232 }
233}
234
235impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
236 fn next_back(&mut self) -> Option<Self::Item> {
237 self.0.next_back().map(|x| {
238 x.as_eval_mut()
239 .expect("Imports should only have Eval instructions")
240 })
241 }
242}
243
244impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
245 fn len(&self) -> usize {
246 self.0.len()
247 }
248}
249
250impl<'a, T> FusedIterator for IterMut<'a, T> {}
251
252#[expect(missing_debug_implementations)]
256pub struct IntoIter<T>(linked_list::IntoIter<Instruction<T>>);
257
258impl<T> Iterator for IntoIter<T> {
259 type Item = T;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 self.0.next().map(|x| {
263 x.into_eval()
264 .expect("Imports should only have Eval instructions")
265 })
266 }
267
268 fn size_hint(&self) -> (usize, Option<usize>) {
269 self.0.size_hint()
270 }
271}
272
273impl<T> DoubleEndedIterator for IntoIter<T> {
274 fn next_back(&mut self) -> Option<Self::Item> {
275 self.0.next_back().map(|x| {
276 x.into_eval()
277 .expect("Imports should only have Eval instructions")
278 })
279 }
280}
281
282impl<T> ExactSizeIterator for IntoIter<T> {
283 fn len(&self) -> usize {
284 self.0.len()
285 }
286}
287
288impl<T> FusedIterator for IntoIter<T> {}
289
290#[cfg(feature = "serde")]
291mod serde_impl {
292 use super::*;
293
294 use core::marker::PhantomData;
295
296 use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
297
298 impl<'de, T> Deserialize<'de> for Imports<T>
299 where
300 T: Deserialize<'de>,
301 {
302 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
303 where
304 D: Deserializer<'de>,
305 {
306 struct ImportsVisitor<T>(PhantomData<T>);
307
308 impl<'de, T> Visitor<'de> for ImportsVisitor<T>
309 where
310 T: Deserialize<'de>,
311 {
312 type Value = Imports<T>;
313
314 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
315 formatter.write_str("a sequence")
316 }
317
318 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
319 where
320 A: SeqAccess<'de>,
321 {
322 let mut inner = LinkedList::new();
323
324 while let Some(e) = seq.next_element()? {
325 inner.push_back(Instruction::Eval(e));
326 }
327
328 Ok(Imports(inner))
329 }
330 }
331
332 let visitor = ImportsVisitor(PhantomData);
333 deserializer.deserialize_seq(visitor)
334 }
335 }
336}
337
338#[derive(Debug, Clone)]
377pub struct Evaluator<Ref, Value> {
378 program: LinkedList<Instruction<Ref>>,
379 trace: Vec<Ref>,
380 value: Option<Value>,
381}
382
383impl<Ref, Value> Default for Evaluator<Ref, Value> {
384 fn default() -> Self {
385 Self::new()
386 }
387}
388
389impl<Ref, Value> Evaluator<Ref, Value> {
390 pub const fn new() -> Self {
392 Self {
393 program: LinkedList::new(),
394 trace: Vec::new(),
395 value: None,
396 }
397 }
398
399 pub const fn with(value: Value) -> Self {
406 Self {
407 program: LinkedList::new(),
408 trace: Vec::new(),
409 value: Some(value),
410 }
411 }
412
413 pub fn import<I>(&mut self, imports: I)
417 where
418 I: Into<Imports<Ref>>,
419 {
420 self._import(imports.into())
421 }
422
423 fn _import(&mut self, imports: Imports<Ref>) {
424 let Imports(mut imports) = imports;
425 self.program.append(&mut imports);
426 }
427
428 #[expect(clippy::should_implement_trait)]
432 pub fn next(&mut self) -> Option<Ref> {
435 loop {
436 match self.program.pop_front()? {
437 Instruction::Enter(x) => {
438 self.trace.push(x);
439 }
440 Instruction::Exit => {
441 self.trace.pop();
442 }
443 Instruction::Eval(x) => break Some(x),
444 }
445 }
446 }
447
448 pub fn finish(self) -> Option<Value> {
456 self.value
457 }
458}
459
460impl<Ref, Value> Evaluator<Ref, Value>
461where
462 Ref: Display,
463{
464 pub fn trace(&self, this: Ref) -> Trace {
500 let mut trace: Trace = self.trace.iter().collect();
501 trace.push_back(this);
502 trace
503 }
504}
505
506impl<Ref, Value> Evaluator<Ref, Value>
507where
508 Ref: Display,
509 Value: Merge,
510{
511 pub fn eval(&mut self, this: Ref, imports: Imports<Ref>, value: Value) -> Result<()> {
521 self.value = match self.value.take() {
522 None => Some(value),
523 Some(old) => match old.merge(value) {
524 Ok(x) => Some(x),
525 Err(mut e) => {
526 e.trace = self.trace(this);
527 return Err(e);
528 }
529 },
530 };
531
532 let Imports(mut imports) = imports;
533 if !imports.is_empty() {
534 imports.push_front(Instruction::Enter(this));
535 imports.push_back(Instruction::Exit);
536 self.program.append_front(&mut imports);
537 }
538
539 Ok(())
540 }
541}
542
543#[cfg(test)]
544mod tests {
545 use module::types::NoMerge;
546 use module::{Context, Error};
547
548 use super::*;
549
550 fn eval<T>(initial: &'static str, modules: &[(&str, &[&'static str], T)]) -> Result<T>
551 where
552 T: Clone + Merge,
553 {
554 let mut x = Evaluator::new();
555
556 x.import(initial);
557 while let Some(this) = x.next() {
558 let Some((_, imports, value)) = modules.iter().find(|(name, _, _)| *name == this)
559 else {
560 return Err(Error::custom("no such module")).with_trace(|| x.trace(this));
561 };
562
563 let imports = imports.iter().copied().collect();
564 let value = value.clone();
565
566 x.eval(this, imports, value)?;
567 }
568
569 let value = x.finish().unwrap();
570 Ok(value)
571 }
572
573 #[test]
574 fn test_module_trace() {
575 let err = eval(
576 "module 1",
577 &[
578 ("module 1", &["module 2"], Some(NoMerge(()))),
579 ("module 2", &["module 3", "module 4"], None),
580 ("module 3", &[], None),
581 ("module 4", &["module 5"], None),
582 ("module 5", &["module 6"], None),
583 ("module 6", &[], Some(NoMerge(()))),
584 ],
585 )
586 .unwrap_err();
587
588 let trace: Vec<_> = err.trace.modules().collect();
589
590 assert_eq!(
591 trace,
592 &["module 1", "module 2", "module 4", "module 5", "module 6"]
593 );
594 }
595
596 #[test]
597 fn test_eval_order() {
598 let err = eval(
602 "module 1",
603 &[
604 ("module 1", &["module 2", "module 3"], Some(NoMerge(()))),
605 ("module 2", &["module 4"], None),
606 ("module 4", &["module 5"], None),
607 ("module 5", &["non-existent"], None),
608 ("module 3", &["module 6"], None),
609 ("module 6", &[], Some(NoMerge(()))),
610 ],
611 )
612 .unwrap_err();
613
614 assert!(!err.kind.is_collision());
615 }
616}