Skip to content

Commit 2647f98

Browse files
committed
fix: annotate whole call statement
Previously when dealing with function pointer calls such as `fnPtr^()` the resolver would only annotate the operator and any arguments. Some codegen parts require an annotation on the whole call statement however (which makes sense), as such this commit fixes the described issue. Visuallized, assuming `fnPtr` points to a function returning a DINT: ``` fnPtr^(); ^^^^^^^^ -> StatementAnnotation::Value { resulting_type: "DINT" } ```
1 parent 58c2a1e commit 2647f98

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

src/resolver.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,22 +2246,29 @@ impl<'i> TypeAnnotator<'i> {
22462246
self.annotate_call_statement(operator, parameters_stmt, &ctx);
22472247
};
22482248

2249-
if let Some(StatementAnnotation::Function { return_type, .. }) = self.annotation_map.get(operator) {
2250-
if let Some(return_type) = self
2251-
.index
2252-
.find_effective_type_by_name(return_type)
2253-
.or_else(|| self.annotation_map.new_index.find_effective_type_by_name(return_type))
2254-
{
2255-
if let Some(StatementAnnotation::ReplacementAst { .. }) = self.annotation_map.get(statement) {
2256-
// if we have a replacement ast, we do not need to annotate the function return type as it would
2257-
// overwrite the replacement ast
2258-
return;
2249+
match self.annotation_map.get(operator) {
2250+
Some(StatementAnnotation::Function { return_type, .. })
2251+
| Some(StatementAnnotation::FunctionPointer { return_type, .. }) => {
2252+
if let Some(return_type) = self
2253+
.index
2254+
.find_effective_type_by_name(return_type)
2255+
.or_else(|| self.annotation_map.new_index.find_effective_type_by_name(return_type))
2256+
{
2257+
if let Some(StatementAnnotation::ReplacementAst { .. }) =
2258+
self.annotation_map.get(statement)
2259+
{
2260+
// if we have a replacement ast, we do not need to annotate the function return type as it would
2261+
// overwrite the replacement ast
2262+
return;
2263+
}
2264+
self.annotate(statement, StatementAnnotation::value(return_type.get_name()));
2265+
} else {
2266+
// Assuming this is a VOID function if no annotation is present
2267+
self.annotate(statement, StatementAnnotation::value(VOID_INTERNAL_NAME));
22592268
}
2260-
self.annotate(statement, StatementAnnotation::value(return_type.get_name()));
2261-
} else {
2262-
// Assuming this is a VOID function if no annotation is present
2263-
self.annotate(statement, StatementAnnotation::value(VOID_INTERNAL_NAME));
22642269
}
2270+
2271+
_ => (),
22652272
}
22662273
}
22672274

src/resolver/tests/fnptr.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ fn function_pointer_method_with_no_arguments() {
5050

5151
// echoPtr^();
5252
// ^^^^^^^^^^
53-
insta::assert_debug_snapshot!(annotations.get(node), @"None");
53+
insta::assert_debug_snapshot!(annotations.get(node), @r#"
54+
Some(
55+
Value {
56+
resulting_type: "DINT",
57+
},
58+
)
59+
"#);
5460
}
5561
}
5662

@@ -112,7 +118,13 @@ fn function_pointer_method_with_arguments() {
112118

113119
// echoPtr^();
114120
// ^^^^^^^^^^
115-
insta::assert_debug_snapshot!(annotations.get(&statements[0]), @"None");
121+
insta::assert_debug_snapshot!(annotations.get(&statements[0]), @r#"
122+
Some(
123+
Value {
124+
resulting_type: "DINT",
125+
},
126+
)
127+
"#);
116128
}
117129

118130
// echoPtr^(instanceFb, localIn, localOut, localInOut);
@@ -193,6 +205,16 @@ fn function_pointer_method_with_arguments() {
193205
},
194206
)
195207
"#);
208+
209+
// echoPtr^(instanceFb, localIn, localOut, localInOut);
210+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
211+
insta::assert_debug_snapshot!(annotations.get(&statements[1]), @r#"
212+
Some(
213+
Value {
214+
resulting_type: "DINT",
215+
},
216+
)
217+
"#);
196218
}
197219

198220
// echoPtr^(instanceFb, in := localIn, out => localOut, inout := localInOut);
@@ -349,7 +371,7 @@ fn void_pointer_casting() {
349371
__vtable: POINTER TO __VOID;
350372
END_VAR
351373
352-
METHOD foo
374+
METHOD foo: DINT
353375
END_METHOD
354376
END_FUNCTION_BLOCK
355377
@@ -416,13 +438,28 @@ fn void_pointer_casting() {
416438
insta::assert_debug_snapshot!(annotations.get(&call.operator), @r#"
417439
Some(
418440
FunctionPointer {
419-
return_type: "VOID",
441+
return_type: "DINT",
420442
qualified_name: "FbA.foo",
421443
},
422444
)
423445
"#);
424446
insta::assert_debug_snapshot!(annotations.get_hint(&call.operator), @"None");
425447
}
448+
449+
{
450+
let node = &unit.implementations.iter().find(|imp| imp.name == "main").unwrap().statements[1];
451+
452+
// vtable_FbA#(instanceFbA.__vtable).foo^(instanceFbA);
453+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
454+
insta::assert_debug_snapshot!(annotations.get(&node), @r#"
455+
Some(
456+
Value {
457+
resulting_type: "DINT",
458+
},
459+
)
460+
"#);
461+
insta::assert_debug_snapshot!(annotations.get_hint(&node), @"None");
462+
}
426463
}
427464

428465
#[test]

0 commit comments

Comments
 (0)