kind_tree/concrete/
visitor.rs

1//! Specifies a visitor trait following the visitor pattern
2//! because it's easier to walk the entire tree
3//! just by some nodes without writing some functions
4//! to walk through everything (yeah i really hate
5//! OOP patterns but this time it's really useful.)
6//!
7//! All of these functions are implemented so we can easily
8//! change these default implementations.
9//! use kind_span::{Range, SyntaxCtxIndex};
10
11use crate::symbol::*;
12use crate::{concrete::expr::*, concrete::Book};
13
14use super::pat::{Pat, PatIdent, PatKind};
15use super::TopLevel;
16use super::{Argument, Attribute, AttributeStyle, Constructor, Entry, Module, Rule};
17
18#[macro_export]
19macro_rules! visit_vec {
20    ($args:expr, $pat:pat => $fun:expr) => {
21        for $pat in $args {
22            $fun
23        }
24    };
25}
26
27#[macro_export]
28macro_rules! visit_opt {
29    ($args:expr, $pat:pat => $fun:expr) => {
30        match $args {
31            Some($pat) => $fun,
32            None => (),
33        }
34    };
35}
36
37use kind_span::{Range, SyntaxCtxIndex};
38
39pub(crate) use visit_opt;
40pub(crate) use visit_vec;
41
42pub trait Visitor: Sized {
43    fn visit_range(&mut self, x: &mut Range) {
44        walk_range(self, x);
45    }
46
47    fn visit_attr_style(&mut self, attr: &mut AttributeStyle) {
48        walk_attr_style(self, attr);
49    }
50
51    fn visit_attr(&mut self, attr: &mut Attribute) {
52        walk_attr(self, attr);
53    }
54
55    fn visit_syntax_ctx(&mut self, synt: &mut SyntaxCtxIndex) {
56        walk_syntax_ctx(self, synt);
57    }
58
59    fn visit_literal(&mut self, range: Range, lit: &mut Literal) {
60        walk_literal(self, range, lit);
61    }
62
63    fn visit_pat_ident(&mut self, ident: &mut PatIdent) {
64        walk_pat_ident(self, ident);
65    }
66
67    fn visit_qualified_ident(&mut self, ident: &mut QualifiedIdent) {
68        walk_qualified_ident(self, ident);
69    }
70
71    fn visit_ident(&mut self, ident: &mut Ident) {
72        walk_ident(self, ident);
73    }
74
75    fn visit_app_binding(&mut self, ident: &mut AppBinding) {
76        walk_app_binding(self, ident);
77    }
78
79    fn visit_destruct(&mut self, ident: &mut Destruct) {
80        walk_destruct(self, ident);
81    }
82
83    fn visit_match(&mut self, matcher: &mut Match) {
84        walk_match(self, matcher);
85    }
86
87    fn visit_constructor(&mut self, construtor: &mut Constructor) {
88        walk_constructor(self, construtor);
89    }
90
91    fn visit_argument(&mut self, argument: &mut Argument) {
92        walk_argument(self, argument);
93    }
94
95    fn visit_book(&mut self, book: &mut Book) {
96        walk_book(self, book)
97    }
98
99    fn visit_entry(&mut self, entry: &mut Entry) {
100        walk_entry(self, entry);
101    }
102
103    fn visit_pat(&mut self, pat: &mut Pat) {
104        walk_pat(self, pat);
105    }
106
107    fn visit_binding(&mut self, binding: &mut Binding) {
108        walk_binding(self, binding);
109    }
110
111    fn visit_top_level(&mut self, toplevel: &mut TopLevel) {
112        walk_top_level(self, toplevel)
113    }
114
115    fn visit_rule(&mut self, rule: &mut Rule) {
116        walk_rule(self, rule);
117    }
118
119    fn visit_module(&mut self, module: &mut Module) {
120        walk_module(self, module);
121    }
122
123    fn visit_substitution(&mut self, subst: &mut Substitution) {
124        walk_substitution(self, subst);
125    }
126
127    fn visit_case_binding(&mut self, case_binding: &mut CaseBinding) {
128        walk_case_binding(self, case_binding);
129    }
130
131    fn visit_case(&mut self, case: &mut Case) {
132        walk_case(self, case);
133    }
134
135    fn visit_sttm(&mut self, sttm: &mut Sttm) {
136        walk_sttm(self, sttm);
137    }
138
139    fn visit_expr(&mut self, expr: &mut Expr) {
140        walk_expr(self, expr);
141    }
142}
143
144pub fn walk_range<T: Visitor>(_: &mut T, _: &mut Range) {}
145
146pub fn walk_syntax_ctx<T: Visitor>(_: &mut T, _: &mut SyntaxCtxIndex) {}
147
148pub fn walk_literal<T: Visitor>( _: &mut T, _: Range, _: &mut Literal) {}
149
150pub fn walk_constructor<T: Visitor>(ctx: &mut T, cons: &mut Constructor) {
151    ctx.visit_ident(&mut cons.name);
152    visit_vec!(cons.args.get_vec(), arg => ctx.visit_argument(arg));
153    visit_opt!(&mut cons.typ, arg => ctx.visit_expr(arg))
154}
155
156pub fn walk_book<T: Visitor>(ctx: &mut T, book: &mut Book) {
157    visit_vec!(&mut book.entries, (_, arg) => ctx.visit_top_level(arg));
158}
159
160pub fn walk_pat_ident<T: Visitor>(ctx: &mut T, ident: &mut PatIdent) {
161    ctx.visit_range(&mut ident.0.range);
162}
163
164pub fn walk_ident<T: Visitor>(ctx: &mut T, ident: &mut Ident) {
165    ctx.visit_range(&mut ident.range);
166}
167
168pub fn walk_qualified_ident<T: Visitor>(ctx: &mut T, ident: &mut QualifiedIdent) {
169    ctx.visit_range(&mut ident.range);
170}
171
172pub fn walk_destruct<T: Visitor>(ctx: &mut T, destruct: &mut Destruct) {
173    match destruct {
174        Destruct::Destruct(range, i, e, _) => {
175            ctx.visit_qualified_ident(i);
176            ctx.visit_range(range);
177            visit_vec!(e, e => ctx.visit_case_binding(e))
178        }
179        Destruct::Ident(i) => ctx.visit_ident(i),
180    }
181}
182
183pub fn walk_binding<T: Visitor>(ctx: &mut T, binding: &mut Binding) {
184    match binding {
185        Binding::Positional(e) => ctx.visit_expr(e),
186        Binding::Named(span, ident, e) => {
187            ctx.visit_range(span);
188            ctx.visit_ident(ident);
189            ctx.visit_expr(e);
190        }
191    }
192}
193
194pub fn walk_app_binding<T: Visitor>(ctx: &mut T, binding: &mut AppBinding) {
195    ctx.visit_expr(&mut binding.data)
196}
197
198pub fn walk_case_binding<T: Visitor>(ctx: &mut T, binding: &mut CaseBinding) {
199    match binding {
200        CaseBinding::Field(ident) => ctx.visit_ident(ident),
201        CaseBinding::Renamed(ident, rename) => {
202            ctx.visit_ident(ident);
203            ctx.visit_ident(rename);
204        }
205    }
206}
207
208pub fn walk_case<T: Visitor>(ctx: &mut T, case: &mut Case) {
209    ctx.visit_ident(&mut case.constructor);
210    for binding in &mut case.bindings {
211        ctx.visit_case_binding(binding);
212    }
213    ctx.visit_expr(&mut case.value)
214}
215
216pub fn walk_match<T: Visitor>(ctx: &mut T, matcher: &mut Match) {
217    ctx.visit_qualified_ident(&mut matcher.typ);
218
219    ctx.visit_ident(&mut matcher.scrutinee);
220
221    if let Some(opt) = &mut matcher.value {
222        ctx.visit_expr(opt);
223    }
224
225    for (name, expr) in &mut matcher.with_vars {
226        ctx.visit_ident(name);
227        if let Some(expr) = expr {
228            ctx.visit_expr(expr);
229        }
230    }
231
232    match &mut matcher.motive {
233        Some(expr) => ctx.visit_expr(expr),
234        None => (),
235    }
236
237    for case in &mut matcher.cases {
238        ctx.visit_case(case)
239    }
240}
241
242pub fn walk_argument<T: Visitor>(ctx: &mut T, argument: &mut Argument) {
243    ctx.visit_ident(&mut argument.name);
244    match &mut argument.typ {
245        Some(typ) => ctx.visit_expr(typ),
246        None => (),
247    }
248    ctx.visit_range(&mut argument.range);
249}
250
251pub fn walk_entry<T: Visitor>(ctx: &mut T, entry: &mut Entry) {
252    ctx.visit_qualified_ident(&mut entry.name);
253    for arg in entry.args.iter_mut() {
254        ctx.visit_argument(arg)
255    }
256    ctx.visit_expr(&mut entry.typ);
257    for rule in &mut entry.rules {
258        ctx.visit_rule(rule)
259    }
260    for attr in &mut entry.attrs {
261        ctx.visit_attr(attr);
262    }
263    ctx.visit_range(&mut entry.range);
264}
265
266pub fn walk_attr<T: Visitor>(ctx: &mut T, attr: &mut Attribute) {
267    ctx.visit_ident(&mut attr.name);
268    ctx.visit_range(&mut attr.range);
269    visit_opt!(&mut attr.value, x => ctx.visit_attr_style(x))
270}
271
272pub fn walk_attr_style<T: Visitor>(ctx: &mut T, attr: &mut AttributeStyle) {
273    match attr {
274        AttributeStyle::Ident(r, _) => {
275            ctx.visit_range(r);
276        }
277        AttributeStyle::String(r, _) => {
278            ctx.visit_range(r);
279        }
280        AttributeStyle::Number(r, _) => {
281            ctx.visit_range(r);
282        }
283        AttributeStyle::List(r, l) => {
284            ctx.visit_range(r);
285            visit_vec!(l.iter_mut(), attr => ctx.visit_attr_style(attr))
286        }
287    }
288}
289
290pub fn walk_pat<T: Visitor>(ctx: &mut T, pat: &mut Pat) {
291    ctx.visit_range(&mut pat.range);
292    match &mut pat.data {
293        PatKind::Var(ident) => ctx.visit_pat_ident(ident),
294        PatKind::Str(_) => (),
295        PatKind::U60(_) => (),
296        PatKind::U120(_) => (),
297        PatKind::F60(_) => (),
298        PatKind::Char(_) => (),
299        PatKind::Hole => (),
300        PatKind::List(ls) => {
301            for pat in ls {
302                ctx.visit_pat(pat)
303            }
304        }
305        PatKind::Pair(fst, snd) => {
306            ctx.visit_pat(fst);
307            ctx.visit_pat(snd);
308        }
309        PatKind::App(t, ls) => {
310            ctx.visit_qualified_ident(t);
311            for pat in ls {
312                ctx.visit_pat(pat)
313            }
314        }
315    }
316}
317
318pub fn walk_rule<T: Visitor>(ctx: &mut T, rule: &mut Rule) {
319    ctx.visit_qualified_ident(&mut rule.name);
320    for pat in &mut rule.pats {
321        ctx.visit_pat(pat);
322    }
323    ctx.visit_expr(&mut rule.body);
324    ctx.visit_range(&mut rule.range);
325}
326
327pub fn walk_top_level<T: Visitor>(ctx: &mut T, toplevel: &mut TopLevel) {
328    match toplevel {
329        super::TopLevel::SumType(sum) => {
330            ctx.visit_qualified_ident(&mut sum.name);
331            visit_vec!(&mut sum.attrs, arg => ctx.visit_attr(arg));
332            visit_vec!(sum.parameters.get_vec(), arg => ctx.visit_argument(arg));
333            visit_vec!(sum.indices.get_vec(), arg => ctx.visit_argument(arg));
334            visit_vec!(&mut sum.constructors, arg => ctx.visit_constructor(arg));
335        }
336        super::TopLevel::RecordType(rec) => {
337            ctx.visit_qualified_ident(&mut rec.name);
338            visit_vec!(&mut rec.attrs, arg => ctx.visit_attr(arg));
339            visit_vec!(rec.parameters.get_vec(), arg => ctx.visit_argument(arg));
340            visit_vec!(&mut rec.fields, (name, _docs, typ) => {
341                ctx.visit_ident(name);
342                ctx.visit_expr(typ);
343            });
344        }
345        super::TopLevel::Entry(entry) => {
346            ctx.visit_entry(entry);
347        }
348    }
349}
350
351pub fn walk_module<T: Visitor>(ctx: &mut T, module: &mut Module) {
352    for toplevel in &mut module.entries {
353        walk_top_level(ctx, toplevel)
354    }
355}
356
357pub fn walk_substitution<T: Visitor>(ctx: &mut T, subst: &mut Substitution) {
358    ctx.visit_expr(&mut subst.expr);
359    ctx.visit_ident(&mut subst.name);
360}
361
362pub fn walk_sttm<T: Visitor>(ctx: &mut T, sttm: &mut Sttm) {
363    ctx.visit_range(&mut sttm.range);
364    match &mut sttm.data {
365        SttmKind::Ask(ident, val, next) => {
366            ctx.visit_destruct(ident);
367            ctx.visit_expr(val);
368            ctx.visit_sttm(next);
369        }
370        SttmKind::Let(destrut, val, next) => {
371            ctx.visit_destruct(destrut);
372            ctx.visit_expr(val);
373            ctx.visit_sttm(next);
374        }
375        SttmKind::Expr(expr, next) => {
376            ctx.visit_expr(expr);
377            ctx.visit_sttm(next);
378        }
379        SttmKind::Return(expr) => {
380            ctx.visit_expr(expr);
381        }
382        SttmKind::RetExpr(expr) => {
383            ctx.visit_expr(expr);
384        }
385    }
386}
387
388pub fn walk_expr<T: Visitor>(ctx: &mut T, expr: &mut Expr) {
389    ctx.visit_range(&mut expr.range);
390    match &mut expr.data {
391        ExprKind::Var { name } => ctx.visit_ident(name),
392        ExprKind::Constr { name, args } => {
393            ctx.visit_qualified_ident(name);
394            for arg in args {
395                ctx.visit_binding(arg);
396            }
397        }
398        ExprKind::Pair { fst, snd } => {
399            ctx.visit_expr(fst);
400            ctx.visit_expr(snd);
401        }
402        ExprKind::All {
403            param: None,
404            typ,
405            body,
406            ..
407        } => {
408            ctx.visit_expr(typ);
409            ctx.visit_expr(body);
410        }
411        ExprKind::All {
412            param: Some(ident),
413            typ,
414            body,
415            ..
416        } => {
417            ctx.visit_ident(ident);
418            ctx.visit_expr(typ);
419            ctx.visit_expr(body);
420        }
421        ExprKind::Sigma {
422            param: None,
423            fst,
424            snd,
425        } => {
426            ctx.visit_expr(fst);
427            ctx.visit_expr(snd);
428        }
429        ExprKind::If { cond, then_, else_ } => {
430            ctx.visit_expr(cond);
431            ctx.visit_expr(then_);
432            ctx.visit_expr(else_);
433        }
434        ExprKind::Sigma {
435            param: Some(ident),
436            fst,
437            snd,
438        } => {
439            ctx.visit_ident(ident);
440            ctx.visit_expr(fst);
441            ctx.visit_expr(snd);
442        }
443        ExprKind::Do { typ, sttm } => {
444            ctx.visit_qualified_ident(typ);
445            ctx.visit_sttm(sttm)
446        }
447        ExprKind::Lambda {
448            param, typ, body, ..
449        } => {
450            ctx.visit_ident(param);
451            match typ {
452                Some(x) => ctx.visit_expr(x),
453                None => (),
454            }
455            ctx.visit_expr(body);
456        }
457        ExprKind::App { fun, args } => {
458            ctx.visit_expr(fun);
459            for arg in args {
460                ctx.visit_app_binding(arg);
461            }
462        }
463        ExprKind::List { args } => {
464            for arg in args {
465                ctx.visit_expr(arg);
466            }
467        }
468        ExprKind::Let { name, val, next } => {
469            ctx.visit_destruct(name);
470            ctx.visit_expr(val);
471            ctx.visit_expr(next);
472        }
473        ExprKind::Ann { val, typ } => {
474            ctx.visit_expr(val);
475            ctx.visit_expr(typ);
476        }
477        ExprKind::Lit { lit } => {
478            ctx.visit_literal(expr.range, lit);
479        }
480        ExprKind::Binary { op: _, fst, snd } => {
481            ctx.visit_expr(fst);
482            ctx.visit_expr(snd);
483        }
484        ExprKind::Open { type_name, var_name, motive, next } => {
485            ctx.visit_qualified_ident(type_name);
486            ctx.visit_ident(var_name);
487            ctx.visit_expr(next);
488            if let Some(res) = motive {
489                ctx.visit_expr(res);
490            }
491        },
492        ExprKind::Hole => {}
493        ExprKind::Subst(subst) => ctx.visit_substitution(subst),
494        ExprKind::Match(matcher) => ctx.visit_match(matcher),
495        ExprKind::SeqRecord(seq) => {
496            ctx.visit_expr(&mut seq.expr);
497            ctx.visit_expr(&mut seq.typ);
498
499            match &mut seq.operation {
500                SeqOperation::Set(expr) => ctx.visit_expr(expr),
501                SeqOperation::Mut(expr) => ctx.visit_expr(expr),
502                SeqOperation::Get => (),
503            }
504        },
505    }
506}