Add explicit CRDT edit contracts and structured query values

This commit is contained in:
Timothy J. Aveni
2026-09-19 22:33:20 -07:00
parent 0555c929b1
commit 4c0c404a39
27 changed files with 3272 additions and 2745 deletions
+21 -4
View File
@@ -405,6 +405,8 @@ const valueOperation = (displayName: string, id: InterfaceOperation["id"], value
outputType: value,
mode: "call",
};
case "edit":
return { id, displayName, inputType: { kind: "change", value }, outputType: valueType.unit, mode: "call" };
case "set":
return {
id,
@@ -494,6 +496,11 @@ const lowerValueMember = (state: LoweringState, context: ValueMemberContext): In
...valueOperation("get", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
...lowerExecution(operation.executionClause()),
});
} else if (operation.EDIT()) {
operations.push({
...valueOperation("edit", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
...lowerExecution(operation.executionClause()),
});
} else if (operation.SET()) {
operations.push({
...valueOperation("set", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
@@ -763,6 +770,13 @@ const lowerInterfaceTemplate = (
return [
{ ...signature("get", id, valueType.unit, type), ...lowerExecution(operation.executionClause()) },
];
if (operation.EDIT())
return [
{
...signature("edit", id, { kind: "change", value: type }, valueType.unit),
...lowerExecution(operation.executionClause()),
},
];
if (operation.SET())
return [
{ ...signature("set", id, type, valueType.unit), ...lowerExecution(operation.executionClause()) },
@@ -939,7 +953,9 @@ const lowerDependencyPort = (state: LoweringState, context: DependencyPortContex
.primitiveList()!
.primitive()
.map((entry) => text(entry));
const invalid = primitives.filter((entry) => !["read", "write", "watch-start", "watch-stop"].includes(entry));
const invalid = primitives.filter(
(entry) => !["read", "write", "edit", "watch-start", "watch-stop"].includes(entry),
);
if (invalid.length > 0) {
loweringIssue(state, context, "invalid-port-primitive", `State port cannot request ${invalid.join(", ")}`);
}
@@ -1405,12 +1421,12 @@ const lowerPackage = (
const name = identifier(clause.identifier(0));
const key = budgetNames[name],
n = Number(clause.INTEGER()!.getText());
if (!key || assigned.has(name) || !Number.isSafeInteger(n) || n < 1 || n > defaultQueryBudgets[key])
if (!key || assigned.has(name) || !Number.isSafeInteger(n) || n < 1 || n > 0xffffffff)
loweringIssue(
state,
clause,
"invalid-query-budget",
`Invalid, duplicate, or excessive query budget ${name}`,
`Invalid, duplicate, or out-of-range query budget ${name}`,
);
else {
declaration.budgets[key] = n;
@@ -1898,6 +1914,7 @@ const lowerConformance = (
const primitives = {
get: "read",
set: "write",
edit: "edit",
"watch-start": "watch-start",
"watch-stop": "watch-stop",
} as const;
@@ -2622,7 +2639,7 @@ const compileCapabilityResourceSourceInternal = (
portNames.add(port.displayName);
const requirement = port.requirement;
if (requirement.kind === "state") {
if (requirement.primitives.some((p) => !["read", "write", "watch-start", "watch-stop"].includes(p)))
if (requirement.primitives.some((p) => !["read", "write", "edit", "watch-start", "watch-stop"].includes(p)))
throw new GenericTypeError("invalid-port-primitive", port.displayName, "Invalid state primitive");
types.push(requirement.valueType);
}