implements PR-07.2
This commit is contained in:
parent
b91a3cea34
commit
14f9b5dd26
@ -73,7 +73,7 @@ to concrete positive/negative test evidence and current status.
|
||||
| PBS13-12.1.4 | Source anchor (`fileId/start/end`) MUST be preserved. | `IRBackendExecutableContractTest#aggregatorMustPreserveExecutableSourceAttribution`; `IRBackendExecutableContractTest#functionContractMustRejectInvalidSlotAndSpanBounds` | N/A | pass | Handoff preserves function and instruction source anchors after aggregation/reindexing. |
|
||||
| PBS13-12.1.5 | Executable body representation MUST be backend-lowerable. | `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites` | `LowerToIRVMServiceTest#lowerMustRejectMissingCallee` | pass | |
|
||||
| PBS13-12.2.1 | Callsite MUST be exactly one of `CALL_FUNC/CALL_HOST/CALL_INTRINSIC`. | `IRBackendExecutableContractTest#callInstructionMustRequireCategorySpecificMetadata` | `IRBackendExecutableContractTest#instructionContractMustRejectMixedMetadataKinds` | pass | |
|
||||
| PBS13-12.2.2 | Backend MUST NOT infer callsite category by textual heuristics. | `PbsFrontendCompilerTest#shouldLowerExecutableFunctionsWithCallsiteCategories`; `IRBackendExecutableContractTest#callInstructionMustRequireCategorySpecificMetadata` | N/A | partial | Semantic-identity coverage exists; dedicated ambiguous-identity regression fixture is still missing. |
|
||||
| PBS13-12.2.2 | Backend MUST NOT infer callsite category by textual heuristics. | `PbsFrontendCompilerTest#shouldClassifyCallableCallEvenWhenNameLooksHostLike`; `PbsFrontendCompilerTest#shouldNotInferCallableCategoryFromMemberCallText`; `PbsFrontendCompilerTest#shouldRejectAmbiguousCallableIdentityInsteadOfGuessingByText`; `IRBackendExecutableContractTest#callInstructionMustRequireCategorySpecificMetadata` | N/A | pass | Dedicated regression fixtures now cover textually misleading names and ambiguous callable identity without category guessing. |
|
||||
| PBS13-12.3.1 | Host-backed callsite MUST preserve canonical `(module,name,version)`. | `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites` | N/A | pass | |
|
||||
| PBS13-12.3.2 | Host ABI shape (`arg_slots`,`ret_slots`) MUST be preserved when available. | `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites` | `BytecodeEmitterTest#emitMustRejectAbiMismatch` | pass | |
|
||||
| PBS13-12.4.1 | Intrinsic callsite MUST preserve canonical intrinsic identity. | `IRBackendExecutableContractTest#aggregatorMustReindexIntrinsicsToBuildGlobalPool` | N/A | pass | |
|
||||
|
||||
@ -693,8 +693,8 @@ public final class PbsFrontendCompiler {
|
||||
return switch (callee) {
|
||||
case PbsAst.IdentifierExpr identifierExpr ->
|
||||
new CalleeIdentity(nameTable.register(identifierExpr.name()), identifierExpr.name());
|
||||
case PbsAst.MemberExpr memberExpr ->
|
||||
new CalleeIdentity(nameTable.register(memberExpr.memberName()), memberExpr.memberName());
|
||||
// Member access does not carry executable callsite identity in v1 lowering.
|
||||
case PbsAst.MemberExpr ignored -> null;
|
||||
case PbsAst.BindExpr bindExpr ->
|
||||
new CalleeIdentity(nameTable.register(bindExpr.functionName()), bindExpr.functionName());
|
||||
case PbsAst.GroupExpr groupExpr -> resolveCalleeIdentity(groupExpr.expression(), nameTable);
|
||||
|
||||
@ -98,6 +98,89 @@ class PbsFrontendCompilerTest {
|
||||
i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldClassifyCallableCallEvenWhenNameLooksHostLike() {
|
||||
final var source = """
|
||||
fn draw_pixel(x: int, y: int) -> int {
|
||||
return x;
|
||||
}
|
||||
|
||||
fn main() -> int {
|
||||
return draw_pixel(1, 2);
|
||||
}
|
||||
""";
|
||||
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
final var compiler = new PbsFrontendCompiler();
|
||||
final var fileBackend = compiler.compileFile(new FileId(43), source, diagnostics);
|
||||
|
||||
assertTrue(diagnostics.isEmpty(), "Valid program should not report diagnostics");
|
||||
final var executableMain = fileBackend.executableFunctions().stream()
|
||||
.filter(fn -> fn.callableName().equals("main"))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
final var callInstruction = executableMain.instructions().stream()
|
||||
.filter(i -> i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertEquals("draw_pixel", callInstruction.calleeCallableName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotInferCallableCategoryFromMemberCallText() {
|
||||
final var source = """
|
||||
fn draw_pixel(x: int, y: int) -> int {
|
||||
return x;
|
||||
}
|
||||
|
||||
fn main() -> int {
|
||||
return gfx.draw_pixel(1, 2);
|
||||
}
|
||||
""";
|
||||
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
final var compiler = new PbsFrontendCompiler();
|
||||
final var fileBackend = compiler.compileFile(new FileId(44), source, diagnostics);
|
||||
|
||||
assertTrue(fileBackend.executableFunctions().stream()
|
||||
.filter(fn -> fn.callableName().equals("main"))
|
||||
.findFirst()
|
||||
.map(fn -> fn.instructions().stream().noneMatch(i ->
|
||||
i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_FUNC
|
||||
|| i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_HOST
|
||||
|| i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.CALL_INTRINSIC))
|
||||
.orElse(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectAmbiguousCallableIdentityInsteadOfGuessingByText() {
|
||||
final var source = """
|
||||
fn draw_pixel(x: int) -> int {
|
||||
return x;
|
||||
}
|
||||
|
||||
fn draw_pixel(x: float) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn main() -> int {
|
||||
return draw_pixel(1);
|
||||
}
|
||||
""";
|
||||
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
final var compiler = new PbsFrontendCompiler();
|
||||
final var fileBackend = compiler.compileFile(new FileId(45), source, diagnostics);
|
||||
|
||||
final var loweringDiagnostic = diagnostics.stream()
|
||||
.filter(d -> d.getCode().equals(PbsSemanticsErrors.E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE.name()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertEquals(DiagnosticPhase.STATIC_SEMANTICS, loweringDiagnostic.getPhase());
|
||||
assertTrue(loweringDiagnostic.getMessage().contains("ambiguous callable identity"));
|
||||
assertEquals(0, fileBackend.executableFunctions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLowerExecutableCallsitesInDeterministicSourceOrder() {
|
||||
final var source = """
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user