Make local graph execution optional across composed packages
This commit is contained in:
@@ -205,6 +205,7 @@ interface LoweringState {
|
||||
fileName: string;
|
||||
diagnostics: CapabilitySourceDiagnostic[];
|
||||
atoms: Map<string, AtomId>;
|
||||
symbols: Map<string, string>;
|
||||
interfaces: Map<string, InterfaceSymbol>;
|
||||
packages: Map<string, PackageSymbol>;
|
||||
attachments: Map<string, AttachmentSymbol>;
|
||||
@@ -387,14 +388,33 @@ const lowerSelectedOperations = (
|
||||
return { operations };
|
||||
};
|
||||
|
||||
const lowerExecution = (context: ExecutionClauseContext | null): { execution?: ExecutionContract } => {
|
||||
const lowerExecution = (
|
||||
state: LoweringState,
|
||||
context: ExecutionClauseContext | null,
|
||||
implementation = false,
|
||||
): { execution?: ExecutionContract } => {
|
||||
if (!context) return {};
|
||||
if (!implementation && context.identifierList())
|
||||
loweringIssue(
|
||||
state,
|
||||
context,
|
||||
"interface-execution-targets",
|
||||
"Interfaces declare effects; execution targets belong to package implementations",
|
||||
);
|
||||
const targets = context
|
||||
.identifierList()
|
||||
?.identifier()
|
||||
.map((node) => {
|
||||
const name = identifier(node);
|
||||
if (name === "server") return name;
|
||||
return requireSymbol(state, state.symbols, name, node, "nominal execution target") ?? `unresolved:${name}`;
|
||||
}) ?? ["server"];
|
||||
return {
|
||||
execution: context.REMOTE()
|
||||
? { kind: "remote" }
|
||||
: {
|
||||
kind: context.SNAPSHOT() ? "snapshot" : "transaction",
|
||||
targets: context.identifierList()!.identifier().map(identifier),
|
||||
targets: implementation ? targets : ["server"],
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -508,17 +528,17 @@ const lowerValueMember = (state: LoweringState, context: ValueMemberContext): In
|
||||
if (operation.GET()) {
|
||||
operations.push({
|
||||
...valueOperation("get", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
});
|
||||
} else if (operation.EDIT()) {
|
||||
operations.push({
|
||||
...valueOperation("edit", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
});
|
||||
} else if (operation.SET()) {
|
||||
operations.push({
|
||||
...valueOperation("set", capabilityId.operation(stringValue(operation.stringLiteral(0))), memberValueType),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
});
|
||||
} else {
|
||||
operations.push(
|
||||
@@ -611,7 +631,7 @@ const lowerRelationshipMember = (
|
||||
);
|
||||
}
|
||||
if (operation.executionClause())
|
||||
Object.assign(operations[operations.length - 1]!, lowerExecution(operation.executionClause()));
|
||||
Object.assign(operations[operations.length - 1]!, lowerExecution(state, operation.executionClause()));
|
||||
}
|
||||
return {
|
||||
kind: "relationship",
|
||||
@@ -653,7 +673,7 @@ const lowerOperationMember = (state: LoweringState, context: OperationMemberCont
|
||||
outputType,
|
||||
mode: "call",
|
||||
...(context.STATIC() ? { scope: "class" as const } : {}),
|
||||
...lowerExecution(context.executionClause()),
|
||||
...lowerExecution(state, context.executionClause()),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -814,18 +834,24 @@ const lowerInterfaceTemplate = (
|
||||
const id = capabilityId.operation(stringValue(operation.stringLiteral(0)));
|
||||
if (operation.GET())
|
||||
return [
|
||||
{ ...signature("get", id, valueType.unit, type), ...lowerExecution(operation.executionClause()) },
|
||||
{
|
||||
...signature("get", id, valueType.unit, type),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
];
|
||||
if (operation.EDIT())
|
||||
return [
|
||||
{
|
||||
...signature("edit", id, { kind: "change", value: type }, valueType.unit),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
];
|
||||
if (operation.SET())
|
||||
return [
|
||||
{ ...signature("set", id, type, valueType.unit), ...lowerExecution(operation.executionClause()) },
|
||||
{
|
||||
...signature("set", id, type, valueType.unit),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
];
|
||||
return [
|
||||
signature("watch-start", id, valueType.unit, valueType.watchHandle, "watch-start", type),
|
||||
@@ -859,7 +885,7 @@ const lowerInterfaceTemplate = (
|
||||
outputType,
|
||||
),
|
||||
...(operation.STATIC() ? { scope: "class" as const } : {}),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -907,7 +933,10 @@ const lowerInterfaceTemplate = (
|
||||
const id = capabilityId.operation(stringValue(operation.stringLiteral(0)));
|
||||
if (operation.RESOLVE())
|
||||
return [
|
||||
{ ...signature("resolve", id, valueType.unit, resolved), ...lowerExecution(operation.executionClause()) },
|
||||
{
|
||||
...signature("resolve", id, valueType.unit, resolved),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
];
|
||||
if (operation.CONNECT() || operation.DISCONNECT())
|
||||
return [
|
||||
@@ -918,7 +947,7 @@ const lowerInterfaceTemplate = (
|
||||
operation.CONNECT() ? keyedTarget : targetType,
|
||||
valueType.unit,
|
||||
),
|
||||
...lowerExecution(operation.executionClause()),
|
||||
...lowerExecution(state, operation.executionClause()),
|
||||
},
|
||||
];
|
||||
return [
|
||||
@@ -1196,7 +1225,7 @@ const lowerPackageOperation = (
|
||||
inputType: lowerValueType(state, context.valueType(0)),
|
||||
outputType: lowerValueType(state, context.valueType(1)),
|
||||
mode: text(context.operationMode()) as InterfaceOperationMode,
|
||||
...lowerExecution(context.executionClause()),
|
||||
...lowerExecution(state, context.executionClause(), true),
|
||||
eventType: event ? lowerValueType(state, event.valueType()) : undefined,
|
||||
receiverRequirement: lowerReceiver(state, context.receiverRequirement()),
|
||||
dependencyPorts: ports,
|
||||
@@ -1213,7 +1242,7 @@ const lowerPackageFunction = (
|
||||
const alias = identifier(context.identifier());
|
||||
const entry: PackageExport = {
|
||||
kind: "function",
|
||||
...lowerExecution(context.executionClause()),
|
||||
...lowerExecution(state, context.executionClause(), true),
|
||||
id: capabilityId.packageExport(stringValue(context.stringLiteral())),
|
||||
displayName: alias,
|
||||
inputType: lowerValueType(state, context.valueType(0)),
|
||||
@@ -1355,7 +1384,7 @@ const lowerGenericPackageExport = (
|
||||
displayName: identifier(context.identifier()),
|
||||
parameters,
|
||||
kind: operation ? "operation" : "function",
|
||||
...lowerExecution(context.executionClause()),
|
||||
...lowerExecution(state, context.executionClause(), true),
|
||||
inputType: state.types.expression(context.valueType(0)!),
|
||||
outputType: state.types.expression(context.valueType(1)!),
|
||||
dependencyPorts,
|
||||
@@ -3092,6 +3121,7 @@ const newLoweringState = (fileName: string, diagnostics: CapabilitySourceDiagnos
|
||||
atoms,
|
||||
types: new GenericSourceTypes(atoms),
|
||||
interfaces: new Map(),
|
||||
symbols: new Map(),
|
||||
packages: new Map(),
|
||||
attachments: new Map(),
|
||||
};
|
||||
@@ -3240,6 +3270,20 @@ const compileCapabilityResourceSourceInternal = (
|
||||
const externalAtoms = externalAtomsFrom(state, preamble.atoms);
|
||||
const imports = registerImports(state, preamble.imports, environment);
|
||||
const externalInterfaces = externalInterfacesFrom(state, preamble.interfaces);
|
||||
for (const declaration of (interfaceContext ?? packageContext)!
|
||||
.resourcePreamble()
|
||||
.flatMap((entry) => entry.symbolDecl() ?? [])) {
|
||||
const name = identifier(declaration.identifier());
|
||||
const identity = stringValue(declaration.stringLiteral());
|
||||
if (name === "server" || identity === "server" || !identity.trim())
|
||||
loweringIssue(
|
||||
state,
|
||||
declaration,
|
||||
"invalid-symbol",
|
||||
"Nominal symbols require a nonempty identity distinct from the server executor",
|
||||
);
|
||||
declareSymbol(state, state.symbols, name, identity, declaration, "symbol");
|
||||
}
|
||||
state.types.declareAliases(preamble.aliases);
|
||||
|
||||
let resource: CapabilityResource;
|
||||
|
||||
Reference in New Issue
Block a user