Skip to content

Commit 89ff513

Browse files
committed
wip: self-review
1 parent 6cba4ce commit 89ff513

File tree

10 files changed

+219
-197
lines changed

10 files changed

+219
-197
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,8 @@ impl AstNode {
14851485
matches!(self.stmt, AstStatement::Literal(AstLiteral::Real(_), ..))
14861486
}
14871487

1488-
pub fn get_name_of_lhs_of_assignment(&self) -> Option<&str> {
1488+
/// Returns the identifier of the left-hand side if this is an assignment statement
1489+
pub fn get_assignment_identifier(&self) -> Option<&str> {
14891490
match &self.stmt {
14901491
AstStatement::Assignment(Assignment { left, .. })
14911492
| AstStatement::OutputAssignment(Assignment { left, .. })

src/builtins.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ fn annotate_comparison_function(
672672
.has_nature(TypeNature::Elementary, annotator.index)
673673
}) {
674674
// we are trying to call this function with a non-elementary type, so we redirect back to the resolver
675-
annotator.annotate_call_statement(operator, Some(parameters), &ctx);
675+
annotator.annotate_arguments(operator, parameters, &ctx);
676676
return;
677677
}
678678

@@ -741,7 +741,7 @@ fn annotate_arithmetic_function(
741741
.has_nature(TypeNature::Num, annotator.index)
742742
}) {
743743
// we are trying to call this function with a non-numerical type, so we redirect back to the resolver
744-
annotator.annotate_call_statement(operator, Some(parameters), &ctx);
744+
annotator.annotate_arguments(operator, parameters, &ctx);
745745
return;
746746
}
747747

src/codegen/generators/expression_generator.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
15321532
let member_location = self
15331533
.index
15341534
.find_fully_qualified_variable(qualified_name)
1535-
.map(VariableIndexEntry::get_location_in_parent)
1535+
.map(VariableIndexEntry::get_position)
15361536
.ok_or_else(|| Diagnostic::unresolved_reference(qualified_name, offset))?;
15371537
let gep: PointerValue<'_> =
15381538
self.llvm.get_member_pointer_from_struct(*qualifier, member_location, name)?;
@@ -2274,7 +2274,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
22742274
Diagnostic::unresolved_reference(qualified_name, data.left.as_ref())
22752275
})?;
22762276

2277-
let index_in_parent = member.get_location_in_parent();
2277+
let index_in_parent = member.get_position();
22782278
let value = self.generate_expression(data.right.as_ref())?;
22792279

22802280
uninitialized_members.remove(member);
@@ -2306,7 +2306,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
23062306
Diagnostic::cannot_generate_initializer(member.get_qualified_name(), assignments)
23072307
})?;
23082308

2309-
member_values.push((member.get_location_in_parent(), initial_value));
2309+
member_values.push((member.get_position(), initial_value));
23102310
}
23112311
let struct_type = self.llvm_index.get_associated_type(struct_name)?.into_struct_type();
23122312
if member_values.len() == struct_type.count_fields() as usize {

src/index.rs

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl VariableIndexEntry {
199199
self.data_type_name.as_str()
200200
}
201201

202-
pub fn get_location_in_parent(&self) -> u32 {
202+
pub fn get_position(&self) -> u32 {
203203
self.location_in_parent
204204
}
205205

@@ -1551,30 +1551,31 @@ impl Index {
15511551
})
15521552
}
15531553

1554-
fn truly_find_local_member(&self, pou: &str, name: &str) -> Option<&VariableIndexEntry> {
1555-
self.type_index.find_type(pou).and_then(|it| it.find_member(name))
1556-
}
1554+
// XXX: This is super specific and currently only being used in the context of argument annotations.
1555+
// Should we move this to the resolver.rs file?
1556+
/// Finds a member in the specified POU, traversing the inheritance chain if necessary. Returns the
1557+
/// [`VariableIndexEntry`] along with the inheritance depth from the given POU to where the member
1558+
/// was declared.
1559+
pub fn find_pou_member_and_depth(&self, pou: &str, name: &str) -> Option<(&VariableIndexEntry, usize)> {
1560+
fn find<'a>(index: &'a Index, pou: &str, name: &str) -> Option<&'a VariableIndexEntry> {
1561+
index.type_index.find_type(pou).and_then(|pou| pou.find_member(name))
1562+
}
15571563

1558-
// TODO: Own type?
1559-
/// Given some POU name and one of its members' name, returns the member and the position including its
1560-
/// inheritance level. For example If we have `A { localVarA }, B extends A { localVarB }`, then
1561-
/// `find_member_with_path("B", "localVarA")` will return `(localVarA, 0, 1)`
1562-
pub fn find_member_with_path(&self, pou: &str, name: &str) -> Option<(String, &VariableIndexEntry, u32)> {
15631564
// Check if the POU has the member locally
1564-
if let Some(entry) = self.truly_find_local_member(pou, name) {
1565-
return Some((pou.to_string(), entry, 0));
1565+
if let Some(entry) = find(self, pou, name) {
1566+
return Some((entry, 0));
15661567
}
15671568

15681569
// ..and if not walk the inheritance chain and re-try
1569-
let mut level = 1;
1570+
let mut depth = 1;
15701571
let mut current_pou = pou;
15711572

1572-
while let Some(parent) = self.find_pou(current_pou).and_then(|it| it.get_super_class()) {
1573-
if let Some(entry) = self.truly_find_local_member(parent, name) {
1574-
return Some((parent.to_string(), entry, level));
1573+
while let Some(parent) = self.find_pou(current_pou).and_then(PouIndexEntry::get_super_class) {
1574+
if let Some(entry) = find(self, parent, name) {
1575+
return Some((entry, depth));
15751576
}
15761577

1577-
level += 1;
1578+
depth += 1;
15781579
current_pou = parent;
15791580
}
15801581

@@ -1731,21 +1732,32 @@ impl Index {
17311732
self.get_pou_types().get(&pou_name.to_lowercase())
17321733
}
17331734

1734-
pub fn get_declared_parameters(&self, pou_name: &str) -> Vec<&VariableIndexEntry> {
1735-
self.get_pou_members(pou_name)
1736-
.iter()
1737-
.filter(|it| it.is_parameter() && !it.is_variadic())
1738-
.collect::<Vec<_>>()
1735+
/// Returns the parameter for the given POU by its location, if it exists.
1736+
///
1737+
/// A parameter is defined as a `VAR_INPUT`, `VAR_OUTPUT` or `VAR_IN_OUT` variable.
1738+
pub fn get_declared_parameter(&self, pou_name: &str, index: u32) -> Option<&VariableIndexEntry> {
1739+
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_declared_parameter_by_location(index))
17391740
}
17401741

1741-
/// Returns all declared parameters of a POU, including those defined in super-classes
1742-
pub fn get_declared_parameters_2nd(&self, pou: &str) -> Vec<&VariableIndexEntry> {
1743-
let mut pou = pou;
1744-
let mut parameters = self.get_declared_parameters(pou);
1742+
/// Returns all declared parameters of a POU, including those defined in super-classes,
1743+
/// in intuitive order: base class parameters first, then derived.
1744+
pub fn get_declared_parameters(&self, pou: &str) -> Vec<&VariableIndexEntry> {
1745+
// Collect all POU names in the inheritance chain from base to derived
1746+
let mut chain = Vec::new();
1747+
let mut current = Some(pou);
1748+
let mut parameters = Vec::new();
17451749

1746-
while let Some(parent) = self.find_pou(pou).and_then(PouIndexEntry::get_super_class) {
1747-
parameters.extend(self.get_declared_parameters(parent));
1748-
pou = parent;
1750+
// Walk the inheritance chain and collect its POU names; only has an effect on function block calls
1751+
while let Some(pou_name) = current {
1752+
chain.push(pou_name);
1753+
current = self.find_pou(pou_name).and_then(PouIndexEntry::get_super_class);
1754+
}
1755+
1756+
// Then, reverse the chain to start at the root and collect its parameters
1757+
for &name in chain.iter().rev() {
1758+
parameters.extend(
1759+
self.get_pou_members(name).iter().filter(|var| var.is_parameter() && !var.is_variadic()),
1760+
);
17491761
}
17501762

17511763
parameters
@@ -1755,13 +1767,6 @@ impl Index {
17551767
self.get_pou_members(pou_name).iter().any(|member| member.is_parameter() && member.is_variadic())
17561768
}
17571769

1758-
/// returns some if the current index is a VAR_INPUT, VAR_IN_OUT or VAR_OUTPUT that is not a variadic argument
1759-
/// In other words it returns some if the member variable at `index` of the given container is a possible parameter in
1760-
/// the call to it
1761-
pub fn get_declared_parameter(&self, pou_name: &str, index: u32) -> Option<&VariableIndexEntry> {
1762-
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_declared_parameter_by_location(index))
1763-
}
1764-
17651770
pub fn get_variadic_member(&self, pou_name: &str) -> Option<&VariableIndexEntry> {
17661771
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_variadic_member())
17671772
}

src/index/tests/index_tests.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,3 +2541,67 @@ fn enum_ensure_a_combination_of_variables_can_be_assigned_in_function() {
25412541
assert!(index.find_local_member("fn", "blue").is_some());
25422542
assert_eq!(index.find_local_member("fn", "blue").unwrap().data_type_name, "EnumType");
25432543
}
2544+
2545+
#[test]
2546+
fn declared_parameters() {
2547+
let (_, index) = index(
2548+
r#"
2549+
FUNCTION_BLOCK FbA
2550+
VAR
2551+
localA: DINT;
2552+
END_VAR
2553+
2554+
VAR_INPUT
2555+
inA: DINT;
2556+
END_VAR
2557+
2558+
VAR_OUTPUT
2559+
outA: DINT;
2560+
END_VAR
2561+
2562+
VAR_IN_OUT
2563+
inoutA: DINT;
2564+
END_VAR
2565+
2566+
METHOD methA
2567+
END_METHOD
2568+
END_FUNCTION_BLOCK
2569+
2570+
FUNCTION_BLOCK FbB EXTENDS FbA
2571+
VAR
2572+
localB: DINT;
2573+
END_VAR
2574+
2575+
VAR_INPUT
2576+
inB: DINT;
2577+
END_VAR
2578+
2579+
VAR_OUTPUT
2580+
outB: DINT;
2581+
END_VAR
2582+
2583+
VAR_IN_OUT
2584+
inoutB: DINT;
2585+
END_VAR
2586+
2587+
METHOD methB
2588+
VAR_INPUT
2589+
inB_meth: DINT;
2590+
END_VAR
2591+
END_METHOD
2592+
END_FUNCTION_BLOCK
2593+
"#,
2594+
);
2595+
2596+
let members = index.get_declared_parameters("FbA").iter().map(|var| &var.name).collect::<Vec<_>>();
2597+
assert_eq!(members, vec!["inA", "outA", "inoutA"]);
2598+
2599+
let members = index.get_declared_parameters("FbB").iter().map(|var| &var.name).collect::<Vec<_>>();
2600+
assert_eq!(members, vec!["inA", "outA", "inoutA", "inB", "outB", "inoutB",]);
2601+
2602+
let members = index.get_declared_parameters("methA").iter().map(|var| &var.name).collect::<Vec<_>>();
2603+
assert!(members.is_empty());
2604+
2605+
let members = index.get_declared_parameters("FbB.methB").iter().map(|var| &var.name).collect::<Vec<_>>();
2606+
assert_eq!(members, vec!["inB_meth"]);
2607+
}

0 commit comments

Comments
 (0)