Add factory creation ports and owner initialization contracts
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user