Skip to content

Commit

Permalink
feat: add lowering stage to add base-class in new variable-block in pou
Browse files Browse the repository at this point in the history
  • Loading branch information
mhasel committed Jan 20, 2025
1 parent b528f0d commit 83ab13b
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 11 deletions.
2 changes: 2 additions & 0 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ pub enum VariableBlockType {
Global,
InOut,
External,
Base,
}

impl Display for VariableBlockType {
Expand All @@ -400,6 +401,7 @@ impl Display for VariableBlockType {
VariableBlockType::Global => write!(f, "Global"),
VariableBlockType::InOut => write!(f, "InOut"),
VariableBlockType::External => write!(f, "External"),
VariableBlockType::Base => write!(f, "Base"),
}
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/plc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use anyhow::{anyhow, Result};
use pipelines::{
participant::CodegenParticipant, AnnotatedProject, BuildPipeline, GeneratedProject, Pipeline,
};
use plc_lowering::inheritance::InheritanceLowerer;
use std::{
ffi::OsStr,
fmt::{Debug, Display},
Expand Down
17 changes: 13 additions & 4 deletions compiler/plc_driver/src/pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use plc_diagnostics::{
diagnostics::{Diagnostic, Severity},
};
use plc_index::GlobalContext;
use plc_lowering::inheritance::InheritanceLowerer;
use project::{
object::Object,
project::{LibraryInformation, Project},
Expand Down Expand Up @@ -249,10 +250,18 @@ impl<T: SourceContainer> BuildPipeline<T> {
pub fn register_default_participants(&mut self) {
use participant::InitParticipant;
// XXX: should we use a static array of participants?

let init_participant =
InitParticipant::new(&self.project.get_init_symbol_name(), self.context.provider());
self.register_mut_participant(Box::new(init_participant));
let participants: Vec<Box<dyn PipelineParticipant>> = vec![];
let mut_participants: Vec<Box<dyn PipelineParticipantMut>> = vec![
Box::new(InitParticipant::new(&self.project.get_init_symbol_name(), self.context.provider())),
Box::new(InheritanceLowerer),
];

for participant in participants {
self.register_participant(participant)
}
for participant in mut_participants {
self.register_mut_participant(participant)
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions compiler/plc_driver/src/pipelines/participant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,13 @@ impl PipelineParticipantMut for InitParticipant {
}

impl PipelineParticipantMut for InheritanceLowerer {
fn pre_index(&self, parsed_project: ParsedProject) -> ParsedProject {
todo!()
fn pre_index(&mut self, parsed_project: ParsedProject) -> ParsedProject {
let ParsedProject { mut units } = parsed_project;
units.iter_mut().for_each(|unit| self.visit_unit(unit));
ParsedProject { units }
}

fn post_annotate(&self, annotated_project: AnnotatedProject) -> AnnotatedProject {
todo!()
fn post_annotate(&mut self, _annotated_project: AnnotatedProject) -> AnnotatedProject {
_annotated_project
}
}
13 changes: 13 additions & 0 deletions compiler/plc_lowering/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "plc_lowering"
version = "0.1.0"
edition = "2021"

[dependencies]
plc = { path = "../..", package = "rusty" }
plc_ast = { path = "../plc_ast" }
plc_source = { path = "../plc_source" }

[dev-dependencies]
insta.workspace = true # TODO: remove individual insta deps from crates
plc_driver = { path = "../plc_driver" }
269 changes: 269 additions & 0 deletions compiler/plc_lowering/src/inheritance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
use plc_ast::{
ast::{
CompilationUnit, DataTypeDeclaration, LinkageType, Pou, PouType, Variable, VariableBlock,
VariableBlockType,
},
mut_visitor::AstVisitorMut,
};
use plc_source::source_location::SourceLocation;

pub struct InheritanceLowerer;

impl InheritanceLowerer {
pub fn visit_unit(&mut self, unit: &mut CompilationUnit) {
self.visit_compilation_unit(unit);
}
}

impl AstVisitorMut for InheritanceLowerer {
fn visit_pou(&mut self, pou: &mut Pou) {
if !matches!(pou.kind, PouType::FunctionBlock | PouType::Class) {
return;
}

let Some(base_name) = pou.super_class.as_ref() else {
return;
};

let base_var = Variable {
name: "__BASE".to_string(),
data_type_declaration: DataTypeDeclaration::DataTypeReference {
referenced_type: base_name.into(),
location: SourceLocation::internal(),
},
location: SourceLocation::internal(),
initializer: None,
address: None,
};

let block = VariableBlock {
variables: vec![base_var],
variable_block_type: VariableBlockType::Base,
linkage: LinkageType::Internal,
location: SourceLocation::internal(),
..Default::default()
};

pou.variable_blocks.insert(0, block);
}
}

#[cfg(test)]
mod tests {
use insta::assert_debug_snapshot;
use plc_driver::parse_and_annotate;
use plc_source::SourceCode;

#[test]
fn after_parsing_a_function_block_contains_ref_to_its_base() {
let src: SourceCode = "
FUNCTION_BLOCK foo
END_FUNCTION_BLOCK
FUNCTION_BLOCK bar EXTENDS foo
END_FUNCTION_BLOCK
"
.into();

let (_, project) = parse_and_annotate("test", vec![src]).unwrap();
let unit = &project.units[0].get_unit().units[1];
assert_debug_snapshot!(unit, @r#"
POU {
name: "bar",
variable_blocks: [
VariableBlock {
variables: [
Variable {
name: "__BASE",
data_type: DataTypeReference {
referenced_type: "foo",
},
},
],
variable_block_type: Base,
},
],
pou_type: FunctionBlock,
return_type: None,
interfaces: [],
}
"#);
}

#[test]
fn write_to_parent_variable_qualified_access() {
let src: SourceCode = "
FUNCTION_BLOCK fb
VAR
x : INT;
y : INT;
END_VAR
END_FUNCTION_BLOCK
FUNCTION_BLOCK fb2 EXTENDS fb
END_FUNCTION_BLOCK
FUNCTION_BLOCK foo
VAR
myFb : fb2;
END_VAR
myFb.x := 1;
END_FUNCTION_BLOCK
"
.into();

let (_, project) = parse_and_annotate("test", vec![src]).unwrap();
let unit = &project.units[0].get_unit().implementations[2];
assert_debug_snapshot!(unit, @r#"
Implementation {
name: "foo",
type_name: "foo",
linkage: Internal,
pou_type: FunctionBlock,
statements: [
Assignment {
left: ReferenceExpr {
kind: Member(
Identifier {
name: "x",
},
),
base: Some(
ReferenceExpr {
kind: Member(
Identifier {
name: "myFb",
},
),
base: Some(
ReferenceExpr {
kind: Member(
Identifier {
name: "__BASE",
},
),
base: None,
},
),
},
),
},
right: LiteralInteger {
value: 1,
},
},
],
location: SourceLocation {
span: Range(
TextLocation {
line: 15,
column: 16,
offset: 347,
}..TextLocation {
line: 15,
column: 28,
offset: 359,
},
),
},
name_location: SourceLocation {
span: Range(
TextLocation {
line: 11,
column: 27,
offset: 262,
}..TextLocation {
line: 11,
column: 30,
offset: 265,
},
),
},
overriding: false,
generic: false,
access: None,
}
"#);
}

#[test]
fn write_to_parent_variable_in_instance() {
let src: SourceCode = r#"
FUNCTION_BLOCK foo
VAR
s : STRING;
END_VAR
END_FUNCTION_BLOCK
FUNCTION_BLOCK bar EXTENDS foo
s := 'world';
END_FUNCTION_BLOCK
"#
.into();

let (_, project) = parse_and_annotate("test", vec![src]).unwrap();
let unit = &project.units[0].get_unit().implementations[1];
assert_debug_snapshot!(unit, @r#"
Implementation {
name: "bar",
type_name: "bar",
linkage: Internal,
pou_type: FunctionBlock,
statements: [
Assignment {
left: ReferenceExpr {
kind: Member(
Identifier {
name: "s",
},
),
base: Some(
ReferenceExpr {
kind: Member(
Identifier {
name: "__BASE",
},
),
base: None,
},
),
},
right: LiteralString {
value: "world",
is_wide: false,
},
},
],
location: SourceLocation {
span: Range(
TextLocation {
line: 8,
column: 16,
offset: 189,
}..TextLocation {
line: 8,
column: 29,
offset: 202,
},
),
},
name_location: SourceLocation {
span: Range(
TextLocation {
line: 7,
column: 27,
offset: 156,
}..TextLocation {
line: 7,
column: 30,
offset: 159,
},
),
},
overriding: false,
generic: false,
access: None,
}
"#);
}
}
2 changes: 2 additions & 0 deletions compiler/plc_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// pub use plc::lowering::*;
pub mod inheritance;
2 changes: 1 addition & 1 deletion src/codegen/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ mod generics_test;
mod initialization_test;
mod multifile_codegen_tests;
mod online_change_tests;
mod oop_tests;
mod parameters_tests;
mod statement_codegen_test;
mod string_tests;
#[cfg(feature = "verify")]
mod switch_case_tests;
mod typesystem_test;
mod vla_tests;
mod oop_tests;
Loading

0 comments on commit 83ab13b

Please sign in to comment.