From 3e14c13979541ada41b0dcce02dfcc0222f165ca Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Sat, 7 Mar 2026 17:49:38 +0000 Subject: [PATCH] implements PR-O1.3 --- .../compiler/pbs/PbsFrontendCompiler.java | 30 +++++++++++++++++-- .../pbs/semantics/PbsSemanticsErrors.java | 1 + .../compiler/pbs/PbsFrontendCompilerTest.java | 25 ++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsFrontendCompiler.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsFrontendCompiler.java index a996f32e..375dbdc4 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsFrontendCompiler.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsFrontendCompiler.java @@ -12,7 +12,9 @@ import p.studio.compiler.pbs.metadata.PbsReservedMetadataExtractor; import p.studio.compiler.pbs.parser.PbsParser; import p.studio.compiler.pbs.semantics.PbsDeclarationSemanticsValidator; import p.studio.compiler.pbs.semantics.PbsFlowSemanticsValidator; +import p.studio.compiler.pbs.semantics.PbsSemanticsErrors; import p.studio.compiler.source.diagnostics.DiagnosticSink; +import p.studio.compiler.source.diagnostics.DiagnosticPhase; import p.studio.compiler.source.identifiers.FileId; import p.studio.utilities.structures.ReadOnlyList; @@ -117,9 +119,13 @@ public final class PbsFrontendCompiler { final ReadOnlyList functions = sourceKind == SourceKind.SDK_INTERFACE ? ReadOnlyList.empty() : lowerFunctions(fileId, ast); + final var loweringErrorBaseline = diagnostics.errorCount(); final ReadOnlyList executableFunctions = sourceKind == SourceKind.SDK_INTERFACE ? ReadOnlyList.empty() - : lowerExecutableFunctions(fileId, ast, moduleKey, reservedMetadata); + : lowerExecutableFunctions(fileId, ast, moduleKey, reservedMetadata, diagnostics); + if (diagnostics.errorCount() > loweringErrorBaseline) { + return IRBackendFile.empty(fileId); + } return new IRBackendFile(fileId, functions, executableFunctions, reservedMetadata); } @@ -140,7 +146,8 @@ public final class PbsFrontendCompiler { final FileId fileId, final PbsAst.File ast, final String moduleKey, - final IRReservedMetadata reservedMetadata) { + final IRReservedMetadata reservedMetadata, + final DiagnosticSink diagnostics) { final var hostByMethodName = new HashMap(); for (final var hostBinding : reservedMetadata.hostMethodBindings()) { hostByMethodName.put(hostBinding.sourceMethodName(), hostBinding); @@ -157,8 +164,25 @@ public final class PbsFrontendCompiler { final var instructions = new ArrayList(); final var callsites = new ArrayList(); collectCallsFromBlock(fn.body(), callsites); + callsites.sort((a, b) -> { + final var deltaStart = Long.compare(a.span().getStart(), b.span().getStart()); + if (deltaStart != 0) { + return deltaStart; + } + return Long.compare(a.span().getEnd(), b.span().getEnd()); + }); for (final var callExpr : callsites) { final var calleeName = extractSimpleCalleeName(callExpr.callee()); + if (calleeName == null || calleeName.isBlank()) { + diagnostics.error( + DiagnosticPhase.STATIC_SEMANTICS, + PbsSemanticsErrors.E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE.name(), + PbsSemanticsErrors.E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE.name(), + Map.of(), + "executable lowering requires resolvable callee identity", + callExpr.span()); + continue; + } final var host = hostByMethodName.get(calleeName); if (host != null) { instructions.add(new IRBackendExecutableFunction.Instruction( @@ -395,7 +419,7 @@ public final class PbsFrontendCompiler { case PbsAst.MemberExpr memberExpr -> memberExpr.memberName(); case PbsAst.BindExpr bindExpr -> bindExpr.functionName(); case PbsAst.GroupExpr groupExpr -> extractSimpleCalleeName(groupExpr.expression()); - default -> ""; + default -> null; }; } } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsSemanticsErrors.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsSemanticsErrors.java index 78ed36a4..13891f49 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsSemanticsErrors.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsSemanticsErrors.java @@ -59,4 +59,5 @@ public enum PbsSemanticsErrors { E_SEM_HANDLE_NON_RESULT, E_SEM_HANDLE_ERROR_MISMATCH, E_SEM_HANDLE_ARM_TERMINAL_INVALID, + E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE, } diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsFrontendCompilerTest.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsFrontendCompilerTest.java index 60fc11c4..ce15d16b 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsFrontendCompilerTest.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsFrontendCompilerTest.java @@ -98,6 +98,31 @@ class PbsFrontendCompilerTest { i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)); } + @Test + void shouldLowerExecutableCallsitesInDeterministicSourceOrder() { + final var source = """ + fn b() -> int { return 1; } + fn c() -> int { return 2; } + fn a() -> int { + b(); + c(); + return 0; + } + """; + + final var diagnostics = DiagnosticSink.empty(); + final var compiler = new PbsFrontendCompiler(); + final var fileBackend = compiler.compileFile(new FileId(99), source, diagnostics); + + assertTrue(diagnostics.isEmpty(), "Valid program should not report diagnostics"); + final var executableA = fileBackend.executableFunctions().stream() + .filter(fn -> fn.callableName().equals("a")) + .findFirst() + .orElseThrow(); + assertEquals("b", executableA.instructions().get(0).calleeCallableName()); + assertEquals("c", executableA.instructions().get(1).calleeCallableName()); + } + @Test void shouldNotLowerWhenSyntaxErrorsExist() { final var source = """