Skip to content

Commit e813641

Browse files
authored
Merge branch 'master' into master
2 parents d612470 + 2090dd3 commit e813641

33 files changed

+1297
-219
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,20 +287,20 @@ impl PouType {
287287

288288
#[derive(Debug, PartialEq)]
289289
pub struct ConfigVariable {
290-
pub name_segments: Vec<String>,
290+
pub reference: AstNode,
291291
pub data_type: DataTypeDeclaration,
292292
pub address: AstNode,
293293
pub location: SourceLocation,
294294
}
295295

296296
impl ConfigVariable {
297297
pub fn new(
298-
name_segments: Vec<String>,
298+
reference: AstNode,
299299
data_type: DataTypeDeclaration,
300300
address: AstNode,
301301
location: SourceLocation,
302302
) -> Self {
303-
Self { name_segments, data_type, address, location }
303+
Self { reference, data_type, address, location }
304304
}
305305
}
306306

@@ -935,6 +935,14 @@ impl AstNode {
935935
}
936936
}
937937

938+
pub fn get_parent_name_of_reference(&self) -> Option<&str> {
939+
if let AstStatement::ReferenceExpr(ReferenceExpr { base: Some(base), .. }, ..) = &self.stmt {
940+
base.as_ref().get_flat_reference_name()
941+
} else {
942+
None
943+
}
944+
}
945+
938946
pub fn get_label_name(&self) -> Option<&str> {
939947
match &self.stmt {
940948
AstStatement::LabelStatement(LabelStatement { name, .. }) => Some(name.as_str()),
@@ -1075,6 +1083,13 @@ impl AstNode {
10751083
let location = self.get_location();
10761084
AstFactory::create_not_expression(self, location, id_provider.next_id())
10771085
}
1086+
1087+
pub fn is_template(&self) -> bool {
1088+
matches!(
1089+
self.stmt,
1090+
AstStatement::HardwareAccess(HardwareAccess { access: DirectAccessType::Template, .. })
1091+
)
1092+
}
10781093
}
10791094

10801095
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

compiler/plc_ast/src/pre_processor.rs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,34 @@ fn process_global_variables(unit: &mut CompilationUnit, id_provider: &mut IdProv
187187
update_generated_globals(unit, mangled_globals);
188188
}
189189

190+
fn process_var_config_variables(unit: &mut CompilationUnit) {
191+
let block = get_internal_global_block(unit);
192+
let variables = unit.var_config.iter().filter_map(|ConfigVariable { data_type, address, .. }| {
193+
let AstStatement::HardwareAccess(hardware) = &address.stmt else {
194+
unreachable!("Must be parsed as hardware access")
195+
};
196+
197+
if hardware.is_template() {
198+
return None;
199+
}
200+
201+
let name = hardware.get_mangled_variable_name();
202+
if block.is_some_and(|it| it.variables.iter().any(|v| v.name == name)) {
203+
return None;
204+
};
205+
206+
Some(Variable {
207+
name,
208+
data_type_declaration: data_type.get_inner_pointer_ty().unwrap_or(data_type.clone()),
209+
initializer: None,
210+
address: None,
211+
location: address.get_location(),
212+
})
213+
});
214+
215+
update_generated_globals(unit, variables.collect())
216+
}
217+
190218
fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Variable>) {
191219
let mut block = if let Some(index) = unit.global_vars.iter().position(|block| {
192220
block.variable_block_type == VariableBlockType::Global && block.location.is_internal()
@@ -200,32 +228,17 @@ fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Var
200228
block.variables.push(var);
201229
}
202230
}
231+
203232
unit.global_vars.push(block);
204233
}
205234

