Skip to content

Commit

Permalink
refactor(indexer): indexing uses SymbolIndexer instead of visitor.rs
Browse files Browse the repository at this point in the history
The indexer utilizes the visitor-trait to visit nodes that contain
symbols. It delegates the concrete work to smaller, specialized
indexer-implementations in src/index/indexer
  • Loading branch information
riederm committed Jun 13, 2024
1 parent 5174c2c commit 867afc3
Show file tree
Hide file tree
Showing 14 changed files with 963 additions and 833 deletions.
5 changes: 5 additions & 0 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,11 @@ impl AstFactory {
pub fn create_label_statement(name: String, location: SourceLocation, id: AstId) -> AstNode {
AstNode { stmt: AstStatement::LabelStatement(LabelStatement { name }), location, id }
}

pub fn create_plus_one_expression(value: AstNode, location: SourceLocation, id: AstId) -> AstNode {
let one = AstFactory::create_literal(AstLiteral::Integer(1), location.clone(), id);
AstFactory::create_binary_expression(value, Operator::Plus, one, id)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct EmptyStatement {}
Expand Down
4 changes: 2 additions & 2 deletions compiler/plc_driver/src/pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<T: SourceContainer + Sync> ParsedProject<T> {
//Preprocess
pre_process(&mut unit, id_provider.clone());
//import to index
let index = plc::index::visitor::visit(&unit);
let index = plc::index::indexer::index(&unit);

(index, unit)
})
Expand All @@ -126,7 +126,7 @@ impl<T: SourceContainer + Sync> ParsedProject<T> {
}
// import builtin functions
let builtins = plc::builtins::parse_built_ins(id_provider);
global_index.import(plc::index::visitor::visit(&builtins));
global_index.import(plc::index::indexer::index(&builtins));

IndexedProject { project: ParsedProject { project: self.project, units }, index: global_index }
}
Expand Down
4 changes: 2 additions & 2 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ use self::{
};

pub mod const_expressions;
pub mod indexer;
mod instance_iterator;
pub mod symbol;
pub mod visitor;

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -97,7 +97,7 @@ pub struct HardwareBinding {
}

impl HardwareBinding {
fn from_statement(index: &mut Index, it: &AstNode, scope: Option<String>) -> Option<Self> {
pub fn from_statement(index: &mut Index, it: &AstNode, scope: Option<String>) -> Option<Self> {
if let AstStatement::HardwareAccess(data) = it.get_stmt() {
Some(HardwareBinding {
access: data.access,
Expand Down
61 changes: 61 additions & 0 deletions src/index/indexer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use global_var_indexer::VarGlobalIndexer;
use implementation_indexer::ImplementationIndexer;
use plc_ast::{
ast::{CompilationUnit, Implementation, VariableBlockType},
visitor::{AstVisitor, Walker},
};
use pou_indexer::PouIndexer;
use user_type_indexer::UserTypeIndexer;

use super::Index;

mod global_var_indexer;
mod implementation_indexer;
mod pou_indexer;
mod user_type_indexer;

/// Indexes all symbols found in the given Compiliation Unit
/// and returns the resulting Index
pub fn index(unit: &CompilationUnit) -> Index {
// let mut index = Index::default();
let mut indexer = SymbolIndexer::default();
unit.walk(&mut indexer);
indexer.index
}

/// Indexer that registers all symbols in the index
#[derive(Default)]
pub struct SymbolIndexer {
pub index: Index,
}

/// The SymbolIndexer is responsible for registering all delcared types and symbols in the index.
impl AstVisitor for SymbolIndexer {
/// Visits a VAR_GLOBAL VariableBlock and registers all variables as globals in the index
fn visit_variable_block(&mut self, block: &plc_ast::ast::VariableBlock) {
if block.variable_block_type == VariableBlockType::Global {
// let the global var indexer handle the global variables
let mut indexer = VarGlobalIndexer::new(block.constant, block.linkage, &mut self.index);
for var in &block.variables {
indexer.visit_variable(var);
}
}
}

/// Visits a user type declaration
/// Registers the user type in the index using the UserTypeIndexer
fn visit_user_type_declaration(&mut self, user_type: &plc_ast::ast::UserTypeDeclaration) {
UserTypeIndexer::new(&mut self.index, user_type).visit_user_type_declaration(user_type);
}

/// Visits a pou and registers all member variables in the index
/// Also registers the pou's struct type in the index
fn visit_pou(&mut self, pou: &plc_ast::ast::Pou) {
PouIndexer::new(&mut self.index).visit_pou(pou);
}

/// Visits an implementation and registers the implementation in the index
fn visit_implementation(&mut self, implementation: &Implementation) {
ImplementationIndexer::new(&mut self.index).index_implementation(implementation);
}
}
37 changes: 37 additions & 0 deletions src/index/indexer/global_var_indexer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use plc_ast::ast::LinkageType;

use crate::index::{HardwareBinding, Index, VariableIndexEntry};

pub struct VarGlobalIndexer<'i> {
constant: bool,
linkage: LinkageType,
index: &'i mut Index,
}

impl VarGlobalIndexer<'_> {
pub fn new(constant: bool, linkage: LinkageType, index: &mut Index) -> VarGlobalIndexer<'_> {
VarGlobalIndexer { constant, linkage, index }
}

pub fn visit_variable(&mut self, var: &plc_ast::ast::Variable) {
let target_type = var.data_type_declaration.get_name().unwrap_or_default();
let initializer = self.index.get_mut_const_expressions().maybe_add_constant_expression(
var.initializer.clone(),
target_type,
None,
);
let variable = VariableIndexEntry::create_global(
&var.name,
&var.name,
var.data_type_declaration.get_name().expect("named variable datatype"),
var.location.clone(),
)
.set_initial_value(initializer)
.set_constant(self.constant)
.set_linkage(self.linkage)
.set_hardware_binding(
var.address.as_ref().and_then(|it| HardwareBinding::from_statement(self.index, it, None)),
);
self.index.register_global_variable(&var.name, variable);
}
}
57 changes: 57 additions & 0 deletions src/index/indexer/implementation_indexer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use plc_ast::ast::{Implementation, PouType, TypeNature};

use crate::{
index::{Index, PouIndexEntry},
typesystem::{self, DataTypeInformation},
};

pub struct ImplementationIndexer<'i> {
index: &'i mut Index,
}

impl<'i> ImplementationIndexer<'i> {
pub fn new(index: &'i mut Index) -> Self {
Self { index }
}

pub fn index_implementation(&mut self, implementation: &Implementation) {
let pou_type = &implementation.pou_type;
let start_location = implementation
.statements
.first()
.map(|it| it.get_location())
.as_ref()
.or(Some(&implementation.location))
.cloned()
.unwrap();
self.index.register_implementation(
&implementation.name,
&implementation.type_name,
pou_type.get_optional_owner_class().as_ref(),
pou_type.into(),
implementation.generic,
start_location,
);
//if we are registing an action, also register a datatype for it
if pou_type == &PouType::Action {
let datatype = typesystem::DataType {
name: implementation.name.to_string(),
initial_value: None,
information: DataTypeInformation::Alias {
name: implementation.name.clone(),
referenced_type: implementation.type_name.clone(),
},
nature: TypeNature::Derived,
location: implementation.name_location.clone(),
};

self.index.register_pou(PouIndexEntry::create_action_entry(
implementation.name.as_str(),
implementation.type_name.as_str(),
implementation.linkage,
implementation.name_location.clone(),
));
self.index.register_pou_type(datatype);
}
}
}
Loading

0 comments on commit 867afc3

Please sign in to comment.