1use crate::RcList;
4use alloc::{boxed::Box, string::String, string::ToString, vec::Vec};
5use core::fmt::{self, Display};
6
7#[derive(Clone, Debug)]
14pub struct Exn<V>(pub(crate) Inner<V>);
15
16#[derive(Clone, Debug)]
17pub(crate) enum Inner<V> {
18 Err(Box<Error<V>>),
19 TailCall(Box<(crate::compile::TermId, crate::filter::Vars<V>, CallInput<V>)>),
24 Break(usize),
25}
26
27#[derive(Clone, Debug)]
28pub(crate) enum CallInput<V> {
29 Run(V),
30 Paths((V, RcList<V>)),
31}
32
33impl<V> CallInput<V> {
34 pub fn unwrap_run(self) -> V {
35 match self {
36 Self::Run(v) => v,
37 _ => panic!(),
38 }
39 }
40
41 pub fn unwrap_paths(self) -> (V, RcList<V>) {
42 match self {
43 Self::Paths(vp) => vp,
44 _ => panic!(),
45 }
46 }
47}
48
49impl<V> Exn<V> {
50 pub(crate) fn get_err(self) -> Result<Error<V>, Self> {
52 match self.0 {
53 Inner::Err(e) => Ok(*e),
54 _ => Err(self),
55 }
56 }
57}
58
59impl<V> From<Error<V>> for Exn<V> {
60 fn from(e: Error<V>) -> Self {
61 Exn(Inner::Err(Box::new(e)))
62 }
63}
64
65#[derive(Clone, Debug, PartialEq, Eq)]
66enum Part<V, S = &'static str> {
67 Val(V),
68 Str(S),
69}
70
71#[derive(Clone, Debug, PartialEq, Eq)]
73pub struct Error<V>(Part<V, Vec<Part<V>>>);
74
75impl<V> Error<V> {
76 pub fn new(v: V) -> Self {
78 Self(Part::Val(v))
79 }
80
81 pub fn path_expr(v: V) -> Self {
83 Self(Part::Str(Vec::from([
84 Part::Str("invalid path expression with input "),
85 Part::Val(v),
86 ])))
87 }
88
89 pub fn typ(v: V, typ: &'static str) -> Self {
91 use Part::{Str, Val};
92 [Str("cannot use "), Val(v), Str(" as "), Str(typ)]
93 .into_iter()
94 .collect()
95 }
96
97 pub fn math(l: V, op: crate::ops::Math, r: V) -> Self {
99 use Part::{Str, Val};
100 [
101 Str("cannot calculate "),
102 Val(l),
103 Str(" "),
104 Str(op.as_str()),
105 Str(" "),
106 Val(r),
107 ]
108 .into_iter()
109 .collect()
110 }
111
112 pub fn index(l: V, r: V) -> Self {
114 use Part::{Str, Val};
115 [Str("cannot index "), Val(l), Str(" with "), Val(r)]
116 .into_iter()
117 .collect()
118 }
119}
120
121impl<V: From<String>> Error<V> {
122 pub fn str(s: impl ToString) -> Self {
124 Self(Part::Val(V::from(s.to_string())))
125 }
126}
127
128impl<V> FromIterator<Part<V>> for Error<V> {
129 fn from_iter<T: IntoIterator<Item = Part<V>>>(iter: T) -> Self {
130 Self(Part::Str(iter.into_iter().collect()))
131 }
132}
133
134impl<V: From<String> + Display> Error<V> {
135 pub fn into_val(self) -> V {
137 if let Part::Val(v) = self.0 {
138 v
139 } else {
140 V::from(self.to_string())
141 }
142 }
143}
144
145impl<V: Display> Display for Error<V> {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 match &self.0 {
148 Part::Val(v) => v.fmt(f),
149 Part::Str(parts) => parts.iter().try_for_each(|part| match part {
150 Part::Val(v) => v.fmt(f),
151 Part::Str(s) => s.fmt(f),
152 }),
153 }
154 }
155}