Add factory creation ports and owner initialization contracts

This commit is contained in:
Timothy J. Aveni
2026-09-19 22:20:55 -07:00
parent 03ac7f8557
commit 0555c929b1
25 changed files with 3899 additions and 3012 deletions
+69 -4
View File
@@ -1009,6 +1009,14 @@ const lowerDependencyPort = (state: LoweringState, context: DependencyPortContex
: undefined;
}
const atomId = requireSymbol(state, state.atoms, targetName, context, "atom");
if (context.CREATION())
return atomId
? {
id,
displayName: name,
requirement: { kind: "creation", atomId, inputType: lowerValueType(state, context.valueType()) },
}
: undefined;
return atomId
? {
id,
@@ -1229,7 +1237,11 @@ const lowerGenericPackageExport = (
throw new GenericTypeError("missing-constructor-input", id, "Constructor ports require an explicit input type");
return {
...base,
requirement: { kind: "constructor", target, inputType: state.types.expression(port.valueType()!) },
requirement: {
kind: port.CREATION() ? "creation" : "constructor",
target,
inputType: state.types.expression(port.valueType()!),
},
};
});
const operation = "receiverRequirement" in context ? context : undefined;
@@ -1567,8 +1579,8 @@ const lowerState = (state: LoweringState, context: StateDeclContext): StateSlotD
attachedTo: atomId,
displayName: identifier(context.identifier(0)),
valueType: lowerValueType(state, context.valueType()),
storagePolicy: policy.OPTIMISTIC_REGISTER()
? { kind: "optimistic-register" }
storagePolicy: policy.REGISTER()
? { kind: "register" }
: {
kind: "crdt-document",
updateType: lowerValueType(state, policy.valueType()),
@@ -1774,6 +1786,24 @@ const lowerBoundDependencies = (
}
const atomName = identifier(entry.identifier(1));
const atomId = requireSymbol(state, state.atoms, atomName, entry, "atom");
if (entry.CREATION())
return atomId
? [
{
portId,
binding: {
kind: "creation",
atomId,
owners: entry.creationOwnerMapping().map((owner) => ({
interfaceRevisionId: new TypeSubstitution(state.types.environment()).application(
state.types.interface(owner.interfaceType()),
),
inputPath: owner.identifier().map(identifier),
})),
},
},
]
: [];
return atomId ? [{ portId, binding: { kind: "constructor", atomId } }] : [];
});
};
@@ -2025,8 +2055,43 @@ const lowerConformance = (
const lowered = lowerRelationshipMaterialization(state, interfaceName, materialization);
return lowered ? [lowered] : [];
});
const initializers = context
.conformanceItem()
.flatMap((item) => (item.initializationDecl() ? [item.initializationDecl()!] : []));
if (initializers.length > 1)
loweringIssue(state, context, "duplicate-initialization", "Declare one initialization mapping per owner");
const initialization = initializers.flatMap((initializer) =>
initializer.initializationField().flatMap((field): import("../capability-model/types.js").InitializationField[] => {
const input = identifier(field.identifier(0));
const attachment = requireSymbol(
state,
state.attachments,
identifier(field.identifier(1)),
field,
"initialization attachment",
);
if (!attachment) return [];
if (field.STATE() && attachment.attachment.kind === "state")
return [{ input, binding: { kind: "state", slotId: attachment.attachment.id } }];
if (field.EDGE() && attachment.attachment.kind === "edge") {
const projectionId = requireSymbol(
state,
attachment.projections,
identifier(field.identifier(2)),
field,
"initialization projection",
);
return projectionId
? [{ input, binding: { kind: "edge", edgeTypeId: attachment.attachment.id, projectionId } }]
: [];
}
loweringIssue(state, field, "invalid-initialization", "Initialization attachment kind does not match");
return [];
}),
);
state.interfaces.set(interfaceName, originalSymbol);
return {
...(initializers.length ? { initialization } : {}),
atomId,
interfaceRevisionId: interfaceSymbol.revisionId,
...(context.stringLiteral() ? { id: capabilityId.conformance(stringValue(context.stringLiteral()!)) } : {}),
@@ -2562,7 +2627,7 @@ const compileCapabilityResourceSourceInternal = (
types.push(requirement.valueType);
}
if (requirement.kind === "edge") types.push({ kind: "object-ref", expectation: requirement.target });
if (requirement.kind === "constructor")
if (requirement.kind === "constructor" || requirement.kind === "creation")
types.push(requirement.inputType, { kind: "object-ref", expectation: requirement.target });
if (requirement.kind === "interface") requires.push(requirement.application);
}