Skip to content

Commit

Permalink
properly annotate initializers
Browse files Browse the repository at this point in the history
  • Loading branch information
riederm committed Jun 18, 2024
1 parent 0474c52 commit 792efdf
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 60 deletions.
8 changes: 1 addition & 7 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1085,13 +1085,7 @@ impl Operator {
/// this means it can be applied bitwise to two operators
/// (e.g. `flags AND 16#0F`)
pub fn is_binary_operator(&self) -> bool {
matches!(
self,
Operator::And
| Operator::Or
| Operator::Xor
| Operator::Not
)
matches!(self, Operator::And | Operator::Or | Operator::Xor | Operator::Not)
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/plc_ast/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,8 @@ impl Walker for ReferenceExpr {
impl Walker for ReferenceAccess {
fn walk<V>(&self, visitor: &mut V)
where
V: AstVisitor {
V: AstVisitor,
{
match &self {
ReferenceAccess::Member(t) | ReferenceAccess::Index(t) | ReferenceAccess::Cast(t) => {
visitor.visit(t)
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ pub mod hardware_binding;
pub mod index;
pub mod lexer;
pub mod linker;
pub mod name_resolver;
pub mod output;
pub mod parser;
pub mod resolver;
pub mod name_resolver;
mod test_utils;

pub mod typesystem;
Expand Down
59 changes: 32 additions & 27 deletions src/name_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use plc_ast::{
ast::{
flatten_expression_list, Assignment, AstNode, AstStatement, DataType, ReferenceAccess, TypeNature,
},
literals::StringValue,
literals::{Array, AstLiteral, StringValue},
visitor::{AstVisitor, Walker},
};
use plc_source::source_location::SourceLocation;
Expand Down Expand Up @@ -282,7 +282,7 @@ impl AstVisitor for NameResolver<'_> {
}
(ReferenceAccess::Cast(target), Some(base)) => {
if let Some(true) =
self.annotations.get_type(stmt.base.as_ref().unwrap(), &self.index).map(|it| it.is_enum())
self.annotations.get_type(stmt.base.as_ref().unwrap(), self.index).map(|it| it.is_enum())
{
self.walk_with_scope(
target,
Expand All @@ -299,7 +299,7 @@ impl AstVisitor for NameResolver<'_> {
if let Some(DataTypeInformation::Pointer { inner_type_name, auto_deref: false, .. }) =
self.index.find_type(base).map(typesystem::DataType::get_type_information)
{
self.annotations.annotate(node, StatementAnnotation::data_type(&inner_type_name));
self.annotations.annotate(node, StatementAnnotation::data_type(inner_type_name));
}
}
(ReferenceAccess::Address, Some(_base)) => {
Expand Down Expand Up @@ -454,12 +454,27 @@ impl AstVisitor for NameResolver<'_> {
self.annotations.copy_annotation(inner, node)
}

fn visit_variable(&mut self, variable: &plc_ast::ast::Variable) {
variable.walk(self);

if let (Some(initializer), Some(variable_type)) =
(&variable.initializer, variable.data_type_declaration.get_name())
{
let mut initializer_annotator = InitializerAnnotator::new(
&self.index.get_intrinsic_type_by_name(variable_type).get_type_information(),
self.index,
&mut self.annotations,
);
initializer.walk(&mut initializer_annotator);
}
}

fn visit_user_type_declaration(&mut self, user_type: &plc_ast::ast::UserTypeDeclaration) {
self.visit_data_type(&user_type.data_type);

if let Some(type_name) = user_type.data_type.get_name() {
let mut initializer_annotator = InitializerAnnotator::new(
&self.index.get_intrinsic_type_by_name(type_name).get_type_information(),
self.index.get_intrinsic_type_by_name(type_name).get_type_information(),
&self.index,
&mut self.annotations,
);
Expand All @@ -486,7 +501,6 @@ impl AstVisitor for NameResolver<'_> {
}

//TODO find better place

/// adds a pointer to the given inner_type to the given index and return's its name
fn add_pointer_type(index: &mut Index, inner_type_name: String) -> String {
let new_type_name = internal_type_name("POINTER_TO_", inner_type_name.as_str());
Expand Down Expand Up @@ -526,29 +540,20 @@ impl<'i> InitializerAnnotator<'i> {
}

impl AstVisitor for InitializerAnnotator<'_> {

fn visit_literal(&mut self, stmt: &plc_ast::literals::AstLiteral, _node: &AstNode) {
match stmt {
plc_ast::literals::AstLiteral::Null => todo!(),
plc_ast::literals::AstLiteral::Integer(_) => todo!(),
plc_ast::literals::AstLiteral::Date(_) => todo!(),
plc_ast::literals::AstLiteral::DateAndTime(_) => todo!(),
plc_ast::literals::AstLiteral::TimeOfDay(_) => todo!(),
plc_ast::literals::AstLiteral::Time(_) => todo!(),
plc_ast::literals::AstLiteral::Real(_) => todo!(),
plc_ast::literals::AstLiteral::Bool(_) => todo!(),
plc_ast::literals::AstLiteral::String(_) => todo!(),
plc_ast::literals::AstLiteral::Array(members) => {
if let (DataTypeInformation::Array { inner_type_name, .. }, Some(inner_type)) =
(self.expected_type, self.index.find_effective_type(inner_type_name))
{

// for member in members.iter() {
// let mut annotator = InitializerAnnotator::new(inner_type, self.index, self.annotations);
// member.walk(&mut annotator);
// }
fn visit_literal(&mut self, stmt: &plc_ast::literals::AstLiteral, node: &AstNode) {
self.annotations.annotate_type_hint(node, StatementAnnotation::value(self.expected_type.get_name()));
if let (
AstLiteral::Array(Array { elements: Some(elements), .. }),
DataTypeInformation::Array { inner_type_name, .. },
) = (stmt, self.expected_type)
{
// hint the elements of an array
if let Some(inner_type) = self.index.find_effective_type_info(inner_type_name) {
for member in flatten_expression_list(elements) {
let mut annotator = InitializerAnnotator::new(inner_type, self.index, self.annotations);
member.walk(&mut annotator);
}
},
}
}
}
}
28 changes: 14 additions & 14 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//! records all resulting types associated with the statement's id.
use rustc_hash::{FxHashMap, FxHashSet};
use std::hash::Hash;
use type_hint_annotator::TypeHintAnnotator;
use std::{hash::Hash};

use plc_ast::{
ast::{
Expand All @@ -17,12 +17,12 @@ use plc_ast::{
},
control_statements::{AstControlStatement, ReturnStatement},
literals::{Array, AstLiteral, StringValue},
provider::IdProvider, visitor::Walker,
provider::IdProvider,
visitor::Walker,
};
use plc_source::source_location::SourceLocation;
use plc_util::convention::internal_type_name;

use crate::{index::{FxIndexMap, FxIndexSet}, name_resolver::NameResolver};
use crate::typesystem::VOID_INTERNAL_NAME;
use crate::{
builtins::{self, BuiltIn},
Expand All @@ -33,6 +33,10 @@ use crate::{
REAL_TYPE, TIME_OF_DAY_TYPE, TIME_TYPE, VOID_TYPE, WORD_TYPE,
},
};
use crate::{
index::{FxIndexMap, FxIndexSet},
name_resolver::NameResolver,
};

pub mod const_evaluator;
pub mod generics;
Expand Down Expand Up @@ -497,8 +501,7 @@ pub trait AnnotationMap {
fn get_hint(&self, s: &AstNode) -> Option<&StatementAnnotation>;

fn get_type_hint_or_type<'i>(&self, s: &AstNode, index: &'i Index) -> Option<&'i typesystem::DataType> {
self.get_hint(s).or_else(|| self.get(s))
.and_then(|s| self.get_type_for_annotation(index, s))
self.get_hint(s).or_else(|| self.get(s)).and_then(|s| self.get_type_for_annotation(index, s))
}

fn get_hidden_function_call(&self, s: &AstNode) -> Option<&AstNode>;
Expand All @@ -519,7 +522,7 @@ pub trait AnnotationMap {
self.get(s).and_then(|it| self.get_type_for_annotation(index, it))
}

fn get_type_name<'i>(&'i self, s: &AstNode) -> Option<&str> {
fn get_type_name(&self, s: &AstNode) -> Option<&str> {
self.get(s).and_then(|it| self.get_type_name_for_annotation(it))
}

Expand All @@ -539,10 +542,10 @@ pub trait AnnotationMap {
.get_hint(statement)
.or_else(|| self.get(statement))
.and_then(|it| self.get_type_name_for_annotation(it)),
StatementAnnotation::Program { qualified_name } =>{
StatementAnnotation::Program { qualified_name } => {
// only return the first segment (without a potential action part)
Some(&qualified_name[0..qualified_name.find(".").unwrap_or(qualified_name.len())])
} ,
Some(&qualified_name[0..qualified_name.find('.').unwrap_or(qualified_name.len())])
}
StatementAnnotation::Type { type_name } => Some(type_name),
StatementAnnotation::Function { .. } | StatementAnnotation::Label { .. } => None,
}
Expand Down Expand Up @@ -768,7 +771,6 @@ impl<'i> TypeAnnotator<'i> {
unit: &'i CompilationUnit,
id_provider: IdProvider,
) -> (AnnotationMapImpl, FxIndexSet<Dependency>, StringLiterals) {

let mut resolver = NameResolver::new(index);
unit.walk(&mut resolver);

Expand All @@ -777,8 +779,6 @@ impl<'i> TypeAnnotator<'i> {

return (type_hint_annotator.annotations, FxIndexSet::default(), resolver.strings);



let mut visitor = TypeAnnotator::new(index);
let ctx = &VisitorContext {
pou: None,
Expand Down Expand Up @@ -1815,7 +1815,8 @@ impl<'i> TypeAnnotator<'i> {

AstLiteral::String(StringValue { is_wide, value, .. }) => {
let string_type_name =
register_string_type(&mut self.annotation_map.new_index, *is_wide, value.len()).to_string();
register_string_type(&mut self.annotation_map.new_index, *is_wide, value.len())
.to_string();
self.annotate(statement, StatementAnnotation::value(string_type_name));

//collect literals so we can generate global constants later
Expand Down Expand Up @@ -1904,7 +1905,6 @@ pub fn register_string_type(index: &mut Index, is_wide: bool, len: usize) -> &st
});
}
index.find_type(new_type_name.as_str()).map(|d| d.get_name()).unwrap_or(VOID_TYPE)

}

/// adds a pointer to the given inner_type to the given index and return's its name
Expand Down
7 changes: 3 additions & 4 deletions src/resolver/tests/resolve_expressions_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ fn complex_expressions_resolves_types_for_literals_directly() {
// c
assert_type_and_hint!(&annotations, &index, c, INT_TYPE, Some(DINT_TYPE));
// (b + USINT#7)
assert_type_and_hint!(&annotations, &index, left, DINT_TYPE, Some(DINT_TYPE));
assert_type_and_hint!(&annotations, &index, left, DINT_TYPE, /* Same */ None);

let AstStatement::ParenExpression(left) = left.get_stmt() else { panic!() };
if let AstNode {
Expand Down Expand Up @@ -2388,7 +2388,6 @@ fn struct_members_initializers_type_hint_test() {

// WHEN this type is annotated
let annotations = annotate_with_ids(&unit, &mut index, id_provider);

// THEN the members's initializers have correct type-hints
if let DataType::StructType { variables, .. } = &unit.user_types[0].data_type {
let hints: Vec<&str> = variables
Expand All @@ -2397,11 +2396,11 @@ fn struct_members_initializers_type_hint_test() {
annotations
.get_type_hint(v.initializer.as_ref().unwrap(), &index)
.map(crate::typesystem::DataType::get_name)
.unwrap()
.unwrap_or_default()
})
.collect();

assert_eq!(hints, vec!["INT", "SINT", "BOOL", "REAL", "LREAL"]);
assert_eq!(hints, vec!["INT", "SINT", "BOOL", /* same as real type*/ "", "LREAL"]);
} else {
unreachable!()
}
Expand Down
10 changes: 6 additions & 4 deletions src/resolver/type_hint_annotator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use plc_ast::{ast::{AstStatement, ReferenceAccess, ReferenceExpr}, visitor::{AstVisitor, Walker}};
use plc_ast::{
ast::{AstStatement, ReferenceAccess, ReferenceExpr},
visitor::{AstVisitor, Walker},
};

use crate::index::Index;

Expand Down Expand Up @@ -52,11 +55,10 @@ impl AstVisitor for TypeHintAnnotator<'_> {

// a cast-statement on a literal should directly annotate the literal correctly (avoid casts)
if let ReferenceAccess::Cast(target) = &stmt.access {
if matches!(target.get_stmt(), AstStatement::Literal{..}) {
self.annotations.copy_annotation(node, &target);
if matches!(target.get_stmt(), AstStatement::Literal { .. }) {
self.annotations.copy_annotation(node, target);
self.annotations.clear_type_hint(&target);
}
}
}

}
2 changes: 1 addition & 1 deletion src/typesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl DataType {
(self.is_numerical() || self.is_bit()) && !self.is_bool()
}

pub fn is_bool(&self) -> bool{
pub fn is_bool(&self) -> bool {
self.information.is_bool()
}

Expand Down

0 comments on commit 792efdf

Please sign in to comment.