Skip to content

Commit

Permalink
feat: add method to register default participants with pipeline (#1392)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhasel authored Jan 24, 2025
1 parent 4ed2778 commit 89520b9
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 51 deletions.
9 changes: 4 additions & 5 deletions compiler/plc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
use anyhow::{anyhow, Result};
use pipelines::{
participant::{CodegenParticipant, InitParticipant},
AnnotatedProject, BuildPipeline, GeneratedProject, Pipeline,
participant::CodegenParticipant, AnnotatedProject, BuildPipeline, GeneratedProject, Pipeline,
};
use std::{
ffi::OsStr,
Expand Down Expand Up @@ -149,6 +148,7 @@ pub fn compile<T: AsRef<str> + AsRef<OsStr> + Debug>(args: &[T]) -> Result<()> {
//Parse the arguments
let mut pipeline = BuildPipeline::new(args)?;
//register participants
pipeline.register_default_participants();
let target = pipeline.compile_parameters.as_ref().and_then(|it| it.target.clone()).unwrap_or_default();
let codegen_participant = CodegenParticipant {
compile_options: pipeline.get_compile_options().unwrap(),
Expand All @@ -163,9 +163,7 @@ pub fn compile<T: AsRef<str> + AsRef<OsStr> + Debug>(args: &[T]) -> Result<()> {
libraries: pipeline.project.get_libraries().to_vec(),
};
pipeline.register_participant(Box::new(codegen_participant));
let init_participant =
InitParticipant::new(&pipeline.project.get_init_symbol_name(), pipeline.context.provider());
pipeline.register_mut_participant(Box::new(init_participant));

let format = pipeline.compile_parameters.as_ref().map(|it| it.error_format).unwrap_or_default();

pipeline.run().map_err(|err| {
Expand Down Expand Up @@ -198,6 +196,7 @@ pub fn parse_and_annotate<T: SourceContainer + Clone>(
mutable_participants: Vec::default(),
participants: Vec::default(),
};
pipeline.register_default_participants();
let project = pipeline.parse()?;
let project = pipeline.index(project)?;
let project = pipeline.annotate(project)?;
Expand Down
41 changes: 28 additions & 13 deletions compiler/plc_driver/src/pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,16 @@ impl BuildPipeline<PathBuf> {
let compile_parameters = CompileParameters::parse(args)?;
compile_parameters.try_into()
}
}

impl<T: SourceContainer> BuildPipeline<T> {
pub fn register_mut_participant(&mut self, participant: Box<dyn PipelineParticipantMut>) {
self.mutable_participants.push(participant)
}

pub fn register_participant(&mut self, participant: Box<dyn PipelineParticipant>) {
self.participants.push(participant)
}
}

impl<T: SourceContainer> BuildPipeline<T> {
pub fn get_compile_options(&self) -> Option<CompileOptions> {
self.compile_parameters.as_ref().map(|params| {
let location = &self.project.get_location().map(|it| it.to_path_buf());
Expand Down Expand Up @@ -245,6 +244,16 @@ impl<T: SourceContainer> BuildPipeline<T> {
log::info!("{err}")
}
}

/// Register all default participants (excluding codegen/linking)
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));
}
}

impl<T: SourceContainer> Pipeline for BuildPipeline<T> {
Expand Down Expand Up @@ -275,6 +284,7 @@ impl<T: SourceContainer> Pipeline for BuildPipeline<T> {
let annotated_project = self.annotate(indexed_project)?;
//TODO : this is post lowering, we might want to control this
if let Some(CompileParameters { output_ast: true, .. }) = self.compile_parameters {
println!("{:#?}", annotated_project.units);
return Ok(());
}

Expand Down Expand Up @@ -310,27 +320,31 @@ impl<T: SourceContainer> Pipeline for BuildPipeline<T> {
self.participants.iter().for_each(|p| {
p.pre_index(&project);
});
let project = self.mutable_participants.iter().fold(project, |project, p| p.pre_index(project));
let project = self.mutable_participants.iter_mut().fold(project, |project, p| p.pre_index(project));
let indexed_project = project.index(self.context.provider());
self.participants.iter().for_each(|p| {
p.post_index(&indexed_project);
});
let indexed_project =
self.mutable_participants.iter().fold(indexed_project, |project, p| p.post_index(project));
Ok(indexed_project)
let project =
self.mutable_participants.iter_mut().fold(indexed_project, |project, p| p.post_index(project));

Ok(project)
}

fn annotate(&mut self, project: IndexedProject) -> Result<AnnotatedProject, Diagnostic> {
self.participants.iter().for_each(|p| {
p.pre_annotate(&project);
});
let project = self.mutable_participants.iter().fold(project, |project, p| p.pre_annotate(project));
let project =
self.mutable_participants.iter_mut().fold(project, |project, p| p.pre_annotate(project));
let annotated_project = project.annotate(self.context.provider());
self.participants.iter().for_each(|p| {
p.post_annotate(&annotated_project);
});
let annotated_project =
self.mutable_participants.iter().fold(annotated_project, |project, p| p.post_annotate(project));
let annotated_project = self
.mutable_participants
.iter_mut()
.fold(annotated_project, |project, p| p.post_annotate(project));
Ok(annotated_project)
}

Expand All @@ -352,7 +366,7 @@ impl<T: SourceContainer> Pipeline for BuildPipeline<T> {
project
.generate_single_module(&context, &compile_options)?
.map(|module| {
self.participants.iter().try_fold((), |_, participant| participant.generate(&module))
self.participants.iter_mut().try_fold((), |_, participant| participant.generate(&module))
})
.unwrap_or(Ok(()))?;
} else {
Expand Down Expand Up @@ -513,8 +527,9 @@ impl ParsedProject {
let builtins = plc::builtins::parse_built_ins(id_provider);
global_index.import(indexer::index(&builtins));

let (full_index, unresolvables) = plc::resolver::const_evaluator::evaluate_constants(global_index);
IndexedProject { project: ParsedProject { units }, index: full_index, unresolvables }
//TODO: evaluate constants should probably be a participant
let (index, unresolvables) = plc::resolver::const_evaluator::evaluate_constants(global_index);
IndexedProject { project: ParsedProject { units }, index, unresolvables }
}
}

Expand Down
26 changes: 5 additions & 21 deletions compiler/plc_driver/src/pipelines/participant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ pub trait PipelineParticipant: Sync + Send {
pub trait PipelineParticipantMut {
/// Implement this to access the project before it gets indexed
/// This happens directly after parsing
fn pre_index(&self, parsed_project: ParsedProject) -> ParsedProject {
fn pre_index(&mut self, parsed_project: ParsedProject) -> ParsedProject {
parsed_project
}
/// Implement this to access the project after it got indexed
/// This happens directly after the index returns
fn post_index(&self, indexed_project: IndexedProject) -> IndexedProject {
fn post_index(&mut self, indexed_project: IndexedProject) -> IndexedProject {
indexed_project
}
/// Implement this to access the project before it gets annotated
/// This happens directly after the constants are evaluated
fn pre_annotate(&self, indexed_project: IndexedProject) -> IndexedProject {
fn pre_annotate(&mut self, indexed_project: IndexedProject) -> IndexedProject {
indexed_project
}
/// Implement this to access the project after it got annotated
/// This happens directly after annotations
fn post_annotate(&self, annotated_project: AnnotatedProject) -> AnnotatedProject {
fn post_annotate(&mut self, annotated_project: AnnotatedProject) -> AnnotatedProject {
annotated_project
}
}
Expand Down Expand Up @@ -204,22 +204,6 @@ impl<T: SourceContainer + Send> PipelineParticipant for CodegenParticipant<T> {
}
}

pub struct LoweringParticipant;

impl PipelineParticipantMut for LoweringParticipant {
fn pre_index(&self, parsed_project: ParsedProject) -> ParsedProject {
parsed_project
}

fn post_index(&self, indexed_project: IndexedProject) -> IndexedProject {
indexed_project
}

fn post_annotate(&self, annotated_project: AnnotatedProject) -> AnnotatedProject {
annotated_project
}
}

pub struct InitParticipant {
symbol_name: String,
id_provider: IdProvider,
Expand All @@ -232,7 +216,7 @@ impl InitParticipant {
}

impl PipelineParticipantMut for InitParticipant {
fn pre_annotate(&self, indexed_project: IndexedProject) -> IndexedProject {
fn pre_annotate(&mut self, indexed_project: IndexedProject) -> IndexedProject {
indexed_project.extend_with_init_units(&self.symbol_name, self.id_provider.clone())
}
}
35 changes: 25 additions & 10 deletions compiler/plc_driver/src/runner.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{pipelines::ParsedProject, CompileOptions};
use crate::{
pipelines::{BuildPipeline, Pipeline},
CompileOptions,
};

use plc::codegen::{CodegenContext, GeneratedModule};
use plc_diagnostics::diagnostician::Diagnostician;
Expand All @@ -23,23 +26,34 @@ impl Default for MainType {
/// Sources must be `Compilable`, default implementations include `String` and `&str`
/// An implementation is also provided for `Vec<SourceContainer>`
///
pub fn compile<T: Compilable>(context: &CodegenContext, source: T) -> GeneratedModule<'_> {
pub fn compile<T: Compilable>(codegen_context: &CodegenContext, source: T) -> GeneratedModule<'_> {
let source = source.containers();
let project = Project::new("TestProject".to_string()).with_sources(source);
let ctxt = GlobalContext::new().with_source(project.get_sources(), None).unwrap();
let mut diagnostician = Diagnostician::null_diagnostician();
let parsed_project = ParsedProject::parse(&ctxt, &project, &mut diagnostician).unwrap();
let indexed_project = parsed_project
.index(ctxt.provider())
.extend_with_init_units(&project.get_init_symbol_name(), ctxt.provider());
let annotated_project = indexed_project.annotate(ctxt.provider());
let context = GlobalContext::new().with_source(project.get_sources(), None).unwrap();
let diagnostician = Diagnostician::null_diagnostician();
let mut pipeline = BuildPipeline {
context,
project,
diagnostician,
compile_parameters: None,
linker: plc::linker::LinkerType::Internal,
mutable_participants: Default::default(),
participants: Default::default(),
};

pipeline.register_default_participants();

let project = pipeline.parse().unwrap();
let project = pipeline.index(project).unwrap();
let project = pipeline.annotate(project).unwrap();

let compile_options = CompileOptions {
optimization: plc::OptimizationLevel::None,
debug_level: plc::DebugLevel::None,
..Default::default()
};

match annotated_project.generate_single_module(context, &compile_options) {
match project.generate_single_module(codegen_context, &compile_options) {
Ok(res) => res.unwrap(),
Err(e) => panic!("{e}"),
}
Expand All @@ -51,6 +65,7 @@ pub fn compile<T: Compilable>(context: &CodegenContext, source: T) -> GeneratedM
pub fn compile_and_run<T, U, S: Compilable>(source: S, params: &mut T) -> U {
let context: CodegenContext = CodegenContext::create();
let module = compile(&context, source);
module.print_to_stderr();
module.run::<T, U>("main", params)
}

Expand Down
1 change: 1 addition & 0 deletions compiler/plc_driver/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ where
optimization: plc::OptimizationLevel::None,
..Default::default()
};
//TODO: participants
pipelines::ParsedProject::parse(&ctxt, &project, &mut diagnostician)?
//Index
.index(ctxt.provider())
Expand Down
4 changes: 2 additions & 2 deletions compiler/plc_source/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum SourceType {

/// SourceContainers offer source-code to be compiled via the load_source function.
/// Furthermore it offers a location-String used when reporting diagnostics.
pub trait SourceContainer: Sync {
pub trait SourceContainer: Sync + Send {
/// loads and returns the SourceEntry that contains the SourceCode and the path it was loaded from
fn load_source(&self, encoding: Option<&'static Encoding>) -> Result<SourceCode, String>;
/// returns the location of this source-container. Used when reporting diagnostics.
Expand Down Expand Up @@ -88,7 +88,7 @@ impl SourceCodeFactory for &str {
}
}

impl<T: AsRef<Path> + Sync> SourceContainer for T {
impl<T: AsRef<Path> + Sync + Send> SourceContainer for T {
fn load_source(&self, encoding: Option<&'static Encoding>) -> Result<SourceCode, String> {
let source_type = self.get_type();
if matches!(source_type, SourceType::Text | SourceType::Xml) {
Expand Down
6 changes: 6 additions & 0 deletions compiler/plc_source/src/source_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ impl Display for SourceLocation {
}
}

impl Default for SourceLocation {
fn default() -> Self {
Self::internal()
}
}

impl SourceLocation {
/// Constructs an undefined SourceRange with a 0..0 range and no filename
pub fn undefined() -> SourceLocation {
Expand Down

0 comments on commit 89520b9

Please sign in to comment.