implements PR-05.0.6

This commit is contained in:
bQUARKz 2026-03-09 06:44:30 +00:00
parent 9aac65a2e9
commit 4e0f3a3532
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
5 changed files with 79 additions and 3 deletions

View File

@ -5,6 +5,8 @@ import p.studio.compiler.models.IRReservedMetadata;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.diagnostics.Diagnostics;
import p.studio.compiler.source.diagnostics.RelatedSpan;
import p.studio.compiler.source.identifiers.HostBindingId;
import p.studio.compiler.source.tables.HostBindingTable;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.HashMap;
@ -25,7 +27,8 @@ public final class PbsHostAdmissionValidator {
final var knownCapabilities = normalizedSet(context.knownCapabilities());
final var declaredCapabilities = normalizedSet(context.declaredCapabilities());
final var requiredCapabilities = new LinkedHashSet<String>();
final var firstCapabilityByHostBinding = new HashMap<String, FirstBindingCapability>();
final var hostBindingTable = new HostBindingTable();
final var firstCapabilityByHostBinding = new HashMap<HostBindingId, FirstBindingCapability>();
for (final var hostBinding : metadata.hostMethodBindings()) {
final var normalizedCapability = normalize(hostBinding.requiredCapability());
@ -68,12 +71,12 @@ public final class PbsHostAdmissionValidator {
continue;
}
final var bindingKey = "%s|%s|%d".formatted(
final var hostBindingId = hostBindingTable.register(
hostBinding.abiModule(),
hostBinding.abiMethod(),
hostBinding.abiVersion());
final var firstBindingCapability = firstCapabilityByHostBinding.putIfAbsent(
bindingKey,
hostBindingId,
new FirstBindingCapability(normalizedCapability, hostBinding.span()));
if (firstBindingCapability != null && !firstBindingCapability.capability().equals(normalizedCapability)) {
Diagnostics.error(

View File

@ -0,0 +1,7 @@
package p.studio.compiler.source.identifiers;
public class HostBindingId extends SourceIdentifier {
public HostBindingId(final int id) {
super(id);
}
}

View File

@ -0,0 +1,19 @@
package p.studio.compiler.source.tables;
import java.util.Objects;
public record HostBindingRef(
String module,
String name,
long version) {
public HostBindingRef {
module = Objects.requireNonNull(module, "module");
name = Objects.requireNonNull(name, "name");
if (module.isBlank() || name.isBlank()) {
throw new IllegalArgumentException("module and name must not be blank");
}
if (version < 0) {
throw new IllegalArgumentException("version must be non-negative");
}
}
}

View File

@ -0,0 +1,17 @@
package p.studio.compiler.source.tables;
import p.studio.compiler.source.identifiers.HostBindingId;
public class HostBindingTable extends InternTable<HostBindingId, HostBindingRef> {
public HostBindingTable() {
super(HostBindingId::new);
}
public HostBindingId register(
final String module,
final String name,
final long version) {
return register(new HostBindingRef(module, name, version));
}
}

View File

@ -0,0 +1,30 @@
package p.studio.compiler.source.tables;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class HostBindingTableTest {
@Test
void shouldInternEqualHostBindingsToSameIdentifier() {
final var table = new HostBindingTable();
final var first = table.register("gfx", "draw_pixel", 1);
final var second = table.register("gfx", "draw_pixel", 1);
final var third = table.register("gfx", "draw_pixel", 2);
assertEquals(first, second);
assertNotEquals(first, third);
assertEquals(2, table.size());
}
@Test
void shouldRejectInvalidHostBindingContract() {
assertThrows(IllegalArgumentException.class, () -> new HostBindingRef("", "draw_pixel", 1));
assertThrows(IllegalArgumentException.class, () -> new HostBindingRef("gfx", "", 1));
assertThrows(IllegalArgumentException.class, () -> new HostBindingRef("gfx", "draw_pixel", -1));
}
}