small code improvements

This commit is contained in:
bQUARKz 2026-02-27 16:19:50 +00:00
parent 956d3128a9
commit f3be4f7946
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
8 changed files with 72 additions and 28 deletions

View File

@ -1,6 +1,7 @@
package p.studio.compiler.pbs;
import p.studio.compiler.models.IRFunction;
import p.studio.compiler.models.IRBackendFile;
import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.lexer.PbsLexer;
import p.studio.compiler.pbs.parser.PbsParser;
@ -13,14 +14,14 @@ import java.util.HashSet;
import java.util.Set;
public final class PbsFrontendCompiler {
public ReadOnlyList<IRFunction> compileFile(
public IRBackendFile compileFile(
final FileId fileId,
final String source,
final DiagnosticSink diagnostics) {
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
final var ast = PbsParser.parse(tokens, fileId, diagnostics);
validateFunctionNames(ast, diagnostics);
return lowerFunctions(fileId, ast);
return new IRBackendFile(fileId, lowerFunctions(fileId, ast));
}
private void validateFunctionNames(

View File

@ -4,10 +4,6 @@ import p.studio.compiler.source.Span;
import p.studio.utilities.structures.ReadOnlyList;
public final class PbsAst {
public sealed interface Statement permits LetStatement, ReturnStatement, ExpressionStatement {
Span span();
}
private PbsAst() {
}
@ -36,6 +32,10 @@ public final class PbsAst {
Span span) {
}
public sealed interface Statement permits LetStatement, ReturnStatement, ExpressionStatement {
Span span();
}
public record Block(
ReadOnlyList<Statement> statements,
Span span) {

View File

@ -4,11 +4,9 @@ import lombok.extern.slf4j.Slf4j;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.models.IRBackend;
import p.studio.compiler.models.IRFunction;
import p.studio.compiler.pbs.PbsFrontendCompiler;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.utilities.logs.LogAggregator;
import p.studio.utilities.structures.MutableList;
@Slf4j
public class PBSFrontendPhaseService implements FrontendPhaseService {
@ -20,7 +18,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
final DiagnosticSink diagnostics,
final LogAggregator logs,
final BuildingIssueSink issues) {
final MutableList<IRFunction> functions = MutableList.create();
final var irBackendAggregator = IRBackend.aggregator();
for (final var pId : ctx.stack.reverseTopologicalOrder) {
final var fileIds = ctx.fileTable.getFiles(pId);
@ -30,10 +28,11 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
switch (sourceHandle.getExtension()) {
case "pbs": {
sourceHandle.readUtf8().ifPresentOrElse(
utf8Content -> functions.addAll(frontendCompiler
.compileFile(fId, utf8Content, diagnostics)
.stream()
.toList()),
utf8Content -> {
final var irBackendFile = frontendCompiler
.compileFile(fId, utf8Content, diagnostics);
irBackendAggregator.merge(irBackendFile);
},
() -> issues.report(builder -> builder
.error(true)
.message("Failed to read file content: %s".formatted(sourceHandle.toString()))));
@ -45,10 +44,8 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
}
}
logs.using(log).debug("PBS frontend lowered %d function(s) to IR".formatted(functions.size()));
return IRBackend
.builder()
.functions(functions.toReadOnlyList())
.build();
final var irBackend = irBackendAggregator.emit();
logs.using(log).debug("PBS frontend lowered to IR BE:\n%s".formatted(irBackend));
return irBackend;
}
}

View File

@ -23,7 +23,8 @@ class PbsFrontendCompilerTest {
final var diagnostics = DiagnosticSink.empty();
final var compiler = new PbsFrontendCompiler();
final var functions = compiler.compileFile(new FileId(0), source, diagnostics);
final var fileBackend = compiler.compileFile(new FileId(0), source, diagnostics);
final var functions = fileBackend.functions();
assertTrue(diagnostics.isEmpty(), "Valid program should not report diagnostics");
assertEquals(2, functions.size());

View File

@ -27,7 +27,6 @@ public class FrontendPhasePipelineStage implements PipelineStage {
final var diagnostics = DiagnosticSink.empty();
final var issues = BuildingIssueSink.empty();
ctx.irBackend = service.get().compile(frontendPhaseContext, diagnostics, logs, issues);
logs.using(log).debug("IR Backend: " + ctx.irBackend);
logs.using(log).debug("Frontend phase completed successfully!");
adaptDiagnostics(diagnostics, issues);
return issues;

View File

@ -2,6 +2,7 @@ package p.studio.compiler.models;
import lombok.Builder;
import lombok.Getter;
import p.studio.utilities.structures.MutableList;
import p.studio.utilities.structures.ReadOnlyList;
@Builder
@ -10,9 +11,28 @@ public class IRBackend {
@Builder.Default
private final ReadOnlyList<IRFunction> functions = ReadOnlyList.empty();
/**
* Returns a stable human-readable representation useful for debug logs and tests.
*/
public static IRBackendAggregator aggregator() {
return new IRBackendAggregator();
}
public static final class IRBackendAggregator {
private final MutableList<IRFunction> functions = MutableList.create();
public void merge(final IRBackendFile backendFile) {
if (backendFile == null) {
return;
}
functions.addAll(backendFile.functions());
}
public IRBackend emit() {
return IRBackend
.builder()
.functions(functions.toReadOnlyList())
.build();
}
}
@Override
public String toString() {
final var sb = new StringBuilder();

View File

@ -0,0 +1,19 @@
package p.studio.compiler.models;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.Objects;
public record IRBackendFile(
FileId fileId,
ReadOnlyList<IRFunction> functions) {
public IRBackendFile {
fileId = Objects.requireNonNull(fileId, "fileId");
functions = functions == null ? ReadOnlyList.empty() : functions;
}
public static IRBackendFile empty(final FileId fileId) {
return new IRBackendFile(fileId, ReadOnlyList.empty());
}
}

View File

@ -1,10 +1,6 @@
package p.studio.utilities.structures;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.*;
import java.util.stream.Stream;
public interface MutableList<T> extends ReadOnlyCollection<T>, List<T> {
@ -114,6 +110,17 @@ public interface MutableList<T> extends ReadOnlyCollection<T>, List<T> {
return asList().containsAll(c);
}
/**
* Appends all functions from the given file using, similar to
* {@link java.util.List#addAll(java.util.Collection)} semantics.
*/
default boolean addAll(final ReadOnlyCollection<? extends T> c) {
if (ReadOnlyCollection.isEmpty(c)) {
return false;
}
return asList().addAll(c.asCollection());
}
@Override
default boolean addAll(final Collection<? extends T> c) {
return asList().addAll(c);