1use crate::ast::node::Node;
2use crate::ast::program::Program;
3use crate::functions::{array, string, ExprCall, Function};
4use crate::{ExprPest, Rule};
5use crate::{bail, Context, Error, Result, Value};
6use indexmap::IndexMap;
7use pest::Parser as PestParser;
8use std::fmt;
9use std::fmt::{Debug, Formatter};
10
11#[derive(Default)]
22pub struct Parser<'a> {
23 pub(crate) functions: IndexMap<String, Function<'a>>,
24}
25
26impl Debug for Parser<'_> {
27 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
28 f.debug_struct("ExprParser").finish()
29 }
30}
31
32impl<'a> Parser<'a> {
33 pub fn new() -> Self {
35 let mut p = Self {
36 functions: IndexMap::new(),
37 };
38 string::add_string_functions(&mut p);
39 array::add_array_functions(&mut p);
40 p
41 }
42
43 pub fn add_function<F>(&mut self, name: &str, f: F)
66 where
67 F: Fn(ExprCall) -> Result<Value> + 'a + Sync + Send,
68 {
69 self.functions.insert(name.to_string(), Box::new(f));
70 }
71
72 pub fn compile(&self, code: &str) -> Result<Program> {
74 #[cfg(debug_assertions)]
75 pest::set_error_detail(true);
76 let pairs = ExprPest::parse(Rule::full, code).map_err(|e| Error::PestError(Box::new(e)))?;
77 Ok(pairs.into())
78 }
79
80 pub fn run(&self, program: Program, ctx: &Context) -> Result<Value> {
82 let mut ctx = ctx.clone();
83 ctx.insert("$env".to_string(), Value::Map(ctx.0.clone()));
84 for (id, expr) in program.lines {
85 ctx.insert(id, self.eval_expr(&ctx, expr)?);
86 }
87 self.eval_expr(&ctx, program.expr)
88 }
89
90 pub fn eval(&self, code: &str, ctx: &Context) -> Result<Value> {
101 let program = self.compile(code)?;
102 self.run(program, ctx)
103 }
104
105 pub fn eval_expr(&self, ctx: &Context, node: Node) -> Result<Value> {
106 let value = match node {
107 Node::Value(value) => value,
108 Node::Ident(id) => {
109 if let Some(value) = ctx.get(&id) {
110 value.clone()
111 } else if let Some(item) = ctx
112 .get("#")
113 .and_then(|o| o.as_map())
114 .and_then(|m| m.get(&id))
115 {
116 item.clone()
117 } else {
118 bail!("Unknown variable: {id}")
119 }
120 }
121 Node::Func {
122 ident,
123 args,
124 predicate,
125 } => {
126 let args = args
127 .into_iter()
128 .map(|e| self.eval_expr(ctx, e))
129 .collect::<Result<_>>()?;
130 self.exec_func(ctx, ident, args, predicate.map(|l| *l))?
131 },
132 Node::Operation {
133 left,
134 operator,
135 right,
136 } => self.eval_operator(ctx, operator, *left, *right)?,
137 Node::Unary { operator, node } => self.eval_unary_operator(ctx, operator, *node)?,
138 Node::Postfix { operator, node } => self.eval_postfix_operator(ctx, operator, *node)?,
139 Node::Array(a) => Value::Array(
140 a.into_iter()
141 .map(|e| self.eval_expr(ctx, e))
142 .collect::<Result<_>>()?,
143 ), Node::Range(start, end) => match (self.eval_expr(ctx, *start)?, self.eval_expr(ctx, *end)?) {
145 (Value::Number(start), Value::Number(end)) => {
146 Value::Array((start..=end).map(Value::Number).collect())
147 }
148 (start, end) => bail!("Invalid range: {start:?}..{end:?}"),
149 }
150 };
151 Ok(value)
152 }
153}