diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/models/AnalysisSnapshot.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/models/AnalysisSnapshot.java index 324f1a5b..3160e38e 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/models/AnalysisSnapshot.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/models/AnalysisSnapshot.java @@ -1,15 +1,15 @@ package p.studio.compiler.models; import p.studio.compiler.messages.BuildingIssue; -import p.studio.compiler.source.tables.FileTable; +import p.studio.compiler.source.tables.FileTableReader; import java.util.List; public record AnalysisSnapshot( List diagnostics, ResolvedWorkspace resolvedWorkspace, - FileTable fileTable, - IRBackend irBackend) { + FileTableReader fileTable, + IRBackendReader irBackend) { public AnalysisSnapshot { diagnostics = List.copyOf(diagnostics); } diff --git a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java index 273f7d25..4a2accbb 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/workspaces/BuilderPipelineService.java @@ -3,9 +3,9 @@ package p.studio.compiler.workspaces; import lombok.extern.slf4j.Slf4j; import p.studio.compiler.exceptions.BuildException; import p.studio.compiler.messages.BuildingIssue; -import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.models.AnalysisSnapshot; import p.studio.compiler.models.BuildResult; +import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.models.CompileResult; import p.studio.compiler.workspaces.stages.*; import p.studio.utilities.logs.LogAggregator; @@ -19,30 +19,45 @@ public class BuilderPipelineService { public final static BuilderPipelineService INSTANCE; static { - final var stages = List.of( + + final var analyses = List.of( new ResolveDepsPipelineStage(), new LoadSourcesPipelineStage(), - new FrontendPhasePipelineStage(), + new FrontendPhasePipelineStage() + ); + + final var compile = List.of( new LowerToIRVMPipelineStage(), new OptimizeIRVMPipelineStage(), new EmitBytecodePipelineStage(), new LinkBytecodePipelineStage(), - new VerifyBytecodePipelineStage(), + new VerifyBytecodePipelineStage() + ); + + final var build = List.of( new WriteBytecodeArtifactPipelineStage() ); - INSTANCE = new BuilderPipelineService(stages); + + INSTANCE = new BuilderPipelineService(analyses, compile, build); } - private final List stages; + private final List analyses; + private final List compile; + private final List build; - BuilderPipelineService(List stages) { - this.stages = stages; + BuilderPipelineService( + final List analyses, + final List compile, + final List build) { + this.analyses = analyses; + this.compile = compile; + this.build = build; } public AnalysisSnapshot analyze( final BuilderPipelineContext ctx, final LogAggregator logs) { - final var diagnostics = runToTerminal(ctx, logs, FrontendPhasePipelineStage.class); + final var diagnostics = run(ctx, logs, analyses, new ArrayList<>()); return new AnalysisSnapshot( diagnostics, ctx.resolvedWorkspace, @@ -53,12 +68,8 @@ public class BuilderPipelineService { public CompileResult compile( final BuilderPipelineContext ctx, final LogAggregator logs) { - final var diagnostics = runToTerminal(ctx, logs, VerifyBytecodePipelineStage.class); - final var analysisSnapshot = new AnalysisSnapshot( - diagnostics, - ctx.resolvedWorkspace, - ctx.fileTable, - ctx.irBackend); + final var analysisSnapshot = this.analyze(ctx, logs); + final var diagnostics = run(ctx, logs, compile, new ArrayList<>(analysisSnapshot.diagnostics())); return new CompileResult( analysisSnapshot, diagnostics, @@ -71,31 +82,19 @@ public class BuilderPipelineService { public BuildResult build( final BuilderPipelineContext ctx, final LogAggregator logs) { - final var diagnostics = runToTerminal(ctx, logs, WriteBytecodeArtifactPipelineStage.class); - final var analysisSnapshot = new AnalysisSnapshot( - diagnostics, - ctx.resolvedWorkspace, - ctx.fileTable, - ctx.irBackend); - final var compileResult = new CompileResult( - analysisSnapshot, - diagnostics, - ctx.irvm, - ctx.optimizedIrvm, - ctx.bytecodeModule, - ctx.bytecodeBytes); + final var compileResult = this.compile(ctx, logs); + final var diagnostics = run(ctx, logs, build, new ArrayList<>(compileResult.diagnostics())); return new BuildResult( compileResult, diagnostics, ctx.bytecodeArtifactPath); } - private List runToTerminal( + private List run( final BuilderPipelineContext ctx, final LogAggregator logs, - final Class terminalStage) { - final var diagnostics = new ArrayList(); - var completed = false; + final List stages, + final List diagnostics) { for (final var builderPipelineStage : stages) { final var issues = builderPipelineStage.run(ctx, logs); diagnostics.addAll(issues.asCollection()); @@ -103,15 +102,8 @@ public class BuilderPipelineService { if (issues.hasErrors()) { throw new BuildException("issues found on pipeline stage: " + builderPipelineStage.getClass().getSimpleName()); } - if (terminalStage.isInstance(builderPipelineStage)) { - completed = true; - break; - } } - if (!completed) { - throw new BuildException("terminal stage not found on builder pipeline: " + terminalStage.getSimpleName()); - } - logs.using(log).info("builder pipeline completed successfully through " + terminalStage.getSimpleName()); + logs.using(log).info("builder pipeline completed successfully"); return List.copyOf(diagnostics); } diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/BuilderPipelineServiceOrderTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/BuilderPipelineServiceOrderTest.java index 44ba2f13..ad630a53 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/BuilderPipelineServiceOrderTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/workspaces/BuilderPipelineServiceOrderTest.java @@ -14,31 +14,36 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class BuilderPipelineServiceOrderTest { @Test - void canonicalOrderMustContainOptimizeBetweenLowerAndEmit() throws Exception { - final Field field = BuilderPipelineService.class.getDeclaredField("stages"); - field.setAccessible(true); - - @SuppressWarnings("unchecked") - final var stages = (List) field.get(BuilderPipelineService.INSTANCE); - final var stageTypes = stages.stream().map(Object::getClass).toList(); + void canonicalOrderMustExposeExpectedStageGroups() throws Exception { + final var analyzeStages = stages("analyses"); + final var compileStages = stages("compile"); + final var buildStages = stages("build"); assertEquals( List.of( ResolveDepsPipelineStage.class, LoadSourcesPipelineStage.class, - FrontendPhasePipelineStage.class, + FrontendPhasePipelineStage.class), + analyzeStages); + + assertEquals( + List.of( LowerToIRVMPipelineStage.class, OptimizeIRVMPipelineStage.class, EmitBytecodePipelineStage.class, LinkBytecodePipelineStage.class, - VerifyBytecodePipelineStage.class, - WriteBytecodeArtifactPipelineStage.class), - stageTypes); + VerifyBytecodePipelineStage.class), + compileStages); + + assertEquals( + List.of(WriteBytecodeArtifactPipelineStage.class), + buildStages); } @Test void publicSurfaceMustExposeExplicitEntryPointsWithoutRun() { - final var methodNames = List.of(BuilderPipelineService.class.getDeclaredMethods()).stream() + final var methodNames = List.of(BuilderPipelineService.class.getMethods()).stream() + .filter(method -> method.getDeclaringClass().equals(BuilderPipelineService.class)) .map(Method::getName) .toList(); @@ -47,4 +52,12 @@ class BuilderPipelineServiceOrderTest { assertTrue(methodNames.contains("build")); assertFalse(methodNames.contains("run")); } + + @SuppressWarnings("unchecked") + private List> stages(final String fieldName) throws Exception { + final Field field = BuilderPipelineService.class.getDeclaredField(fieldName); + field.setAccessible(true); + final var stages = (List) field.get(BuilderPipelineService.INSTANCE); + return stages.stream().map(Object::getClass).toList(); + } } diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackend.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackend.java index fdc469c1..92bbdb73 100644 --- a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackend.java +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackend.java @@ -13,7 +13,7 @@ import java.util.LinkedHashSet; @Builder @Getter -public class IRBackend { +public class IRBackend implements IRBackendReader { @Builder.Default private final String entryPointCallableName = "main"; @Builder.Default diff --git a/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackendReader.java b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackendReader.java new file mode 100644 index 00000000..a7db83ae --- /dev/null +++ b/prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models/IRBackendReader.java @@ -0,0 +1,20 @@ +package p.studio.compiler.models; + +import p.studio.compiler.source.identifiers.ModuleId; +import p.studio.compiler.source.tables.CallableSignatureRef; +import p.studio.compiler.source.tables.IntrinsicReference; +import p.studio.compiler.source.tables.ModuleReference; +import p.studio.utilities.structures.ReadOnlyList; + +public interface IRBackendReader { + String getEntryPointCallableName(); + ModuleId getEntryPointModuleId(); + ReadOnlyList getFunctions(); + ReadOnlyList getSyntheticFunctions(); + ReadOnlyList getGlobals(); + ReadOnlyList getExecutableFunctions(); + ReadOnlyList getModulePool(); + ReadOnlyList getCallableSignatures(); + ReadOnlyList getIntrinsicPool(); + IRReservedMetadata getReservedMetadata(); +} diff --git a/prometeu-studio/src/main/java/p/studio/workspaces/builder/ShipperWorkspace.java b/prometeu-studio/src/main/java/p/studio/workspaces/builder/ShipperWorkspace.java index 628ce6df..c383adcb 100644 --- a/prometeu-studio/src/main/java/p/studio/workspaces/builder/ShipperWorkspace.java +++ b/prometeu-studio/src/main/java/p/studio/workspaces/builder/ShipperWorkspace.java @@ -7,6 +7,7 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import p.studio.Container; import p.studio.compiler.messages.BuilderPipelineConfig; +import p.studio.compiler.models.BuilderPipelineContext; import p.studio.compiler.workspaces.BuilderPipelineService; import p.studio.projects.ProjectReference; import p.studio.utilities.i18n.I18n; @@ -67,7 +68,8 @@ public class ShipperWorkspace extends Workspace { logs.clear(); final var logAggregator = LogAggregator.with(logs::appendText); final var config = new BuilderPipelineConfig(false, projectReference.rootPath().toString()); - BuilderPipelineService.INSTANCE.run(config, logAggregator); + final var ctx = BuilderPipelineContext.fromConfig(config); + BuilderPipelineService.INSTANCE.build(ctx, logAggregator); }); clearButton.textProperty().bind(Container.i18n().bind(I18n.WORKSPACE_SHIPPER_BUTTON_CLEAR));