implements PR-05.3

This commit is contained in:
bQUARKz 2026-03-09 06:56:47 +00:00
parent 9c294774db
commit ee25b867a7
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 38 additions and 6 deletions

View File

@ -2,6 +2,8 @@ package p.studio.compiler.backend.irvm;
public enum IRVMLoweringErrorCode {
LOWER_IRVM_EMPTY_EXECUTABLE_INPUT,
LOWER_IRVM_ENTRYPOINT_MISSING,
LOWER_IRVM_ENTRYPOINT_AMBIGUOUS,
LOWER_IRVM_MISSING_CALLEE,
LOWER_IRVM_INVALID_INTRINSIC_ID,
LOWER_IRVM_CALL_ARG_SLOTS_MISMATCH,

View File

@ -217,13 +217,20 @@ public class LowerToIRVMService {
final ReadOnlyList<IRBackendExecutableFunction> functions) {
final var sorted = new ArrayList<>(functions.asList());
sorted.sort(FUNCTION_ORDER);
var entrypoint = sorted.getFirst();
for (final var candidate : sorted) {
if ("main".equals(candidate.callableName())) {
entrypoint = candidate;
break;
}
final var entrypoints = sorted.stream()
.filter(candidate -> "main".equals(candidate.callableName()))
.toList();
if (entrypoints.isEmpty()) {
throw new IRVMLoweringException(
IRVMLoweringErrorCode.LOWER_IRVM_ENTRYPOINT_MISSING,
"missing entrypoint callable 'main'");
}
if (entrypoints.size() > 1) {
throw new IRVMLoweringException(
IRVMLoweringErrorCode.LOWER_IRVM_ENTRYPOINT_AMBIGUOUS,
"ambiguous entrypoint: found %d callables named 'main'".formatted(entrypoints.size()));
}
final var entrypoint = entrypoints.getFirst();
final var ordered = new ArrayList<IRBackendExecutableFunction>(sorted.size());
ordered.add(entrypoint);
for (final var fn : sorted) {

View File

@ -130,6 +130,29 @@ class LowerToIRVMServiceTest {
assertEquals(IRVMLoweringErrorCode.LOWER_IRVM_MISSING_JUMP_TARGET, thrown.code());
}
@Test
void lowerMustRejectWhenEntrypointIsMissing() {
final var backend = IRBackend.builder()
.executableFunctions(ReadOnlyList.from(
fn("helper", "app", 10, ReadOnlyList.from(ret()))))
.build();
final var thrown = assertThrows(IRVMLoweringException.class, () -> new LowerToIRVMService().lower(backend));
assertEquals(IRVMLoweringErrorCode.LOWER_IRVM_ENTRYPOINT_MISSING, thrown.code());
}
@Test
void lowerMustRejectWhenEntrypointIsAmbiguous() {
final var backend = IRBackend.builder()
.executableFunctions(ReadOnlyList.from(
fn("main", "app", 10, ReadOnlyList.from(ret())),
fn("main", "sdk", 11, ReadOnlyList.from(ret()))))
.build();
final var thrown = assertThrows(IRVMLoweringException.class, () -> new LowerToIRVMService().lower(backend));
assertEquals(IRVMLoweringErrorCode.LOWER_IRVM_ENTRYPOINT_AMBIGUOUS, thrown.code());
}
private static IRBackendExecutableFunction fn(
final String name,
final String moduleKey,