1use super::error::EvalResultExt;
2use super::*;
3use indexmap::map::Entry;
4use std::hash::Hash;
5
6impl private::Sealed for Body {}
7
8impl Evaluate for Body {
9 type Output = Self;
10
11 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
12 self.iter()
13 .map(|structure| structure.evaluate(ctx))
14 .collect()
15 }
16
17 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
18 #[allow(clippy::manual_try_fold)]
19 self.iter_mut().fold(Ok(()), |res, structure| {
20 res.add_errors(structure.evaluate_in_place(ctx))
21 })
22 }
23}
24
25impl private::Sealed for Structure {}
26
27impl Evaluate for Structure {
28 type Output = Self;
29
30 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
31 match self {
32 Structure::Attribute(attr) => attr.evaluate(ctx).map(Structure::Attribute),
33 Structure::Block(block) => block.evaluate(ctx).map(Structure::Block),
34 }
35 }
36
37 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
38 match self {
39 Structure::Attribute(attr) => attr.evaluate_in_place(ctx),
40 Structure::Block(block) => block.evaluate_in_place(ctx),
41 }
42 }
43}
44
45impl private::Sealed for Attribute {}
46
47impl Evaluate for Attribute {
48 type Output = Self;
49
50 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
51 Ok(Attribute {
52 key: self.key.clone(),
53 expr: self.expr.evaluate(ctx).map(Into::into)?,
54 })
55 }
56
57 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
58 self.expr.evaluate_in_place(ctx)
59 }
60}
61
62impl private::Sealed for Block {}
63
64impl Evaluate for Block {
65 type Output = Self;
66
67 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
68 Ok(Block {
69 identifier: self.identifier.clone(),
70 labels: self.labels.clone(),
71 body: self.body.evaluate(ctx)?,
72 })
73 }
74
75 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
76 self.body.evaluate_in_place(ctx)
77 }
78}
79
80impl private::Sealed for Expression {}
81
82impl Evaluate for Expression {
83 type Output = Value;
84
85 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
86 let ctx = &ctx.child_with_expr(self);
87 match self {
88 Expression::Array(array) => array.evaluate(ctx).map(Value::Array),
89 Expression::Object(object) => object.evaluate(ctx).map(Value::Object),
90 Expression::TemplateExpr(expr) => expr.evaluate(ctx),
91 Expression::Variable(ident) => ctx.lookup_var(ident).cloned(),
92 Expression::Traversal(traversal) => traversal.evaluate(ctx),
93 Expression::FuncCall(func_call) => func_call.evaluate(ctx),
94 Expression::Parenthesis(expr) => expr.evaluate(ctx),
95 Expression::Conditional(cond) => cond.evaluate(ctx),
96 Expression::Operation(op) => op.evaluate(ctx),
97 Expression::ForExpr(expr) => expr.evaluate(ctx),
98 other => Ok(Value::from(other.clone())),
99 }
100 }
101
102 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
103 if !matches!(
106 self,
107 Expression::Null | Expression::Bool(_) | Expression::Number(_) | Expression::String(_)
108 ) {
109 evaluate_nested_exprs(self, ctx)?;
110 let value = self.evaluate(ctx)?;
111 *self = value.into();
112 }
113
114 Ok(())
115 }
116}
117
118fn evaluate_nested_exprs(expr: &mut Expression, ctx: &Context) -> EvalResult<(), Errors> {
119 let expr_clone = expr.clone();
120 let ctx = &ctx.child_with_expr(&expr_clone);
121
122 match expr {
123 Expression::Array(array) => array.evaluate_in_place(ctx),
124 Expression::Object(object) => object.evaluate_in_place(ctx),
125 Expression::Traversal(traversal) => traversal.evaluate_in_place(ctx),
126 Expression::FuncCall(func_call) => func_call.evaluate_in_place(ctx),
127 Expression::Parenthesis(expr) => expr.evaluate_in_place(ctx),
128 Expression::Conditional(cond) => cond.evaluate_in_place(ctx),
129 Expression::Operation(op) => op.evaluate_in_place(ctx),
130 Expression::ForExpr(expr) => expr.evaluate_in_place(ctx),
131 _ => Ok(()),
132 }
133}
134
135impl<T> private::Sealed for Vec<T> where T: Evaluate {}
136
137impl<T> Evaluate for Vec<T>
138where
139 T: Evaluate,
140{
141 type Output = Vec<T::Output>;
142
143 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
144 self.iter().map(|expr| expr.evaluate(ctx)).collect()
145 }
146
147 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
148 #[allow(clippy::manual_try_fold)]
149 self.iter_mut().fold(Ok(()), |res, element| {
150 res.add_errors(element.evaluate_in_place(ctx))
151 })
152 }
153}
154
155impl<K, V> private::Sealed for Object<K, V>
156where
157 K: Evaluate,
158 V: Evaluate,
159{
160}
161
162impl<K, V> Evaluate for Object<K, V>
163where
164 K: Evaluate + Eq,
165 K::Output: Hash + Eq,
166 V: Evaluate,
167{
168 type Output = Map<K::Output, V::Output>;
169
170 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
171 self.iter()
172 .map(|(key, expr)| Ok((key.evaluate(ctx)?, expr.evaluate(ctx)?)))
173 .collect()
174 }
175
176 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
177 let mut new_object = Object::with_capacity(self.len());
178
179 #[allow(clippy::manual_try_fold)]
180 let res = self
181 .drain(..)
182 .fold(Ok(()), |mut res, (mut key, mut value)| {
183 res = res
184 .add_errors(key.evaluate_in_place(ctx))
185 .add_errors(value.evaluate_in_place(ctx));
186 new_object.insert(key, value);
187 res
188 });
189
190 *self = new_object;
191
192 res
193 }
194}
195
196impl private::Sealed for ObjectKey {}
197
198impl Evaluate for ObjectKey {
199 type Output = String;
200
201 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
202 match self {
203 ObjectKey::Expression(expr) => expr::evaluate_object_key(expr, ctx),
204 ident => Ok(ident.to_string()),
205 }
206 }
207
208 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
209 if let ObjectKey::Expression(expr) = self {
210 expr.evaluate_in_place(ctx)?;
211 }
212
213 Ok(())
214 }
215}
216
217impl private::Sealed for TemplateExpr {}
218
219impl Evaluate for TemplateExpr {
220 type Output = Value;
221
222 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
223 let template = Template::from_expr(self)?;
224 let elements = template.elements();
225
226 match elements.first() {
232 Some(Element::Interpolation(interp)) if elements.len() == 1 => {
233 interp.expr.evaluate(ctx)
234 }
235 _ => template.evaluate(ctx).map(Value::String),
236 }
237 }
238}
239
240impl private::Sealed for Template {}
241
242impl Evaluate for Template {
243 type Output = String;
244
245 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
246 let mut result = String::new();
247 template::evaluate_template(&mut result, self, ctx, Strip::None, Strip::None)?;
248 Ok(result)
249 }
250
251 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
252 #[allow(clippy::manual_try_fold)]
253 self.elements_mut()
254 .iter_mut()
255 .fold(Ok(()), |mut res, element| match element {
256 Element::Literal(_) => res,
257 Element::Interpolation(interp) => {
258 res.add_errors(interp.expr.evaluate_in_place(ctx))
259 }
260 Element::Directive(dir) => match &mut **dir {
261 Directive::If(dir) => {
262 res = res
263 .add_errors(dir.cond_expr.evaluate_in_place(ctx))
264 .add_errors(dir.true_template.evaluate_in_place(ctx));
265
266 match &mut dir.false_template {
267 Some(false_template) => {
268 res.add_errors(false_template.evaluate_in_place(ctx))
269 }
270 None => res,
271 }
272 }
273 Directive::For(dir) => res
274 .add_errors(dir.collection_expr.evaluate_in_place(ctx))
275 .add_errors(dir.template.evaluate_in_place(ctx)),
276 },
277 })
278 }
279}
280
281impl private::Sealed for Traversal {}
282
283impl Evaluate for Traversal {
284 type Output = Value;
285
286 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
287 let value = self.expr.evaluate(ctx)?;
288 let deque = self.operators.iter().collect();
289 expr::evaluate_traversal(value, deque, ctx)
290 }
291
292 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
293 #[allow(clippy::manual_try_fold)]
294 self.operators
295 .iter_mut()
296 .fold(Ok(()), |res, operator| match operator {
297 TraversalOperator::Index(expr) => res.add_errors(expr.evaluate_in_place(ctx)),
298 _ => res,
299 })
300 }
301}
302
303impl private::Sealed for FuncCall {}
304
305impl Evaluate for FuncCall {
306 type Output = Value;
307
308 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
309 let name = &self.name;
310 let func = ctx.lookup_func(name)?;
311 let len = self.args.len();
312 let mut args = Vec::with_capacity(len);
313
314 for (index, arg) in self.args.iter().enumerate() {
315 if self.expand_final && index == len - 1 {
316 args.extend(expr::evaluate_array(arg, ctx)?);
317 } else {
318 args.push(arg.evaluate(ctx)?);
319 }
320 }
321
322 func.call(args)
323 .map_err(|err| ctx.error(ErrorKind::FuncCall(name.clone(), err)))
324 }
325
326 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
327 self.args.evaluate_in_place(ctx)
328 }
329}
330
331impl private::Sealed for Conditional {}
332
333impl Evaluate for Conditional {
334 type Output = Value;
335
336 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
337 if expr::evaluate_bool(&self.cond_expr, ctx)? {
338 self.true_expr.evaluate(ctx)
339 } else {
340 self.false_expr.evaluate(ctx)
341 }
342 }
343
344 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
345 let cond = expr::evaluate_bool(&self.cond_expr, ctx)?;
346
347 self.cond_expr = Expression::from(cond);
348
349 if cond {
350 self.true_expr.evaluate_in_place(ctx)
351 } else {
352 self.false_expr.evaluate_in_place(ctx)
353 }
354 }
355}
356
357impl private::Sealed for Operation {}
358
359impl Evaluate for Operation {
360 type Output = Value;
361
362 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
363 match self {
364 Operation::Unary(unary) => unary.evaluate(ctx),
365 Operation::Binary(binary) => binary.evaluate(ctx),
366 }
367 }
368
369 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
370 match self {
371 Operation::Unary(unary) => unary.evaluate_in_place(ctx),
372 Operation::Binary(binary) => binary.evaluate_in_place(ctx),
373 }
374 }
375}
376
377impl private::Sealed for UnaryOp {}
378
379impl Evaluate for UnaryOp {
380 type Output = Value;
381
382 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
383 use {UnaryOperator::*, Value::*};
384
385 let value = self.expr.evaluate(ctx)?;
386
387 let value = match (self.operator, value) {
388 (Not, Bool(v)) => Bool(!v),
389 (Neg, Number(n)) => Number(-n),
390 (operator, value) => return Err(ctx.error(ErrorKind::UnaryOp(operator, value))),
391 };
392
393 Ok(value)
394 }
395
396 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
397 self.expr.evaluate_in_place(ctx)
398 }
399}
400
401impl private::Sealed for BinaryOp {}
402
403impl Evaluate for BinaryOp {
404 type Output = Value;
405
406 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
407 use {BinaryOperator::*, Value::*};
408
409 let lhs = self.lhs_expr.evaluate(ctx)?;
410 let rhs = self.rhs_expr.evaluate(ctx)?;
411
412 let value = match (lhs, self.operator, rhs) {
413 (lhs, Eq, rhs) => Bool(lhs == rhs),
414 (lhs, NotEq, rhs) => Bool(lhs != rhs),
415 (Bool(lhs), And, Bool(rhs)) => Bool(lhs && rhs),
416 (Bool(lhs), Or, Bool(rhs)) => Bool(lhs || rhs),
417 (Number(lhs), LessEq, Number(rhs)) => Bool(lhs <= rhs),
418 (Number(lhs), GreaterEq, Number(rhs)) => Bool(lhs >= rhs),
419 (Number(lhs), Less, Number(rhs)) => Bool(lhs < rhs),
420 (Number(lhs), Greater, Number(rhs)) => Bool(lhs > rhs),
421 (Number(lhs), Plus, Number(rhs)) => Number(lhs + rhs),
422 (Number(lhs), Minus, Number(rhs)) => Number(lhs - rhs),
423 (Number(lhs), Mul, Number(rhs)) => Number(lhs * rhs),
424 (Number(lhs), Div, Number(rhs)) => Number(lhs / rhs),
425 (Number(lhs), Mod, Number(rhs)) => Number(lhs % rhs),
426 (lhs, operator, rhs) => return Err(ctx.error(ErrorKind::BinaryOp(lhs, operator, rhs))),
427 };
428
429 Ok(value)
430 }
431
432 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
433 self.lhs_expr
434 .evaluate_in_place(ctx)
435 .add_errors(self.rhs_expr.evaluate_in_place(ctx))
436 }
437}
438
439impl private::Sealed for ForExpr {}
440
441impl Evaluate for ForExpr {
442 type Output = Value;
443
444 fn evaluate(&self, ctx: &Context) -> EvalResult<Self::Output> {
445 let collection = expr::Collection::from_for_expr(self, ctx)?;
446
447 if let Some(key_expr) = &self.key_expr {
448 let mut result = Map::with_capacity(collection.len());
450
451 for ctx in collection {
452 let ctx = &ctx?;
453 let key = expr::evaluate_object_key(key_expr, ctx)?;
454 let value = self.value_expr.evaluate(ctx)?;
455
456 if self.grouping {
457 result
458 .entry(key)
459 .or_insert_with(|| Value::Array(Vec::new()))
460 .as_array_mut()
461 .unwrap()
462 .push(value);
463 } else {
464 match result.entry(key) {
465 Entry::Occupied(entry) => {
466 return Err(ctx.error(ErrorKind::KeyExists(entry.key().clone())))
467 }
468 Entry::Vacant(entry) => {
469 entry.insert(value);
470 }
471 }
472 }
473 }
474
475 Ok(Value::Object(result))
476 } else {
477 let result = collection
479 .into_iter()
480 .map(|ctx| self.value_expr.evaluate(&ctx?))
481 .collect::<EvalResult<_>>()?;
482
483 Ok(Value::Array(result))
484 }
485 }
486
487 fn evaluate_in_place(&mut self, ctx: &Context) -> EvalResult<(), Errors> {
488 self.collection_expr.evaluate_in_place(ctx)
489 }
490}