1use crate::ast::*;
35use crate::dsl::*;
36use crate::sfc::Network;
37
38pub trait Acceptor {
40 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E>;
41}
42
43impl<X> Acceptor for Vec<X>
45where
46 X: Acceptor,
47{
48 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
49 match self
50 .into_iter()
51 .map(|x| x.accept(visitor))
52 .find(|r| r.is_err())
53 {
54 Some(err) => {
55 err
58 }
59 None => {
60 Ok(V::Value::default())
62 }
63 }
64 }
65}
66
67impl<X> Acceptor for Option<X>
69where
70 X: Acceptor,
71{
72 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
73 match self.as_ref() {
74 Some(x) => x.accept(visitor),
75 None => Ok(V::Value::default()),
76 }
77 }
78}
79
80pub trait Visitor<E> {
83 type Value: Default;
88
89 fn walk(&mut self, node: &Library) -> Result<Self::Value, E> {
90 Acceptor::accept(&node.elems, self)
91 }
92
93 fn visit_configuration_declaration(
94 &mut self,
95 node: &ConfigurationDeclaration,
96 ) -> Result<Self::Value, E> {
97 visit_configuration_declaration(self, node)
98 }
99
100 fn visit_resource_declaration(&mut self, node: &ResourceDeclaration) -> Result<Self::Value, E> {
101 visit_resource_declaration(self, node)
102 }
103
104 fn visit_declaration(&mut self, node: &Declaration) -> Result<Self::Value, E> {
105 visit_declaration(self, node)
106 }
107
108 fn visit_enum_declaration(&mut self, node: &EnumerationDeclaration) -> Result<Self::Value, E> {
109 visit_enum_declaration(self, node)
110 }
111
112 fn visit_function_block_declaration(
113 &mut self,
114 node: &FunctionBlockDeclaration,
115 ) -> Result<Self::Value, E> {
116 visit_function_block_declaration(self, node)
117 }
118
119 fn visit_function_declaration(&mut self, node: &FunctionDeclaration) -> Result<Self::Value, E> {
120 visit_function_declaration(self, node)
121 }
122
123 fn visit_program_declaration(&mut self, node: &ProgramDeclaration) -> Result<Self::Value, E> {
124 visit_program_declaration(self, node)
125 }
126
127 fn visit_located_var_init(&mut self, node: &LocatedVarInit) -> Result<Self::Value, E> {
128 todo!()
129 }
130
131 fn visit_var_init_decl(&mut self, node: &VarInitDecl) -> Result<Self::Value, E> {
132 visit_var_init_decl(self, &node)
133 }
134
135 fn visit_sfc(&mut self, node: &Sfc) -> Result<Self::Value, E> {
136 Acceptor::accept(&node.networks, self)
137 }
138
139 fn visit_statements(&mut self, node: &Statements) -> Result<Self::Value, E> {
140 Acceptor::accept(&node.body, self)
141 }
142
143 fn visit_assignment(&mut self, node: &Assignment) -> Result<Self::Value, E> {
144 Acceptor::accept(&node.target, self)
145 }
146
147 fn visit_if(&mut self, node: &If) -> Result<Self::Value, E> {
148 visit_if(self, &node)
149 }
150
151 fn visit_compare(&mut self, op: &CompareOp, terms: &Vec<ExprKind>) -> Result<Self::Value, E> {
152 visit_compare(self, op, terms)
153 }
154
155 fn visit_binary_op(
156 &mut self,
157 op: &Vec<Operator>,
158 terms: &Vec<ExprKind>,
159 ) -> Result<Self::Value, E> {
160 visit_binary_op(self, op, terms)
163 }
164
165 fn visit_unary_op(&mut self, op: &UnaryOp, term: &ExprKind) -> Result<Self::Value, E> {
166 visit_unary_op(self, op, term)
167 }
168
169 fn visit_direct_variable(&mut self, node: &DirectVariable) -> Result<Self::Value, E> {
170 todo!()
171 }
172
173 fn visit_symbolic_variable(&mut self, node: &SymbolicVariable) -> Result<Self::Value, E> {
174 Ok(Self::Value::default())
176 }
177
178 fn visit_fb_call(&mut self, fb_call: &FbCall) -> Result<Self::Value, E> {
179 Ok(Self::Value::default())
181 }
182
183 fn visit_enumerated_type_initializer(
184 &mut self,
185 init: &EnumeratedTypeInitializer,
186 ) -> Result<Self::Value, E> {
187 Ok(Self::Value::default())
189 }
190
191 fn visit_enumerated_values_initializer(
192 &mut self,
193 init: &EnumeratedValuesInitializer,
194 ) -> Result<Self::Value, E> {
195 Ok(Self::Value::default())
197 }
198
199 fn visit_function_block_type_initializer(
200 &mut self,
201 init: &FunctionBlockTypeInitializer,
202 ) -> Result<Self::Value, E> {
203 Ok(Self::Value::default())
205 }
206}
207
208pub fn visit_configuration_declaration<V: Visitor<E> + ?Sized, E>(
209 v: &mut V,
210 node: &ConfigurationDeclaration,
211) -> Result<V::Value, E> {
212 Acceptor::accept(&node.global_var, v)?;
213 Acceptor::accept(&node.resource_decl, v)
214}
215
216pub fn visit_resource_declaration<V: Visitor<E> + ?Sized, E>(
217 v: &mut V,
218 node: &ResourceDeclaration,
219) -> Result<V::Value, E> {
220 Acceptor::accept(&node.global_vars, v)
221 }
223
224pub fn visit_declaration<V: Visitor<E> + ?Sized, E>(
225 v: &mut V,
226 node: &Declaration,
227) -> Result<V::Value, E> {
228 Acceptor::accept(&node.initializer, v)
229}
230
231pub fn visit_enum_declaration<V: Visitor<E> + ?Sized, E>(
232 v: &mut V,
233 node: &EnumerationDeclaration,
234) -> Result<V::Value, E> {
235 Acceptor::accept(&node.spec, v)
236}
237
238pub fn visit_function_block_declaration<V: Visitor<E> + ?Sized, E>(
239 v: &mut V,
240 node: &FunctionBlockDeclaration,
241) -> Result<V::Value, E> {
242 Acceptor::accept(&node.inputs, v)?;
243 Acceptor::accept(&node.outputs, v)?;
244 Acceptor::accept(&node.inouts, v)?;
245 Acceptor::accept(&node.vars, v)?;
246 Acceptor::accept(&node.externals, v)?;
247 Acceptor::accept(&node.body, v)
248}
249
250pub fn visit_program_declaration<V: Visitor<E> + ?Sized, E>(
251 v: &mut V,
252 node: &ProgramDeclaration,
253) -> Result<V::Value, E> {
254 Acceptor::accept(&node.inputs, v)?;
255 Acceptor::accept(&node.outputs, v)?;
256 Acceptor::accept(&node.inouts, v)?;
257 Acceptor::accept(&node.vars, v)?;
258 Acceptor::accept(&node.body, v)
259}
260
261pub fn visit_function_declaration<V: Visitor<E> + ?Sized, E>(
262 v: &mut V,
263 node: &FunctionDeclaration,
264) -> Result<V::Value, E> {
265 Acceptor::accept(&node.inputs, v)?;
266 Acceptor::accept(&node.outputs, v)?;
267 Acceptor::accept(&node.inouts, v)?;
268 Acceptor::accept(&node.vars, v)?;
269 Acceptor::accept(&node.externals, v)?;
270 Acceptor::accept(&node.body, v)
271}
272
273pub fn visit_var_init_decl<V: Visitor<E> + ?Sized, E>(
274 v: &mut V,
275 node: &VarInitDecl,
276) -> Result<V::Value, E> {
277 Acceptor::accept(&node.initializer, v)
278}
279
280pub fn visit_if<V: Visitor<E> + ?Sized, E>(v: &mut V, node: &If) -> Result<V::Value, E> {
281 Acceptor::accept(&node.expr, v)?;
282 Acceptor::accept(&node.body, v)?;
283 Acceptor::accept(&node.else_body, v)
284}
285
286pub fn visit_compare<V: Visitor<E> + ?Sized, E>(
287 v: &mut V,
288 op: &CompareOp,
289 terms: &Vec<ExprKind>,
290) -> Result<V::Value, E> {
291 Acceptor::accept(terms, v)
292}
293
294pub fn visit_binary_op<V: Visitor<E> + ?Sized, E>(
295 v: &mut V,
296 op: &Vec<Operator>,
297 terms: &Vec<ExprKind>,
298) -> Result<V::Value, E> {
299 Acceptor::accept(terms, v)
301}
302
303pub fn visit_unary_op<V: Visitor<E> + ?Sized, E>(
304 v: &mut V,
305 op: &UnaryOp,
306 term: &ExprKind,
307) -> Result<V::Value, E> {
308 Acceptor::accept(term, v)
310}
311
312impl Acceptor for LibraryElement {
313 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
314 match self {
315 LibraryElement::ConfigurationDeclaration(config) => {
316 visitor.visit_configuration_declaration(config)
317 }
318 LibraryElement::DataTypeDeclaration(data_type_decl) => {
319 Acceptor::accept(data_type_decl, visitor)
320 }
321 LibraryElement::FunctionBlockDeclaration(func_block_decl) => {
322 visitor.visit_function_block_declaration(func_block_decl)
323 }
324 LibraryElement::FunctionDeclaration(func_decl) => {
325 visitor.visit_function_declaration(func_decl)
326 }
327 LibraryElement::ProgramDeclaration(prog_decl) => {
328 visitor.visit_program_declaration(prog_decl)
329 }
330 }
331 }
332}
333
334impl Acceptor for ResourceDeclaration {
335 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
336 visitor.visit_resource_declaration(self)
337 }
338}
339
340impl Acceptor for Declaration {
341 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
342 visitor.visit_declaration(self)
343 }
344}
345
346impl Acceptor for EnumerationDeclaration {
347 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
348 visitor.visit_enum_declaration(self)
349 }
350}
351
352impl Acceptor for EnumeratedSpecificationKind {
353 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
354 Ok(V::Value::default())
356 }
357}
358
359impl Acceptor for TypeInitializer {
360 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
361 match self {
362 TypeInitializer::Simple {
363 type_name,
364 initial_value,
365 } => Ok(V::Value::default()),
366 TypeInitializer::EnumeratedValues(ev) => {
367 visitor.visit_enumerated_values_initializer(ev)
368 }
369 TypeInitializer::EnumeratedType(et) => visitor.visit_enumerated_type_initializer(et),
370 TypeInitializer::FunctionBlock(fbi) => {
371 visitor.visit_function_block_type_initializer(fbi)
372 }
373 TypeInitializer::Structure { type_name } => Ok(V::Value::default()),
374 TypeInitializer::LateResolvedType(_) => Ok(V::Value::default()),
375 }
376 }
378}
379
380impl Acceptor for VarInitKind {
381 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
382 match self {
383 VarInitKind::VarInit(init) => visitor.visit_var_init_decl(init),
384 VarInitKind::LocatedVarInit(located_var) => visitor.visit_located_var_init(located_var),
385 }
386 }
387}
388
389impl Acceptor for ExprKind {
390 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
391 match self {
392 ExprKind::Compare { op, terms } => visitor.visit_compare(op, terms),
393 ExprKind::BinaryOp { ops, terms } => visitor.visit_binary_op(ops, terms),
394 ExprKind::UnaryOp { op, term } => visitor.visit_unary_op(op, term.as_ref()),
395 ExprKind::Const(_) => {
396 todo!()
397 }
398 ExprKind::Variable(variable) => Acceptor::accept(variable, visitor),
399 ExprKind::Function {
400 name,
401 param_assignment,
402 } => {
403 todo!()
404 }
405 }
406 }
407}
408
409impl Acceptor for VarInitDecl {
410 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
411 visitor.visit_var_init_decl(self)
412 }
413}
414
415impl Acceptor for FunctionBlockBody {
416 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
417 match self {
418 FunctionBlockBody::Sfc(network) => visitor.visit_sfc(network),
419 FunctionBlockBody::Statements(stmts) => visitor.visit_statements(stmts),
420 FunctionBlockBody::Empty() => Ok(V::Value::default()),
422 }
423 }
424}
425
426impl Acceptor for StmtKind {
427 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
428 match self {
429 StmtKind::Assignment(node) => visitor.visit_assignment(node),
430 StmtKind::If(node) => visitor.visit_if(node),
431 StmtKind::FbCall(node) => visitor.visit_fb_call(node),
432 }
433 }
434}
435
436impl Acceptor for Network {
437 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
438 Ok(V::Value::default())
440 }
441}
442
443impl Acceptor for Variable {
444 fn accept<V: Visitor<E> + ?Sized, E>(&self, visitor: &mut V) -> Result<V::Value, E> {
445 match self {
446 Variable::DirectVariable(var) => visitor.visit_direct_variable(var),
447 Variable::SymbolicVariable(var) => visitor.visit_symbolic_variable(var),
448 Variable::MultiElementVariable(_) => {
449 todo!()
450 }
451 }
452 }
453}
454
455mod test {
456 use super::*;
457 use crate::ast::*;
458 use crate::core::{Id, SourceLoc};
459 use crate::dsl::*;
460 use std::collections::LinkedList;
461 use std::fmt::Error;
462
463 struct Descender {
464 names: LinkedList<String>,
465 }
466 impl Descender {
467 fn new() -> Descender {
468 Descender {
469 names: LinkedList::new(),
470 }
471 }
472 }
473
474 impl Visitor<Error> for Descender {
475 type Value = ();
476
477 fn visit_direct_variable(&mut self, variable: &DirectVariable) -> Result<(), Error> {
478 let mut dst = &mut self.names;
479 dst.push_back(variable.to_string());
480 Ok(())
481 }
482
483 fn visit_symbolic_variable(&mut self, var: &SymbolicVariable) -> Result<(), Error> {
484 let mut dst = &mut self.names;
485 dst.push_back(var.name.to_string());
486 Ok(())
487 }
488
489 fn visit_fb_call(&mut self, fb_call: &FbCall) -> Result<(), Error> {
490 let mut dst = &mut self.names;
491 dst.push_back(fb_call.var_name.to_string());
492 Ok(())
493 }
494 }
495
496 #[test]
497 fn walk_when_has_symbolic_variable_then_visits_variable() {
498 let library = Library {
499 elems: vec![LibraryElement::ProgramDeclaration(ProgramDeclaration {
500 type_name: Id::from("plc_prg"),
501 inputs: vec![VarInitDecl::simple_input(
502 "Reset",
503 "BOOL",
504 SourceLoc::new(0),
505 )],
506 outputs: vec![],
507 inouts: vec![],
508 vars: vec![],
509 body: FunctionBlockBody::stmts(vec![StmtKind::fb_assign(
510 "AverageVal",
511 vec!["Cnt1", "Cnt2"],
512 "_TMP_AverageVal17_OUT",
513 )]),
514 })],
515 };
516
517 let mut descender = Descender::new();
518
519 descender.walk(&library);
520
521 assert_eq!(1, descender.names.len())
522 }
523}