implements PLN-0011 pipeline callsite and test migration

This commit is contained in:
bQUARKz 2026-03-30 19:02:56 +01:00
parent c467a2642f
commit 9d2a9955c0
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
13 changed files with 49 additions and 33 deletions

View File

@ -9,4 +9,4 @@
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0010","status":"open","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[{"id":"AGD-0010","file":"AGD-0010-studio-code-editor-workspace-foundations.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[{"id":"AGD-0011","file":"AGD-0011-compiler-analyze-compile-build-pipeline-split.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0007","file":"DEC-0007-compiler-analyze-compile-build-pipeline-split.md","status":"in_progress","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0011"}],"plans":[{"id":"PLN-0009","file":"PLN-0009-compiler-pipeline-spec-and-contract-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0010","file":"PLN-0010-refactor-builder-pipeline-service-into-entrypoints.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0011","file":"PLN-0011-migrate-callsites-and-tests-to-build-compile-analyze.md","status":"review","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[{"id":"AGD-0011","file":"AGD-0011-compiler-analyze-compile-build-pipeline-split.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0007","file":"DEC-0007-compiler-analyze-compile-build-pipeline-split.md","status":"in_progress","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0011"}],"plans":[{"id":"PLN-0009","file":"PLN-0009-compiler-pipeline-spec-and-contract-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0010","file":"PLN-0010-refactor-builder-pipeline-service-into-entrypoints.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0011","file":"PLN-0011-migrate-callsites-and-tests-to-build-compile-analyze.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]}],"lessons":[]}

View File

@ -2,9 +2,9 @@
id: PLN-0011
ticket: compiler-analyze-compile-build-pipeline-split
title: Migrate compiler callsites and tests to explicit build, compile, and analyze entrypoints
status: review
status: done
created: 2026-03-30
completed:
completed: 2026-03-30
tags:
- compiler
- pipeline

View File

@ -33,8 +33,4 @@ public class BuilderPipelineContext {
public static BuilderPipelineContext fromConfig(final BuilderPipelineConfig config) {
return new BuilderPipelineContext(config, config.sourceProviderFactory());
}
public static BuilderPipelineContext compilerContext(final BuilderPipelineConfig config) {
return fromConfig(config);
}
}

View File

@ -150,7 +150,7 @@ class BackendGateIIntegrationTest {
}
private BytecodeModule emitFromBackend(final IRBackend backend) {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = backend;
final var lowerIssues = new LowerToIRVMPipelineStage().run(ctx, LogAggregator.empty());

View File

@ -28,6 +28,7 @@ class MainProjectPipelineIntegrationTest {
assertNotNull(snapshot.resolvedWorkspace(), "analyze must expose resolved workspace");
assertNotNull(snapshot.fileTable(), "analyze must expose file table");
assertNotNull(snapshot.irBackend(), "analyze must expose frontend semantic result");
assertNotNull(snapshot.diagnostics(), "analyze must expose diagnostics collection");
assertFalse(Files.exists(outputPath), "analyze must not write output: " + outputPath);
}
@ -43,6 +44,7 @@ class MainProjectPipelineIntegrationTest {
() -> "compile unexpectedly failed for " + projectRoot);
assertNotNull(result.analysisSnapshot(), "compile must retain analysis snapshot");
assertNotNull(result.diagnostics(), "compile must expose diagnostics collection");
assertNotNull(result.bytecodeModule(), "compile must expose bytecode module");
assertNotNull(result.bytecodeBytes(), "compile must expose bytecode bytes");
assertTrue(result.bytecodeBytes().length > 0, "compile must expose non-empty bytecode bytes");
@ -60,6 +62,9 @@ class MainProjectPipelineIntegrationTest {
final var result = assertDoesNotThrow(
() -> BuilderPipelineService.INSTANCE.build(context, logs),
() -> "build unexpectedly failed for " + projectRoot);
assertNotNull(result.diagnostics(), "build must expose diagnostics collection");
assertNotNull(result.compileResult(), "build must retain compile payload");
assertNotNull(result.compileResult().analysisSnapshot(), "build must retain analysis payload");
assertEquals(outputPath, result.bytecodeArtifactPath(), "build must expose written artifact path");
assertTrue(Files.exists(outputPath), "build did not write output: " + outputPath);
assertTrue(Files.size(outputPath) > 0, "build wrote empty bytecode file: " + outputPath);

View File

@ -3,10 +3,13 @@ package p.studio.compiler.workspaces;
import org.junit.jupiter.api.Test;
import p.studio.compiler.workspaces.stages.*;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class BuilderPipelineServiceOrderTest {
@ -32,4 +35,16 @@ class BuilderPipelineServiceOrderTest {
WriteBytecodeArtifactPipelineStage.class),
stageTypes);
}
@Test
void publicSurfaceMustExposeExplicitEntryPointsWithoutRun() {
final var methodNames = List.of(BuilderPipelineService.class.getDeclaredMethods()).stream()
.map(Method::getName)
.toList();
assertTrue(methodNames.contains("analyze"));
assertTrue(methodNames.contains("compile"));
assertTrue(methodNames.contains("build"));
assertFalse(methodNames.contains("run"));
}
}

View File

@ -133,25 +133,25 @@ class BackendSafetyGateSUTest {
}
private static p.studio.compiler.messages.BuildingIssueSink runLower(final IRBackend backend) {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = backend;
return new LowerToIRVMPipelineStage().run(ctx, LogAggregator.empty());
}
private static p.studio.compiler.messages.BuildingIssueSink runOptimize(final IRVMProgram program) {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irvm = program;
return new OptimizeIRVMPipelineStage().run(ctx, LogAggregator.empty());
}
private static p.studio.compiler.messages.BuildingIssueSink runEmit(final IRVMProgram program) {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.optimizedIrvm = program;
return new EmitBytecodePipelineStage().run(ctx, LogAggregator.empty());
}
private static byte[] emitBytes(final IRBackend backend) {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = backend;
final var lowerIssues = new LowerToIRVMPipelineStage().run(ctx, LogAggregator.empty());

View File

@ -14,7 +14,7 @@ class EmitBytecodePipelineStageTest {
@Test
void runMustFailWhenOptimizedIrvmIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
final var stage = new EmitBytecodePipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
@ -28,7 +28,7 @@ class EmitBytecodePipelineStageTest {
@Test
void runMustFailWhenInternalOpcodesRemain() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.optimizedIrvm = new IRVMProgram(true, BytecodeEmitter.EmissionPlan.empty());
final var stage = new EmitBytecodePipelineStage();
@ -42,7 +42,7 @@ class EmitBytecodePipelineStageTest {
@Test
void runMustFailWhenInternalOpcodesRemainEvenWithNonEmptyEmissionPlan() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.optimizedIrvm = new IRVMProgram(
new p.studio.compiler.backend.irvm.IRVMModule(
"experimental-v1",
@ -79,7 +79,7 @@ class EmitBytecodePipelineStageTest {
@Test
void runMustEmitBytecodeWhenPreconditionsAreSatisfied() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.optimizedIrvm = new IRVMProgram(
false,
new BytecodeEmitter.EmissionPlan(

View File

@ -17,7 +17,7 @@ class LinkBytecodePipelineStageTest {
@Test
void runMustFailWhenBytecodeModuleIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
final var stage = new LinkBytecodePipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
@ -30,7 +30,7 @@ class LinkBytecodePipelineStageTest {
@Test
void runMustReportHostcallIndexPrecheckFailure() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.bytecodeModule = new BytecodeModule(
0,
ReadOnlyList.empty(),

View File

@ -17,7 +17,7 @@ class LowerToIRVMPipelineStageTest {
@Test
void runMustFailWhenIrBackendIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
final var stage = new LowerToIRVMPipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
@ -31,7 +31,7 @@ class LowerToIRVMPipelineStageTest {
@Test
void runMustLowerExecutableFunctionsToIrvm() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = IRBackend.builder()
.entryPointModuleId(new p.studio.compiler.source.identifiers.ModuleId(0))
.executableFunctions(ReadOnlyList.from(new IRBackendExecutableFunction(
@ -64,7 +64,7 @@ class LowerToIRVMPipelineStageTest {
@Test
void runMustPropagateConfiguredVmProfileToLowering() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, ".", "experimental-v1"));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, ".", "experimental-v1"));
ctx.irBackend = IRBackend.builder()
.entryPointModuleId(new p.studio.compiler.source.identifiers.ModuleId(0))
.executableFunctions(ReadOnlyList.from(new IRBackendExecutableFunction(
@ -97,7 +97,7 @@ class LowerToIRVMPipelineStageTest {
@Test
void runMustAttachSourceAttributionForLoweringFailure() {
final var callSpan = new Span(new FileId(9), 12, 24);
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = IRBackend.builder()
.entryPointModuleId(new p.studio.compiler.source.identifiers.ModuleId(0))
.executableFunctions(ReadOnlyList.from(new IRBackendExecutableFunction(
@ -141,7 +141,7 @@ class LowerToIRVMPipelineStageTest {
@Test
void runMustRejectCallWhenStackDoesNotProvideDeclaredArgs() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irBackend = IRBackend.builder()
.entryPointModuleId(new p.studio.compiler.source.identifiers.ModuleId(0))
.executableFunctions(ReadOnlyList.from(

View File

@ -13,7 +13,7 @@ class OptimizeIRVMPipelineStageTest {
@Test
void runMustFailWhenIrvmIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
final var stage = new OptimizeIRVMPipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
@ -27,7 +27,7 @@ class OptimizeIRVMPipelineStageTest {
@Test
void runMustProduceNoopOptimizedProgram() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irvm = new IRVMProgram(new IRVMModule(
"core-v1",
ReadOnlyList.from(new IRVMFunction(
@ -49,7 +49,7 @@ class OptimizeIRVMPipelineStageTest {
@Test
void runMustRejectUnsupportedVmProfile() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.irvm = new IRVMProgram(new IRVMModule(
"experimental",
ReadOnlyList.from(new IRVMFunction(
@ -70,7 +70,7 @@ class OptimizeIRVMPipelineStageTest {
@Test
void runMustAcceptSupportedNonDefaultVmProfile() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, ".", "experimental-v1"));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, ".", "experimental-v1"));
ctx.irvm = new IRVMProgram(new IRVMModule(
"experimental-v1",
ReadOnlyList.from(new IRVMFunction(

View File

@ -17,7 +17,7 @@ class VerifyBytecodePipelineStageTest {
@Test
void runMustFailWhenBytecodeModuleIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
final var stage = new VerifyBytecodePipelineStage();
final var issues = stage.run(ctx, LogAggregator.empty());
@ -30,7 +30,7 @@ class VerifyBytecodePipelineStageTest {
@Test
void runMustRejectRawSyscallInPreload() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.bytecodeModule = new BytecodeModule(
0,
ReadOnlyList.empty(),

View File

@ -20,7 +20,7 @@ class WriteBytecodeArtifactPipelineStageTest {
@Test
void runMustFailWhenRootProjectPathIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.bytecodeBytes = new byte[] { 0x01 };
final var issues = new WriteBytecodeArtifactPipelineStage().run(ctx, LogAggregator.empty());
@ -33,7 +33,7 @@ class WriteBytecodeArtifactPipelineStageTest {
@Test
void runMustFailWhenBytecodeInputIsMissing() {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.rootProjectPathCanon = tempDir;
final var issues = new WriteBytecodeArtifactPipelineStage().run(ctx, LogAggregator.empty());
@ -46,7 +46,7 @@ class WriteBytecodeArtifactPipelineStageTest {
@Test
void runMustWriteBuildProgramPbxFromByteArray() throws Exception {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.rootProjectPathCanon = tempDir;
ctx.bytecodeBytes = new byte[] { 0x50, 0x42, 0x58, 0x00 };
@ -61,7 +61,7 @@ class WriteBytecodeArtifactPipelineStageTest {
@Test
void runMustWriteBuildProgramPbxFromModuleWhenByteArrayIsMissing() throws Exception {
final var ctx = BuilderPipelineContext.compilerContext(new BuilderPipelineConfig(false, "."));
final var ctx = BuilderPipelineContext.fromConfig(new BuilderPipelineConfig(false, "."));
ctx.rootProjectPathCanon = tempDir;
ctx.bytecodeModule = new BytecodeModule(
0,