Skip to content

Commit 691a88f

Browse files
committed
refactor and more resolver tests
1 parent b8e4d06 commit 691a88f

File tree

2 files changed

+96
-70
lines changed

2 files changed

+96
-70
lines changed

src/resolver.rs

+29-61
Original file line numberDiff line numberDiff line change
@@ -1637,44 +1637,37 @@ impl<'i> TypeAnnotator<'i> {
16371637
fn visit_statement_expression(&mut self, ctx: &VisitorContext, statement: &AstNode) {
16381638
match statement.get_stmt() {
16391639
AstStatement::This => {
1640-
if let Some(pou) = ctx.pou.and_then(|name| self.index.find_pou(name)) {
1641-
match pou {
1642-
// TODO: #THIS for functionblock and for method if parent is of type functionblock
1643-
PouIndexEntry::FunctionBlock { name, .. }
1644-
| PouIndexEntry::Method { parent_name: name, .. } => {
1645-
if let Some(parent_name) = self.index.find_pou(name) {
1646-
match parent_name {
1647-
PouIndexEntry::FunctionBlock { .. } | PouIndexEntry::Method { .. } => {
1648-
let ptr_name = format!("{}.__THIS", name);
1649-
if self
1650-
.index
1651-
.find_type(&ptr_name)
1652-
.or_else(|| self.annotation_map.new_index.find_type(&ptr_name))
1653-
.is_none()
1654-
{
1655-
let information = DataTypeInformation::Pointer {
1656-
name: ptr_name.clone(),
1657-
inner_type_name: name.to_string(),
1658-
auto_deref: None,
1659-
};
1660-
let dt = crate::typesystem::DataType {
1661-
name: ptr_name.clone(),
1662-
initial_value: None,
1663-
information,
1664-
nature: TypeNature::Any,
1665-
location: SourceLocation::internal(),
1666-
};
1667-
self.annotation_map.new_index.register_type(dt);
1668-
}
1669-
self.annotate(statement, StatementAnnotation::value(ptr_name));
1670-
}
1671-
_ => {}
1672-
}
1673-
}
1674-
}
1675-
_ => {}
1640+
let name = match ctx.pou.and_then(|name| self.index.find_pou(name)) {
1641+
Some(PouIndexEntry::FunctionBlock { name, .. }) => name,
1642+
Some(PouIndexEntry::Method { parent_name: name, .. })
1643+
if self.index.find_pou(&name).is_some_and(|it| it.is_function_block()) =>
1644+
{
1645+
name
16761646
}
1647+
_ => return,
1648+
};
1649+
let ptr_name = format!("{}.__THIS", name);
1650+
if self
1651+
.index
1652+
.find_type(&ptr_name)
1653+
.or_else(|| self.annotation_map.new_index.find_type(&ptr_name))
1654+
.is_none()
1655+
{
1656+
let information = DataTypeInformation::Pointer {
1657+
name: ptr_name.clone(),
1658+
inner_type_name: name.to_string(),
1659+
auto_deref: None,
1660+
};
1661+
let dt = crate::typesystem::DataType {
1662+
name: ptr_name.clone(),
1663+
initial_value: None,
1664+
information,
1665+
nature: TypeNature::Any,
1666+
location: SourceLocation::internal(),
1667+
};
1668+
self.annotation_map.new_index.register_type(dt);
16771669
}
1670+
self.annotate(statement, StatementAnnotation::value(ptr_name));
16781671
}
16791672
AstStatement::DirectAccess(data, ..) => {
16801673
let ctx = VisitorContext { qualifier: None, ..ctx.clone() };
@@ -2016,31 +2009,6 @@ impl<'i> TypeAnnotator<'i> {
20162009
ctx: &VisitorContext<'_>,
20172010
) -> Option<StatementAnnotation> {
20182011
match reference.get_stmt() {
2019-
AstStatement::This => {
2020-
// Only `THIS` in FunctionBlock/methods context
2021-
// TODO: also support methods
2022-
if let Some(pou) = ctx.pou.and_then(|name| self.index.find_pou(name)) {
2023-
match pou {
2024-
// TODO: #THIS for functionblock and for method if parent is of type functionblock
2025-
PouIndexEntry::FunctionBlock { name, .. }
2026-
| PouIndexEntry::Method { parent_name: name, .. } => {
2027-
if let Some(parent_name) = self.index.find_pou(name) {
2028-
match parent_name {
2029-
PouIndexEntry::FunctionBlock { .. } | PouIndexEntry::Method { .. } => {
2030-
Some(StatementAnnotation::value(name))
2031-
}
2032-
_ => None,
2033-
}
2034-
} else {
2035-
None
2036-
}
2037-
}
2038-
_ => None,
2039-
}
2040-
} else {
2041-
None
2042-
}
2043-
}
20442012
AstStatement::Identifier(name, ..) => ctx
20452013
.resolve_strategy
20462014
.iter()

src/resolver/tests/resolve_expressions_tests.rs

+67-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::panic;
2+
use std::os::linux::raw::stat;
23

34
use insta::{assert_debug_snapshot, assert_snapshot};
45
use plc_ast::{
@@ -6001,7 +6002,6 @@ fn this_should_not_be_in_programs() {
60016002
myvar : INT;
60026003
END_VAR
60036004
this^.myvar := 8;
6004-
myvar := this^.myvar;
60056005
END_PROGRAM
60066006
",
60076007
id_provider.clone(),
@@ -6010,21 +6010,18 @@ fn this_should_not_be_in_programs() {
60106010
let AstStatement::Assignment(statement_1) = unit.implementations[0].statements[0].get_stmt() else {
60116011
unreachable!()
60126012
};
6013-
let AstStatement::Assignment(statement_2) = unit.implementations[0].statements[1].get_stmt() else {
6014-
unreachable!()
6015-
};
6016-
assert!(index.find_type("fb.__THIS").is_none());
6013+
assert!(index.find_type("myProg.__THIS").is_none());
6014+
60176015
// TODO: #THIS: should we still have the annotations?
6018-
assert_type_and_hint!(&annotations, &index, &statement_1.left, "INT", None);
6019-
assert_type_and_hint!(&annotations, &index, &statement_2.right, "INT", Some("INT"));
6016+
// Yes, this is the correct since it's the AST which is the result of the parser.
60206017
let AstStatement::ReferenceExpr(ReferenceExpr { base: Some(deref), .. }) = statement_1.left.get_stmt()
60216018
else {
60226019
unreachable!();
60236020
};
60246021
let AstStatement::ReferenceExpr(ReferenceExpr { base: Some(this), .. }) = deref.get_stmt() else {
60256022
unreachable!();
60266023
};
6027-
assert_type_and_hint!(&annotations, &index, this, "fb.__THIS", None);
6024+
assert!(annotations.get(this).is_none());
60286025
}
60296026

60306027
#[test]
@@ -6070,5 +6067,66 @@ fn is_this_in_methods_of_function_blocks() {
60706067
unreachable!();
60716068
};
60726069
assert_type_and_hint!(&annotations, &index, this, "fb.__THIS", None);
6073-
assert_eq!(1, 2);
6070+
// assert_eq!(1, 2);
6071+
}
6072+
6073+
#[test]
6074+
fn just_this() {
6075+
let id_provider = IdProvider::default();
6076+
let (unit, mut index) = index_with_ids(
6077+
"
6078+
FUNCTION_BLOCK fb
6079+
this;
6080+
END_FUNCTION_BLOCK
6081+
",
6082+
id_provider.clone(),
6083+
);
6084+
6085+
let annotations = annotate_with_ids(&unit, &mut index, id_provider);
6086+
let statement = &unit.implementations[0].statements[0];
6087+
assert!(index.find_type("fb.__THIS").is_some());
6088+
assert_type_and_hint!(&annotations, &index, statement, "fb.__THIS", None);
6089+
}
6090+
6091+
#[test]
6092+
fn this_assignment() {
6093+
let id_provider = IdProvider::default();
6094+
let (unit, mut index) = index_with_ids(
6095+
"
6096+
FUNCTION_BLOCK fb
6097+
VAR
6098+
x : REF_TO fb;
6099+
END_VAR
6100+
x := this;
6101+
END_FUNCTION_BLOCK
6102+
",
6103+
id_provider.clone(),
6104+
);
6105+
6106+
let annotations = annotate_with_ids(&unit, &mut index, id_provider);
6107+
let statement = &unit.implementations[0].statements[0];
6108+
dbg!(&statement);
6109+
assert!(index.find_type("fb.__THIS").is_some());
6110+
assert_type_and_hint!(&annotations, &index, statement, "fb.__THIS", None);
6111+
}
6112+
6113+
#[test]
6114+
fn this_call() {
6115+
let id_provider = IdProvider::default();
6116+
let (unit, mut index) = index_with_ids(
6117+
"
6118+
FUNCTION_BLOCK fb
6119+
VAR
6120+
END_VAR
6121+
this^();
6122+
END_FUNCTION_BLOCK
6123+
",
6124+
id_provider.clone(),
6125+
);
6126+
6127+
let annotations = annotate_with_ids(&unit, &mut index, id_provider);
6128+
let statement = &unit.implementations[0].statements[0];
6129+
dbg!(&statement);
6130+
assert!(index.find_type("fb.__THIS").is_some());
6131+
assert_type_and_hint!(&annotations, &index, statement, "fb.__THIS", None);
60746132
}

0 commit comments

Comments
 (0)