Skip to main content

plc_ast/
control_statements.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::Debug;
3
4use plc_source::source_location::SourceLocation;
5
6use crate::ast::AstNode;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(bound(deserialize = "'de: 'static"))]
10pub struct IfStatement {
11    pub blocks: Vec<ConditionalBlock>,
12    pub else_block: Vec<AstNode>,
13    pub end_location: SourceLocation,
14}
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(bound(deserialize = "'de: 'static"))]
18pub struct ForLoopStatement {
19    pub counter: Box<AstNode>,
20    pub start: Box<AstNode>,
21    pub end: Box<AstNode>,
22    pub by_step: Option<Box<AstNode>>,
23    pub body: Vec<AstNode>,
24    pub end_location: SourceLocation,
25}
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28#[serde(bound(deserialize = "'de: 'static"))]
29/// used for While and Repeat loops
30pub struct LoopStatement {
31    pub condition: Box<AstNode>,
32    pub body: Vec<AstNode>,
33    pub end_location: SourceLocation,
34}
35
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37#[serde(bound(deserialize = "'de: 'static"))]
38pub struct CaseStatement {
39    pub selector: Box<AstNode>,
40    pub case_blocks: Vec<ConditionalBlock>,
41    pub else_block: Vec<AstNode>,
42    pub end_location: SourceLocation,
43}
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46#[serde(bound(deserialize = "'de: 'static"))]
47pub enum AstControlStatement {
48    If(IfStatement),
49    ForLoop(ForLoopStatement),
50    WhileLoop(LoopStatement),
51    RepeatLoop(LoopStatement),
52    Case(CaseStatement),
53}
54
55#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
56#[serde(bound(deserialize = "'de: 'static"))]
57pub struct ConditionalBlock {
58    pub condition: Box<AstNode>,
59    pub body: Vec<AstNode>,
60}
61
62#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
63#[serde(bound(deserialize = "'de: 'static"))]
64pub struct ReturnStatement {
65    /// Indicates that the given condition must evaluate to true in order for the return to take place.
66    /// Only used in CFC where the condition may be [`Some`] and [`None`] otherwise.
67    pub condition: Option<Box<AstNode>>,
68}
69
70impl ForLoopStatement {
71    pub fn get_conditionals(&self) -> Vec<&AstNode> {
72        let mut conditionals = Vec::new();
73
74        conditionals.push(self.counter.as_ref());
75        conditionals.push(self.start.as_ref());
76        conditionals.push(self.end.as_ref());
77        if let Some(ref step) = self.by_step {
78            conditionals.push(step);
79        }
80
81        conditionals
82    }
83}