1
+ /*use std::collections::HashSet;
2
+
3
+ use crate::dsl::parser::ast::{Expr, File, Function, Operator, Pattern, Properties, Type};
4
+
5
+ #[derive(Debug)]
6
+ pub struct SemanticAnalyzer {
7
+ logical_properties: HashSet<String>,
8
+ operators: HashSet<String>,
9
+ identifiers: Vec<HashSet<String>>,
10
+ }
11
+
12
+ impl SemanticAnalyzer {
13
+ pub fn new() -> Self {
14
+ SemanticAnalyzer {
15
+ logical_properties: HashSet::new(),
16
+ operators: HashSet::new(),
17
+ identifiers: Vec::new(),
18
+ }
19
+ }
20
+
21
+ fn enter_scope(&mut self) {
22
+ self.identifiers.push(HashSet::new());
23
+ }
24
+
25
+ fn exit_scope(&mut self) {
26
+ self.identifiers.pop();
27
+ }
28
+
29
+ fn add_identifier(&mut self, name: String) -> Result<(), String> {
30
+ if let Some(scope) = self.identifiers.last_mut() {
31
+ if scope.contains(&name) {
32
+ return Err(format!("Duplicate identifier name: {}", name));
33
+ }
34
+ scope.insert(name);
35
+ }
36
+ Ok(())
37
+ }
38
+
39
+ fn lookup_identifier(&self, name: &str) -> bool {
40
+ self.identifiers
41
+ .iter()
42
+ .rev()
43
+ .any(|scope| scope.contains(name))
44
+ }
45
+
46
+ fn is_valid_scalar_type(&self, ty: &Type) -> bool {
47
+ match ty {
48
+ Type::Array(inner) => self.is_valid_scalar_type(inner),
49
+ Type::Int64 | Type::String | Type::Bool | Type::Float64 => true,
50
+ _ => false,
51
+ }
52
+ }
53
+
54
+ fn is_valid_logical_type(&self, ty: &Type) -> bool {
55
+ match ty {
56
+ Type::Array(inner) => self.is_valid_logical_type(inner),
57
+ Type::Int64 | Type::String | Type::Bool | Type::Float64 => true,
58
+ _ => false,
59
+ }
60
+ }
61
+
62
+ fn is_valid_property_type(&self, ty: &Type) -> bool {
63
+ match ty {
64
+ Type::Array(inner) => self.is_valid_property_type(inner),
65
+ Type::Tuple(fields) => fields.iter().all(|f| self.is_valid_property_type(f)),
66
+ Type::Map(a, b) => self.is_valid_property_type(a) && self.is_valid_property_type(b),
67
+ Type::Int64 | Type::String | Type::Bool | Type::Float64 => true,
68
+ Type::Function(_, _) => false,
69
+ Type::Operator(_) => false,
70
+ }
71
+ }
72
+
73
+ fn validate_properties(&mut self, properties: &Properties) -> Result<(), String> {
74
+ for field in &properties.fields {
75
+ if !self.is_valid_property_type(&field.ty) {
76
+ return Err(format!("Invalid type in properties: {:?}", field.ty));
77
+ }
78
+ }
79
+
80
+ self.logical_properties = properties
81
+ .fields
82
+ .iter()
83
+ .map(|field| field.name.clone())
84
+ .collect();
85
+
86
+ Ok(())
87
+ }
88
+
89
+ fn validate_operator(&mut self, operator: &Operator) -> Result<(), String> {
90
+ match operator {
91
+ Operator::Scalar(scalar_op) => {
92
+ if self.operators.contains(&scalar_op.name) {
93
+ return Err(format!("Duplicate operator name: {}", scalar_op.name));
94
+ }
95
+ self.operators.insert(scalar_op.name.clone());
96
+
97
+ for field in &scalar_op.fields {
98
+ if !self.is_valid_scalar_type(&field.ty) {
99
+ return Err(format!("Invalid type in scalar operator: {:?}", field.ty));
100
+ }
101
+ }
102
+ }
103
+ Operator::Logical(logical_op) => {
104
+ if self.operators.contains(&logical_op.name) {
105
+ return Err(format!("Duplicate operator name: {}", logical_op.name));
106
+ }
107
+ self.operators.insert(logical_op.name.clone());
108
+
109
+ for field in &logical_op.fields {
110
+ if !self.is_valid_logical_type(&field.ty) {
111
+ return Err(format!("Invalid type in logical operator: {:?}", field.ty));
112
+ }
113
+ }
114
+
115
+ // Check that derived properties match the logical properties fields
116
+ for (prop_name, _) in &logical_op.derived_props {
117
+ if !self.operators.iter().any(|f| f == prop_name) {
118
+ return Err(format!(
119
+ "Derived property not found in logical properties: {}",
120
+ prop_name
121
+ ));
122
+ }
123
+ }
124
+
125
+ // Check that all logical properties fields have corresponding derived properties
126
+ for field in &self.logical_properties {
127
+ if !logical_op.derived_props.contains_key(field) {
128
+ return Err(format!(
129
+ "Logical property field '{}' is missing a derived property",
130
+ field
131
+ ));
132
+ }
133
+ }
134
+ }
135
+ }
136
+ Ok(())
137
+ }
138
+
139
+ // Validate a function definition
140
+ fn validate_function(&mut self, function: &Function) -> Result<(), String> {
141
+ if self.function_names.contains(&function.name) {
142
+ return Err(format!("Duplicate function name: {}", function.name));
143
+ }
144
+ self.function_names.insert(function.name.clone());
145
+
146
+ self.enter_scope();
147
+ for (param_name, _) in &function.params {
148
+ self.add_identifier(param_name.clone())?;
149
+ }
150
+ self.validate_expr(&function.body)?;
151
+ self.exit_scope();
152
+
153
+ Ok(())
154
+ }
155
+
156
+ // Validate an expression
157
+ fn validate_expr(&mut self, expr: &Expr) -> Result<(), String> {
158
+ match expr {
159
+ Expr::Var(name) => {
160
+ if self.lookup_identifier(name) {
161
+ return Err(format!("Undefined identifier: {}", name));
162
+ }
163
+ }
164
+ Expr::Val(name, expr1, expr2) => {
165
+ self.validate_expr(expr1)?;
166
+ self.add_identifier(name.clone())?;
167
+ self.validate_expr(expr2)?;
168
+ }
169
+ Expr::Match(expr, arms) => {
170
+ self.validate_expr(expr)?;
171
+ for arm in arms {
172
+ self.validate_pattern(&arm.pattern)?;
173
+ self.validate_expr(&arm.expr)?;
174
+ }
175
+ }
176
+ Expr::If(cond, then_expr, else_expr) => {
177
+ self.validate_expr(cond)?;
178
+ self.validate_expr(then_expr)?;
179
+ self.validate_expr(else_expr)?;
180
+ }
181
+ Expr::Binary(left, _, right) => {
182
+ self.validate_expr(left)?;
183
+ self.validate_expr(right)?;
184
+ }
185
+ Expr::Unary(_, expr) => {
186
+ self.validate_expr(expr)?;
187
+ }
188
+ Expr::Call(func, args) => {
189
+ self.validate_expr(func)?;
190
+ for arg in args {
191
+ self.validate_expr(arg)?;
192
+ }
193
+ }
194
+ Expr::Member(expr, _) => {
195
+ self.validate_expr(expr)?;
196
+ }
197
+ Expr::MemberCall(expr, _, args) => {
198
+ self.validate_expr(expr)?;
199
+ for arg in args {
200
+ self.validate_expr(arg)?;
201
+ }
202
+ }
203
+ Expr::ArrayIndex(array, index) => {
204
+ self.validate_expr(array)?;
205
+ self.validate_expr(index)?;
206
+ }
207
+ Expr::Literal(_) => {}
208
+ Expr::Fail(_) => {}
209
+ Expr::Closure(params, body) => {
210
+ self.enter_scope();
211
+ for param in params {
212
+ self.add_identifier(param.clone())?;
213
+ }
214
+ self.validate_expr(body)?;
215
+ self.exit_scope();
216
+ }
217
+ _ => {}
218
+ }
219
+ Ok(())
220
+ }
221
+
222
+ // Validate a pattern
223
+ fn validate_pattern(&mut self, pattern: &Pattern) -> Result<(), String> {
224
+ match pattern {
225
+ Pattern::Bind(name, pat) => {
226
+ self.add_identifier(name.clone())?;
227
+ self.validate_pattern(pat)?;
228
+ }
229
+ Pattern::Constructor(_, pats) => {
230
+ for pat in pats {
231
+ self.validate_pattern(pat)?;
232
+ }
233
+ }
234
+ Pattern::Literal(_) => {}
235
+ Pattern::Wildcard => {}
236
+ Pattern::Var(name) => {
237
+ self.add_identifier(name.clone())?;
238
+ }
239
+ }
240
+ Ok(())
241
+ }
242
+
243
+ // Validate a complete file
244
+ pub fn validate_file(&mut self, file: &File) -> Result<(), String> {
245
+ self.validate_properties(&file.properties)?;
246
+
247
+ for operator in &file.operators {
248
+ self.validate_operator(operator)?;
249
+ }
250
+
251
+ for function in &file.functions {
252
+ self.validate_function(function)?;
253
+ }
254
+
255
+ Ok(())
256
+ }
257
+ }
258
+ */
0 commit comments