Skip to content

Commit c74f3b5

Browse files
mhaselvolsa
andauthored
refactor: Removing backing property field (#1418)
Previously the property implementation would have a backing field with each property declaration in a POU. For example two properties `foo` and `bar` would insert two variables inside the POU. This would as a side effect affect the ffi of POUs using properties. Another consideration was duplication of used memory if the backing field ends up not being used in the getter/setter. Additionally, using different properties to represent the same state/value in different units was not achievable without major drawbacks (i.e. having a temperature field in the POU with 3 separate getters for Celsius, Fahrenheit and Kelvin). To mitigate that side-effect the backing field has been removed. As a result the resolver has been updated to identify property references. The already existing lowering logic will then make use of these annotations and simply lower GET and SET property annotations into concrete method calls. This implementation also significantly simplifies the implementation of further OOP features regarding properties, e.g. inheriting/extending properties, which would previously result in duplicate/unused backing fields in derived POUs. --------- Co-authored-by: Volkan <volkanxvs@gmail.com> Co-authored-by: Volkan Sagcan <volkan.sagcan@bachmann.info>
1 parent f5ab238 commit c74f3b5

File tree

44 files changed

+2074
-1677
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2074
-1677
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,13 @@ pub struct Pou {
4242
pub generics: Vec<GenericBinding>,
4343
pub linkage: LinkageType,
4444
pub super_class: Option<Identifier>,
45+
pub is_const: bool,
46+
4547
/// A list of interfaces this POU implements
4648
pub interfaces: Vec<Identifier>,
47-
pub is_const: bool,
49+
50+
/// A list of properties this POU contains
51+
pub properties: Vec<PropertyBlock>,
4852
}
4953

5054
#[derive(Debug, PartialEq)]
@@ -62,17 +66,15 @@ pub struct Identifier {
6266
pub location: SourceLocation,
6367
}
6468

69+
/// The property container as a whole, which contains [`PropertyImplementation`]s
6570
#[derive(Debug, PartialEq, Clone)]
66-
pub struct Property {
67-
pub name: String,
68-
pub name_location: SourceLocation,
69-
pub parent_kind: PouType,
70-
pub parent_name: String,
71-
pub parent_name_location: SourceLocation,
72-
pub datatype: DataTypeDeclaration,
71+
pub struct PropertyBlock {
72+
pub name: Identifier,
73+
pub return_type: DataTypeDeclaration,
7374
pub implementations: Vec<PropertyImplementation>,
7475
}
7576

77+
/// The declaration and implementation of a properties accessor (GET or SET)
7678
#[derive(Debug, PartialEq, Clone)]
7779
pub struct PropertyImplementation {
7880
pub kind: PropertyKind,
@@ -88,6 +90,18 @@ pub enum PropertyKind {
8890
Set,
8991
}
9092

93+
impl From<&PropertyBlock> for Variable {
94+
fn from(value: &PropertyBlock) -> Self {
95+
Variable {
96+
name: value.name.name.clone(),
97+
data_type_declaration: value.return_type.clone(),
98+
initializer: None,
99+
address: None,
100+
location: value.name.location.clone(),
101+
}
102+
}
103+
}
104+
91105
impl std::fmt::Display for PropertyKind {
92106
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93107
match self {
@@ -339,9 +353,6 @@ pub enum PouType {
339353
/// The parent of this method, i.e. a function block, class or an interface
340354
parent: String,
341355

342-
/// The fully qualified name of the property this GET or SET method represents
343-
property: Option<String>,
344-
345356
declaration_kind: DeclarationKind,
346357
},
347358
Init,
@@ -412,7 +423,6 @@ pub struct CompilationUnit {
412423
pub interfaces: Vec<Interface>,
413424
pub user_types: Vec<UserTypeDeclaration>,
414425
pub file: FileMarker,
415-
pub properties: Vec<Property>,
416426
}
417427

418428
impl CompilationUnit {
@@ -425,7 +435,6 @@ impl CompilationUnit {
425435
interfaces: Vec::new(),
426436
user_types: Vec::new(),
427437
file: FileMarker::File(file_name),
428-
properties: Vec::new(),
429438
}
430439
}
431440

@@ -457,9 +466,6 @@ pub enum VariableBlockType {
457466
Global,
458467
InOut,
459468
External,
460-
461-
/// A compiler internal variable block representing all properties defined within a stateful POU
462-
Property,
463469
}
464470

465471
impl Display for VariableBlockType {
@@ -472,7 +478,6 @@ impl Display for VariableBlockType {
472478
VariableBlockType::Global => write!(f, "Global"),
473479
VariableBlockType::InOut => write!(f, "InOut"),
474480
VariableBlockType::External => write!(f, "External"),
475-
VariableBlockType::Property => write!(f, "Property"),
476481
}
477482
}
478483
}
@@ -504,19 +509,6 @@ impl VariableBlock {
504509
self.variables = variables;
505510
self
506511
}
507-
508-
/// Creates a new (internal) variable block with a block type of [`Property`]
509-
pub fn property(variables: Vec<Variable>) -> VariableBlock {
510-
VariableBlock {
511-
access: AccessModifier::Internal,
512-
constant: false,
513-
retain: false,
514-
variables,
515-
variable_block_type: VariableBlockType::Property,
516-
linkage: LinkageType::Internal,
517-
location: SourceLocation::internal(),
518-
}
519-
}
520512
}
521513

522514
impl Default for VariableBlock {
@@ -1147,6 +1139,13 @@ impl AstNode {
11471139
matches!(self.stmt, AstStatement::ReferenceExpr(..))
11481140
}
11491141

1142+
pub fn is_member_access(&self) -> bool {
1143+
matches!(
1144+
self.stmt,
1145+
AstStatement::ReferenceExpr(ReferenceExpr { access: ReferenceAccess::Member(..), .. }, ..)
1146+
)
1147+
}
1148+
11501149
pub fn is_call(&self) -> bool {
11511150
matches!(self.stmt, AstStatement::CallStatement(..))
11521151
}
@@ -1380,12 +1379,8 @@ mod tests {
13801379
assert_eq!(PouType::Action.to_string(), "Action");
13811380
assert_eq!(PouType::Class.to_string(), "Class");
13821381
assert_eq!(
1383-
PouType::Method {
1384-
parent: String::new(),
1385-
property: None,
1386-
declaration_kind: DeclarationKind::Concrete
1387-
}
1388-
.to_string(),
1382+
PouType::Method { parent: String::new(), declaration_kind: DeclarationKind::Concrete }
1383+
.to_string(),
13891384
"Method"
13901385
);
13911386
}

compiler/plc_ast/src/mut_visitor.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::borrow::BorrowMut;
66
use crate::ast::{
77
flatten_expression_list, Assignment, AstNode, AstStatement, BinaryExpression, CallStatement,
88
CompilationUnit, DataType, DataTypeDeclaration, DirectAccess, HardwareAccess, Implementation, Interface,
9-
JumpStatement, MultipliedStatement, Pou, RangeStatement, ReferenceAccess, ReferenceExpr, UnaryExpression,
10-
UserTypeDeclaration, Variable, VariableBlock,
9+
JumpStatement, MultipliedStatement, Pou, PropertyBlock, RangeStatement, ReferenceAccess, ReferenceExpr,
10+
UnaryExpression, UserTypeDeclaration, Variable, VariableBlock,
1111
};
1212
use crate::control_statements::{AstControlStatement, ConditionalBlock, ReturnStatement};
1313
use crate::literals::AstLiteral;
@@ -208,6 +208,8 @@ pub trait AstVisitorMut: Sized {
208208
fn visit_allocation(&mut self, _node: &mut AstNode) {}
209209

210210
fn visit_interface(&mut self, _interface: &mut Interface) {}
211+
212+
fn visit_property(&mut self, _property: &mut PropertyBlock) {}
211213
}
212214

213215
impl WalkerMut for AstLiteral {
@@ -537,6 +539,10 @@ impl WalkerMut for Pou {
537539
visitor.visit_variable_block(block);
538540
}
539541

542+
for property in &mut self.properties {
543+
visitor.visit_property(property);
544+
}
545+
540546
if let Some(rt) = self.return_type.as_mut() {
541547
visitor.visit_data_type_declaration(rt)
542548
}

compiler/plc_ast/src/visitor.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::ast::{
55
flatten_expression_list, Allocation, Assignment, AstNode, AstStatement, BinaryExpression, CallStatement,
66
CompilationUnit, ConfigVariable, DataType, DataTypeDeclaration, DefaultValue, DirectAccess,
77
EmptyStatement, HardwareAccess, Implementation, Interface, JumpStatement, LabelStatement,
8-
MultipliedStatement, Pou, RangeStatement, ReferenceAccess, ReferenceExpr, UnaryExpression,
8+
MultipliedStatement, Pou, PropertyBlock, RangeStatement, ReferenceAccess, ReferenceExpr, UnaryExpression,
99
UserTypeDeclaration, Variable, VariableBlock,
1010
};
1111
use crate::control_statements::{AstControlStatement, ConditionalBlock, ReturnStatement};
@@ -166,6 +166,9 @@ pub trait AstVisitor: Sized {
166166
interface.walk(self);
167167
}
168168

169+
/// Visits a `Property`.
170+
fn visit_property(&mut self, _property: &PropertyBlock) {}
171+
169172
/// Visits an enum element `AstNode` node.
170173
/// Make sure to call `walk` on the `AstNode` node to visit its children.
171174
/// # Arguments
@@ -767,6 +770,10 @@ impl Walker for Pou {
767770
visitor.visit_variable_block(block);
768771
}
769772

773+
for property in &self.properties {
774+
visitor.visit_property(property);
775+
}
776+
770777
self.return_type.as_ref().inspect(|rt| visitor.visit_data_type_declaration(rt));
771778
}
772779
}

compiler/plc_driver/src/pipelines/validator.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use super::{participant::PipelineParticipant, ParsedProject};
55
impl PipelineParticipant for ParticipantValidator {
66
fn pre_index(&mut self, project: &ParsedProject) {
77
for unit in &project.units {
8-
self.validate_properties(&unit.properties);
8+
for pou in &unit.units {
9+
self.validate_properties(pou);
10+
}
911
}
1012

1113
self.report_diagnostics();

0 commit comments

Comments
 (0)