implements PR-08.4
This commit is contained in:
parent
2a68d27eca
commit
505a4f72ce
@ -389,6 +389,10 @@ public final class PbsFrontendCompiler {
|
||||
.add(callableId);
|
||||
returnSlotsByCallableId.put(callableId, importedCallable.returnSlots());
|
||||
}
|
||||
final var callableSignatureByCallableId = new HashMap<CallableId, CallableSignatureRef>();
|
||||
for (final var callableId : callableIdTable.identifiers()) {
|
||||
callableSignatureByCallableId.put(callableId, callableIdTable.get(callableId));
|
||||
}
|
||||
|
||||
final var executableFunctions = new ArrayList<IRBackendExecutableFunction>(localCallables.size());
|
||||
for (final var callable : localCallables) {
|
||||
@ -411,6 +415,7 @@ public final class PbsFrontendCompiler {
|
||||
intrinsicReturnOwnerByCanonical,
|
||||
builtinConstOwnerByNameId,
|
||||
callableIdsByNameAndArity,
|
||||
callableSignatureByCallableId,
|
||||
returnSlotsByCallableId,
|
||||
intrinsicIdTable,
|
||||
localSlotByNameId);
|
||||
@ -964,11 +969,16 @@ public final class PbsFrontendCompiler {
|
||||
return;
|
||||
}
|
||||
final var calleeCallableId = callableCandidates.getFirst();
|
||||
final var calleeSignature = context.callableSignatureByCallableId().get(calleeCallableId);
|
||||
if (calleeSignature == null) {
|
||||
reportUnsupportedLowering("executable lowering resolved callable without signature metadata", callExpr.span(), context);
|
||||
return;
|
||||
}
|
||||
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.CALL_FUNC,
|
||||
context.moduleId(),
|
||||
context.moduleKey(),
|
||||
calleeIdentity.primaryCallableDisplayName(),
|
||||
calleeSignature.moduleId(),
|
||||
calleeSignature.moduleKey(),
|
||||
calleeSignature.callableName(),
|
||||
calleeCallableId,
|
||||
null,
|
||||
null,
|
||||
@ -1347,6 +1357,7 @@ public final class PbsFrontendCompiler {
|
||||
private final Map<IntrinsicCanonicalKey, String> intrinsicReturnOwnerByCanonical;
|
||||
private final Map<NameId, String> builtinConstOwnerByNameId;
|
||||
private final Map<CallableResolutionKey, List<CallableId>> callableIdsByNameAndArity;
|
||||
private final Map<CallableId, CallableSignatureRef> callableSignatureByCallableId;
|
||||
private final Map<CallableId, Integer> returnSlotsByCallableId;
|
||||
private final IntrinsicTable intrinsicIdTable;
|
||||
private final Map<NameId, Integer> localSlotByNameId;
|
||||
@ -1364,6 +1375,7 @@ public final class PbsFrontendCompiler {
|
||||
final Map<IntrinsicCanonicalKey, String> intrinsicReturnOwnerByCanonical,
|
||||
final Map<NameId, String> builtinConstOwnerByNameId,
|
||||
final Map<CallableResolutionKey, List<CallableId>> callableIdsByNameAndArity,
|
||||
final Map<CallableId, CallableSignatureRef> callableSignatureByCallableId,
|
||||
final Map<CallableId, Integer> returnSlotsByCallableId,
|
||||
final IntrinsicTable intrinsicIdTable,
|
||||
final Map<NameId, Integer> localSlotByNameId) {
|
||||
@ -1376,6 +1388,7 @@ public final class PbsFrontendCompiler {
|
||||
this.intrinsicReturnOwnerByCanonical = intrinsicReturnOwnerByCanonical;
|
||||
this.builtinConstOwnerByNameId = builtinConstOwnerByNameId;
|
||||
this.callableIdsByNameAndArity = callableIdsByNameAndArity;
|
||||
this.callableSignatureByCallableId = callableSignatureByCallableId;
|
||||
this.returnSlotsByCallableId = returnSlotsByCallableId;
|
||||
this.intrinsicIdTable = intrinsicIdTable;
|
||||
this.localSlotByNameId = localSlotByNameId == null ? Map.of() : localSlotByNameId;
|
||||
@ -1417,6 +1430,10 @@ public final class PbsFrontendCompiler {
|
||||
return callableIdsByNameAndArity;
|
||||
}
|
||||
|
||||
private Map<CallableId, CallableSignatureRef> callableSignatureByCallableId() {
|
||||
return callableSignatureByCallableId;
|
||||
}
|
||||
|
||||
private Map<CallableId, Integer> returnSlotsByCallableId() {
|
||||
return returnSlotsByCallableId;
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class PBSFrontendPhaseServiceTest {
|
||||
@ -138,6 +139,82 @@ class PBSFrontendPhaseServiceTest {
|
||||
assertEquals("good", irBackend.getFunctions().getFirst().name());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEmitCallFuncWithCalleeModuleIdentityFromResolvedTarget() throws IOException {
|
||||
final var projectRoot = tempDir.resolve("project-callsite-module-identity");
|
||||
final var sourceRoot = projectRoot.resolve("src");
|
||||
final var moduleAPath = sourceRoot.resolve("a");
|
||||
final var moduleBPath = sourceRoot.resolve("b");
|
||||
Files.createDirectories(moduleAPath);
|
||||
Files.createDirectories(moduleBPath);
|
||||
|
||||
final var sourceA = moduleAPath.resolve("source.pbs");
|
||||
final var barrelA = moduleAPath.resolve("mod.barrel");
|
||||
Files.writeString(sourceA, """
|
||||
fn target() -> int {
|
||||
return 1;
|
||||
}
|
||||
""");
|
||||
Files.writeString(barrelA, "pub fn target() -> int;");
|
||||
|
||||
final var sourceB = moduleBPath.resolve("source.pbs");
|
||||
final var barrelB = moduleBPath.resolve("mod.barrel");
|
||||
Files.writeString(sourceB, """
|
||||
import { target } from @app:a;
|
||||
|
||||
fn caller() -> int {
|
||||
return target();
|
||||
}
|
||||
""");
|
||||
Files.writeString(barrelB, "pub fn caller() -> int;");
|
||||
|
||||
final var projectTable = new ProjectTable();
|
||||
final var fileTable = new FileTable(1);
|
||||
final var projectId = projectTable.register(ProjectDescriptor.builder()
|
||||
.rootPath(projectRoot)
|
||||
.name("app")
|
||||
.version("1.0.0")
|
||||
.sourceRoots(ReadOnlyList.wrap(List.of(sourceRoot)))
|
||||
.build());
|
||||
|
||||
registerFile(projectId, projectRoot, sourceA, fileTable);
|
||||
registerFile(projectId, projectRoot, barrelA, fileTable);
|
||||
registerFile(projectId, projectRoot, sourceB, fileTable);
|
||||
registerFile(projectId, projectRoot, barrelB, fileTable);
|
||||
|
||||
final var ctx = new FrontendPhaseContext(
|
||||
projectTable,
|
||||
fileTable,
|
||||
new BuildStack(ReadOnlyList.wrap(List.of(projectId))));
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
|
||||
final var irBackend = new PBSFrontendPhaseService().compile(
|
||||
ctx,
|
||||
diagnostics,
|
||||
LogAggregator.empty(),
|
||||
BuildingIssueSink.empty());
|
||||
|
||||
assertTrue(diagnostics.isEmpty(), diagnostics.stream().map(d -> d.getCode() + ":" + d.getMessage()).toList().toString());
|
||||
|
||||
final var targetFn = irBackend.getExecutableFunctions().stream()
|
||||
.filter(function -> "target".equals(function.callableName()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
final var callerFn = irBackend.getExecutableFunctions().stream()
|
||||
.filter(function -> "caller".equals(function.callableName()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
final var callInstruction = callerFn.instructions().stream()
|
||||
.filter(instruction -> instruction.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
|
||||
assertNotNull(callInstruction.calleeModuleId());
|
||||
assertEquals(targetFn.moduleId().getIndex(), callInstruction.calleeModuleId().getIndex());
|
||||
assertEquals(targetFn.moduleKey(), callInstruction.calleeModuleKey());
|
||||
assertTrue(callerFn.moduleId().getIndex() != callInstruction.calleeModuleId().getIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLowerAllSourcesWhenNoAdmissionErrorsExist() throws IOException {
|
||||
final var projectRoot = tempDir.resolve("project-valid");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user