Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bcf1489
fix: build script for macOS development
volsa Jul 5, 2025
dc4097c
test: Integration tests
volsa Aug 1, 2025
a0d3bf1
chore: Add Makefile
volsa Aug 1, 2025
3f7551c
resolver: Annotate function pointers
volsa Aug 1, 2025
7d2d504
codegen: Index function types
volsa Aug 1, 2025
af3f440
resolver: Annotate named arguments in function pointer call
volsa Aug 2, 2025
892ce11
resolver: Register dependencies to parent POUs
volsa Aug 2, 2025
77827dc
codegen: Generate function pointer calls
volsa Aug 2, 2025
d36784c
resolver: Fix type-hint annotation of function pointer arguments
volsa Aug 2, 2025
dc9efe7
chore: clippy
volsa Aug 2, 2025
1b5843b
codegen: Convert logging of module IR generation from debug to trace …
volsa Aug 2, 2025
0f33daa
test: Fix remaining tests
volsa Aug 3, 2025
58c2a1e
test: Add test using `THIS^`
volsa Aug 3, 2025
2647f98
fix: annotate whole call statement
volsa Aug 13, 2025
cd6dcc0
fix: Function pointer to function block body
volsa Aug 21, 2025
c8fd17d
vtable: Generate struct definition and global instances
volsa Aug 3, 2025
23ffab7
test: fix failing tests introduced with previous commit
volsa Aug 3, 2025
d9d58f8
test: add some integration tests
volsa Aug 3, 2025
b23232d
feat: Desugaring of polymorphic method calls
volsa Aug 3, 2025
ec0b5e3
fix: Initialize __vtable member field
volsa Aug 14, 2025
27a06a5
chore: Fix rebase
volsa Aug 26, 2025
213376f
fix: Polymorphic function block calls
volsa Aug 26, 2025
f84e98f
feat: Support REF_TO and REFERENCE TO
volsa Aug 27, 2025
7b5c6f5
chore: merge master
volsa Aug 30, 2025
f08c2db
test: Fix incorrect code in unit test
volsa Aug 30, 2025
68cdbf7
refactor: self-review
volsa Aug 30, 2025
44a4401
test: Add function block body method to external C file
volsa Sep 2, 2025
a8533ec
docs: Mark rustdoc codeblocks as text
volsa Sep 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
literals::{AstLiteral, StringValue},
pre_processor,
provider::IdProvider,
ser::AstSerializer,
};

use plc_source::source_location::*;
Expand Down Expand Up @@ -395,6 +396,14 @@ impl PouType {
pub fn is_stateful(&self) -> bool {
matches!(self, PouType::FunctionBlock | PouType::Program | PouType::Class)
}

pub fn is_class(&self) -> bool {
matches!(self, PouType::Class)
}

pub fn is_function_block(&self) -> bool {
matches!(self, PouType::FunctionBlock)
}
}

#[derive(Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -504,6 +513,10 @@ pub struct VariableBlock {
}

