Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add method to register default participants with pipeline #1392

Merged
merged 3 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading