1use crate::AstNode;
4use dsntk_feel::closure::Closure;
5use dsntk_feel::{Name, QualifiedName};
6use std::collections::BTreeSet;
7
8#[derive(Default)]
10pub struct ClosureBuilder {
11 parameter_names: BTreeSet<QualifiedName>,
13 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 fn visit_0(&mut self, _: usize) -> Vec<Name> {
42 vec![]
43 }
44
45 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), 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 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 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 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}