impl VariableBlock {
pub fn global() -> Self {
VariableBlock::default().with_block_type(VariableBlockType::Global)
}

pub fn with_block_type(mut self, block_type: VariableBlockType) -> Self {
self.kind = block_type;
self
Expand Down Expand Up @@ -1306,6 +1319,10 @@ impl AstNode {
matches!(node.get_stmt_peeled(), AstStatement::Super(Some(_)))
}

pub fn is_super_or_super_deref(&self) -> bool {
self.is_super() || self.is_super_deref()
}

pub fn has_super_metadata(&self) -> bool {
self.get_metadata()
.or_else(|| self.get_identifier().and_then(|it| it.get_metadata()))
Expand Down Expand Up @@ -1412,6 +1429,30 @@ impl AstNode {
AstNode { metadata: Some(metadata), ..self }
}

pub fn is_deref(&self) -> bool {
matches!(
self,
AstNode {
stmt: AstStatement::ReferenceExpr(ReferenceExpr { access: ReferenceAccess::Deref, .. }),
..
}
)
}

pub fn get_call_operator(&self) -> Option<&AstNode> {
match &self.stmt {
AstStatement::CallStatement(CallStatement { operator, .. }) => Some(operator),
_ => None,
}
}

pub fn get_ref_expr_mut(&mut self) -> Option<&mut ReferenceExpr> {
match &mut self.stmt {
AstStatement::ReferenceExpr(expr) => Some(expr),
_ => None,
}
}

pub fn get_deref_expr(&self) -> Option<&ReferenceExpr> {
match &self.stmt {
AstStatement::ReferenceExpr(expr) => match expr {
Expand All @@ -1421,6 +1462,24 @@ impl AstNode {
_ => None,
}
}

pub fn get_base(&self) -> Option<&AstNode> {
match &self.stmt {
AstStatement::ReferenceExpr(ReferenceExpr { base: Some(base), .. }) => Some(base.as_ref()),
_ => None,
}
}

pub fn get_base_mut(&mut self) -> Option<&mut AstNode> {
match &mut self.stmt {
AstStatement::ReferenceExpr(ReferenceExpr { base: Some(base), .. }) => Some(base.as_mut()),
_ => None,
}
}

pub fn as_string(&self) -> String {
AstSerializer::format(self)
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -1451,9 +1510,17 @@ impl Display for Operator {
Operator::Multiplication => "*",
Operator::Division => "/",
Operator::Equal => "=",
Operator::NotEqual => "<>",
Operator::Modulo => "MOD",
Operator::Less => "<",
Operator::Greater => ">",
Operator::LessOrEqual => "<=",
Operator::GreaterOrEqual => ">=",
Operator::Not => "NOT",
Operator::And => "AND",
Operator::Or => "OR",
Operator::Xor => "XOR",
Operator::Exponentiation => "**",
_ => unimplemented!(),
};
f.write_str(symbol)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/plc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ pub mod literals;
pub mod mut_visitor;
mod pre_processor;
pub mod provider;
pub mod ser;
pub mod visitor;
18 changes: 8 additions & 10 deletions compiler/plc_ast/src/pre_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ fn process_global_variables(unit: &mut CompilationUnit, id_provider: &mut IdProv
}

fn process_var_config_variables(unit: &mut CompilationUnit) {
let block = get_internal_global_block(unit);
let variables = unit.var_config.iter().filter_map(|ConfigVariable { data_type, address, .. }| {
let AstStatement::HardwareAccess(hardware) = &address.stmt else {
unreachable!("Must be parsed as hardware access")
Expand All @@ -206,10 +205,12 @@ fn process_var_config_variables(unit: &mut CompilationUnit) {
return None;
}

// Check if the mangled variable already exists in any of the global variable blocks
// XXX: Not a fan of this, we should fix the underlying issue with variable block creation here...
let name = hardware.get_mangled_variable_name();
if block.is_some_and(|it| it.variables.iter().any(|v| v.name == name)) {
return None;
};
if find_mangled_variable(unit, &name) {
return None; // Already exists, skip
}

Some(Variable {
name,
Expand All @@ -220,7 +221,7 @@ fn process_var_config_variables(unit: &mut CompilationUnit) {
})
});

update_generated_globals(unit, variables.collect())
update_generated_globals(unit, variables.collect());
}

fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Variable>) {
Expand All @@ -242,11 +243,8 @@ fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Var
unit.global_vars.push(block);
}

fn get_internal_global_block(unit: &CompilationUnit) -> Option<&VariableBlock> {
unit.global_vars
.iter()
.position(|block| block.kind == VariableBlockType::Global && block.location.is_builtin_internal())
.and_then(|index| unit.global_vars.get(index))
fn find_mangled_variable(unit: &CompilationUnit, name: &str) -> bool {
unit.global_vars.iter().flat_map(|block| &block.variables).any(|var| var.name == name)
}

fn build_enum_initializer(
Expand Down
Loading