explain/
explain.rs

1use rscel::{
2    Addition, AstNode, BindContext, CelContext, CelResult, CelValue, ConditionalAnd, ConditionalOr,
3    Expr, ExprList, Ident, Member, MemberPrime, Multiplication, NegList, NotList, ObjInit,
4    ObjInits, Primary, Relation, SourceRange, Unary,
5};
6
7struct RangeNode {
8    pub range: SourceRange,
9
10    pub children: Vec<Box<RangeNode>>,
11}
12
13impl RangeNode {
14    fn empty(range: SourceRange) -> Self {
15        RangeNode {
16            range,
17            children: Vec::new(),
18        }
19    }
20
21    fn with_children(range: SourceRange, children: impl Iterator<Item = Box<RangeNode>>) -> Self {
22        RangeNode {
23            range,
24            children: children.collect(),
25        }
26    }
27
28    fn range(&self) -> SourceRange {
29        self.range
30    }
31
32    fn into_children(self) -> Vec<Box<RangeNode>> {
33        self.children
34    }
35}
36
37fn main() {
38    let args: Vec<_> = std::env::args().collect();
39
40    if args.len() < 2 {
41        eprintln!("Usage: {} <prog> [bindings]", args[0]);
42        return;
43    }
44
45    let bindings: serde_json::Value = if args.len() == 3 {
46        serde_json::from_str(&args[2]).expect("Failed to parse bindings")
47    } else {
48        serde_json::from_str::<serde_json::Value>("{}").unwrap()
49    };
50
51    let prog = rscel::Program::from_source(&args[1]).expect("Failed to compile");
52    let ast = prog.details().ast().unwrap();
53
54    let dumper = AstDumper::new();
55    let tree = dumper.dump_expr_node(ast);
56
57    let mut queue = Vec::new();
58    queue.push((tree, 0));
59
60    while !queue.is_empty() {
61        let (curr_node, depth) = queue.pop().expect("wut");
62
63        // for now only handle one line
64        let range = curr_node.range();
65
66        let start = range.start().col();
67        let end = range.end().col();
68
69        let src = &args[1][start..end];
70
71        print!("{}{} => ", " ".to_owned().repeat(depth), src);
72        match eval(src, &bindings) {
73            Ok(val) => println!("{}", val),
74            Err(err) => println!("err: {}", err),
75        }
76
77        for node in curr_node.into_children().into_iter().rev() {
78            if node.range() != range {
79                queue.push((node, depth + 1));
80            }
81        }
82    }
83}
84
85fn eval(source: &str, bindings: &serde_json::Value) -> CelResult<CelValue> {
86    let mut ctx = CelContext::new();
87
88    ctx.add_program_str("main", source)?;
89
90    let mut bind = BindContext::new();
91    bind.bind_params_from_json_obj(bindings.clone())?;
92
93    Ok(ctx.exec("main", &bind)?)
94}
95
96struct AstDumper;
97
98impl AstDumper {
99    fn new() -> Self {
100        AstDumper {}
101    }
102
103    fn dump_expr_node(&self, node: &AstNode<Expr>) -> Box<RangeNode> {
104        match node.node() {
105            Expr::Unary(nxt) => self.dump_or_node(nxt),
106            Expr::Ternary {
107                condition,
108                true_clause,
109                false_clause,
110            } => Box::new(RangeNode::with_children(
111                node.range(),
112                [
113                    self.dump_or_node(condition),
114                    self.dump_or_node(true_clause),
115                    self.dump_expr_node(false_clause),
116                ]
117                .into_iter(),
118            )),
119            Expr::Match { .. } => todo!(),
120        }
121    }
122
123    fn dump_or_node(&self, node: &AstNode<ConditionalOr>) -> Box<RangeNode> {
124        match node.node() {
125            ConditionalOr::Unary(nxt) => self.dump_and_node(nxt),
126            ConditionalOr::Binary { lhs, rhs } => Box::new(RangeNode::with_children(
127                node.range(),
128                [self.dump_or_node(lhs), self.dump_and_node(rhs)].into_iter(),
129            )),
130        }
131    }
132
133    fn dump_and_node(&self, node: &AstNode<ConditionalAnd>) -> Box<RangeNode> {
134        match node.node() {
135            ConditionalAnd::Unary(nxt) => self.dump_relation(nxt),
136            ConditionalAnd::Binary { lhs, rhs } => Box::new(RangeNode::with_children(
137                node.range(),
138                [self.dump_and_node(lhs), self.dump_relation(rhs)].into_iter(),
139            )),
140        }
141    }
142
143    fn dump_relation(&self, node: &AstNode<Relation>) -> Box<RangeNode> {
144        match node.node() {
145            Relation::Unary(nxt) => self.dump_addition(nxt),
146            Relation::Binary { lhs, op: _op, rhs } => Box::new(RangeNode::with_children(
147                node.range(),
148                [self.dump_relation(lhs), self.dump_addition(rhs)].into_iter(),
149            )),
150        }
151    }
152
153    fn dump_addition(&self, node: &AstNode<Addition>) -> Box<RangeNode> {
154        match node.node() {
155            Addition::Unary(nxt) => self.dump_multiplication(nxt),
156            Addition::Binary { lhs, op: _op, rhs } => Box::new(RangeNode::with_children(
157                node.range(),
158                [self.dump_addition(lhs), self.dump_multiplication(rhs)].into_iter(),
159            )),
160        }
161    }
162
163    fn dump_multiplication(&self, node: &AstNode<Multiplication>) -> Box<RangeNode> {
164        match node.node() {
165            Multiplication::Unary(nxt) => self.dump_uniary(nxt),
166            Multiplication::Binary { lhs, op: _op, rhs } => Box::new(RangeNode::with_children(
167                node.range(),
168                [self.dump_multiplication(lhs), self.dump_uniary(rhs)].into_iter(),
169            )),
170        }
171    }
172
173    fn dump_uniary(&self, node: &AstNode<Unary>) -> Box<RangeNode> {
174        match node.node() {
175            Unary::Member(nxt) => self.dump_member(nxt),
176            Unary::NegMember { negs, member } => {
177                self.dump_neg(negs);
178                let mem = self.dump_member(member);
179                Box::new(RangeNode::with_children(node.range(), [mem].into_iter()))
180            }
181            Unary::NotMember { nots, member } => {
182                self.dump_not(nots);
183                let mem = self.dump_member(member);
184                Box::new(RangeNode::with_children(node.range(), [mem].into_iter()))
185            }
186        }
187    }
188
189    fn dump_neg(&self, node: &AstNode<NegList>) {
190        match node.node() {
191            NegList::List { tail } => self.dump_neg(tail),
192            NegList::EmptyList => {}
193        }
194    }
195
196    fn dump_not(&self, node: &AstNode<NotList>) {
197        match node.node() {
198            NotList::List { tail } => self.dump_not(tail),
199            NotList::EmptyList => {}
200        }
201    }
202
203    fn dump_member(&self, node: &AstNode<Member>) -> Box<RangeNode> {
204        let mut children = vec![self.dump_primary(&node.node().primary)];
205        for member in node.node().member.iter() {
206            children.push(self.dump_member_prime(member));
207        }
208
209        Box::new(RangeNode::with_children(node.range(), children.into_iter()))
210    }
211
212    fn dump_primary(&self, node: &AstNode<Primary>) -> Box<RangeNode> {
213        match node.node() {
214            Primary::Type => Box::new(RangeNode::empty(node.range())),
215            Primary::Ident(_) => Box::new(RangeNode::empty(node.range())),
216            Primary::Parens(expr) => Box::new(RangeNode::with_children(
217                node.range(),
218                [self.dump_expr_node(expr)].into_iter(),
219            )),
220            Primary::ListConstruction(exprs) => self.dump_expr_list(exprs),
221            Primary::ObjectInit(objinits) => self.dump_obj_inits(objinits),
222            Primary::Literal(_) => Box::new(RangeNode::empty(node.range())),
223        }
224    }
225
226    fn dump_member_prime(&self, node: &AstNode<MemberPrime>) -> Box<RangeNode> {
227        match node.node() {
228            MemberPrime::MemberAccess { ident } => self.dump_ident(&ident),
229            MemberPrime::Call { call } => self.dump_expr_list(call),
230            MemberPrime::ArrayAccess { access } => self.dump_expr_node(access),
231            MemberPrime::Empty => Box::new(RangeNode::empty(node.range())),
232        }
233    }
234
235    fn dump_ident(&self, node: &AstNode<Ident>) -> Box<RangeNode> {
236        Box::new(RangeNode::empty(node.range()))
237    }
238
239    fn dump_expr_list(&self, node: &AstNode<ExprList>) -> Box<RangeNode> {
240        Box::new(RangeNode::with_children(
241            node.range(),
242            node.node()
243                .exprs
244                .clone()
245                .into_iter()
246                .map(|x| self.dump_expr_node(&x)),
247        ))
248    }
249
250    fn dump_obj_inits(&self, node: &AstNode<ObjInits>) -> Box<RangeNode> {
251        Box::new(RangeNode::with_children(
252            node.range(),
253            node.node()
254                .inits
255                .clone()
256                .into_iter()
257                .map(|x| self.dump_obj_init(&x)),
258        ))
259    }
260
261    fn dump_obj_init(&self, node: &AstNode<ObjInit>) -> Box<RangeNode> {
262        self.dump_expr_node(&node.node().key);
263        self.dump_expr_node(&node.node().value);
264        Box::new(RangeNode::empty(node.range()))
265    }
266}