implements PR-O1.3
This commit is contained in:
parent
9e3d9ccb93
commit
3e14c13979
@ -12,7 +12,9 @@ import p.studio.compiler.pbs.metadata.PbsReservedMetadataExtractor;
|
|||||||
import p.studio.compiler.pbs.parser.PbsParser;
|
import p.studio.compiler.pbs.parser.PbsParser;
|
||||||
import p.studio.compiler.pbs.semantics.PbsDeclarationSemanticsValidator;
|
import p.studio.compiler.pbs.semantics.PbsDeclarationSemanticsValidator;
|
||||||
import p.studio.compiler.pbs.semantics.PbsFlowSemanticsValidator;
|
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.DiagnosticSink;
|
||||||
|
import p.studio.compiler.source.diagnostics.DiagnosticPhase;
|
||||||
import p.studio.compiler.source.identifiers.FileId;
|
import p.studio.compiler.source.identifiers.FileId;
|
||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
@ -117,9 +119,13 @@ public final class PbsFrontendCompiler {
|
|||||||
final ReadOnlyList<IRFunction> functions = sourceKind == SourceKind.SDK_INTERFACE
|
final ReadOnlyList<IRFunction> functions = sourceKind == SourceKind.SDK_INTERFACE
|
||||||
? ReadOnlyList.empty()
|
? ReadOnlyList.empty()
|
||||||
: lowerFunctions(fileId, ast);
|
: lowerFunctions(fileId, ast);
|
||||||
|
final var loweringErrorBaseline = diagnostics.errorCount();
|
||||||
final ReadOnlyList<IRBackendExecutableFunction> executableFunctions = sourceKind == SourceKind.SDK_INTERFACE
|
final ReadOnlyList<IRBackendExecutableFunction> executableFunctions = sourceKind == SourceKind.SDK_INTERFACE
|
||||||
? ReadOnlyList.empty()
|
? 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);
|
return new IRBackendFile(fileId, functions, executableFunctions, reservedMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +146,8 @@ public final class PbsFrontendCompiler {
|
|||||||
final FileId fileId,
|
final FileId fileId,
|
||||||
final PbsAst.File ast,
|
final PbsAst.File ast,
|
||||||
final String moduleKey,
|
final String moduleKey,
|
||||||
final IRReservedMetadata reservedMetadata) {
|
final IRReservedMetadata reservedMetadata,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
final var hostByMethodName = new HashMap<String, IRReservedMetadata.HostMethodBinding>();
|
final var hostByMethodName = new HashMap<String, IRReservedMetadata.HostMethodBinding>();
|
||||||
for (final var hostBinding : reservedMetadata.hostMethodBindings()) {
|
for (final var hostBinding : reservedMetadata.hostMethodBindings()) {
|
||||||
hostByMethodName.put(hostBinding.sourceMethodName(), hostBinding);
|
hostByMethodName.put(hostBinding.sourceMethodName(), hostBinding);
|
||||||
@ -157,8 +164,25 @@ public final class PbsFrontendCompiler {
|
|||||||
final var instructions = new ArrayList<IRBackendExecutableFunction.Instruction>();
|
final var instructions = new ArrayList<IRBackendExecutableFunction.Instruction>();
|
||||||
final var callsites = new ArrayList<PbsAst.CallExpr>();
|
final var callsites = new ArrayList<PbsAst.CallExpr>();
|
||||||
collectCallsFromBlock(fn.body(), callsites);
|
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) {
|
for (final var callExpr : callsites) {
|
||||||
final var calleeName = extractSimpleCalleeName(callExpr.callee());
|
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);
|
final var host = hostByMethodName.get(calleeName);
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
instructions.add(new IRBackendExecutableFunction.Instruction(
|
instructions.add(new IRBackendExecutableFunction.Instruction(
|
||||||
@ -395,7 +419,7 @@ public final class PbsFrontendCompiler {
|
|||||||
case PbsAst.MemberExpr memberExpr -> memberExpr.memberName();
|
case PbsAst.MemberExpr memberExpr -> memberExpr.memberName();
|
||||||
case PbsAst.BindExpr bindExpr -> bindExpr.functionName();
|
case PbsAst.BindExpr bindExpr -> bindExpr.functionName();
|
||||||
case PbsAst.GroupExpr groupExpr -> extractSimpleCalleeName(groupExpr.expression());
|
case PbsAst.GroupExpr groupExpr -> extractSimpleCalleeName(groupExpr.expression());
|
||||||
default -> "<unknown>";
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,4 +59,5 @@ public enum PbsSemanticsErrors {
|
|||||||
E_SEM_HANDLE_NON_RESULT,
|
E_SEM_HANDLE_NON_RESULT,
|
||||||
E_SEM_HANDLE_ERROR_MISMATCH,
|
E_SEM_HANDLE_ERROR_MISMATCH,
|
||||||
E_SEM_HANDLE_ARM_TERMINAL_INVALID,
|
E_SEM_HANDLE_ARM_TERMINAL_INVALID,
|
||||||
|
E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,6 +98,31 @@ class PbsFrontendCompilerTest {
|
|||||||
i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC));
|
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
|
@Test
|
||||||
void shouldNotLowerWhenSyntaxErrorsExist() {
|
void shouldNotLowerWhenSyntaxErrorsExist() {
|
||||||
final var source = """
|
final var source = """
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user