Skip to content

Commit 64b759a

Browse files
committed
convert correctness tests to lit
1 parent a991a8c commit 64b759a

8 files changed

+127
-162
lines changed

src/validation/statement.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -777,20 +777,26 @@ fn validate_ref_assignment<T: AnnotationMap>(
777777
assignment: &Assignment,
778778
assignment_location: &SourceLocation,
779779
) {
780-
// Assert that the rhs is a variable that can be referenced
781-
if !assignment.right.is_reference() {
782-
validator.push_diagnostic(
783-
Diagnostic::new("Invalid assignment, expected a reference")
784-
.with_location(&assignment.right.location)
785-
.with_error_code("E098"),
786-
);
787-
}
780+
let mut assert_reference = |node: &AstNode| {
781+
if !node.is_reference() {
782+
validator.push_diagnostic(
783+
Diagnostic::new("Invalid assignment, expected a reference")
784+
.with_location(&node.location)
785+
.with_error_code("E098"),
786+
);
787+
}
788+
};
789+
790+
assert_reference(&assignment.left);
791+
assert_reference(&assignment.right);
788792

789793
// Lastly, assert the type the lhs references matches with the rhs
790-
let type_lhs = context.annotations.get_type(&assignment.left, context.index).unwrap();
791-
let type_rhs = context.annotations.get_type(&assignment.right, context.index).unwrap();
794+
let type_lhs = context.annotations.get_type_or_void(&assignment.left, context.index);
795+
let type_rhs = context.annotations.get_type_or_void(&assignment.right, context.index);
796+
let type_info_lhs = context.index.find_elementary_pointer_type(type_lhs.get_type_information());
797+
let type_info_rhs = context.index.find_elementary_pointer_type(type_rhs.get_type_information());
792798

793-
if type_lhs != type_rhs {
799+
if type_info_lhs != type_info_rhs {
794800
validator.push_diagnostic(
795801
Diagnostic::new(format!(
796802
"Invalid assignment, types {} and {} differ",

src/validation/tests/assignment_validation_tests.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,11 +1246,12 @@ fn reference_to_variables_and_ref_assignments() {
12461246
referenceToFooInitializedArray : REFERENCE TO ARRAY[1..5] OF DINT;
12471247
END_VAR
12481248
1249-
referenceToFoo REF= foo;
1249+
refToFoo REF= foo;
1250+
referenceToFoo REF= foo;
12501251
12511252
// Invalid
1253+
1 REF= foo;
12521254
foo REF= foo;
1253-
refToFoo REF= foo;
12541255
referenceToFoo REF= 0;
12551256
referenceToFoo REF= referenceToFoo;
12561257
END_FUNCTION
@@ -1293,16 +1294,16 @@ fn reference_to_variables_and_ref_assignments() {
12931294
│ │
12941295
│ REFERENCE TO variables can not reference arrays, pointers or bits
12951296
1296-
error[E098]: Invalid assignment, types REF_TO DINT and DINT differ
1297+
error[E098]: Invalid assignment, expected a reference
12971298
┌─ <internal>:30:13
12981299
1299-
30 │ refToFoo REF= foo;
1300-
│ ^^^^^^^^^^^^^^^^^ Invalid assignment, types REF_TO DINT and DINT differ
1300+
30 │ 1 REF= foo;
1301+
│ ^ Invalid assignment, expected a reference
13011302
13021303
error[E098]: Invalid assignment, expected a reference
1303-
┌─ <internal>:31:33
1304+
┌─ <internal>:32:33
13041305
1305-
31 │ referenceToFoo REF= 0;
1306+
32 │ referenceToFoo REF= 0;
13061307
│ ^ Invalid assignment, expected a reference
13071308
13081309
"###);

src/validation/variable.rs

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -217,49 +217,52 @@ fn validate_reference_to_declaration<T: AnnotationMap>(
217217
variable: &Variable,
218218
variable_entry: &VariableIndexEntry,
219219
) {
220-
if let Some(variable_type) = context.index.find_effective_type_by_name(variable_entry.get_type_name()) {
221-
if variable_type.get_type_information().is_reference_to() {
222-
let DataTypeInformation::Pointer { inner_type_name, .. } = variable_type.get_type_information()
223-
else {
224-
unreachable!("`REFERENCE TO` is defined as a pointer, hence this must exist")
225-
};
220+
let Some(variable_ty) = context.index.find_effective_type_by_name(variable_entry.get_type_name()) else {
221+
return;
222+
};
226223

227-
// Assert that no initializers are present in the `REFERENCE TO` declaration
228-
if let Some(ref initializer) = variable.initializer {
229-
if variable_type.get_type_information().is_reference_to() {
230-
validator.push_diagnostic(
231-
Diagnostic::new("Initializations of REFERENCE TO variables are disallowed")
232-
.with_location(&initializer.location)
233-
.with_error_code("E099"),
234-
);
235-
}
236-
}
224+
if !variable_ty.get_type_information().is_reference_to() {
225+
return;
226+
}
237227

238-
// Assert that the referenced type is no variable reference
239-
let qualifier = context.qualifier.unwrap_or_default();
240-
let inner_ty_is_local_var = context.index.find_member(qualifier, inner_type_name).is_some();
241-
let inner_ty_is_global_var = context.index.find_global_variable(inner_type_name).is_some();
228+
let Some(inner_ty_name) = variable_ty.get_type_information().get_inner_pointer_type_name() else {
229+
unreachable!("`REFERENCE TO` is defined as a pointer, hence this must exist")
230+
};
242231

243-
if inner_ty_is_local_var || inner_ty_is_global_var {
244-
validator.push_diagnostic(
245-
Diagnostic::new("REFERENCE TO variables can not reference other variables")
246-
.with_location(&variable_type.location)
247-
.with_error_code("E099"),
248-
);
249-
}
232+
// Assert that no initializers are present in the `REFERENCE TO` declaration
233+
if let Some(ref initializer) = variable.initializer {
234+
if variable_ty.get_type_information().is_reference_to() {
235+
validator.push_diagnostic(
236+
Diagnostic::new("Initializations of REFERENCE TO variables are disallowed")
237+
.with_location(&initializer.location)
238+
.with_error_code("E099"),
239+
);
240+
}
241+
}
250242

251-
// Lastly assert that the referenced type is no array, pointer or bit
252-
let inner_type = context.index.find_effective_type_by_name(inner_type_name);
253-
if let Some(ty) = inner_type {
254-
if ty.is_array() || ty.is_pointer() || ty.is_bit() {
255-
validator.push_diagnostic(
256-
Diagnostic::new("REFERENCE TO variables can not reference arrays, pointers or bits")
257-
.with_location(&variable.location)
258-
.with_secondary_location(&ty.location)
259-
.with_error_code("E099"),
260-
);
261-
}
262-
}
243+
// Assert that the referenced type is no variable reference
244+
let qualifier = context.qualifier.unwrap_or_default();
245+
let inner_ty_is_local_var = context.index.find_member(qualifier, inner_ty_name).is_some();
246+
let inner_ty_is_global_var = context.index.find_global_variable(inner_ty_name).is_some();
247+
248+
if inner_ty_is_local_var || inner_ty_is_global_var {
249+
validator.push_diagnostic(
250+
Diagnostic::new("REFERENCE TO variables can not reference other variables")
251+
.with_location(&variable_ty.location)
252+
.with_error_code("E099"),
253+
);
254+
}
255+
256+
// Lastly assert that the referenced type is no array, pointer or bit
257+
let inner_type = context.index.find_effective_type_by_name(inner_ty_name);
258+
if let Some(ty) = inner_type {
259+
if ty.is_array() || ty.is_pointer() || ty.is_bit() {
260+
validator.push_diagnostic(
261+
Diagnostic::new("REFERENCE TO variables can not reference arrays, pointers or bits")
262+
.with_location(&variable.location)
263+
.with_secondary_location(&ty.location)
264+
.with_error_code("E099"),
265+
);
263266
}
264267
}
265268
}

tests/correctness/pointers.rs

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -242,108 +242,3 @@ fn value_behind_function_block_pointer_is_assigned_to_correctly() {
242242
assert!(!maintype.a);
243243
assert!(maintype.b);
244244
}
245-
246-
#[test]
247-
fn reference_assignment() {
248-
let function = r"
249-
FUNCTION main : DINT
250-
VAR
251-
a : REF_TO DINT;
252-
b : DINT := 5;
253-
END_VAR
254-
255-
a REF= b;
256-
main := a^;
257-
END_FUNCTION
258-
";
259-
260-
let res: i32 = compile_and_run(function.to_string(), &mut MainType::default());
261-
assert_eq!(5, res);
262-
}
263-
264-
#[test]
265-
fn reference_to_assignment() {
266-
let function = r"
267-
FUNCTION main : DINT
268-
VAR
269-
a : REFERENCE TO DINT;
270-
b : DINT := 5;
271-
END_VAR
272-
a REF= b;
273-
main := a;
274-
END_FUNCTION
275-
";
276-
277-
let res: i32 = compile_and_run(function, &mut MainType::default());
278-
assert_eq!(5, res);
279-
}
280-
281-
#[test]
282-
fn reference_to_variable_referencing_other_reference_to_variable() {
283-
let function = r"
284-
FUNCTION main : DINT
285-
VAR
286-
foo : REFERENCE TO DINT;
287-
bar : REFERENCE TO DINT;
288-
qux : DINT;
289-
END_VAR
290-
291-
bar REF= qux;
292-
foo REF= bar;
293-
qux := 5;
294-
295-
main := foo; // foo -> bar -> qux
296-
END_FUNCTION
297-
";
298-
299-
let res: i32 = compile_and_run(function, &mut MainType::default());
300-
assert_eq!(5, res);
301-
}
302-
303-
#[test]
304-
fn reference_to_variable_referencing_itself() {
305-
let function = r"
306-
FUNCTION main : DINT
307-
VAR
308-
foo : REFERENCE TO DINT;
309-
bar : REFERENCE TO DINT;
310-
qux : DINT;
311-
END_VAR
312-
313-
foo REF= bar;
314-
bar REF= qux;
315-
316-
bar REF= bar;
317-
qux := 5;
318-
319-
main := bar; // bar (-> bar) -> qux
320-
END_FUNCTION
321-
";
322-
323-
let res: i32 = compile_and_run(function, &mut MainType::default());
324-
assert_eq!(5, res);
325-
}
326-
327-
#[test]
328-
fn reference_to_variable_referencing_struct() {
329-
let function = r"
330-
TYPE Transaction : STRUCT
331-
id : DINT;
332-
amount : DINT;
333-
message : STRING;
334-
END_STRUCT END_TYPE
335-
336-
FUNCTION main : DINT
337-
VAR
338-
txn : Transaction := (id := 1, amount := 5, message := 'whats up');
339-
refTxn : REFERENCE TO Transaction;
340-
END_VAR
341-
342-
refTxn REF= txn;
343-
main := refTxn.amount;
344-
END_FUNCTION
345-
";
346-
347-
let res: i32 = compile_and_run(function, &mut MainType::default());
348-
assert_eq!(5, res);
349-
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
// CHECK: 5
3+
FUNCTION main : DINT
4+
VAR
5+
a : REF_TO DINT;
6+
b : DINT := 5;
7+
END_VAR
8+
a REF= b;
9+
10+
printf('%d$N', a^);
11+
END_FUNCTION
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
// CHECK: 5
3+
FUNCTION main : DINT
4+
VAR
5+
foo : REFERENCE TO DINT;
6+
bar : REFERENCE TO DINT;
7+
qux : DINT;
8+
END_VAR
9+
10+
foo REF= bar;
11+
bar REF= qux;
12+
13+
bar REF= bar;
14+
qux := 5;
15+
16+
printf('%d$N', bar); // bar (-> bar) -> qux
17+
END_FUNCTION
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
// CHECK: 5
3+
FUNCTION main : DINT
4+
VAR
5+
foo : REFERENCE TO DINT;
6+
bar : REFERENCE TO DINT;
7+
qux : DINT;
8+
END_VAR
9+
10+
bar REF= qux;
11+
foo REF= bar;
12+
qux := 5;
13+
14+
printf('%d$N', foo); // foo -> bar -> qux
15+
END_FUNCTION
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: (%COMPILE %s && %RUN) | %CHECK %s
2+
// CHECK: 5
3+
TYPE Transaction : STRUCT
4+
id : DINT;
5+
amount : DINT;
6+
message : STRING;
7+
END_STRUCT END_TYPE
8+
9+
FUNCTION main : DINT
10+
VAR
11+
txn : Transaction := (id := 1, amount := 5, message := 'whats up');
12+
refTxn : REFERENCE TO Transaction;
13+
END_VAR
14+
15+
refTxn REF= txn;
16+
printf('%d$N', refTxn.amount);
17+
END_FUNCTION

0 commit comments

Comments
 (0)