1use std::iter::Sum;
4
5use crate::diagnostics::Diagnostic;
6
7pub trait ConstantFolding {
9 type Error;
11 type T;
13
14 fn constant_fold(&mut self) -> Result<(), Self::Error>;
16
17 fn constant_folded(mut self) -> Result<Self, Self::Error>
19 where
20 Self: Sized,
21 {
22 self.constant_fold()?;
23 Ok(self)
24 }
25
26 fn const_value(&self) -> Option<Self::T> {
28 None
29 }
30}
31
32impl<T: ConstantFolding> ConstantFolding for Box<T> {
33 type Error = T::Error;
34
35 type T = T::T;
36
37 fn constant_fold(&mut self) -> Result<(), Self::Error> {
38 self.as_mut().constant_fold()
39 }
40
41 fn constant_folded(self) -> Result<Self, Self::Error>
42 where
43 Self: Sized,
44 {
45 (*self).constant_folded().map(Box::new)
46 }
47
48 fn const_value(&self) -> Option<Self::T> {
49 self.as_ref().const_value()
50 }
51}
52
53impl<E: ConstantFolding> ConstantFolding for Vec<E> {
54 type Error = E::Error;
55
56 type T = Vec<E::T>;
57
58 fn constant_fold(&mut self) -> Result<(), Self::Error> {
59 self.iter_mut().try_for_each(|e| e.constant_fold())
60 }
61
62 fn const_value(&self) -> Option<Self::T> {
63 self.iter().map(|e| e.const_value()).collect()
64 }
65}
66
67impl<E: ConstantFolding> ConstantFolding for [E] {
68 type Error = E::Error;
69
70 type T = Vec<E::T>;
71
72 fn constant_fold(&mut self) -> Result<(), Self::Error> {
73 self.iter_mut().try_for_each(|e| e.constant_fold())
74 }
75
76 fn const_value(&self) -> Option<Self::T> {
77 self.iter().map(|e| e.const_value()).collect()
78 }
79}
80
81pub trait Canonicalize {
83 fn canonicalize(&mut self);
85
86 fn canonicalized(mut self) -> Self
88 where
89 Self: Sized,
90 {
91 self.canonicalize();
92 self
93 }
94}
95
96impl<E: Canonicalize> Canonicalize for Vec<E> {
97 fn canonicalize(&mut self) {
98 for e in self {
99 e.canonicalize();
100 }
101 }
102}
103
104impl<E: Canonicalize> Canonicalize for [E] {
105 fn canonicalize(&mut self) {
106 for e in self {
107 e.canonicalize();
108 }
109 }
110}
111
112impl<T: Canonicalize> Canonicalize for Box<T> {
113 fn canonicalize(&mut self) {
114 self.as_mut().canonicalize()
115 }
116}
117
118pub trait Evaluate<Output> {
120 fn evaluate(&self) -> Output;
122}
123
124impl<O, T: Evaluate<O>> Evaluate<O> for Box<T> {
125 fn evaluate(&self) -> O {
126 self.as_ref().evaluate()
127 }
128}
129
130impl<O, T: Evaluate<O>> Evaluate<Option<O>> for Option<T> {
131 fn evaluate(&self) -> Option<O> {
132 self.as_ref().map(Evaluate::<O>::evaluate)
133 }
134}
135
136impl<O: Sum, T: Evaluate<O>> Evaluate<O> for [T] {
137 fn evaluate(&self) -> O {
138 self.iter().map(Evaluate::<O>::evaluate).sum()
139 }
140}
141
142impl<O: Sum, T: Evaluate<O>> Evaluate<O> for Vec<T> {
143 fn evaluate(&self) -> O {
144 self.iter().map(Evaluate::<O>::evaluate).sum()
145 }
146}
147
148pub trait Validatable {
150 type Diagnostic: Diagnostic;
152
153 type Context: ?Sized;
155
156 fn validate_with_context(
159 &self,
160 context: &Self::Context,
161 ) -> Result<Vec<Self::Diagnostic>, Vec<Self::Diagnostic>>;
162
163 fn validate(&self) -> Result<Vec<Self::Diagnostic>, Vec<Self::Diagnostic>>
166 where
167 Self::Context: Default,
168 {
169 self.validate_with_context(&Default::default())
170 }
171}