Skip to content

Commit 90e6e9c

Browse files
authored
refactor: Parse VAR_CONFIG variables left-hand-side as references (#1316)
Changes how VAR_CONFIG variables are parsed. The left-hand side (before the AT keyword) is now parsed as a reference, which is then resolved and annotated by the resolver.
1 parent 3753527 commit 90e6e9c

File tree

6 files changed

+325
-38
lines changed

6 files changed

+325
-38
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 17 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,20 @@ impl AstNode {
935935
}
936936
}
937937

938+
pub fn get_flat_base_reference_name(&self) -> Option<&str> {
939+
match &self.stmt {
940+
AstStatement::ReferenceExpr(ReferenceExpr { base: Some(base), .. }, ..) => {
941+
base.as_ref().get_flat_base_reference_name()
942+
}
943+
AstStatement::ReferenceExpr(
944+
ReferenceExpr { access: ReferenceAccess::Member(reference), base: None },
945+
..,
946+
) => reference.as_ref().get_flat_base_reference_name(),
947+
AstStatement::Identifier(name, ..) => Some(name),
948+
_ => None,
949+
}
950+
}
951+
938952
pub fn get_label_name(&self) -> Option<&str> {
939953
match &self.stmt {
940954
AstStatement::LabelStatement(LabelStatement { name, .. }) => Some(name.as_str()),

src/parser.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,17 +1093,7 @@ fn parse_config_variables(lexer: &mut ParseSession) -> Vec<ConfigVariable> {
10931093

10941094
fn try_parse_config_var(lexer: &mut ParseSession) -> Option<ConfigVariable> {
10951095
let start = lexer.location();
1096-
let mut segments: Vec<String> = vec![];
1097-
while lexer.token == Identifier {
1098-
segments.push(lexer.slice_and_advance());
1099-
1100-
if lexer.token == KeywordColon || lexer.token == KeywordAt {
1101-
break;
1102-
}
1103-
1104-
lexer.try_consume(&KeywordDot);
1105-
}
1106-
1096+
let qualified_reference = parse_reference(lexer);
11071097
let location = start.span(&lexer.last_location());
11081098
if !lexer.try_consume(&KeywordAt) {
11091099
lexer.accept_diagnostic(Diagnostic::missing_token("AT", lexer.location()));
@@ -1131,7 +1121,7 @@ fn try_parse_config_var(lexer: &mut ParseSession) -> Option<ConfigVariable> {
11311121
lexer.last_location().span(&lexer.location()),
11321122
))
11331123
}
1134-
ConfigVariable::new(segments, dt, address, location)
1124+
ConfigVariable::new(qualified_reference, dt, address, location)
11351125
})
11361126
}
11371127

src/parser/tests/variable_parser_tests.rs

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ fn date_and_time_constants_test() {
252252
fn var_config_test() {
253253
let src = "
254254
VAR_CONFIG
255-
instance1.foo AT %IX3.1 : BOOL;
256-
instance2.bar AT %IX5.6 : BOOL;
255+
instance1.foo.qux AT %IX3.1 : BOOL;
256+
instance2.bar.qux AT %IX5.6 : BOOL;
257257
END_VAR
258258
";
259259
let (result, diag) = parse(src);
@@ -264,10 +264,32 @@ fn var_config_test() {
264264
global_vars: [],
265265
var_config: [
266266
ConfigVariable {
267-
name_segments: [
268-
"instance1",
269-
"foo",
270-
],
267+
reference: ReferenceExpr {
268+
kind: Member(
269+
Identifier {
270+
name: "qux",
271+
},
272+
),
273+
base: Some(
274+
ReferenceExpr {
275+
kind: Member(
276+
Identifier {
277+
name: "foo",
278+
},
279+
),
280+
base: Some(
281+
ReferenceExpr {
282+
kind: Member(
283+
Identifier {
284+
name: "instance1",
285+
},
286+
),
287+
base: None,
288+
},
289+
),
290+
},
291+
),
292+
},
271293
data_type: DataTypeReference {
272294
referenced_type: "BOOL",
273295
},
@@ -286,12 +308,12 @@ fn var_config_test() {
286308
span: Range(
287309
TextLocation {
288310
line: 2,
289-
column: 22,
290-
offset: 38,
311+
column: 26,
312+
offset: 42,
291313
}..TextLocation {
292314
line: 2,
293-
column: 31,
294-
offset: 47,
315+
column: 35,
316+
offset: 51,
295317
},
296318
),
297319
},
@@ -304,17 +326,39 @@ fn var_config_test() {
304326
offset: 24,
305327
}..TextLocation {
306328
line: 2,
307-
column: 21,
308-
offset: 37,
329+
column: 25,
330+
offset: 41,
309331
},
310332
),
311333
},
312334
},
313335
ConfigVariable {
314-
name_segments: [
315-
"instance2",
316-
"bar",
317-
],
336+
reference: ReferenceExpr {
337+
kind: Member(
338+
Identifier {
339+
name: "qux",
340+
},
341+
),
342+
base: Some(
343+
ReferenceExpr {
344+
kind: Member(
345+
Identifier {
346+
name: "bar",
347+
},
348+
),
349+
base: Some(
350+
ReferenceExpr {
351+
kind: Member(
352+
Identifier {
353+
name: "instance2",
354+
},
355+
),
356+
base: None,
357+
},
358+
),
359+
},
360+
),
361+
},
318362
data_type: DataTypeReference {
319363
referenced_type: "BOOL",
320364
},
@@ -333,12 +377,12 @@ fn var_config_test() {
333377
span: Range(
334378
TextLocation {
335379
line: 3,
336-
column: 22,
337-
offset: 78,
380+
column: 26,
381+
offset: 86,
338382
}..TextLocation {
339383
line: 3,
340-
column: 31,
341-
offset: 87,
384+
column: 35,
385+
offset: 95,
342386
},
343387
),
344388
},
@@ -348,11 +392,11 @@ fn var_config_test() {
348392
TextLocation {
349393
line: 3,
350394
column: 8,
351-
offset: 64,
395+
offset: 68,
352396
}..TextLocation {
353397
line: 3,
354-
column: 21,
355-
offset: 77,
398+
column: 25,
399+
offset: 85,
356400
},
357401
),
358402
},

src/resolver.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,11 @@ impl<'i> TypeAnnotator<'i> {
815815
i.statements.iter().for_each(|s| visitor.visit_statement(&body_ctx.with_pou(i.name.as_str()), s));
816816
}
817817

818+
for config_variable in &unit.var_config {
819+
let Some(base) = &config_variable.reference.get_flat_base_reference_name() else { continue };
820+
visitor.visit_statement(&ctx.with_pou(base), &config_variable.reference);
821+
}
822+
818823
// enum initializers may have been introduced by the visitor (indexer)
819824
// so we should try to resolve and type-annotate them here as well
820825
for enum_element in index.get_all_enum_variants().iter().filter(|it| it.is_in_unit(&unit.file_name)) {

src/resolver/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod const_resolver_tests;
22
mod lowering;
33
mod resolve_and_lower_init_functions;
4+
mod resolve_config_variables;
45
mod resolve_control_statments;
56
mod resolve_expressions_tests;
67
mod resolve_generic_calls;

0 commit comments

Comments
 (0)