206-
fn process_var_config_variables(unit: &mut CompilationUnit) {
207-
let variables =
208-
unit.var_config.iter().filter_map(|ConfigVariable { data_type, address, location, .. }| {
209-
let AstStatement::HardwareAccess(hardware) = &address.stmt else {
210-
unreachable!("Must be parsed as hardware access")
211-
};
212-
213-
if hardware.is_template() {
214-
return None;
215-
}
216-
217-
let name = hardware.get_mangled_variable_name();
218-
219-
Some(Variable {
220-
name,
221-
data_type_declaration: data_type.clone(),
222-
initializer: None,
223-
address: None,
224-
location: location.clone(),
225-
})
226-
});
227-
228-
update_generated_globals(unit, variables.collect())
235+
fn get_internal_global_block(unit: &CompilationUnit) -> Option<&VariableBlock> {
236+
unit.global_vars
237+
.iter()
238+
.position(|block| {
239+
block.variable_block_type == VariableBlockType::Global && block.location.is_internal()
240+
})
241+
.and_then(|index| unit.global_vars.get(index))
229242
}
230243

231244
fn build_enum_initializer(

compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,16 @@ lazy_static! {
196196
E092, Info, include_str!("./error_codes/E092.md"),
197197
E093, Warning, include_str!("./error_codes/E093.md"),
198198
E094, Error, include_str!("./error_codes/E094.md"),
199-
E095, Error, include_str!("./error_codes/E095.md"), // Action call without `()`
200-
E096, Warning, include_str!("./error_codes/E096.md"), // Integer Condition
201-
E097, Error, include_str!("./error_codes/E097.md"), // Invalid Array Range
202-
E098, Error, include_str!("./error_codes/E098.md"), // Invalid `REF=` assignment
203-
E099, Error, include_str!("./error_codes/E099.md"), // Invalid `REFERENCE TO` declaration
204-
E100, Error, include_str!("./error_codes/E100.md"), // Immutable variable address
199+
E095, Error, include_str!("./error_codes/E095.md"), // Action call without `()`
200+
E096, Warning, include_str!("./error_codes/E096.md"), // Integer Condition
201+
E097, Error, include_str!("./error_codes/E097.md"), // Invalid Array Range
202+
E098, Error, include_str!("./error_codes/E098.md"), // Invalid `REF=` assignment
203+
E099, Error, include_str!("./error_codes/E099.md"), // Invalid `REFERENCE TO` declaration
204+
E100, Error, include_str!("./error_codes/E100.md"), // Immutable variable address
205+
E101, Error, include_str!("./error_codes/E101.md"), // Invalid VAR_CONFIG / Template Variable Declaration
206+
E102, Error, include_str!("./error_codes/E102.md"), // Template variable without hardware binding
207+
E103, Error, include_str!("./error_codes/E103.md"), // Immutable Hardware Binding
208+
E104, Error, include_str!("./error_codes/E104.md"), // Config Variable With Incomplete Address
205209
);
206210
}
207211

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Template variable does not exist
2+
3+
A variable was configured in a `VAR_CONFIG` block, but the variable can not be found in the code.
4+
5+
Erroneous code example:
6+
```
7+
VAR_CONFIG
8+
main.foo.bar AT %IX1.0 : BOOL;
9+
END_VAR
10+
11+
PROGRAM main
12+
VAR
13+
foo : foo_fb;
14+
END_VAR
15+
END_PROGRAM
16+
17+
FUNCTION_BLOCK foo_fb
18+
VAR
19+
qux AT %I* : BOOL;
20+
END_VAR
21+
END_FUNCTION_BLOCK
22+
```
23+
24+
In this example a variable named `bar` is configured, however the function block `foo_fb` does not contain
25+
a `bar` variable. The could should have been `main.foo.qux AT %IX1.0 : BOOL` instead for it to be valid.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Template variable without hardware binding
2+
3+
A template variable must contain a hardware binding.
4+
5+
6+
Erroneous code example:
7+
```
8+
VAR_CONFIG
9+
main.foo.bar AT %IX1.0 : BOOL;
10+
END_VAR
11+
12+
PROGRAM main
13+
VAR
14+
foo : foo_fb;
15+
END_VAR
16+
END_PROGRAM
17+
18+
FUNCTION_BLOCK foo_fb
19+
VAR
20+
bar : BOOL;
21+
END_VAR
22+
END_FUNCTION_BLOCK
23+
```
24+
25+
In this example the `VAR_CONFIG` block declares the `bar` variable inside `foo_fb` as a
26+
template variable. However `bar` does not have a hardware binding. For the example to be
27+
considered valid, `bar` should have been declared as e.g. `bar AT %I* : BOOL`.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Immutable Hardware Binding
2+
3+
Variables configured in a `VAR_CONFIG` block can not override their hardware binding.
4+
5+
Erroneous code example:
6+
```
7+
VAR_CONFIG
8+
main.foo.bar AT %IX1.0 : BOOL;
9+
END_VAR
10+
11+
PROGRAM main
12+
VAR
13+
foo : foo_fb;
14+
END_VAR
15+
END_PROGRAM
16+
17+
FUNCTION_BLOCK foo_fb
18+
VAR
19+
bar AT IX1.5: BOOL;
20+
END_VAR
21+
END_FUNCTION_BLOCK
22+
```
23+
24+
In this example the `VAR_CONFIG` block configures `bar` to have a hardware adress `IX1.0`.
25+
However, at the same time the `bar` inside the POU `foo_fb` assigns a hardware address `IX1.5`.
26+
27+
For the code to be considered valid, `bar` should have been declared as `bar AT %I* : BOOL`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Config Variable With Incomplete Address
2+
3+
Variables defined in a `VAR_CONFIG` block, i.e. config variables, must specify a complete address.
4+
5+
Erroneous code example:
6+
```
7+
VAR_CONFIG
8+
main.foo.bar AT %I* : BOOL;
9+
END_VAR
10+
```
11+
12+
In this example `main.foo.bar` has specified a placeholder hardware address.
13+
For the example to be considered valid, a specific address such as `%IX1.0` should have been declared.

libs/stdlib/iec61131-st/arithmetic_functions.st

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@ VAR_GLOBAL
1212
E_LREAL : LREAL;
1313
END_VAR
1414

15+
(********************
16+
*
17+
* This operator returns the value of adding up the operands.
18+
* It overloads the variadic builtin implementation of ADD, which is implemented for ANY_NUM
19+
*
20+
*********************)
21+
FUNCTION ADD < T1: ANY, T2: ANY >: T1
22+
VAR_INPUT
23+
IN1: T1;
24+
IN2: T2...;
25+
END_VAR
26+
END_FUNCTION
27+
28+
(********************
29+
*
30+
* This operator produces the multiplication of the operands.
31+
* It overloads the variadic builtin implementation of MUL, which is implemented for ANY_NUM
32+
*
33+
*********************)
34+
FUNCTION MUL < T1: ANY, T2: ANY >: T1
35+
VAR_INPUT
36+
IN1: T1;
37+
IN2: T2...;
38+
END_VAR
39+
END_FUNCTION
40+
1541
(* Calculates the square root of a given value *)
1642
{external}
1743
FUNCTION SQRT<T : ANY_REAL> : T

libs/stdlib/iec61131-st/date_time_numeric_functions.st

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
1-
(********************
2-
*
3-
* This operator returns the value of adding up the operands.
4-
* It overloads the variadic builtin implementation of ADD, which is impemented for ANY_NUM
5-
*
6-
*********************)
7-
FUNCTION ADD < T1: ANY, T2: ANY >: T1
8-
VAR_INPUT
9-
IN1: T1;
10-
IN2: T2;
11-
END_VAR
12-
END_FUNCTION
13-
141
(* Specialized implementation of ADD for TIME *)
152
FUNCTION ADD__TIME__TIME: TIME
163
VAR_INPUT
@@ -340,19 +327,6 @@ END_VAR
340327
SUB_LDT_LDT := SUB_DT_DT(IN1, IN2);
341328
END_FUNCTION
342329

343-
(********************
344-
*
345-
* This operator produces the multiplication of the operands.
346-
* It overloads the variadic builtin implementation of MUL, which is impemented for ANY_NUM
347-
*
348-
*********************)
349-
FUNCTION MUL < T1: ANY, T2: ANY >: T1
350-
VAR_INPUT
351-
IN1: T1;
352-
IN2: T2;
353-
END_VAR
354-
END_FUNCTION
355-
356330
(********************
357331
*
358332
* This operator produces the multiplication of TIME and ANY_NUM.

0 commit comments

Comments
 (0)