dsntk_feel_parser/
closure.rs

1//! Implementation of the context for closures (lambdas).
2
3use crate::AstNode;
4use dsntk_feel::closure::Closure;
5use dsntk_feel::{Name, QualifiedName};
6use std::collections::BTreeSet;
7
8/// Context for closures (lambdas).
9#[derive(Default)]
10pub struct ClosureBuilder {
11  /// Collection of parameter names in function definitions.
12  parameter_names: BTreeSet<QualifiedName>,
13  /// Collection of names used in expressions.
14  names: BTreeSet<QualifiedName>,
15}
16
17impl ClosureBuilder {
18  pub fn from_node(node: &AstNode) -> Closure {
19    let mut closure_context = ClosureBuilder::default();
20    closure_context.visit_1(node, 0);
21    closure_context
22      .names
23      .difference(&closure_context.parameter_names)
24      .cloned()
25      .collect::<Vec<QualifiedName>>()
26      .into()
27  }
28
29  pub fn from_function_definition(lhs: &AstNode, rhs: &AstNode) -> Closure {
30    let mut closure_context = ClosureBuilder::default();
31    closure_context.visit_2(lhs, rhs, 0);
32    closure_context
33      .names
34      .difference(&closure_context.parameter_names)
35      .cloned()
36      .collect::<Vec<QualifiedName>>()
37      .into()
38  }
39
40  /// Returns an empty vector of names.
41  fn visit_0(&mut self, _: usize) -> Vec<Name> {
42    vec![]
43  }
44
45  /// Visits a single AST node.
46  fn visit_1(&mut self, node: &AstNode, path_level: usize) -> Vec<Name> {
47    match node {
48      AstNode::Add(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
49      AstNode::And(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
50      AstNode::At(_) => self.visit_0(path_level),
51      AstNode::Between(lhs, mhs, rhs) => self.visit_3(lhs, mhs, rhs, path_level),
52      AstNode::Boolean(_) => self.visit_0(path_level),
53      AstNode::CommaList(lhs) => self.visit_list(lhs, path_level),
54      AstNode::Context(lhs) => self.visit_list(lhs, path_level),
55      AstNode::ContextEntry(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
56      AstNode::ContextEntryKey(_) => self.visit_0(path_level),
57      AstNode::ContextType(lhs) => self.visit_list(lhs, path_level),
58      AstNode::ContextTypeEntry(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
59      AstNode::ContextTypeEntryKey(_) => self.visit_0(path_level),
60      AstNode::Div(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
61      AstNode::Eq(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
62      AstNode::EvaluatedExpression(lhs) => self.visit_1(lhs, path_level),
63      AstNode::Every(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
64      AstNode::Exp(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
65      AstNode::ExpressionList(lhs) => self.visit_list(lhs, path_level),
66      AstNode::FeelType(_) => self.visit_0(path_level),
67      AstNode::Filter(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
68      AstNode::For(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
69      AstNode::FormalParameter(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
70      AstNode::FormalParameters(lhs) => self.visit_list(lhs, path_level),
71      AstNode::FunctionBody(lhs, _) => self.visit_1(lhs, path_level),
72      AstNode::FunctionDefinition(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
73      AstNode::FunctionInvocation(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
74      AstNode::FunctionType(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
75      AstNode::Ge(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
76      AstNode::Gt(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
77      AstNode::If(lhs, mhs, rhs) => self.visit_3(lhs, mhs, rhs, path_level),
78      AstNode::In(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
79      AstNode::InstanceOf(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
80      AstNode::IntervalEnd(lhs, _) => self.visit_1(lhs, path_level),
81      AstNode::IntervalStart(lhs, _) => self.visit_1(lhs, path_level),
82      AstNode::Irrelevant => self.visit_0(path_level),
83      AstNode::IterationContexts(lhs) => self.visit_list(lhs, path_level),
84      AstNode::IterationContextSingle(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
85      AstNode::IterationContextInterval(lhs, mhs, rhs) => self.visit_3(lhs, mhs, rhs, path_level),
86      AstNode::Le(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
87      AstNode::List(lhs) => self.visit_list(lhs, path_level),
88      AstNode::ListType(lhs) => self.visit_1(lhs, path_level),
89      AstNode::Lt(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
90      AstNode::Mul(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
91      AstNode::Name(name) => {
92        if path_level == 0 {
93          let closure_name = name.clone();
94          self.names.insert(closure_name.into());
95        }
96        vec![name.clone()]
97      }
98      AstNode::NamedParameter(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
99      AstNode::NamedParameters(lhs) => self.visit_list(lhs, path_level),
100      AstNode::Neg(lhs) => self.visit_1(lhs, path_level),
101      AstNode::NegatedList(lhs) => self.visit_list(lhs, path_level),
102      AstNode::Null => self.visit_0(path_level),
103      AstNode::Numeric(_, _, _, _) => self.visit_0(path_level),
104      AstNode::Nq(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
105      AstNode::Or(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
106      AstNode::Out(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
107      AstNode::ParameterName(name) => {
108        let parameter_name = name.clone();
109        self.parameter_names.insert(parameter_name.into());
110        vec![name.clone()]
111      }
112      AstNode::ParameterTypes(lhs) => self.visit_list(lhs, path_level),
113      AstNode::Path(lhs, rhs) => {
114        let mut parts = self.visit_1(rhs, path_level + 1);
115        let mut name = self.visit_1(lhs, path_level + 1);
116        parts.append(&mut name);
117        if path_level == 0 {
118          let mut closure_parts = parts.clone();
119          closure_parts.reverse();
120          self.names.insert(closure_parts.into());
121        }
122        parts
123      }
124      AstNode::PositionalParameters(lhs) => self.visit_list(lhs, path_level),
125      AstNode::QualifiedName(lhs) => self.visit_list(lhs, path_level),
126      AstNode::QualifiedNameSegment(_name) => self.visit_0(path_level), //TODO verify if also must be used
127      AstNode::QuantifiedContext(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
128      AstNode::QuantifiedContexts(lhs) => self.visit_list(lhs, path_level),
129      AstNode::Range(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
130      AstNode::RangeType(lhs) => self.visit_1(lhs, path_level),
131      AstNode::Some(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
132      AstNode::String(_) => self.visit_0(path_level),
133      AstNode::Sub(lhs, rhs) => self.visit_2(lhs, rhs, path_level),
134      AstNode::UnaryGe(lhs) => self.visit_1(lhs, path_level),
135      AstNode::UnaryGt(lhs) => self.visit_1(lhs, path_level),
136      AstNode::UnaryLe(lhs) => self.visit_1(lhs, path_level),
137      AstNode::UnaryLt(lhs) => self.visit_1(lhs, path_level),
138      AstNode::UnaryEq(lhs) => self.visit_1(lhs, path_level),
139      AstNode::UnaryNe(lhs) => self.visit_1(lhs, path_level),
140      AstNode::Satisfies(lhs) => self.visit_1(lhs, path_level),
141    }
142  }
143
144  /// Visits two AST nodes.
145  fn visit_2(&mut self, lhs: &AstNode, rhs: &AstNode, path_level: usize) -> Vec<Name> {
146    self.visit_1(lhs, path_level);
147    self.visit_1(rhs, path_level);
148    vec![]
149  }
150
151  /// Visits three AST nodes.
152  fn visit_3(&mut self, lhs: &AstNode, mhs: &AstNode, rhs: &AstNode, path_level: usize) -> Vec<Name> {
153    self.visit_1(lhs, path_level);
154    self.visit_1(mhs, path_level);
155    self.visit_1(rhs, path_level);
156    vec![]
157  }
158
159  /// Visits a list of AST nodes.
160  fn visit_list(&mut self, lhs: &Vec<AstNode>, path_level: usize) -> Vec<Name> {
161    for item in lhs {
162      self.visit_1(item, path_level);
163    }
164    vec![]
165  }
166}