fix: ensuring ADR assignment on REFERENCE TO variables raises an error#1597
fix: ensuring ADR assignment on REFERENCE TO variables raises an error#1597Angus-Bethke-Bachmann merged 8 commits intomasterfrom
Conversation
|
The failing build will be fixed with the fix_arm_constructors branch, we can ignore it here |
src/validation/statement.rs
Outdated
| AstStatement::CallStatement(call_stmt) => { | ||
| if let Some(identifier) = call_stmt.operator.get_identifier() { | ||
| match identifier.get_stmt() { | ||
| AstStatement::Identifier(id) => id.to_lowercase() == "adr", |
There was a problem hiding this comment.
I briefly skimmed through this PR, that line caught my attention however. Is there perhaps an alternative to string matching? I believe the built-ins have their own closure (functions) which do validation, not sure they carry enough information to enclose the left side however. Might be worth looking into?
There was a problem hiding this comment.
I had a look at the builtins, but we have no helper functions that specifically validate the function name. I could however adapt this to call the "get_builtin" method as an extra step of validation to verify that that the call statement is a builtin before directly verifying that it is the ADR function? In either case I will need to do string validation.
Perhaps then it makes sense to make a helper function in the builtins for this specific purpose? Let me know what you think.
There was a problem hiding this comment.
Perhaps then it makes sense to make a helper function in the builtins for this specific purpose?
If you can think of a way that is not overkill go for it, otherwise let's move forward with the pragmatic (though maybe not performative) solution of raw string matching. fwiw, opus recommended
fn node_is_builtin_adr<T: AnnotationMap>(node: &AstNode, context: &ValidationContext<T>) -> bool {
let AstStatement::CallStatement(CallStatement { operator, .. }) = node.get_stmt_peeled() else {
return false;
};
let Some(call_name) = context.annotations.get_call_name(operator.as_ref()) else {
return false;
};
let Some(adr_builtin) = builtins::get_builtin("ADR") else {
return false;
};
context
.index
.get_builtin_function(call_name)
.is_some_and(|builtin| std::ptr::eq(builtin, adr_builtin))
}
(essentially what you mentioned in your comment)
There was a problem hiding this comment.
I have implemented this suggestion :)
| ┌─ <internal>:9:13 | ||
| │ | ||
| 9 │ refe := ADR(myDint); | ||
| │ ^^^^^^^^^^^^^^^^^^^ ADR call cannot be assigned to variable declared as 'REFERENCE TO'. Did you mean to use 'REF='? |
There was a problem hiding this comment.
I'm assuming this aligns with the behavior of CodeSys?
There was a problem hiding this comment.
The CODESYS behaviour is slightly different, it returns a type mismatch: "Cannot convert type 'POINTER TO DINT' to type 'DINT'".
So we arrive at the same conclusion via different means. In this case, I believe we give more information about the problem and hint at resolving it. That being said, I am open to trying to resolve this as a type mismatch validation.
There was a problem hiding this comment.
Nope, I was just curious whether ADR is truly disallowed in a REFERENCE TO context. I agree though, our message in that case is much more helpful.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1597 +/- ##
==========================================
- Coverage 94.66% 94.65% -0.02%
==========================================
Files 185 187 +2
Lines 58437 58840 +403
==========================================
+ Hits 55322 55695 +373
- Misses 3115 3145 +30 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Changed
Chore
Testing