grit_pattern_matcher/pattern/
iter_pattern.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
use super::{
    accessor::Accessor, container::Container, dynamic_snippet::DynamicPattern,
    list_index::ListIndex, patterns::Pattern, predicates::Predicate, regex::RegexLike,
};
use crate::{
    context::{QueryContext, StaticDefinitions},
    pattern::{
        ast_node_pattern::AstNodePattern,
        list_index::{ContainerOrIndex, ListOrContainer},
        patterns::CodeSnippet,
    },
};

pub struct PatternOrPredicateIterator<'a, Q: QueryContext> {
    patterns: Vec<PatternOrPredicate<'a, Q>>,
    definitions: &'a StaticDefinitions<'a, Q>,
}

impl<'a, Q: QueryContext> Iterator for PatternOrPredicateIterator<'a, Q> {
    type Item = PatternOrPredicate<'a, Q>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(pattern) = self.patterns.pop() {
            self.patterns.extend(pattern.children(self.definitions));
            Some(pattern)
        } else {
            None
        }
    }
}

impl<'a, Q: QueryContext> PatternOrPredicateIterator<'a, Q> {
    fn from_pattern(pattern: &'a Pattern<Q>, definitions: &'a StaticDefinitions<Q>) -> Self {
        Self {
            patterns: vec![PatternOrPredicate::Pattern(pattern)],
            definitions,
        }
    }
    fn from_predicate(predicate: &'a Predicate<Q>, definitions: &'a StaticDefinitions<Q>) -> Self {
        Self {
            patterns: vec![PatternOrPredicate::Predicate(predicate)],
            definitions,
        }
    }
}

// todo maybe add variable?
#[derive(Clone, Copy)]
pub enum PatternOrPredicate<'a, Q: QueryContext> {
    Pattern(&'a Pattern<Q>),
    Predicate(&'a Predicate<Q>),
    DynamicPattern(&'a DynamicPattern<Q>),
}

impl<'a, Q: QueryContext> PatternOrPredicate<'a, Q> {
    fn children(&self, definitions: &'a StaticDefinitions<Q>) -> Vec<PatternOrPredicate<'a, Q>> {
        match self {
            PatternOrPredicate::Pattern(p) => p.children(definitions),
            PatternOrPredicate::Predicate(p) => p.children(definitions),
            PatternOrPredicate::DynamicPattern(p) => p.children(definitions),
        }
    }
}

impl<Q: QueryContext> Predicate<Q> {
    pub fn iter<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> PatternOrPredicateIterator<'a, Q> {
        PatternOrPredicateIterator::from_predicate(self, definitions)
    }

    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        match self {
            Predicate::Call(call) => {
                let mut base = args_children(&call.args, definitions);
                let def = definitions.get_predicate(call.index);
                if let Some(def) = def {
                    base.push(PatternOrPredicate::Predicate(&def.predicate));
                }
                base
            }
            Predicate::Not(not) => vec![PatternOrPredicate::Predicate(&not.predicate)],
            Predicate::If(if_) => vec![
                PatternOrPredicate::Predicate(&if_.if_),
                PatternOrPredicate::Predicate(&if_.then),
                PatternOrPredicate::Predicate(&if_.else_),
            ],
            Predicate::True => vec![],
            Predicate::False => vec![],
            Predicate::Or(or) => predicates_children(&or.predicates, definitions),
            Predicate::Maybe(m) => vec![PatternOrPredicate::Predicate(&m.predicate)],
            Predicate::And(and) => predicates_children(&and.predicates, definitions),
            Predicate::Any(any) => predicates_children(&any.predicates, definitions),
            Predicate::Rewrite(rewrite) => {
                let mut res = rewrite.right.children(definitions);
                res.push(PatternOrPredicate::Pattern(&rewrite.left));
                res
            }
            Predicate::Log(log) => log
                .message
                .iter()
                .map(PatternOrPredicate::Pattern)
                .collect(),
            Predicate::Match(match_) => match_
                .pattern
                .iter()
                .map(PatternOrPredicate::Pattern)
                .collect(),
            Predicate::Equal(equal) => vec![PatternOrPredicate::Pattern(&equal.pattern)],
            Predicate::Assignment(assignment) => {
                vec![PatternOrPredicate::Pattern(&assignment.pattern)]
            }
            Predicate::Accumulate(accumulate) => vec![
                PatternOrPredicate::Pattern(&accumulate.left),
                PatternOrPredicate::Pattern(&accumulate.right),
            ],
            Predicate::Return(return_) => vec![PatternOrPredicate::Pattern(&return_.pattern)],
        }
    }
}

impl<Q: QueryContext> Container<Q> {
    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        match self {
            Container::Variable(_) => vec![],
            Container::Accessor(a) => a.children(definitions),
            Container::ListIndex(l) => l.children(definitions),
            Container::FunctionCall(f) => {
                let mut base = args_children(&f.args, definitions);
                let def = definitions.get_function(f.index);
                if let Some(def) = def {
                    base.push(PatternOrPredicate::Predicate(&def.function));
                }
                base
            }
        }
    }
}

impl<Q: QueryContext> Accessor<Q> {
    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        match &self.map {
            super::accessor::AccessorMap::Container(c) => c.children(definitions),
            super::accessor::AccessorMap::Map(m) => m
                .elements
                .values()
                .map(PatternOrPredicate::Pattern)
                .collect(),
        }
    }
}

impl<Q: QueryContext> DynamicPattern<Q> {
    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        match &self {
            super::dynamic_snippet::DynamicPattern::Variable(_) => Vec::new(),
            super::dynamic_snippet::DynamicPattern::Accessor(a) => a.children(definitions),
            super::dynamic_snippet::DynamicPattern::ListIndex(l) => l.children(definitions),
            super::dynamic_snippet::DynamicPattern::Snippet(_) => Vec::new(),
            super::dynamic_snippet::DynamicPattern::List(l) => l
                .elements
                .iter()
                .flat_map(|d| d.children(definitions))
                .collect(),
            super::dynamic_snippet::DynamicPattern::CallBuiltIn(c) => {
                args_children(&c.args, definitions)
            }
            super::dynamic_snippet::DynamicPattern::CallFunction(c) => {
                args_children(&c.args, definitions)
            }
            super::dynamic_snippet::DynamicPattern::CallForeignFunction(c) => {
                args_children(&c.args, definitions)
            }
        }
    }
}

impl<Q: QueryContext> ListIndex<Q> {
    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        let mut v = Vec::new();
        let list = match &self.list {
            ListOrContainer::Container(c) => c.children(definitions),
            ListOrContainer::List(l) => patterns_children(&l.patterns, definitions),
        };
        let index = match &self.index {
            ContainerOrIndex::Container(c) => c.children(definitions),
            ContainerOrIndex::Index(_) => Vec::new(),
        };
        v.extend(list);
        v.extend(index);
        v
    }
}

fn args_children<'a, Q: QueryContext>(
    args: &'a [Option<Pattern<Q>>],
    _definitions: &'a StaticDefinitions<Q>,
) -> Vec<PatternOrPredicate<'a, Q>> {
    args.iter()
        .flat_map(|p| p.as_ref().map(PatternOrPredicate::Pattern))
        .collect()
}

fn patterns_children<'a, Q: QueryContext>(
    patterns: &'a [Pattern<Q>],
    _definitions: &'a StaticDefinitions<Q>,
) -> Vec<PatternOrPredicate<'a, Q>> {
    patterns.iter().map(PatternOrPredicate::Pattern).collect()
}

fn predicates_children<'a, Q: QueryContext>(
    predicates: &'a [Predicate<Q>],
    _definitions: &'a StaticDefinitions<Q>,
) -> Vec<PatternOrPredicate<'a, Q>> {
    predicates
        .iter()
        .map(PatternOrPredicate::Predicate)
        .collect()
}

impl<Q: QueryContext> Pattern<Q> {
    pub fn iter<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> PatternOrPredicateIterator<'a, Q> {
        PatternOrPredicateIterator::from_pattern(self, definitions)
    }

    fn children<'a>(
        &'a self,
        definitions: &'a StaticDefinitions<Q>,
    ) -> Vec<PatternOrPredicate<'a, Q>> {
        match self {
            Pattern::AstNode(a) => a.children(definitions),
            Pattern::List(l) => patterns_children(&l.patterns, definitions),
            Pattern::ListIndex(l) => l.children(definitions),
            Pattern::Map(m) => m
                .elements
                .values()
                .map(PatternOrPredicate::Pattern)
                .collect(),
            Pattern::Accessor(a) => a.children(definitions),
            Pattern::Call(c) => {
                let mut base = args_children(&c.args, definitions);
                let def = definitions.get_pattern(c.index);
                if let Some(def) = def {
                    base.push(PatternOrPredicate::Pattern(def.pattern()));
                }
                base
            }
            Pattern::Regex(r) => {
                if let RegexLike::Pattern(p) = &r.regex {
                    p.children(definitions)
                } else {
                    Vec::new()
                }
            }
            Pattern::File(f) => {
                let mut v = Vec::new();
                let n = f.name.children(definitions);
                let b = f.body.children(definitions);
                v.extend(n);
                v.extend(b);
                v
            }
            Pattern::Files(f) => f.pattern.children(definitions),
            Pattern::Bubble(b) => {
                let mut children = args_children(&b.args, definitions);
                children.extend(b.pattern_def.pattern().children(definitions));
                children
            }
            Pattern::Limit(l) => l.pattern.children(definitions),
            Pattern::CallBuiltIn(c) => args_children(&c.args, definitions),
            Pattern::CallFunction(c) => {
                let mut children = args_children(&c.args, definitions);
                let def = definitions.get_function(c.index);
                if let Some(def) = def {
                    children.extend(def.function.children(definitions));
                }
                children
            }
            Pattern::CallForeignFunction(c) => args_children(&c.args, definitions),
            Pattern::CallbackPattern(_) => vec![],
            Pattern::Assignment(a) => vec![PatternOrPredicate::Pattern(&a.pattern)],
            Pattern::Accumulate(a) => vec![
                PatternOrPredicate::Pattern(&a.left),
                PatternOrPredicate::Pattern(&a.right),
            ],
            Pattern::And(a) => patterns_children(&a.patterns, definitions),
            Pattern::Or(o) => patterns_children(&o.patterns, definitions),
            Pattern::Maybe(m) => vec![PatternOrPredicate::Pattern(&m.pattern)],
            Pattern::Any(a) => patterns_children(&a.patterns, definitions),
            Pattern::Not(n) => vec![PatternOrPredicate::Pattern(&n.pattern)],
            Pattern::If(i) => vec![
                PatternOrPredicate::Predicate(&i.if_),
                PatternOrPredicate::Pattern(&i.then),
                PatternOrPredicate::Pattern(&i.else_),
            ],
            Pattern::Undefined => Vec::new(),
            Pattern::Top => Vec::new(),
            Pattern::Bottom => Vec::new(),
            Pattern::Underscore => Vec::new(),
            Pattern::StringConstant(_) => Vec::new(),
            Pattern::AstLeafNode(_) => Vec::new(),
            Pattern::IntConstant(_) => Vec::new(),
            Pattern::FloatConstant(_) => Vec::new(),
            Pattern::BooleanConstant(_) => Vec::new(),
            Pattern::Dynamic(d) => d.children(definitions),
            Pattern::CodeSnippet(c) => {
                let mut v = Vec::new();
                let p = c.patterns().map(|p| PatternOrPredicate::Pattern(p));
                let d = c
                    .dynamic_snippet()
                    .map(|d| d.children(definitions))
                    .unwrap_or(Vec::new());
                v.extend(p);
                v.extend(d);
                v
            }
            Pattern::Variable(_) => Vec::new(),
            Pattern::Rewrite(r) => {
                vec![
                    PatternOrPredicate::Pattern(&r.left),
                    PatternOrPredicate::DynamicPattern(&r.right),
                ]
            }
            Pattern::Log(l) => l.message.iter().map(PatternOrPredicate::Pattern).collect(),
            Pattern::Range(_) => Vec::new(),
            Pattern::Contains(c) => c
                .until
                .iter()
                .map(PatternOrPredicate::Pattern)
                .chain(Some(PatternOrPredicate::Pattern(&c.contains)))
                .collect(),
            Pattern::Includes(i) => vec![PatternOrPredicate::Pattern(&i.includes)],
            Pattern::Within(w) => vec![PatternOrPredicate::Pattern(&w.pattern)],
            Pattern::After(a) => vec![PatternOrPredicate::Pattern(&a.after)],
            Pattern::Before(b) => vec![PatternOrPredicate::Pattern(&b.before)],
            Pattern::Where(w) => vec![
                PatternOrPredicate::Pattern(&w.pattern),
                PatternOrPredicate::Predicate(&w.side_condition),
            ],
            Pattern::Some(s) => vec![PatternOrPredicate::Pattern(&s.pattern)],
            Pattern::Every(a) => vec![PatternOrPredicate::Pattern(&a.pattern)],
            Pattern::Add(a) => vec![
                PatternOrPredicate::Pattern(&a.lhs),
                PatternOrPredicate::Pattern(&a.rhs),
            ],
            Pattern::Subtract(a) => vec![
                PatternOrPredicate::Pattern(&a.lhs),
                PatternOrPredicate::Pattern(&a.rhs),
            ],
            Pattern::Multiply(a) => vec![
                PatternOrPredicate::Pattern(&a.lhs),
                PatternOrPredicate::Pattern(&a.rhs),
            ],
            Pattern::Divide(a) => vec![
                PatternOrPredicate::Pattern(&a.lhs),
                PatternOrPredicate::Pattern(&a.rhs),
            ],
            Pattern::Modulo(a) => vec![
                PatternOrPredicate::Pattern(&a.lhs),
                PatternOrPredicate::Pattern(&a.rhs),
            ],
            Pattern::Dots => Vec::new(),
            Pattern::Sequential(s) => s
                .iter()
                .map(|s| PatternOrPredicate::Pattern(&s.pattern))
                .collect(),
            Pattern::Like(l) => vec![
                PatternOrPredicate::Pattern(&l.like),
                PatternOrPredicate::Pattern(&l.threshold),
            ],
        }
    }
}