Build workspace agent, capability graph, and versioned cutovers

This commit is contained in:
2026-09-05 12:33:52 -07:00
parent c4d42a0ac5
commit f5ced64533
53 changed files with 5527 additions and 2520 deletions
+80 -12
View File
@@ -13,10 +13,29 @@ on parse-tree shapes or declaration order.
```sh
nix develop
quixos-capability-compile ../quixos-instance/workspaces/todo.capabilities.qx
quixos-workspace-compile \
--root ../quixos-instance/workspaces/todo \
--checkout-root /tmp/quixos-resolved-resources
```
The compiler validates exact identities, interface operation coverage,
`workspace.qx` contains workspace-local atoms, attachments, conformances, and
constructor bindings. Each imported interface has an `interface.qx` in its own
repository; each imported package similarly has a `package.qx`. Source
locations never appear in those declarations. `quixos.lock` supplies their
exact Git repositories and commits, and the workspace compiler resolves that
dependency graph recursively.
Inside an interface or package manifest, `import interface Named;` is a true
source dependency: the repository lock must pin it, and tooling may use the
full contract for generated types. `external atom` and `external interface`
declare nominal identities which the final importing workspace must provide.
The latter is appropriate for relationship targets and other opaque
references; it deliberately does not grant the contract needed for an
interface invocation port. This distinction permits mutually referential
interface identities without creating a cycle in the Git Merkle graph.
The compiler validates exact identities, recursive lock/source agreement,
external requirement satisfaction, interface operation coverage,
attachment ownership, native state/edge providers, package receiver and
dependency-port requirements, constructors, and the exact runtime closure.
Generics, interface composition, declarative forwarding, automatic
@@ -26,21 +45,69 @@ from v1.
## Repository locks
Every workspace, interface, and package repository carries a `quixos.lock`.
It pins the exact Quixos toolchain revision plus exact Git sources for imported
interfaces and packages. The v1 Git source is deliberately only a repository
URL and full commit ID; the publisher-owned reachability tag and Nix fetch
details are derived from those values.
A resource lock is not a miniature workspace: it contains only the exact
Quixos commit that resource was authored against plus its dependency list.
It also pins exact Git sources for interfaces and packages named by that
resource's own manifest. Resource Git sources are deliberately only a
repository URL and full commit ID; the publisher-owned reachability tag and
Nix fetch details are derived from those values.
A workspace root additionally records its Quixos selection policy and ref.
Its `commit` is the exact compatibility baseline shared by the resource graph,
not necessarily the runtime candidate. `pinned` requires the ref, baseline,
and candidate to be one commit. `track-development` lets Central resolve the
named development ref to a newer candidate while preserving the authored
baseline. `track-release` is reserved for compatibility-filtered release-line
advancement and is not implemented yet.
```sh
quixos-lock-check quixos.lock
qx resource publish
quixos-resource-compile \
--root . --kind package \
--repository https://repos.quixos.org/example/package-example.git \
--commit 1111111111111111111111111111111111111111 \
--checkout-root /tmp/quixos-resource-dependencies
qx-workspace resource publish
```
The second command runs from a jj checkout. It validates the lock, snapshots
the current working-copy commit, and pushes the immutable tag
The resource compiler validates the local manifest against the recursively
resolved locks without turning the resource into a workspace. The final
command runs from a jj checkout. It performs that same recursive compilation,
snapshots the current working-copy commit, and pushes the immutable tag
`refs/tags/quixos-reachability/<commit>` without advancing an authoring
bookmark.
A workspace root may split its resource pins into same-repository fragments:
```text
quixos-lock version 1 {
quixos source {
repository "https://repos.quixos.org/quixos/quixos.git";
policy track-development;
ref "dev/alice/main";
commit "1111111111111111111111111111111111111111";
}
import "locks/web-studio.lock";
}
```
```text
quixos-lock fragment version 1 {
package CanvasRuntime source {
repository "https://repos.quixos.org/org-quixos-web-studio/package-canvas-runtime.git";
commit "2222222222222222222222222222222222222222";
}
}
```
Import paths are normalized, repository-root-relative paths. Absolute paths,
URLs, traversal, empty segments, directories, and symbolic links are rejected.
Fragments may import other fragments; cycles fail, shared fragments are loaded
once, and duplicate resource bindings fail across the flattened closure.
`quixos-lock-check` resolves the complete closure and reports its `sourceFiles`
alongside the flattened resources. The root Git commit content-addresses every
fragment, so fragments do not become independent repositories or identities.
## Package descriptors
Executable package metadata remains protobuf text format:
@@ -59,6 +126,7 @@ their exact dependency ports.
nix develop -c yarn test
```
The suite covers parsing/diagnostics, source-order independence, ordinary call
operations, semantic validation, exact closure/tree-shaking, private and shared
attachments, package port injection, and constructors.
The suite covers parsing/diagnostics, recursive repository assembly, external
requirement validation, source-order independence, ordinary call operations,
semantic validation, exact closure/tree-shaking, private and shared
attachments, related-object interface-port injection, and constructors.
+26
View File
@@ -15,20 +15,34 @@
src = pkgs.lib.cleanSource ./.;
overrideAttrs = old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [
pkgs.diffutils
pkgs.esbuild
pkgs.protobuf
];
buildPhase = ''
runHook preBuild
mkdir -p "$TMPDIR/generated-before"
cp --recursive src/gen "$TMPDIR/generated-before/proto"
cp --recursive src/capability-language/generated "$TMPDIR/generated-before/capability"
cp --recursive src/resource-lock/generated "$TMPDIR/generated-before/lock"
export QUIXOS_PROTO_PATH="${pkgs.protobuf}/include:$PWD/proto''${QUIXOS_PROTO_PATH:+:$QUIXOS_PROTO_PATH}"
patchShebangs node_modules/.bin node_modules/@bufbuild/protoc-gen-es/bin
yarn build
diff --recursive --unified "$TMPDIR/generated-before/proto" src/gen
diff --recursive --unified "$TMPDIR/generated-before/capability" src/capability-language/generated
diff --recursive --unified "$TMPDIR/generated-before/lock" src/resource-lock/generated
esbuild dist/src/descriptor-check.js \
--bundle --platform=node --target=node24 --format=esm \
--outfile=quixos-descriptor-check.mjs
esbuild dist/src/capability-language/cli.js \
--bundle --platform=node --target=node24 --format=esm \
--outfile=quixos-capability-compile.mjs
esbuild dist/src/capability-language/workspace-cli.js \
--bundle --platform=node --target=node24 --format=esm \
--outfile=quixos-workspace-compile.mjs
esbuild dist/src/capability-language/resource-cli.js \
--bundle --platform=node --target=node24 --format=esm \
--outfile=quixos-resource-compile.mjs
esbuild dist/src/resource-lock/cli.js \
--bundle --platform=node --target=node24 --format=esm \
--outfile=quixos-lock-check.mjs
@@ -60,6 +74,16 @@ EOF
exec ${pkgs.nodejs_24}/bin/node "$out/libexec/quixos-protocol/quixos-capability-compile.mjs" "\$@"
EOF
chmod +x "$out/bin/quixos-capability-compile"
cat > "$out/bin/quixos-workspace-compile" <<EOF
#!/bin/sh
exec ${pkgs.nodejs_24}/bin/node "$out/libexec/quixos-protocol/quixos-workspace-compile.mjs" "\$@"
EOF
chmod +x "$out/bin/quixos-workspace-compile"
cat > "$out/bin/quixos-resource-compile" <<EOF
#!/bin/sh
exec ${pkgs.nodejs_24}/bin/node "$out/libexec/quixos-protocol/quixos-resource-compile.mjs" "\$@"
EOF
chmod +x "$out/bin/quixos-resource-compile"
cat > "$out/bin/quixos-lock-check" <<EOF
#!/bin/sh
exec ${pkgs.nodejs_24}/bin/node "$out/libexec/quixos-protocol/quixos-lock-check.mjs" "\$@"
@@ -68,6 +92,8 @@ EOF
mkdir -p "$out/libexec/quixos-protocol"
install -m644 quixos-descriptor-check.mjs "$out/libexec/quixos-protocol/quixos-descriptor-check.mjs"
install -m644 quixos-capability-compile.mjs "$out/libexec/quixos-protocol/quixos-capability-compile.mjs"
install -m644 quixos-workspace-compile.mjs "$out/libexec/quixos-protocol/quixos-workspace-compile.mjs"
install -m644 quixos-resource-compile.mjs "$out/libexec/quixos-protocol/quixos-resource-compile.mjs"
install -m644 quixos-lock-check.mjs "$out/libexec/quixos-protocol/quixos-lock-check.mjs"
runHook postInstall
'';
+29 -14
View File
@@ -2,6 +2,8 @@ grammar QuixosCapability;
document
: workspaceDecl EOF
| interfaceResourceDecl EOF
| packageResourceDecl EOF
;
workspaceDecl
@@ -11,29 +13,40 @@ workspaceDecl
workspaceItem
: atomDecl
| interfaceDecl
| packageDecl
| resourceImportDecl
| sharedAttachmentDecl
| conformanceDecl
| constructorBindingDecl
;
resourceImportDecl
: IMPORT INTERFACE identifier SEMI
| IMPORT PACKAGE identifier SEMI
;
externalAtomDecl
: EXTERNAL ATOM identifier ID stringLiteral SEMI
;
externalInterfaceDecl
: EXTERNAL INTERFACE identifier REVISION stringLiteral SEMI
;
resourcePreamble
: resourceImportDecl
| externalAtomDecl
| externalInterfaceDecl
;
atomDecl
: ATOM identifier ID stringLiteral (DOC stringLiteral)? SEMI
;
interfaceDecl
: INTERFACE identifier ID stringLiteral REVISION stringLiteral sourceBlock
interfaceResourceDecl
: resourcePreamble* INTERFACE identifier ID stringLiteral REVISION stringLiteral
LBRACE interfaceMember* RBRACE
;
sourceBlock
: SOURCE LBRACE
REPOSITORY stringLiteral SEMI
COMMIT stringLiteral SEMI
RBRACE
;
interfaceMember
: valueMember
| relationshipMember
@@ -73,8 +86,8 @@ targetConstraint
| INTERFACE identifier
;
packageDecl
: PACKAGE identifier ID stringLiteral REVISION stringLiteral sourceBlock
packageResourceDecl
: resourcePreamble* PACKAGE identifier ID stringLiteral REVISION stringLiteral
LBRACE packageExport* RBRACE
;
@@ -237,7 +250,7 @@ dependencyBindingBlock
dependencyBinding
: identifier TO STATE identifier (VIA EDGE identifier DOT identifier)? SEMI
| identifier TO EDGE identifier DOT identifier (VIA EDGE identifier DOT identifier)? SEMI
| identifier TO INTERFACE identifier SEMI
| identifier TO INTERFACE identifier (VIA EDGE identifier DOT identifier)? SEMI
| identifier TO CONSTRUCTOR identifier SEMI
;
@@ -307,6 +320,8 @@ stringLiteral
;
WORKSPACE: 'workspace';
IMPORT: 'import';
EXTERNAL: 'external';
ATOM: 'atom';
INTERFACE: 'interface';
INTERFACES: 'interfaces';
+28 -2
View File
@@ -1,17 +1,22 @@
grammar QuixosLock;
document
: QUIXOS_LOCK VERSION INTEGER LBRACE quixosEntry resourceEntry* RBRACE EOF
: QUIXOS_LOCK FRAGMENT? VERSION INTEGER LBRACE
(quixosEntry | importEntry | resourceEntry)* RBRACE EOF
;
quixosEntry
: QUIXOS SOURCE sourceBlock
: QUIXOS SOURCE quixosSourceBlock
;
resourceEntry
: resourceKind identifier SOURCE sourceBlock
;
importEntry
: IMPORT stringLiteral SEMI
;
resourceKind
: INTERFACE
| PACKAGE
@@ -24,6 +29,20 @@ sourceBlock
RBRACE
;
quixosSourceBlock
: LBRACE
REPOSITORY stringLiteral SEMI
(POLICY sourcePolicy SEMI REF stringLiteral SEMI)?
COMMIT stringLiteral SEMI
RBRACE
;
sourcePolicy
: PINNED
| TRACK_RELEASE
| TRACK_DEVELOPMENT
;
identifier
: IDENTIFIER
;
@@ -33,6 +52,7 @@ stringLiteral
;
QUIXOS_LOCK: 'quixos-lock';
FRAGMENT: 'fragment';
VERSION: 'version';
QUIXOS: 'quixos';
SOURCE: 'source';
@@ -40,6 +60,12 @@ INTERFACE: 'interface';
PACKAGE: 'package';
REPOSITORY: 'repository';
COMMIT: 'commit';
POLICY: 'policy';
REF: 'ref';
PINNED: 'pinned';
TRACK_RELEASE: 'track-release';
TRACK_DEVELOPMENT: 'track-development';
IMPORT: 'import';
LBRACE: '{';
RBRACE: '}';
+2
View File
@@ -6,6 +6,8 @@
"type": "module",
"bin": {
"quixos-capability-compile": "dist/src/capability-language/cli.js",
"quixos-resource-compile": "dist/src/capability-language/resource-cli.js",
"quixos-workspace-compile": "dist/src/capability-language/workspace-cli.js",
"quixos-descriptor-check": "dist/src/descriptor-check.js",
"quixos-lock-check": "dist/src/resource-lock/cli.js"
},
+1
View File
@@ -49,6 +49,7 @@ message InvokeCapabilityResponse {
bool ok = 3;
camino.Value result = 4;
string error = 5;
repeated quixos.runtime.DerivedDependency dependencies = 6;
}
message WatchCapabilityRequest {
+1 -1
View File
@@ -17,7 +17,7 @@ message InjectedDependency {
oneof binding {
string state_slot_id = 2;
EdgeDependency edge = 3;
string receiver_interface_revision_id = 4;
string interface_revision_id = 4;
string constructor_atom_id = 5;
}
// Defaults to the invocation receiver. A checked dependency traversal can
+1
View File
@@ -29,6 +29,7 @@ message InvokeResponse {
bool ok = 1;
camino.Value result = 2;
string error = 3;
repeated DerivedDependency dependencies = 4;
}
message WatchRequest {
+365
View File
@@ -0,0 +1,365 @@
import { readFile } from "node:fs/promises";
import path from "node:path";
import {
capabilityId,
compileWorkspaceRevision,
type AtomDefinition,
type CompiledWorkspaceRevision,
type InterfaceRevision,
type PackageRevision,
type SourceRevision,
type WorkspaceRevision,
} from "../capability-model/index.js";
import {
loadQuixosLock,
type GitSource,
type LockedResource,
type QuixosRepositoryLock,
} from "../resource-lock/index.js";
import {
compileCapabilityResourceSource,
compileCapabilitySource,
type CapabilityImportEnvironment,
type CapabilityResource,
type CapabilityResourceImport,
} from "./parser.js";
export type CapabilityRepositorySnapshot = {
directory: string;
};
export type CapabilityRepositoryResolver = (
source: GitSource,
kind: LockedResource["kind"],
) => Promise<CapabilityRepositorySnapshot>;
export type ResolvedCapabilityResource = {
key: string;
kind: LockedResource["kind"];
source: GitSource;
directory: string;
lock: QuixosRepositoryLock;
resource: CapabilityResource;
dependencies: ReadonlyMap<string, ResolvedCapabilityResource>;
};
export type CompiledWorkspaceRepository = {
workspace: WorkspaceRevision;
plan: CompiledWorkspaceRevision;
lock: QuixosRepositoryLock;
resources: ResolvedCapabilityResource[];
directResources: ReadonlyMap<string, ResolvedCapabilityResource>;
};
export type CompiledCapabilityResourceRepository = {
resource: CapabilityResource;
lock: QuixosRepositoryLock;
resources: ResolvedCapabilityResource[];
directResources: ReadonlyMap<string, ResolvedCapabilityResource>;
};
const sourceKey = (kind: LockedResource["kind"], source: GitSource) =>
`${kind}\0${source.repository}\0${source.commit.toLowerCase()}`;
const bindingKey = (kind: LockedResource["kind"], binding: string) =>
`${kind}\0${binding}`;
const importsKey = (entry: CapabilityResourceImport | LockedResource) =>
bindingKey(entry.kind, entry.binding);
const assertImportsMatchLock = (
label: string,
imports: readonly CapabilityResourceImport[],
resources: readonly LockedResource[],
) => {
const authored = [...imports].map(importsKey).sort();
const locked = [...resources].map(importsKey).sort();
if (
authored.length !== locked.length ||
authored.some((entry, index) => entry !== locked[index])
) {
throw new Error(
`${label} imports do not match quixos.lock:\n` +
`authored: ${authored.join(", ") || "none"}\n` +
`locked: ${locked.join(", ") || "none"}`,
);
}
};
const exactRevisions = <Revision extends {
revisionId: string;
source: SourceRevision;
}>(revisions: readonly Revision[]) => {
const seen = new Set<string>();
return revisions.filter((revision) => {
const key = `${revision.revisionId}\0${revision.source.repository}\0${revision.source.commit}`;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
};
const exactAtoms = (atoms: readonly AtomDefinition[]) => {
const seen = new Set<string>();
return atoms.filter((atom) => {
if (seen.has(atom.id)) return false;
seen.add(atom.id);
return true;
});
};
const diagnosticsMessage = (
label: string,
diagnostics: readonly {
fileName: string;
line: number;
column: number;
phase: string;
code: string;
message: string;
path?: string;
}[],
) => `${label} did not compile:\n${diagnostics.map((entry) => {
const location = entry.line > 0
? `${entry.fileName}:${entry.line}:${entry.column + 1}`
: `${entry.fileName}${entry.path ? `:${entry.path}` : ""}`;
return `${location}: ${entry.phase} ${entry.code}: ${entry.message}`;
}).join("\n")}`;
const revisionFor = (node: ResolvedCapabilityResource) =>
node.resource.revision;
const resourceClosure = (
roots: readonly ResolvedCapabilityResource[],
): ResolvedCapabilityResource[] => {
const result: ResolvedCapabilityResource[] = [];
const seen = new Set<string>();
const visit = (node: ResolvedCapabilityResource) => {
if (seen.has(node.key)) return;
seen.add(node.key);
for (const dependency of node.dependencies.values()) visit(dependency);
result.push(node);
};
for (const root of roots) visit(root);
return result;
};
const environmentFor = (
direct: readonly [LockedResource, ResolvedCapabilityResource][],
closure: readonly ResolvedCapabilityResource[],
): CapabilityImportEnvironment => ({
interfaces: new Map(direct.flatMap(([locked, node]) =>
node.resource.kind === "interface"
? [[locked.binding, node.resource.revision] as const]
: [])),
packages: new Map(direct.flatMap(([locked, node]) =>
node.resource.kind === "package"
? [[locked.binding, node.resource.revision] as const]
: [])),
interfaceClosure: exactRevisions(closure.flatMap((node) =>
node.resource.kind === "interface" ? [node.resource.revision] : [])),
packageClosure: exactRevisions(closure.flatMap((node) =>
node.resource.kind === "package" ? [node.resource.revision] : [])),
externalAtoms: exactAtoms(closure.flatMap((node) => node.resource.externalAtoms)),
});
const createResourceGraphResolver = (
quixosCommit: string,
resolveResource: CapabilityRepositoryResolver,
) => {
const resolved = new Map<string, Promise<ResolvedCapabilityResource>>();
const active: string[] = [];
const visit = async (
locked: LockedResource,
suppliedSnapshot?: CapabilityRepositorySnapshot,
): Promise<ResolvedCapabilityResource> => {
const key = sourceKey(locked.kind, locked.source);
const cached = resolved.get(key);
if (cached) {
if (active.includes(key)) {
throw new Error(`Resource dependency cycle: ${[...active, key].join(" -> ")}`);
}
return await cached;
}
const pending = (async () => {
active.push(key);
try {
const snapshot = suppliedSnapshot ?? await resolveResource(locked.source, locked.kind);
const lockResult = await loadQuixosLock(path.join(snapshot.directory, "quixos.lock"));
if (!lockResult.ok) {
throw new Error(diagnosticsMessage(`${locked.kind} ${locked.binding} lock`, lockResult.diagnostics));
}
if (lockResult.lock.quixos.policy) {
throw new Error(
`${locked.kind} ${locked.binding} lock declares workspace Quixos policy ` +
`${lockResult.lock.quixos.policy}; resource locks may only declare their exact authored-against commit`,
);
}
if (lockResult.lock.quixos.commit.toLowerCase() !== quixosCommit.toLowerCase()) {
throw new Error(
`${locked.kind} ${locked.binding} selects Quixos ${lockResult.lock.quixos.commit}, ` +
`but the repository graph selects ${quixosCommit}`,
);
}
const directPairs: Array<[LockedResource, ResolvedCapabilityResource]> = [];
for (const dependency of lockResult.lock.resources) {
directPairs.push([dependency, await visit(dependency)]);
}
const dependencyClosure = resourceClosure(
directPairs.map(([, node]) => node),
);
const environment = environmentFor(directPairs, dependencyClosure);
const manifestName = locked.kind === "interface" ? "interface.qx" : "package.qx";
const manifestPath = path.join(snapshot.directory, manifestName);
const sourceText = await readFile(manifestPath, "utf8");
const compiled = compileCapabilityResourceSource(sourceText, {
source: locked.source,
fileName: manifestPath,
environment,
});
if (!compiled.ok) {
throw new Error(diagnosticsMessage(`${locked.kind} ${locked.binding}`, compiled.diagnostics));
}
if (compiled.resource.kind !== locked.kind) {
throw new Error(
`${manifestPath} declares ${compiled.resource.kind}, not ${locked.kind}`,
);
}
assertImportsMatchLock(manifestPath, compiled.resource.imports, lockResult.lock.resources);
return {
key,
kind: locked.kind,
source: locked.source,
directory: snapshot.directory,
lock: lockResult.lock,
resource: compiled.resource,
dependencies: new Map(directPairs.map(([dependency, node]) => [
bindingKey(dependency.kind, dependency.binding),
node,
])),
};
} finally {
active.pop();
}
})();
resolved.set(key, pending);
return await pending;
};
return {
visit,
nodes: async () => await Promise.all(resolved.values()),
};
};
export const compileCapabilityResourceRepository = async (options: {
rootDirectory: string;
kind: LockedResource["kind"];
source: GitSource;
resolveResource: CapabilityRepositoryResolver;
}): Promise<CompiledCapabilityResourceRepository> => {
const lockResult = await loadQuixosLock(path.join(options.rootDirectory, "quixos.lock"));
if (!lockResult.ok) {
throw new Error(diagnosticsMessage("Resource lock", lockResult.diagnostics));
}
const resolver = createResourceGraphResolver(
lockResult.lock.quixos.commit,
options.resolveResource,
);
const root = await resolver.visit({
kind: options.kind,
binding: "<root>",
source: options.source,
}, { directory: options.rootDirectory });
return {
resource: root.resource,
lock: root.lock,
resources: await resolver.nodes(),
directResources: root.dependencies,
};
};
export const compileWorkspaceRepository = async (options: {
rootDirectory: string;
resolveResource: CapabilityRepositoryResolver;
workspaceId?: string;
workspaceRevisionId?: string;
sourceRootCommit?: string;
}): Promise<CompiledWorkspaceRepository> => {
const rootLockResult = await loadQuixosLock(
path.join(options.rootDirectory, "quixos.lock"),
);
if (!rootLockResult.ok) {
throw new Error(diagnosticsMessage("Workspace lock", rootLockResult.diagnostics));
}
const rootLock = rootLockResult.lock;
const resolver = createResourceGraphResolver(rootLock.quixos.commit, options.resolveResource);
const directPairs: Array<[LockedResource, ResolvedCapabilityResource]> = [];
for (const locked of rootLock.resources) {
directPairs.push([locked, await resolver.visit(locked)]);
}
const nodes = await resolver.nodes();
const environment = environmentFor(directPairs, nodes);
const workspacePath = path.join(options.rootDirectory, "workspace.qx");
const workspaceSource = await readFile(workspacePath, "utf8");
const compiled = compileCapabilitySource(workspaceSource, workspacePath, environment);
if (!compiled.ok) {
throw new Error(diagnosticsMessage("Workspace", compiled.diagnostics));
}
assertImportsMatchLock(workspacePath, compiled.imports, rootLock.resources);
const availableInterfaceIds = new Set(
nodes.flatMap((node) => node.resource.kind === "interface"
? [node.resource.revision.revisionId]
: []),
);
const availableAtomIds = new Set(compiled.workspace.atoms.map((atom) => atom.id));
for (const node of nodes) {
for (const requirement of node.resource.externalInterfaces) {
if (!availableInterfaceIds.has(requirement.revisionId)) {
throw new Error(
`${node.kind} ${node.resource.revision.displayName} requires external interface ` +
`${requirement.binding} (${requirement.revisionId}), but the workspace resource graph does not provide it`,
);
}
}
for (const atom of node.resource.externalAtoms) {
if (!availableAtomIds.has(atom.id)) {
throw new Error(
`${node.kind} ${node.resource.revision.displayName} requires external atom ` +
`${atom.displayName} (${atom.id}), but the workspace does not define it`,
);
}
}
}
const workspace: WorkspaceRevision = {
...compiled.workspace,
...(options.workspaceId
? { workspaceId: capabilityId.workspace(options.workspaceId) }
: {}),
...(options.workspaceRevisionId
? { id: capabilityId.workspaceRevision(options.workspaceRevisionId) }
: {}),
...(options.sourceRootCommit
? { sourceRootCommit: options.sourceRootCommit }
: {}),
};
const checked = compileWorkspaceRevision(workspace);
if (!checked.ok) {
throw new Error(
`Instantiated workspace did not compile:\n${checked.issues.map((entry) =>
`${entry.path}: ${entry.message}`).join("\n")}`,
);
}
return {
workspace,
plan: checked.plan,
lock: rootLock,
resources: nodes,
directResources: new Map(directPairs.map(([locked, node]) => [
bindingKey(locked.kind, locked.binding),
node,
])),
};
};
File diff suppressed because one or more lines are too long
@@ -1,193 +1,197 @@
WORKSPACE=1
ATOM=2
INTERFACE=3
INTERFACES=4
PACKAGE=5
VALUE=6
RELATION=7
OPERATION=8
FUNCTION=9
CONSTRUCTOR=10
CONSTRUCTS=11
CONFORM=12
AS=13
BIND=14
TO=15
PRIVATE=16
SHARED=17
STATE=18
EDGE=19
PROJECTION=20
WITH=21
USING=22
VIA=23
MATERIALIZE=24
IF=25
ABSENT=26
ON=27
POLICY=28
DEFAULT=29
SOURCE=30
REPOSITORY=31
COMMIT=32
REVISION=33
ID=34
DOC=35
MODE=36
EMITS=37
RECEIVER=38
REQUIRES=39
ANY=40
GET=41
SET=42
WATCH=43
START=44
STOP=45
READ=46
WRITE=47
RESOLVE=48
CONNECT=49
DISCONNECT=50
CALL=51
WATCH_START=52
WATCH_STOP=53
SUBSCRIBE=54
UNSUBSCRIBE=55
OPTIMISTIC_REGISTER=56
CRDT=57
OPTIONAL_ONE=58
EXACTLY_ONE=59
MANY_UNIQUE=60
MANY=61
ORDERED=62
UNIT=63
WATCH_HANDLE=64
MESSAGE=65
ATOM_REF=66
INTERFACE_REF=67
OPTIONAL=68
LIST=69
BOOL=70
BYTES=71
DOUBLE=72
INT32=73
INT64=74
STRING=75
UINT32=76
UINT64=77
TRUE=78
FALSE=79
NULL=80
ARROW=81
COLON=82
SEMI=83
COMMA=84
DOT=85
LBRACE=86
RBRACE=87
LBRACK=88
RBRACK=89
LPAREN=90
RPAREN=91
LT=92
GT=93
INTEGER=94
JSON_NUMBER=95
IDENTIFIER=96
STRING_LITERAL=97
LINE_COMMENT=98
BLOCK_COMMENT=99
WS=100
IMPORT=2
EXTERNAL=3
ATOM=4
INTERFACE=5
INTERFACES=6
PACKAGE=7
VALUE=8
RELATION=9
OPERATION=10
FUNCTION=11
CONSTRUCTOR=12
CONSTRUCTS=13
CONFORM=14
AS=15
BIND=16
TO=17
PRIVATE=18
SHARED=19
STATE=20
EDGE=21
PROJECTION=22
WITH=23
USING=24
VIA=25
MATERIALIZE=26
IF=27
ABSENT=28
ON=29
POLICY=30
DEFAULT=31
SOURCE=32
REPOSITORY=33
COMMIT=34
REVISION=35
ID=36
DOC=37
MODE=38
EMITS=39
RECEIVER=40
REQUIRES=41
ANY=42
GET=43
SET=44
WATCH=45
START=46
STOP=47
READ=48
WRITE=49
RESOLVE=50
CONNECT=51
DISCONNECT=52
CALL=53
WATCH_START=54
WATCH_STOP=55
SUBSCRIBE=56
UNSUBSCRIBE=57
OPTIMISTIC_REGISTER=58
CRDT=59
OPTIONAL_ONE=60
EXACTLY_ONE=61
MANY_UNIQUE=62
MANY=63
ORDERED=64
UNIT=65
WATCH_HANDLE=66
MESSAGE=67
ATOM_REF=68
INTERFACE_REF=69
OPTIONAL=70
LIST=71
BOOL=72
BYTES=73
DOUBLE=74
INT32=75
INT64=76
STRING=77
UINT32=78
UINT64=79
TRUE=80
FALSE=81
NULL=82
ARROW=83
COLON=84
SEMI=85
COMMA=86
DOT=87
LBRACE=88
RBRACE=89
LBRACK=90
RBRACK=91
LPAREN=92
RPAREN=93
LT=94
GT=95
INTEGER=96
JSON_NUMBER=97
IDENTIFIER=98
STRING_LITERAL=99
LINE_COMMENT=100
BLOCK_COMMENT=101
WS=102
'workspace'=1
'atom'=2
'interface'=3
'interfaces'=4
'package'=5
'value'=6
'relation'=7
'operation'=8
'function'=9
'constructor'=10
'constructs'=11
'conform'=12
'as'=13
'bind'=14
'to'=15
'private'=16
'shared'=17
'state'=18
'edge'=19
'projection'=20
'with'=21
'using'=22
'via'=23
'materialize'=24
'if'=25
'absent'=26
'on'=27
'policy'=28
'default'=29
'source'=30
'repository'=31
'commit'=32
'revision'=33
'id'=34
'doc'=35
'mode'=36
'emits'=37
'receiver'=38
'requires'=39
'any'=40
'get'=41
'set'=42
'watch'=43
'start'=44
'stop'=45
'read'=46
'write'=47
'resolve'=48
'connect'=49
'disconnect'=50
'call'=51
'watch-start'=52
'watch-stop'=53
'subscribe'=54
'unsubscribe'=55
'optimistic-register'=56
'crdt'=57
'optional-one'=58
'exactly-one'=59
'many-unique'=60
'many'=61
'ordered'=62
'unit'=63
'watch-handle'=64
'message'=65
'atom-ref'=66
'interface-ref'=67
'optional'=68
'list'=69
'bool'=70
'bytes'=71
'double'=72
'int32'=73
'int64'=74
'string'=75
'uint32'=76
'uint64'=77
'true'=78
'false'=79
'null'=80
'->'=81
':'=82
';'=83
','=84
'.'=85
'{'=86
'}'=87
'['=88
']'=89
'('=90
')'=91
'<'=92
'>'=93
'import'=2
'external'=3
'atom'=4
'interface'=5
'interfaces'=6
'package'=7
'value'=8
'relation'=9
'operation'=10
'function'=11
'constructor'=12
'constructs'=13
'conform'=14
'as'=15
'bind'=16
'to'=17
'private'=18
'shared'=19
'state'=20
'edge'=21
'projection'=22
'with'=23
'using'=24
'via'=25
'materialize'=26
'if'=27
'absent'=28
'on'=29
'policy'=30
'default'=31
'source'=32
'repository'=33
'commit'=34
'revision'=35
'id'=36
'doc'=37
'mode'=38
'emits'=39
'receiver'=40
'requires'=41
'any'=42
'get'=43
'set'=44
'watch'=45
'start'=46
'stop'=47
'read'=48
'write'=49
'resolve'=50
'connect'=51
'disconnect'=52
'call'=53
'watch-start'=54
'watch-stop'=55
'subscribe'=56
'unsubscribe'=57
'optimistic-register'=58
'crdt'=59
'optional-one'=60
'exactly-one'=61
'many-unique'=62
'many'=63
'ordered'=64
'unit'=65
'watch-handle'=66
'message'=67
'atom-ref'=68
'interface-ref'=69
'optional'=70
'list'=71
'bool'=72
'bytes'=73
'double'=74
'int32'=75
'int64'=76
'string'=77
'uint32'=78
'uint64'=79
'true'=80
'false'=81
'null'=82
'->'=83
':'=84
';'=85
','=86
'.'=87
'{'=88
'}'=89
'['=90
']'=91
'('=92
')'=93
'<'=94
'>'=95
File diff suppressed because one or more lines are too long
@@ -1,193 +1,197 @@
WORKSPACE=1
ATOM=2
INTERFACE=3
INTERFACES=4
PACKAGE=5
VALUE=6
RELATION=7
OPERATION=8
FUNCTION=9
CONSTRUCTOR=10
CONSTRUCTS=11
CONFORM=12
AS=13
BIND=14
TO=15
PRIVATE=16
SHARED=17
STATE=18
EDGE=19
PROJECTION=20
WITH=21
USING=22
VIA=23
MATERIALIZE=24
IF=25
ABSENT=26
ON=27
POLICY=28
DEFAULT=29
SOURCE=30
REPOSITORY=31
COMMIT=32
REVISION=33
ID=34
DOC=35
MODE=36
EMITS=37
RECEIVER=38
REQUIRES=39
ANY=40
GET=41
SET=42
WATCH=43
START=44
STOP=45
READ=46
WRITE=47
RESOLVE=48
CONNECT=49
DISCONNECT=50
CALL=51
WATCH_START=52
WATCH_STOP=53
SUBSCRIBE=54
UNSUBSCRIBE=55
OPTIMISTIC_REGISTER=56
CRDT=57
OPTIONAL_ONE=58
EXACTLY_ONE=59
MANY_UNIQUE=60
MANY=61
ORDERED=62
UNIT=63
WATCH_HANDLE=64
MESSAGE=65
ATOM_REF=66
INTERFACE_REF=67
OPTIONAL=68
LIST=69
BOOL=70
BYTES=71
DOUBLE=72
INT32=73
INT64=74
STRING=75
UINT32=76
UINT64=77
TRUE=78
FALSE=79
NULL=80
ARROW=81
COLON=82
SEMI=83
COMMA=84
DOT=85
LBRACE=86
RBRACE=87
LBRACK=88
RBRACK=89
LPAREN=90
RPAREN=91
LT=92
GT=93
INTEGER=94
JSON_NUMBER=95
IDENTIFIER=96
STRING_LITERAL=97
LINE_COMMENT=98
BLOCK_COMMENT=99
WS=100
IMPORT=2
EXTERNAL=3
ATOM=4
INTERFACE=5
INTERFACES=6
PACKAGE=7
VALUE=8
RELATION=9
OPERATION=10
FUNCTION=11
CONSTRUCTOR=12
CONSTRUCTS=13
CONFORM=14
AS=15
BIND=16
TO=17
PRIVATE=18
SHARED=19
STATE=20
EDGE=21
PROJECTION=22
WITH=23
USING=24
VIA=25
MATERIALIZE=26
IF=27
ABSENT=28
ON=29
POLICY=30
DEFAULT=31
SOURCE=32
REPOSITORY=33
COMMIT=34
REVISION=35
ID=36
DOC=37
MODE=38
EMITS=39
RECEIVER=40
REQUIRES=41
ANY=42
GET=43
SET=44
WATCH=45
START=46
STOP=47
READ=48
WRITE=49
RESOLVE=50
CONNECT=51
DISCONNECT=52
CALL=53
WATCH_START=54
WATCH_STOP=55
SUBSCRIBE=56
UNSUBSCRIBE=57
OPTIMISTIC_REGISTER=58
CRDT=59
OPTIONAL_ONE=60
EXACTLY_ONE=61
MANY_UNIQUE=62
MANY=63
ORDERED=64
UNIT=65
WATCH_HANDLE=66
MESSAGE=67
ATOM_REF=68
INTERFACE_REF=69
OPTIONAL=70
LIST=71
BOOL=72
BYTES=73
DOUBLE=74
INT32=75
INT64=76
STRING=77
UINT32=78
UINT64=79
TRUE=80
FALSE=81
NULL=82
ARROW=83
COLON=84
SEMI=85
COMMA=86
DOT=87
LBRACE=88
RBRACE=89
LBRACK=90
RBRACK=91
LPAREN=92
RPAREN=93
LT=94
GT=95
INTEGER=96
JSON_NUMBER=97
IDENTIFIER=98
STRING_LITERAL=99
LINE_COMMENT=100
BLOCK_COMMENT=101
WS=102
'workspace'=1
'atom'=2
'interface'=3
'interfaces'=4
'package'=5
'value'=6
'relation'=7
'operation'=8
'function'=9
'constructor'=10
'constructs'=11
'conform'=12
'as'=13
'bind'=14
'to'=15
'private'=16
'shared'=17
'state'=18
'edge'=19
'projection'=20
'with'=21
'using'=22
'via'=23
'materialize'=24
'if'=25
'absent'=26
'on'=27
'policy'=28
'default'=29
'source'=30
'repository'=31
'commit'=32
'revision'=33
'id'=34
'doc'=35
'mode'=36
'emits'=37
'receiver'=38
'requires'=39
'any'=40
'get'=41
'set'=42
'watch'=43
'start'=44
'stop'=45
'read'=46
'write'=47
'resolve'=48
'connect'=49
'disconnect'=50
'call'=51
'watch-start'=52
'watch-stop'=53
'subscribe'=54
'unsubscribe'=55
'optimistic-register'=56
'crdt'=57
'optional-one'=58
'exactly-one'=59
'many-unique'=60
'many'=61
'ordered'=62
'unit'=63
'watch-handle'=64
'message'=65
'atom-ref'=66
'interface-ref'=67
'optional'=68
'list'=69
'bool'=70
'bytes'=71
'double'=72
'int32'=73
'int64'=74
'string'=75
'uint32'=76
'uint64'=77
'true'=78
'false'=79
'null'=80
'->'=81
':'=82
';'=83
','=84
'.'=85
'{'=86
'}'=87
'['=88
']'=89
'('=90
')'=91
'<'=92
'>'=93
'import'=2
'external'=3
'atom'=4
'interface'=5
'interfaces'=6
'package'=7
'value'=8
'relation'=9
'operation'=10
'function'=11
'constructor'=12
'constructs'=13
'conform'=14
'as'=15
'bind'=16
'to'=17
'private'=18
'shared'=19
'state'=20
'edge'=21
'projection'=22
'with'=23
'using'=24
'via'=25
'materialize'=26
'if'=27
'absent'=28
'on'=29
'policy'=30
'default'=31
'source'=32
'repository'=33
'commit'=34
'revision'=35
'id'=36
'doc'=37
'mode'=38
'emits'=39
'receiver'=40
'requires'=41
'any'=42
'get'=43
'set'=44
'watch'=45
'start'=46
'stop'=47
'read'=48
'write'=49
'resolve'=50
'connect'=51
'disconnect'=52
'call'=53
'watch-start'=54
'watch-stop'=55
'subscribe'=56
'unsubscribe'=57
'optimistic-register'=58
'crdt'=59
'optional-one'=60
'exactly-one'=61
'many-unique'=62
'many'=63
'ordered'=64
'unit'=65
'watch-handle'=66
'message'=67
'atom-ref'=68
'interface-ref'=69
'optional'=70
'list'=71
'bool'=72
'bytes'=73
'double'=74
'int32'=75
'int64'=76
'string'=77
'uint32'=78
'uint64'=79
'true'=80
'false'=81
'null'=82
'->'=83
':'=84
';'=85
','=86
'.'=87
'{'=88
'}'=89
'['=90
']'=91
'('=92
')'=93
'<'=94
'>'=95
@@ -5,146 +5,149 @@ import { Token } from "antlr4ng";
export class QuixosCapabilityLexer extends antlr.Lexer {
public static readonly WORKSPACE = 1;
public static readonly ATOM = 2;
public static readonly INTERFACE = 3;
public static readonly INTERFACES = 4;
public static readonly PACKAGE = 5;
public static readonly VALUE = 6;
public static readonly RELATION = 7;
public static readonly OPERATION = 8;
public static readonly FUNCTION = 9;
public static readonly CONSTRUCTOR = 10;
public static readonly CONSTRUCTS = 11;
public static readonly CONFORM = 12;
public static readonly AS = 13;
public static readonly BIND = 14;
public static readonly TO = 15;
public static readonly PRIVATE = 16;
public static readonly SHARED = 17;
public static readonly STATE = 18;
public static readonly EDGE = 19;
public static readonly PROJECTION = 20;
public static readonly WITH = 21;
public static readonly USING = 22;
public static readonly VIA = 23;
public static readonly MATERIALIZE = 24;
public static readonly IF = 25;
public static readonly ABSENT = 26;
public static readonly ON = 27;
public static readonly POLICY = 28;
public static readonly DEFAULT = 29;
public static readonly SOURCE = 30;
public static readonly REPOSITORY = 31;
public static readonly COMMIT = 32;
public static readonly REVISION = 33;
public static readonly ID = 34;
public static readonly DOC = 35;
public static readonly MODE = 36;
public static readonly EMITS = 37;
public static readonly RECEIVER = 38;
public static readonly REQUIRES = 39;
public static readonly ANY = 40;
public static readonly GET = 41;
public static readonly SET = 42;
public static readonly WATCH = 43;
public static readonly START = 44;
public static readonly STOP = 45;
public static readonly READ = 46;
public static readonly WRITE = 47;
public static readonly RESOLVE = 48;
public static readonly CONNECT = 49;
public static readonly DISCONNECT = 50;
public static readonly CALL = 51;
public static readonly WATCH_START = 52;
public static readonly WATCH_STOP = 53;
public static readonly SUBSCRIBE = 54;
public static readonly UNSUBSCRIBE = 55;
public static readonly OPTIMISTIC_REGISTER = 56;
public static readonly CRDT = 57;
public static readonly OPTIONAL_ONE = 58;
public static readonly EXACTLY_ONE = 59;
public static readonly MANY_UNIQUE = 60;
public static readonly MANY = 61;
public static readonly ORDERED = 62;
public static readonly UNIT = 63;
public static readonly WATCH_HANDLE = 64;
public static readonly MESSAGE = 65;
public static readonly ATOM_REF = 66;
public static readonly INTERFACE_REF = 67;
public static readonly OPTIONAL = 68;
public static readonly LIST = 69;
public static readonly BOOL = 70;
public static readonly BYTES = 71;
public static readonly DOUBLE = 72;
public static readonly INT32 = 73;
public static readonly INT64 = 74;
public static readonly STRING = 75;
public static readonly UINT32 = 76;
public static readonly UINT64 = 77;
public static readonly TRUE = 78;
public static readonly FALSE = 79;
public static readonly NULL = 80;
public static readonly ARROW = 81;
public static readonly COLON = 82;
public static readonly SEMI = 83;
public static readonly COMMA = 84;
public static readonly DOT = 85;
public static readonly LBRACE = 86;
public static readonly RBRACE = 87;
public static readonly LBRACK = 88;
public static readonly RBRACK = 89;
public static readonly LPAREN = 90;
public static readonly RPAREN = 91;
public static readonly LT = 92;
public static readonly GT = 93;
public static readonly INTEGER = 94;
public static readonly JSON_NUMBER = 95;
public static readonly IDENTIFIER = 96;
public static readonly STRING_LITERAL = 97;
public static readonly LINE_COMMENT = 98;
public static readonly BLOCK_COMMENT = 99;
public static readonly WS = 100;
public static readonly IMPORT = 2;
public static readonly EXTERNAL = 3;
public static readonly ATOM = 4;
public static readonly INTERFACE = 5;
public static readonly INTERFACES = 6;
public static readonly PACKAGE = 7;
public static readonly VALUE = 8;
public static readonly RELATION = 9;
public static readonly OPERATION = 10;
public static readonly FUNCTION = 11;
public static readonly CONSTRUCTOR = 12;
public static readonly CONSTRUCTS = 13;
public static readonly CONFORM = 14;
public static readonly AS = 15;
public static readonly BIND = 16;
public static readonly TO = 17;
public static readonly PRIVATE = 18;
public static readonly SHARED = 19;
public static readonly STATE = 20;
public static readonly EDGE = 21;
public static readonly PROJECTION = 22;
public static readonly WITH = 23;
public static readonly USING = 24;
public static readonly VIA = 25;
public static readonly MATERIALIZE = 26;
public static readonly IF = 27;
public static readonly ABSENT = 28;
public static readonly ON = 29;
public static readonly POLICY = 30;
public static readonly DEFAULT = 31;
public static readonly SOURCE = 32;
public static readonly REPOSITORY = 33;
public static readonly COMMIT = 34;
public static readonly REVISION = 35;
public static readonly ID = 36;
public static readonly DOC = 37;
public static readonly MODE = 38;
public static readonly EMITS = 39;
public static readonly RECEIVER = 40;
public static readonly REQUIRES = 41;
public static readonly ANY = 42;
public static readonly GET = 43;
public static readonly SET = 44;
public static readonly WATCH = 45;
public static readonly START = 46;
public static readonly STOP = 47;
public static readonly READ = 48;
public static readonly WRITE = 49;
public static readonly RESOLVE = 50;
public static readonly CONNECT = 51;
public static readonly DISCONNECT = 52;
public static readonly CALL = 53;
public static readonly WATCH_START = 54;
public static readonly WATCH_STOP = 55;
public static readonly SUBSCRIBE = 56;
public static readonly UNSUBSCRIBE = 57;
public static readonly OPTIMISTIC_REGISTER = 58;
public static readonly CRDT = 59;
public static readonly OPTIONAL_ONE = 60;
public static readonly EXACTLY_ONE = 61;
public static readonly MANY_UNIQUE = 62;
public static readonly MANY = 63;
public static readonly ORDERED = 64;
public static readonly UNIT = 65;
public static readonly WATCH_HANDLE = 66;
public static readonly MESSAGE = 67;
public static readonly ATOM_REF = 68;
public static readonly INTERFACE_REF = 69;
public static readonly OPTIONAL = 70;
public static readonly LIST = 71;
public static readonly BOOL = 72;
public static readonly BYTES = 73;
public static readonly DOUBLE = 74;
public static readonly INT32 = 75;
public static readonly INT64 = 76;
public static readonly STRING = 77;
public static readonly UINT32 = 78;
public static readonly UINT64 = 79;
public static readonly TRUE = 80;
public static readonly FALSE = 81;
public static readonly NULL = 82;
public static readonly ARROW = 83;
public static readonly COLON = 84;
public static readonly SEMI = 85;
public static readonly COMMA = 86;
public static readonly DOT = 87;
public static readonly LBRACE = 88;
public static readonly RBRACE = 89;
public static readonly LBRACK = 90;
public static readonly RBRACK = 91;
public static readonly LPAREN = 92;
public static readonly RPAREN = 93;
public static readonly LT = 94;
public static readonly GT = 95;
public static readonly INTEGER = 96;
public static readonly JSON_NUMBER = 97;
public static readonly IDENTIFIER = 98;
public static readonly STRING_LITERAL = 99;
public static readonly LINE_COMMENT = 100;
public static readonly BLOCK_COMMENT = 101;
public static readonly WS = 102;
public static readonly channelNames = [
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
];
public static readonly literalNames = [
null, "'workspace'", "'atom'", "'interface'", "'interfaces'", "'package'",
"'value'", "'relation'", "'operation'", "'function'", "'constructor'",
"'constructs'", "'conform'", "'as'", "'bind'", "'to'", "'private'",
"'shared'", "'state'", "'edge'", "'projection'", "'with'", "'using'",
"'via'", "'materialize'", "'if'", "'absent'", "'on'", "'policy'",
"'default'", "'source'", "'repository'", "'commit'", "'revision'",
"'id'", "'doc'", "'mode'", "'emits'", "'receiver'", "'requires'",
"'any'", "'get'", "'set'", "'watch'", "'start'", "'stop'", "'read'",
"'write'", "'resolve'", "'connect'", "'disconnect'", "'call'", "'watch-start'",
"'watch-stop'", "'subscribe'", "'unsubscribe'", "'optimistic-register'",
"'crdt'", "'optional-one'", "'exactly-one'", "'many-unique'", "'many'",
"'ordered'", "'unit'", "'watch-handle'", "'message'", "'atom-ref'",
"'interface-ref'", "'optional'", "'list'", "'bool'", "'bytes'",
"'double'", "'int32'", "'int64'", "'string'", "'uint32'", "'uint64'",
"'true'", "'false'", "'null'", "'->'", "':'", "';'", "','", "'.'",
"'{'", "'}'", "'['", "']'", "'('", "')'", "'<'", "'>'"
null, "'workspace'", "'import'", "'external'", "'atom'", "'interface'",
"'interfaces'", "'package'", "'value'", "'relation'", "'operation'",
"'function'", "'constructor'", "'constructs'", "'conform'", "'as'",
"'bind'", "'to'", "'private'", "'shared'", "'state'", "'edge'",
"'projection'", "'with'", "'using'", "'via'", "'materialize'", "'if'",
"'absent'", "'on'", "'policy'", "'default'", "'source'", "'repository'",
"'commit'", "'revision'", "'id'", "'doc'", "'mode'", "'emits'",
"'receiver'", "'requires'", "'any'", "'get'", "'set'", "'watch'",
"'start'", "'stop'", "'read'", "'write'", "'resolve'", "'connect'",
"'disconnect'", "'call'", "'watch-start'", "'watch-stop'", "'subscribe'",
"'unsubscribe'", "'optimistic-register'", "'crdt'", "'optional-one'",
"'exactly-one'", "'many-unique'", "'many'", "'ordered'", "'unit'",
"'watch-handle'", "'message'", "'atom-ref'", "'interface-ref'",
"'optional'", "'list'", "'bool'", "'bytes'", "'double'", "'int32'",
"'int64'", "'string'", "'uint32'", "'uint64'", "'true'", "'false'",
"'null'", "'->'", "':'", "';'", "','", "'.'", "'{'", "'}'", "'['",
"']'", "'('", "')'", "'<'", "'>'"
];
public static readonly symbolicNames = [
null, "WORKSPACE", "ATOM", "INTERFACE", "INTERFACES", "PACKAGE",
"VALUE", "RELATION", "OPERATION", "FUNCTION", "CONSTRUCTOR", "CONSTRUCTS",
"CONFORM", "AS", "BIND", "TO", "PRIVATE", "SHARED", "STATE", "EDGE",
"PROJECTION", "WITH", "USING", "VIA", "MATERIALIZE", "IF", "ABSENT",
"ON", "POLICY", "DEFAULT", "SOURCE", "REPOSITORY", "COMMIT", "REVISION",
"ID", "DOC", "MODE", "EMITS", "RECEIVER", "REQUIRES", "ANY", "GET",
"SET", "WATCH", "START", "STOP", "READ", "WRITE", "RESOLVE", "CONNECT",
"DISCONNECT", "CALL", "WATCH_START", "WATCH_STOP", "SUBSCRIBE",
"UNSUBSCRIBE", "OPTIMISTIC_REGISTER", "CRDT", "OPTIONAL_ONE", "EXACTLY_ONE",
"MANY_UNIQUE", "MANY", "ORDERED", "UNIT", "WATCH_HANDLE", "MESSAGE",
"ATOM_REF", "INTERFACE_REF", "OPTIONAL", "LIST", "BOOL", "BYTES",
"DOUBLE", "INT32", "INT64", "STRING", "UINT32", "UINT64", "TRUE",
"FALSE", "NULL", "ARROW", "COLON", "SEMI", "COMMA", "DOT", "LBRACE",
"RBRACE", "LBRACK", "RBRACK", "LPAREN", "RPAREN", "LT", "GT", "INTEGER",
"JSON_NUMBER", "IDENTIFIER", "STRING_LITERAL", "LINE_COMMENT", "BLOCK_COMMENT",
"WS"
null, "WORKSPACE", "IMPORT", "EXTERNAL", "ATOM", "INTERFACE", "INTERFACES",
"PACKAGE", "VALUE", "RELATION", "OPERATION", "FUNCTION", "CONSTRUCTOR",
"CONSTRUCTS", "CONFORM", "AS", "BIND", "TO", "PRIVATE", "SHARED",
"STATE", "EDGE", "PROJECTION", "WITH", "USING", "VIA", "MATERIALIZE",
"IF", "ABSENT", "ON", "POLICY", "DEFAULT", "SOURCE", "REPOSITORY",
"COMMIT", "REVISION", "ID", "DOC", "MODE", "EMITS", "RECEIVER",
"REQUIRES", "ANY", "GET", "SET", "WATCH", "START", "STOP", "READ",
"WRITE", "RESOLVE", "CONNECT", "DISCONNECT", "CALL", "WATCH_START",
"WATCH_STOP", "SUBSCRIBE", "UNSUBSCRIBE", "OPTIMISTIC_REGISTER",
"CRDT", "OPTIONAL_ONE", "EXACTLY_ONE", "MANY_UNIQUE", "MANY", "ORDERED",
"UNIT", "WATCH_HANDLE", "MESSAGE", "ATOM_REF", "INTERFACE_REF",
"OPTIONAL", "LIST", "BOOL", "BYTES", "DOUBLE", "INT32", "INT64",
"STRING", "UINT32", "UINT64", "TRUE", "FALSE", "NULL", "ARROW",
"COLON", "SEMI", "COMMA", "DOT", "LBRACE", "RBRACE", "LBRACK", "RBRACK",
"LPAREN", "RPAREN", "LT", "GT", "INTEGER", "JSON_NUMBER", "IDENTIFIER",
"STRING_LITERAL", "LINE_COMMENT", "BLOCK_COMMENT", "WS"
];
public static readonly modeNames = [
@@ -152,22 +155,23 @@ export class QuixosCapabilityLexer extends antlr.Lexer {
];
public static readonly ruleNames = [
"WORKSPACE", "ATOM", "INTERFACE", "INTERFACES", "PACKAGE", "VALUE",
"RELATION", "OPERATION", "FUNCTION", "CONSTRUCTOR", "CONSTRUCTS",
"CONFORM", "AS", "BIND", "TO", "PRIVATE", "SHARED", "STATE", "EDGE",
"PROJECTION", "WITH", "USING", "VIA", "MATERIALIZE", "IF", "ABSENT",
"ON", "POLICY", "DEFAULT", "SOURCE", "REPOSITORY", "COMMIT", "REVISION",
"ID", "DOC", "MODE", "EMITS", "RECEIVER", "REQUIRES", "ANY", "GET",
"SET", "WATCH", "START", "STOP", "READ", "WRITE", "RESOLVE", "CONNECT",
"DISCONNECT", "CALL", "WATCH_START", "WATCH_STOP", "SUBSCRIBE",
"UNSUBSCRIBE", "OPTIMISTIC_REGISTER", "CRDT", "OPTIONAL_ONE", "EXACTLY_ONE",
"MANY_UNIQUE", "MANY", "ORDERED", "UNIT", "WATCH_HANDLE", "MESSAGE",
"ATOM_REF", "INTERFACE_REF", "OPTIONAL", "LIST", "BOOL", "BYTES",
"DOUBLE", "INT32", "INT64", "STRING", "UINT32", "UINT64", "TRUE",
"FALSE", "NULL", "ARROW", "COLON", "SEMI", "COMMA", "DOT", "LBRACE",
"RBRACE", "LBRACK", "RBRACK", "LPAREN", "RPAREN", "LT", "GT", "INTEGER",
"JSON_NUMBER", "IDENTIFIER", "STRING_LITERAL", "ESC", "HEX", "LINE_COMMENT",
"BLOCK_COMMENT", "WS",
"WORKSPACE", "IMPORT", "EXTERNAL", "ATOM", "INTERFACE", "INTERFACES",
"PACKAGE", "VALUE", "RELATION", "OPERATION", "FUNCTION", "CONSTRUCTOR",
"CONSTRUCTS", "CONFORM", "AS", "BIND", "TO", "PRIVATE", "SHARED",
"STATE", "EDGE", "PROJECTION", "WITH", "USING", "VIA", "MATERIALIZE",
"IF", "ABSENT", "ON", "POLICY", "DEFAULT", "SOURCE", "REPOSITORY",
"COMMIT", "REVISION", "ID", "DOC", "MODE", "EMITS", "RECEIVER",
"REQUIRES", "ANY", "GET", "SET", "WATCH", "START", "STOP", "READ",
"WRITE", "RESOLVE", "CONNECT", "DISCONNECT", "CALL", "WATCH_START",
"WATCH_STOP", "SUBSCRIBE", "UNSUBSCRIBE", "OPTIMISTIC_REGISTER",
"CRDT", "OPTIONAL_ONE", "EXACTLY_ONE", "MANY_UNIQUE", "MANY", "ORDERED",
"UNIT", "WATCH_HANDLE", "MESSAGE", "ATOM_REF", "INTERFACE_REF",
"OPTIONAL", "LIST", "BOOL", "BYTES", "DOUBLE", "INT32", "INT64",
"STRING", "UINT32", "UINT64", "TRUE", "FALSE", "NULL", "ARROW",
"COLON", "SEMI", "COMMA", "DOT", "LBRACE", "RBRACE", "LBRACK", "RBRACK",
"LPAREN", "RPAREN", "LT", "GT", "INTEGER", "JSON_NUMBER", "IDENTIFIER",
"STRING_LITERAL", "ESC", "HEX", "LINE_COMMENT", "BLOCK_COMMENT",
"WS",
];
@@ -189,7 +193,7 @@ export class QuixosCapabilityLexer extends antlr.Lexer {
public get modeNames(): string[] { return QuixosCapabilityLexer.modeNames; }
public static readonly _serializedATN: number[] = [
4,0,100,937,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
4,0,102,957,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,
19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,
@@ -204,324 +208,332 @@ export class QuixosCapabilityLexer extends antlr.Lexer {
78,7,78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,2,83,7,83,2,84,7,
84,2,85,7,85,2,86,7,86,2,87,7,87,2,88,7,88,2,89,7,89,2,90,7,90,2,
91,7,91,2,92,7,92,2,93,7,93,2,94,7,94,2,95,7,95,2,96,7,96,2,97,7,
97,2,98,7,98,2,99,7,99,2,100,7,100,2,101,7,101,1,0,1,0,1,0,1,0,1,
0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,
2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,
4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,
6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,
7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,
9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,
10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,12,1,12,1,
12,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,
15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,
17,1,17,1,17,1,17,1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,
19,1,19,1,19,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,21,1,
21,1,21,1,21,1,21,1,21,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,
23,1,23,1,23,1,23,1,23,1,23,1,23,1,23,1,24,1,24,1,24,1,25,1,25,1,
25,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,
27,1,27,1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,29,1,29,1,29,1,
29,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,30,1,30,1,30,1,30,1,
30,1,30,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,32,1,32,1,32,1,32,1,
32,1,32,1,32,1,32,1,32,1,33,1,33,1,33,1,34,1,34,1,34,1,34,1,35,1,
35,1,35,1,35,1,35,1,36,1,36,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,
37,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,
38,1,38,1,39,1,39,1,39,1,39,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,
41,1,42,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1,43,1,43,1,
44,1,44,1,44,1,44,1,44,1,45,1,45,1,45,1,45,1,45,1,46,1,46,1,46,1,
46,1,46,1,46,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,48,1,48,1,
48,1,48,1,48,1,48,1,48,1,48,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,
49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,
51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,52,1,52,1,52,1,
52,1,52,1,52,1,52,1,52,1,52,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,
53,1,53,1,53,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,
54,1,54,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,
55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,56,1,56,1,56,1,56,1,
56,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,
57,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,
59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,60,1,
60,1,60,1,60,1,60,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,62,1,
62,1,62,1,62,1,62,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,
63,1,63,1,63,1,63,1,64,1,64,1,64,1,64,1,64,1,64,1,64,1,64,1,65,1,
65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,66,1,66,1,66,1,66,1,66,1,
66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,67,1,67,1,67,1,67,1,
67,1,67,1,67,1,67,1,67,1,68,1,68,1,68,1,68,1,68,1,69,1,69,1,69,1,
69,1,69,1,70,1,70,1,70,1,70,1,70,1,70,1,71,1,71,1,71,1,71,1,71,1,
71,1,71,1,72,1,72,1,72,1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,
73,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,75,1,75,1,75,1,75,1,75,1,
75,1,75,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,77,1,77,1,77,1,77,1,
77,1,78,1,78,1,78,1,78,1,78,1,78,1,79,1,79,1,79,1,79,1,79,1,80,1,
80,1,80,1,81,1,81,1,82,1,82,1,83,1,83,1,84,1,84,1,85,1,85,1,86,1,
86,1,87,1,87,1,88,1,88,1,89,1,89,1,90,1,90,1,91,1,91,1,92,1,92,1,
93,3,93,838,8,93,1,93,4,93,841,8,93,11,93,12,93,842,1,94,3,94,846,
8,94,1,94,1,94,1,94,5,94,851,8,94,10,94,12,94,854,9,94,3,94,856,
8,94,1,94,1,94,4,94,860,8,94,11,94,12,94,861,3,94,864,8,94,1,94,
1,94,3,94,868,8,94,1,94,4,94,871,8,94,11,94,12,94,872,3,94,875,8,
94,1,95,1,95,5,95,879,8,95,10,95,12,95,882,9,95,1,96,1,96,1,96,5,
96,887,8,96,10,96,12,96,890,9,96,1,96,1,96,1,97,1,97,1,97,1,97,1,
97,1,97,1,97,1,97,3,97,902,8,97,1,98,1,98,1,99,1,99,1,99,1,99,5,
99,910,8,99,10,99,12,99,913,9,99,1,99,1,99,1,100,1,100,1,100,1,100,
5,100,921,8,100,10,100,12,100,924,9,100,1,100,1,100,1,100,1,100,
1,100,1,101,4,101,932,8,101,11,101,12,101,933,1,101,1,101,1,922,
0,102,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,
25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,
47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,
69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,
91,46,93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55,
111,56,113,57,115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,
65,131,66,133,67,135,68,137,69,139,70,141,71,143,72,145,73,147,74,
149,75,151,76,153,77,155,78,157,79,159,80,161,81,163,82,165,83,167,
84,169,85,171,86,173,87,175,88,177,89,179,90,181,91,183,92,185,93,
187,94,189,95,191,96,193,97,195,0,197,0,199,98,201,99,203,100,1,
0,11,1,0,48,57,1,0,49,57,2,0,69,69,101,101,2,0,43,43,45,45,3,0,65,
90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,4,0,10,10,13,13,34,
34,92,92,8,0,34,34,47,47,92,92,98,98,102,102,110,110,114,114,116,
116,3,0,48,57,65,70,97,102,2,0,10,10,13,13,3,0,9,10,13,13,32,32,
951,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,
0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,
0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,
0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,
0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,
0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,
0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,
0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,
0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,
0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99,1,0,0,0,
0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0,0,109,1,
0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0,117,1,0,0,0,0,
119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0,127,1,0,
0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0,135,1,0,0,0,0,137,
1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0,0,0,0,145,1,0,0,0,
0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,1,
0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,
165,1,0,0,0,0,167,1,0,0,0,0,169,1,0,0,0,0,171,1,0,0,0,0,173,1,0,
0,0,0,175,1,0,0,0,0,177,1,0,0,0,0,179,1,0,0,0,0,181,1,0,0,0,0,183,
1,0,0,0,0,185,1,0,0,0,0,187,1,0,0,0,0,189,1,0,0,0,0,191,1,0,0,0,
0,193,1,0,0,0,0,199,1,0,0,0,0,201,1,0,0,0,0,203,1,0,0,0,1,205,1,
0,0,0,3,215,1,0,0,0,5,220,1,0,0,0,7,230,1,0,0,0,9,241,1,0,0,0,11,
249,1,0,0,0,13,255,1,0,0,0,15,264,1,0,0,0,17,274,1,0,0,0,19,283,
1,0,0,0,21,295,1,0,0,0,23,306,1,0,0,0,25,314,1,0,0,0,27,317,1,0,
0,0,29,322,1,0,0,0,31,325,1,0,0,0,33,333,1,0,0,0,35,340,1,0,0,0,
37,346,1,0,0,0,39,351,1,0,0,0,41,362,1,0,0,0,43,367,1,0,0,0,45,373,
1,0,0,0,47,377,1,0,0,0,49,389,1,0,0,0,51,392,1,0,0,0,53,399,1,0,
0,0,55,402,1,0,0,0,57,409,1,0,0,0,59,417,1,0,0,0,61,424,1,0,0,0,
63,435,1,0,0,0,65,442,1,0,0,0,67,451,1,0,0,0,69,454,1,0,0,0,71,458,
1,0,0,0,73,463,1,0,0,0,75,469,1,0,0,0,77,478,1,0,0,0,79,487,1,0,
0,0,81,491,1,0,0,0,83,495,1,0,0,0,85,499,1,0,0,0,87,505,1,0,0,0,
89,511,1,0,0,0,91,516,1,0,0,0,93,521,1,0,0,0,95,527,1,0,0,0,97,535,
1,0,0,0,99,543,1,0,0,0,101,554,1,0,0,0,103,559,1,0,0,0,105,571,1,
0,0,0,107,582,1,0,0,0,109,592,1,0,0,0,111,604,1,0,0,0,113,624,1,
0,0,0,115,629,1,0,0,0,117,642,1,0,0,0,119,654,1,0,0,0,121,666,1,
0,0,0,123,671,1,0,0,0,125,679,1,0,0,0,127,684,1,0,0,0,129,697,1,
0,0,0,131,705,1,0,0,0,133,714,1,0,0,0,135,728,1,0,0,0,137,737,1,
0,0,0,139,742,1,0,0,0,141,747,1,0,0,0,143,753,1,0,0,0,145,760,1,
0,0,0,147,766,1,0,0,0,149,772,1,0,0,0,151,779,1,0,0,0,153,786,1,
0,0,0,155,793,1,0,0,0,157,798,1,0,0,0,159,804,1,0,0,0,161,809,1,
0,0,0,163,812,1,0,0,0,165,814,1,0,0,0,167,816,1,0,0,0,169,818,1,
0,0,0,171,820,1,0,0,0,173,822,1,0,0,0,175,824,1,0,0,0,177,826,1,
0,0,0,179,828,1,0,0,0,181,830,1,0,0,0,183,832,1,0,0,0,185,834,1,
0,0,0,187,837,1,0,0,0,189,845,1,0,0,0,191,876,1,0,0,0,193,883,1,
0,0,0,195,893,1,0,0,0,197,903,1,0,0,0,199,905,1,0,0,0,201,916,1,
0,0,0,203,931,1,0,0,0,205,206,5,119,0,0,206,207,5,111,0,0,207,208,
5,114,0,0,208,209,5,107,0,0,209,210,5,115,0,0,210,211,5,112,0,0,
211,212,5,97,0,0,212,213,5,99,0,0,213,214,5,101,0,0,214,2,1,0,0,
0,215,216,5,97,0,0,216,217,5,116,0,0,217,218,5,111,0,0,218,219,5,
109,0,0,219,4,1,0,0,0,220,221,5,105,0,0,221,222,5,110,0,0,222,223,
5,116,0,0,223,224,5,101,0,0,224,225,5,114,0,0,225,226,5,102,0,0,
226,227,5,97,0,0,227,228,5,99,0,0,228,229,5,101,0,0,229,6,1,0,0,
0,230,231,5,105,0,0,231,232,5,110,0,0,232,233,5,116,0,0,233,234,
5,101,0,0,234,235,5,114,0,0,235,236,5,102,0,0,236,237,5,97,0,0,237,
238,5,99,0,0,238,239,5,101,0,0,239,240,5,115,0,0,240,8,1,0,0,0,241,
242,5,112,0,0,242,243,5,97,0,0,243,244,5,99,0,0,244,245,5,107,0,
0,245,246,5,97,0,0,246,247,5,103,0,0,247,248,5,101,0,0,248,10,1,
0,0,0,249,250,5,118,0,0,250,251,5,97,0,0,251,252,5,108,0,0,252,253,
5,117,0,0,253,254,5,101,0,0,254,12,1,0,0,0,255,256,5,114,0,0,256,
257,5,101,0,0,257,258,5,108,0,0,258,259,5,97,0,0,259,260,5,116,0,
0,260,261,5,105,0,0,261,262,5,111,0,0,262,263,5,110,0,0,263,14,1,
0,0,0,264,265,5,111,0,0,265,266,5,112,0,0,266,267,5,101,0,0,267,
268,5,114,0,0,268,269,5,97,0,0,269,270,5,116,0,0,270,271,5,105,0,
0,271,272,5,111,0,0,272,273,5,110,0,0,273,16,1,0,0,0,274,275,5,102,
0,0,275,276,5,117,0,0,276,277,5,110,0,0,277,278,5,99,0,0,278,279,
5,116,0,0,279,280,5,105,0,0,280,281,5,111,0,0,281,282,5,110,0,0,
282,18,1,0,0,0,283,284,5,99,0,0,284,285,5,111,0,0,285,286,5,110,
0,0,286,287,5,115,0,0,287,288,5,116,0,0,288,289,5,114,0,0,289,290,
5,117,0,0,290,291,5,99,0,0,291,292,5,116,0,0,292,293,5,111,0,0,293,
294,5,114,0,0,294,20,1,0,0,0,295,296,5,99,0,0,296,297,5,111,0,0,
297,298,5,110,0,0,298,299,5,115,0,0,299,300,5,116,0,0,300,301,5,
114,0,0,301,302,5,117,0,0,302,303,5,99,0,0,303,304,5,116,0,0,304,
305,5,115,0,0,305,22,1,0,0,0,306,307,5,99,0,0,307,308,5,111,0,0,
308,309,5,110,0,0,309,310,5,102,0,0,310,311,5,111,0,0,311,312,5,
114,0,0,312,313,5,109,0,0,313,24,1,0,0,0,314,315,5,97,0,0,315,316,
5,115,0,0,316,26,1,0,0,0,317,318,5,98,0,0,318,319,5,105,0,0,319,
320,5,110,0,0,320,321,5,100,0,0,321,28,1,0,0,0,322,323,5,116,0,0,
323,324,5,111,0,0,324,30,1,0,0,0,325,326,5,112,0,0,326,327,5,114,
0,0,327,328,5,105,0,0,328,329,5,118,0,0,329,330,5,97,0,0,330,331,
5,116,0,0,331,332,5,101,0,0,332,32,1,0,0,0,333,334,5,115,0,0,334,
335,5,104,0,0,335,336,5,97,0,0,336,337,5,114,0,0,337,338,5,101,0,
0,338,339,5,100,0,0,339,34,1,0,0,0,340,341,5,115,0,0,341,342,5,116,
0,0,342,343,5,97,0,0,343,344,5,116,0,0,344,345,5,101,0,0,345,36,
1,0,0,0,346,347,5,101,0,0,347,348,5,100,0,0,348,349,5,103,0,0,349,
350,5,101,0,0,350,38,1,0,0,0,351,352,5,112,0,0,352,353,5,114,0,0,
353,354,5,111,0,0,354,355,5,106,0,0,355,356,5,101,0,0,356,357,5,
99,0,0,357,358,5,116,0,0,358,359,5,105,0,0,359,360,5,111,0,0,360,
361,5,110,0,0,361,40,1,0,0,0,362,363,5,119,0,0,363,364,5,105,0,0,
364,365,5,116,0,0,365,366,5,104,0,0,366,42,1,0,0,0,367,368,5,117,
0,0,368,369,5,115,0,0,369,370,5,105,0,0,370,371,5,110,0,0,371,372,
5,103,0,0,372,44,1,0,0,0,373,374,5,118,0,0,374,375,5,105,0,0,375,
376,5,97,0,0,376,46,1,0,0,0,377,378,5,109,0,0,378,379,5,97,0,0,379,
380,5,116,0,0,380,381,5,101,0,0,381,382,5,114,0,0,382,383,5,105,
0,0,383,384,5,97,0,0,384,385,5,108,0,0,385,386,5,105,0,0,386,387,
5,122,0,0,387,388,5,101,0,0,388,48,1,0,0,0,389,390,5,105,0,0,390,
391,5,102,0,0,391,50,1,0,0,0,392,393,5,97,0,0,393,394,5,98,0,0,394,
395,5,115,0,0,395,396,5,101,0,0,396,397,5,110,0,0,397,398,5,116,
0,0,398,52,1,0,0,0,399,400,5,111,0,0,400,401,5,110,0,0,401,54,1,
0,0,0,402,403,5,112,0,0,403,404,5,111,0,0,404,405,5,108,0,0,405,
406,5,105,0,0,406,407,5,99,0,0,407,408,5,121,0,0,408,56,1,0,0,0,
409,410,5,100,0,0,410,411,5,101,0,0,411,412,5,102,0,0,412,413,5,
97,0,0,413,414,5,117,0,0,414,415,5,108,0,0,415,416,5,116,0,0,416,
58,1,0,0,0,417,418,5,115,0,0,418,419,5,111,0,0,419,420,5,117,0,0,
420,421,5,114,0,0,421,422,5,99,0,0,422,423,5,101,0,0,423,60,1,0,
0,0,424,425,5,114,0,0,425,426,5,101,0,0,426,427,5,112,0,0,427,428,
5,111,0,0,428,429,5,115,0,0,429,430,5,105,0,0,430,431,5,116,0,0,
431,432,5,111,0,0,432,433,5,114,0,0,433,434,5,121,0,0,434,62,1,0,
0,0,435,436,5,99,0,0,436,437,5,111,0,0,437,438,5,109,0,0,438,439,
5,109,0,0,439,440,5,105,0,0,440,441,5,116,0,0,441,64,1,0,0,0,442,
443,5,114,0,0,443,444,5,101,0,0,444,445,5,118,0,0,445,446,5,105,
0,0,446,447,5,115,0,0,447,448,5,105,0,0,448,449,5,111,0,0,449,450,
5,110,0,0,450,66,1,0,0,0,451,452,5,105,0,0,452,453,5,100,0,0,453,
68,1,0,0,0,454,455,5,100,0,0,455,456,5,111,0,0,456,457,5,99,0,0,
457,70,1,0,0,0,458,459,5,109,0,0,459,460,5,111,0,0,460,461,5,100,
0,0,461,462,5,101,0,0,462,72,1,0,0,0,463,464,5,101,0,0,464,465,5,
109,0,0,465,466,5,105,0,0,466,467,5,116,0,0,467,468,5,115,0,0,468,
74,1,0,0,0,469,470,5,114,0,0,470,471,5,101,0,0,471,472,5,99,0,0,
472,473,5,101,0,0,473,474,5,105,0,0,474,475,5,118,0,0,475,476,5,
101,0,0,476,477,5,114,0,0,477,76,1,0,0,0,478,479,5,114,0,0,479,480,
5,101,0,0,480,481,5,113,0,0,481,482,5,117,0,0,482,483,5,105,0,0,
483,484,5,114,0,0,484,485,5,101,0,0,485,486,5,115,0,0,486,78,1,0,
0,0,487,488,5,97,0,0,488,489,5,110,0,0,489,490,5,121,0,0,490,80,
1,0,0,0,491,492,5,103,0,0,492,493,5,101,0,0,493,494,5,116,0,0,494,
82,1,0,0,0,495,496,5,115,0,0,496,497,5,101,0,0,497,498,5,116,0,0,
498,84,1,0,0,0,499,500,5,119,0,0,500,501,5,97,0,0,501,502,5,116,
0,0,502,503,5,99,0,0,503,504,5,104,0,0,504,86,1,0,0,0,505,506,5,
115,0,0,506,507,5,116,0,0,507,508,5,97,0,0,508,509,5,114,0,0,509,
510,5,116,0,0,510,88,1,0,0,0,511,512,5,115,0,0,512,513,5,116,0,0,
513,514,5,111,0,0,514,515,5,112,0,0,515,90,1,0,0,0,516,517,5,114,
0,0,517,518,5,101,0,0,518,519,5,97,0,0,519,520,5,100,0,0,520,92,
1,0,0,0,521,522,5,119,0,0,522,523,5,114,0,0,523,524,5,105,0,0,524,
525,5,116,0,0,525,526,5,101,0,0,526,94,1,0,0,0,527,528,5,114,0,0,
528,529,5,101,0,0,529,530,5,115,0,0,530,531,5,111,0,0,531,532,5,
108,0,0,532,533,5,118,0,0,533,534,5,101,0,0,534,96,1,0,0,0,535,536,
5,99,0,0,536,537,5,111,0,0,537,538,5,110,0,0,538,539,5,110,0,0,539,
540,5,101,0,0,540,541,5,99,0,0,541,542,5,116,0,0,542,98,1,0,0,0,
543,544,5,100,0,0,544,545,5,105,0,0,545,546,5,115,0,0,546,547,5,
99,0,0,547,548,5,111,0,0,548,549,5,110,0,0,549,550,5,110,0,0,550,
551,5,101,0,0,551,552,5,99,0,0,552,553,5,116,0,0,553,100,1,0,0,0,
554,555,5,99,0,0,555,556,5,97,0,0,556,557,5,108,0,0,557,558,5,108,
0,0,558,102,1,0,0,0,559,560,5,119,0,0,560,561,5,97,0,0,561,562,5,
116,0,0,562,563,5,99,0,0,563,564,5,104,0,0,564,565,5,45,0,0,565,
566,5,115,0,0,566,567,5,116,0,0,567,568,5,97,0,0,568,569,5,114,0,
0,569,570,5,116,0,0,570,104,1,0,0,0,571,572,5,119,0,0,572,573,5,
97,0,0,573,574,5,116,0,0,574,575,5,99,0,0,575,576,5,104,0,0,576,
577,5,45,0,0,577,578,5,115,0,0,578,579,5,116,0,0,579,580,5,111,0,
0,580,581,5,112,0,0,581,106,1,0,0,0,582,583,5,115,0,0,583,584,5,
117,0,0,584,585,5,98,0,0,585,586,5,115,0,0,586,587,5,99,0,0,587,
588,5,114,0,0,588,589,5,105,0,0,589,590,5,98,0,0,590,591,5,101,0,
0,591,108,1,0,0,0,592,593,5,117,0,0,593,594,5,110,0,0,594,595,5,
115,0,0,595,596,5,117,0,0,596,597,5,98,0,0,597,598,5,115,0,0,598,
599,5,99,0,0,599,600,5,114,0,0,600,601,5,105,0,0,601,602,5,98,0,
0,602,603,5,101,0,0,603,110,1,0,0,0,604,605,5,111,0,0,605,606,5,
112,0,0,606,607,5,116,0,0,607,608,5,105,0,0,608,609,5,109,0,0,609,
610,5,105,0,0,610,611,5,115,0,0,611,612,5,116,0,0,612,613,5,105,
0,0,613,614,5,99,0,0,614,615,5,45,0,0,615,616,5,114,0,0,616,617,
5,101,0,0,617,618,5,103,0,0,618,619,5,105,0,0,619,620,5,115,0,0,
620,621,5,116,0,0,621,622,5,101,0,0,622,623,5,114,0,0,623,112,1,
0,0,0,624,625,5,99,0,0,625,626,5,114,0,0,626,627,5,100,0,0,627,628,
5,116,0,0,628,114,1,0,0,0,629,630,5,111,0,0,630,631,5,112,0,0,631,
632,5,116,0,0,632,633,5,105,0,0,633,634,5,111,0,0,634,635,5,110,
0,0,635,636,5,97,0,0,636,637,5,108,0,0,637,638,5,45,0,0,638,639,
5,111,0,0,639,640,5,110,0,0,640,641,5,101,0,0,641,116,1,0,0,0,642,
643,5,101,0,0,643,644,5,120,0,0,644,645,5,97,0,0,645,646,5,99,0,
0,646,647,5,116,0,0,647,648,5,108,0,0,648,649,5,121,0,0,649,650,
5,45,0,0,650,651,5,111,0,0,651,652,5,110,0,0,652,653,5,101,0,0,653,
118,1,0,0,0,654,655,5,109,0,0,655,656,5,97,0,0,656,657,5,110,0,0,
657,658,5,121,0,0,658,659,5,45,0,0,659,660,5,117,0,0,660,661,5,110,
0,0,661,662,5,105,0,0,662,663,5,113,0,0,663,664,5,117,0,0,664,665,
5,101,0,0,665,120,1,0,0,0,666,667,5,109,0,0,667,668,5,97,0,0,668,
669,5,110,0,0,669,670,5,121,0,0,670,122,1,0,0,0,671,672,5,111,0,
0,672,673,5,114,0,0,673,674,5,100,0,0,674,675,5,101,0,0,675,676,
5,114,0,0,676,677,5,101,0,0,677,678,5,100,0,0,678,124,1,0,0,0,679,
680,5,117,0,0,680,681,5,110,0,0,681,682,5,105,0,0,682,683,5,116,
0,0,683,126,1,0,0,0,684,685,5,119,0,0,685,686,5,97,0,0,686,687,5,
116,0,0,687,688,5,99,0,0,688,689,5,104,0,0,689,690,5,45,0,0,690,
691,5,104,0,0,691,692,5,97,0,0,692,693,5,110,0,0,693,694,5,100,0,
0,694,695,5,108,0,0,695,696,5,101,0,0,696,128,1,0,0,0,697,698,5,
109,0,0,698,699,5,101,0,0,699,700,5,115,0,0,700,701,5,115,0,0,701,
702,5,97,0,0,702,703,5,103,0,0,703,704,5,101,0,0,704,130,1,0,0,0,
705,706,5,97,0,0,706,707,5,116,0,0,707,708,5,111,0,0,708,709,5,109,
0,0,709,710,5,45,0,0,710,711,5,114,0,0,711,712,5,101,0,0,712,713,
5,102,0,0,713,132,1,0,0,0,714,715,5,105,0,0,715,716,5,110,0,0,716,
717,5,116,0,0,717,718,5,101,0,0,718,719,5,114,0,0,719,720,5,102,
0,0,720,721,5,97,0,0,721,722,5,99,0,0,722,723,5,101,0,0,723,724,
5,45,0,0,724,725,5,114,0,0,725,726,5,101,0,0,726,727,5,102,0,0,727,
134,1,0,0,0,728,729,5,111,0,0,729,730,5,112,0,0,730,731,5,116,0,
0,731,732,5,105,0,0,732,733,5,111,0,0,733,734,5,110,0,0,734,735,
5,97,0,0,735,736,5,108,0,0,736,136,1,0,0,0,737,738,5,108,0,0,738,
739,5,105,0,0,739,740,5,115,0,0,740,741,5,116,0,0,741,138,1,0,0,
0,742,743,5,98,0,0,743,744,5,111,0,0,744,745,5,111,0,0,745,746,5,
108,0,0,746,140,1,0,0,0,747,748,5,98,0,0,748,749,5,121,0,0,749,750,
5,116,0,0,750,751,5,101,0,0,751,752,5,115,0,0,752,142,1,0,0,0,753,
754,5,100,0,0,754,755,5,111,0,0,755,756,5,117,0,0,756,757,5,98,0,
0,757,758,5,108,0,0,758,759,5,101,0,0,759,144,1,0,0,0,760,761,5,
105,0,0,761,762,5,110,0,0,762,763,5,116,0,0,763,764,5,51,0,0,764,
765,5,50,0,0,765,146,1,0,0,0,766,767,5,105,0,0,767,768,5,110,0,0,
768,769,5,116,0,0,769,770,5,54,0,0,770,771,5,52,0,0,771,148,1,0,
0,0,772,773,5,115,0,0,773,774,5,116,0,0,774,775,5,114,0,0,775,776,
5,105,0,0,776,777,5,110,0,0,777,778,5,103,0,0,778,150,1,0,0,0,779,
780,5,117,0,0,780,781,5,105,0,0,781,782,5,110,0,0,782,783,5,116,
0,0,783,784,5,51,0,0,784,785,5,50,0,0,785,152,1,0,0,0,786,787,5,
117,0,0,787,788,5,105,0,0,788,789,5,110,0,0,789,790,5,116,0,0,790,
791,5,54,0,0,791,792,5,52,0,0,792,154,1,0,0,0,793,794,5,116,0,0,
794,795,5,114,0,0,795,796,5,117,0,0,796,797,5,101,0,0,797,156,1,
0,0,0,798,799,5,102,0,0,799,800,5,97,0,0,800,801,5,108,0,0,801,802,
5,115,0,0,802,803,5,101,0,0,803,158,1,0,0,0,804,805,5,110,0,0,805,
806,5,117,0,0,806,807,5,108,0,0,807,808,5,108,0,0,808,160,1,0,0,
0,809,810,5,45,0,0,810,811,5,62,0,0,811,162,1,0,0,0,812,813,5,58,
0,0,813,164,1,0,0,0,814,815,5,59,0,0,815,166,1,0,0,0,816,817,5,44,
0,0,817,168,1,0,0,0,818,819,5,46,0,0,819,170,1,0,0,0,820,821,5,123,
0,0,821,172,1,0,0,0,822,823,5,125,0,0,823,174,1,0,0,0,824,825,5,
91,0,0,825,176,1,0,0,0,826,827,5,93,0,0,827,178,1,0,0,0,828,829,
5,40,0,0,829,180,1,0,0,0,830,831,5,41,0,0,831,182,1,0,0,0,832,833,
5,60,0,0,833,184,1,0,0,0,834,835,5,62,0,0,835,186,1,0,0,0,836,838,
5,45,0,0,837,836,1,0,0,0,837,838,1,0,0,0,838,840,1,0,0,0,839,841,
7,0,0,0,840,839,1,0,0,0,841,842,1,0,0,0,842,840,1,0,0,0,842,843,
1,0,0,0,843,188,1,0,0,0,844,846,5,45,0,0,845,844,1,0,0,0,845,846,
1,0,0,0,846,855,1,0,0,0,847,856,5,48,0,0,848,852,7,1,0,0,849,851,
7,0,0,0,850,849,1,0,0,0,851,854,1,0,0,0,852,850,1,0,0,0,852,853,
1,0,0,0,853,856,1,0,0,0,854,852,1,0,0,0,855,847,1,0,0,0,855,848,
1,0,0,0,856,863,1,0,0,0,857,859,5,46,0,0,858,860,7,0,0,0,859,858,
1,0,0,0,860,861,1,0,0,0,861,859,1,0,0,0,861,862,1,0,0,0,862,864,
1,0,0,0,863,857,1,0,0,0,863,864,1,0,0,0,864,874,1,0,0,0,865,867,
7,2,0,0,866,868,7,3,0,0,867,866,1,0,0,0,867,868,1,0,0,0,868,870,
1,0,0,0,869,871,7,0,0,0,870,869,1,0,0,0,871,872,1,0,0,0,872,870,
1,0,0,0,872,873,1,0,0,0,873,875,1,0,0,0,874,865,1,0,0,0,874,875,
1,0,0,0,875,190,1,0,0,0,876,880,7,4,0,0,877,879,7,5,0,0,878,877,
1,0,0,0,879,882,1,0,0,0,880,878,1,0,0,0,880,881,1,0,0,0,881,192,
1,0,0,0,882,880,1,0,0,0,883,888,5,34,0,0,884,887,3,195,97,0,885,
887,8,6,0,0,886,884,1,0,0,0,886,885,1,0,0,0,887,890,1,0,0,0,888,
886,1,0,0,0,888,889,1,0,0,0,889,891,1,0,0,0,890,888,1,0,0,0,891,
892,5,34,0,0,892,194,1,0,0,0,893,901,5,92,0,0,894,902,7,7,0,0,895,
896,5,117,0,0,896,897,3,197,98,0,897,898,3,197,98,0,898,899,3,197,
98,0,899,900,3,197,98,0,900,902,1,0,0,0,901,894,1,0,0,0,901,895,
1,0,0,0,902,196,1,0,0,0,903,904,7,8,0,0,904,198,1,0,0,0,905,906,
5,47,0,0,906,907,5,47,0,0,907,911,1,0,0,0,908,910,8,9,0,0,909,908,
1,0,0,0,910,913,1,0,0,0,911,909,1,0,0,0,911,912,1,0,0,0,912,914,
1,0,0,0,913,911,1,0,0,0,914,915,6,99,0,0,915,200,1,0,0,0,916,917,
5,47,0,0,917,918,5,42,0,0,918,922,1,0,0,0,919,921,9,0,0,0,920,919,
1,0,0,0,921,924,1,0,0,0,922,923,1,0,0,0,922,920,1,0,0,0,923,925,
1,0,0,0,924,922,1,0,0,0,925,926,5,42,0,0,926,927,5,47,0,0,927,928,
1,0,0,0,928,929,6,100,0,0,929,202,1,0,0,0,930,932,7,10,0,0,931,930,
1,0,0,0,932,933,1,0,0,0,933,931,1,0,0,0,933,934,1,0,0,0,934,935,
1,0,0,0,935,936,6,101,0,0,936,204,1,0,0,0,18,0,837,842,845,852,855,
861,863,867,872,874,880,886,888,901,911,922,933,1,6,0,0
97,2,98,7,98,2,99,7,99,2,100,7,100,2,101,7,101,2,102,7,102,2,103,
7,103,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,
3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,
5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,
7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,
9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,
1,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,
1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,13,1,13,
1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,15,1,15,1,15,1,15,
1,15,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,18,
1,18,1,18,1,18,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,20,
1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,21,1,21,1,21,1,21,1,21,1,21,
1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,1,23,
1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,
1,25,1,25,1,25,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,27,
1,28,1,28,1,28,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,30,1,30,1,30,
1,30,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,32,
1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,33,1,33,1,33,
1,33,1,33,1,33,1,33,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,34,
1,35,1,35,1,35,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,38,
1,38,1,38,1,38,1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,
1,39,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,
1,41,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1,44,1,44,1,44,1,44,
1,44,1,44,1,45,1,45,1,45,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,46,
1,47,1,47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,48,1,48,1,49,1,49,
1,49,1,49,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,50,1,50,
1,50,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,52,
1,52,1,52,1,52,1,52,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,53,
1,53,1,53,1,53,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,1,54,
1,54,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,56,1,56,
1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,57,1,57,1,57,
1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,
1,57,1,57,1,57,1,57,1,58,1,58,1,58,1,58,1,58,1,59,1,59,1,59,1,59,
1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,59,1,60,1,60,1,60,1,60,
1,60,1,60,1,60,1,60,1,60,1,60,1,60,1,60,1,61,1,61,1,61,1,61,1,61,
1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,62,1,62,1,62,1,62,1,62,1,63,
1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,64,1,64,1,64,1,64,1,64,1,65,
1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,66,
1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,67,1,67,1,67,1,67,1,67,1,67,
1,67,1,67,1,67,1,68,1,68,1,68,1,68,1,68,1,68,1,68,1,68,1,68,1,68,
1,68,1,68,1,68,1,68,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,
1,70,1,70,1,70,1,70,1,70,1,71,1,71,1,71,1,71,1,71,1,72,1,72,1,72,
1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,73,1,73,1,74,1,74,1,74,
1,74,1,74,1,74,1,75,1,75,1,75,1,75,1,75,1,75,1,76,1,76,1,76,1,76,
1,76,1,76,1,76,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,78,1,78,1,78,
1,78,1,78,1,78,1,78,1,79,1,79,1,79,1,79,1,79,1,80,1,80,1,80,1,80,
1,80,1,80,1,81,1,81,1,81,1,81,1,81,1,82,1,82,1,82,1,83,1,83,1,84,
1,84,1,85,1,85,1,86,1,86,1,87,1,87,1,88,1,88,1,89,1,89,1,90,1,90,
1,91,1,91,1,92,1,92,1,93,1,93,1,94,1,94,1,95,3,95,858,8,95,1,95,
4,95,861,8,95,11,95,12,95,862,1,96,3,96,866,8,96,1,96,1,96,1,96,
5,96,871,8,96,10,96,12,96,874,9,96,3,96,876,8,96,1,96,1,96,4,96,
880,8,96,11,96,12,96,881,3,96,884,8,96,1,96,1,96,3,96,888,8,96,1,
96,4,96,891,8,96,11,96,12,96,892,3,96,895,8,96,1,97,1,97,5,97,899,
8,97,10,97,12,97,902,9,97,1,98,1,98,1,98,5,98,907,8,98,10,98,12,
98,910,9,98,1,98,1,98,1,99,1,99,1,99,1,99,1,99,1,99,1,99,1,99,3,
99,922,8,99,1,100,1,100,1,101,1,101,1,101,1,101,5,101,930,8,101,
10,101,12,101,933,9,101,1,101,1,101,1,102,1,102,1,102,1,102,5,102,
941,8,102,10,102,12,102,944,9,102,1,102,1,102,1,102,1,102,1,102,
1,103,4,103,952,8,103,11,103,12,103,953,1,103,1,103,1,942,0,104,
1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,
27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,
49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,
71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,
93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55,111,56,
113,57,115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,65,131,
66,133,67,135,68,137,69,139,70,141,71,143,72,145,73,147,74,149,75,
151,76,153,77,155,78,157,79,159,80,161,81,163,82,165,83,167,84,169,
85,171,86,173,87,175,88,177,89,179,90,181,91,183,92,185,93,187,94,
189,95,191,96,193,97,195,98,197,99,199,0,201,0,203,100,205,101,207,
102,1,0,11,1,0,48,57,1,0,49,57,2,0,69,69,101,101,2,0,43,43,45,45,
3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,4,0,10,10,13,
13,34,34,92,92,8,0,34,34,47,47,92,92,98,98,102,102,110,110,114,114,
116,116,3,0,48,57,65,70,97,102,2,0,10,10,13,13,3,0,9,10,13,13,32,
32,971,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,
0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,
0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,
0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,
0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,
0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,
0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,
0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,
0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,
0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99,1,0,0,
0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0,0,109,
1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0,117,1,0,0,0,
0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0,127,1,
0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0,135,1,0,0,0,0,
137,1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0,0,0,0,145,1,0,
0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,
1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,
0,165,1,0,0,0,0,167,1,0,0,0,0,169,1,0,0,0,0,171,1,0,0,0,0,173,1,
0,0,0,0,175,1,0,0,0,0,177,1,0,0,0,0,179,1,0,0,0,0,181,1,0,0,0,0,
183,1,0,0,0,0,185,1,0,0,0,0,187,1,0,0,0,0,189,1,0,0,0,0,191,1,0,
0,0,0,193,1,0,0,0,0,195,1,0,0,0,0,197,1,0,0,0,0,203,1,0,0,0,0,205,
1,0,0,0,0,207,1,0,0,0,1,209,1,0,0,0,3,219,1,0,0,0,5,226,1,0,0,0,
7,235,1,0,0,0,9,240,1,0,0,0,11,250,1,0,0,0,13,261,1,0,0,0,15,269,
1,0,0,0,17,275,1,0,0,0,19,284,1,0,0,0,21,294,1,0,0,0,23,303,1,0,
0,0,25,315,1,0,0,0,27,326,1,0,0,0,29,334,1,0,0,0,31,337,1,0,0,0,
33,342,1,0,0,0,35,345,1,0,0,0,37,353,1,0,0,0,39,360,1,0,0,0,41,366,
1,0,0,0,43,371,1,0,0,0,45,382,1,0,0,0,47,387,1,0,0,0,49,393,1,0,
0,0,51,397,1,0,0,0,53,409,1,0,0,0,55,412,1,0,0,0,57,419,1,0,0,0,
59,422,1,0,0,0,61,429,1,0,0,0,63,437,1,0,0,0,65,444,1,0,0,0,67,455,
1,0,0,0,69,462,1,0,0,0,71,471,1,0,0,0,73,474,1,0,0,0,75,478,1,0,
0,0,77,483,1,0,0,0,79,489,1,0,0,0,81,498,1,0,0,0,83,507,1,0,0,0,
85,511,1,0,0,0,87,515,1,0,0,0,89,519,1,0,0,0,91,525,1,0,0,0,93,531,
1,0,0,0,95,536,1,0,0,0,97,541,1,0,0,0,99,547,1,0,0,0,101,555,1,0,
0,0,103,563,1,0,0,0,105,574,1,0,0,0,107,579,1,0,0,0,109,591,1,0,
0,0,111,602,1,0,0,0,113,612,1,0,0,0,115,624,1,0,0,0,117,644,1,0,
0,0,119,649,1,0,0,0,121,662,1,0,0,0,123,674,1,0,0,0,125,686,1,0,
0,0,127,691,1,0,0,0,129,699,1,0,0,0,131,704,1,0,0,0,133,717,1,0,
0,0,135,725,1,0,0,0,137,734,1,0,0,0,139,748,1,0,0,0,141,757,1,0,
0,0,143,762,1,0,0,0,145,767,1,0,0,0,147,773,1,0,0,0,149,780,1,0,
0,0,151,786,1,0,0,0,153,792,1,0,0,0,155,799,1,0,0,0,157,806,1,0,
0,0,159,813,1,0,0,0,161,818,1,0,0,0,163,824,1,0,0,0,165,829,1,0,
0,0,167,832,1,0,0,0,169,834,1,0,0,0,171,836,1,0,0,0,173,838,1,0,
0,0,175,840,1,0,0,0,177,842,1,0,0,0,179,844,1,0,0,0,181,846,1,0,
0,0,183,848,1,0,0,0,185,850,1,0,0,0,187,852,1,0,0,0,189,854,1,0,
0,0,191,857,1,0,0,0,193,865,1,0,0,0,195,896,1,0,0,0,197,903,1,0,
0,0,199,913,1,0,0,0,201,923,1,0,0,0,203,925,1,0,0,0,205,936,1,0,
0,0,207,951,1,0,0,0,209,210,5,119,0,0,210,211,5,111,0,0,211,212,
5,114,0,0,212,213,5,107,0,0,213,214,5,115,0,0,214,215,5,112,0,0,
215,216,5,97,0,0,216,217,5,99,0,0,217,218,5,101,0,0,218,2,1,0,0,
0,219,220,5,105,0,0,220,221,5,109,0,0,221,222,5,112,0,0,222,223,
5,111,0,0,223,224,5,114,0,0,224,225,5,116,0,0,225,4,1,0,0,0,226,
227,5,101,0,0,227,228,5,120,0,0,228,229,5,116,0,0,229,230,5,101,
0,0,230,231,5,114,0,0,231,232,5,110,0,0,232,233,5,97,0,0,233,234,
5,108,0,0,234,6,1,0,0,0,235,236,5,97,0,0,236,237,5,116,0,0,237,238,
5,111,0,0,238,239,5,109,0,0,239,8,1,0,0,0,240,241,5,105,0,0,241,
242,5,110,0,0,242,243,5,116,0,0,243,244,5,101,0,0,244,245,5,114,
0,0,245,246,5,102,0,0,246,247,5,97,0,0,247,248,5,99,0,0,248,249,
5,101,0,0,249,10,1,0,0,0,250,251,5,105,0,0,251,252,5,110,0,0,252,
253,5,116,0,0,253,254,5,101,0,0,254,255,5,114,0,0,255,256,5,102,
0,0,256,257,5,97,0,0,257,258,5,99,0,0,258,259,5,101,0,0,259,260,
5,115,0,0,260,12,1,0,0,0,261,262,5,112,0,0,262,263,5,97,0,0,263,
264,5,99,0,0,264,265,5,107,0,0,265,266,5,97,0,0,266,267,5,103,0,
0,267,268,5,101,0,0,268,14,1,0,0,0,269,270,5,118,0,0,270,271,5,97,
0,0,271,272,5,108,0,0,272,273,5,117,0,0,273,274,5,101,0,0,274,16,
1,0,0,0,275,276,5,114,0,0,276,277,5,101,0,0,277,278,5,108,0,0,278,
279,5,97,0,0,279,280,5,116,0,0,280,281,5,105,0,0,281,282,5,111,0,
0,282,283,5,110,0,0,283,18,1,0,0,0,284,285,5,111,0,0,285,286,5,112,
0,0,286,287,5,101,0,0,287,288,5,114,0,0,288,289,5,97,0,0,289,290,
5,116,0,0,290,291,5,105,0,0,291,292,5,111,0,0,292,293,5,110,0,0,
293,20,1,0,0,0,294,295,5,102,0,0,295,296,5,117,0,0,296,297,5,110,
0,0,297,298,5,99,0,0,298,299,5,116,0,0,299,300,5,105,0,0,300,301,
5,111,0,0,301,302,5,110,0,0,302,22,1,0,0,0,303,304,5,99,0,0,304,
305,5,111,0,0,305,306,5,110,0,0,306,307,5,115,0,0,307,308,5,116,
0,0,308,309,5,114,0,0,309,310,5,117,0,0,310,311,5,99,0,0,311,312,
5,116,0,0,312,313,5,111,0,0,313,314,5,114,0,0,314,24,1,0,0,0,315,
316,5,99,0,0,316,317,5,111,0,0,317,318,5,110,0,0,318,319,5,115,0,
0,319,320,5,116,0,0,320,321,5,114,0,0,321,322,5,117,0,0,322,323,
5,99,0,0,323,324,5,116,0,0,324,325,5,115,0,0,325,26,1,0,0,0,326,
327,5,99,0,0,327,328,5,111,0,0,328,329,5,110,0,0,329,330,5,102,0,
0,330,331,5,111,0,0,331,332,5,114,0,0,332,333,5,109,0,0,333,28,1,
0,0,0,334,335,5,97,0,0,335,336,5,115,0,0,336,30,1,0,0,0,337,338,
5,98,0,0,338,339,5,105,0,0,339,340,5,110,0,0,340,341,5,100,0,0,341,
32,1,0,0,0,342,343,5,116,0,0,343,344,5,111,0,0,344,34,1,0,0,0,345,
346,5,112,0,0,346,347,5,114,0,0,347,348,5,105,0,0,348,349,5,118,
0,0,349,350,5,97,0,0,350,351,5,116,0,0,351,352,5,101,0,0,352,36,
1,0,0,0,353,354,5,115,0,0,354,355,5,104,0,0,355,356,5,97,0,0,356,
357,5,114,0,0,357,358,5,101,0,0,358,359,5,100,0,0,359,38,1,0,0,0,
360,361,5,115,0,0,361,362,5,116,0,0,362,363,5,97,0,0,363,364,5,116,
0,0,364,365,5,101,0,0,365,40,1,0,0,0,366,367,5,101,0,0,367,368,5,
100,0,0,368,369,5,103,0,0,369,370,5,101,0,0,370,42,1,0,0,0,371,372,
5,112,0,0,372,373,5,114,0,0,373,374,5,111,0,0,374,375,5,106,0,0,
375,376,5,101,0,0,376,377,5,99,0,0,377,378,5,116,0,0,378,379,5,105,
0,0,379,380,5,111,0,0,380,381,5,110,0,0,381,44,1,0,0,0,382,383,5,
119,0,0,383,384,5,105,0,0,384,385,5,116,0,0,385,386,5,104,0,0,386,
46,1,0,0,0,387,388,5,117,0,0,388,389,5,115,0,0,389,390,5,105,0,0,
390,391,5,110,0,0,391,392,5,103,0,0,392,48,1,0,0,0,393,394,5,118,
0,0,394,395,5,105,0,0,395,396,5,97,0,0,396,50,1,0,0,0,397,398,5,
109,0,0,398,399,5,97,0,0,399,400,5,116,0,0,400,401,5,101,0,0,401,
402,5,114,0,0,402,403,5,105,0,0,403,404,5,97,0,0,404,405,5,108,0,
0,405,406,5,105,0,0,406,407,5,122,0,0,407,408,5,101,0,0,408,52,1,
0,0,0,409,410,5,105,0,0,410,411,5,102,0,0,411,54,1,0,0,0,412,413,
5,97,0,0,413,414,5,98,0,0,414,415,5,115,0,0,415,416,5,101,0,0,416,
417,5,110,0,0,417,418,5,116,0,0,418,56,1,0,0,0,419,420,5,111,0,0,
420,421,5,110,0,0,421,58,1,0,0,0,422,423,5,112,0,0,423,424,5,111,
0,0,424,425,5,108,0,0,425,426,5,105,0,0,426,427,5,99,0,0,427,428,
5,121,0,0,428,60,1,0,0,0,429,430,5,100,0,0,430,431,5,101,0,0,431,
432,5,102,0,0,432,433,5,97,0,0,433,434,5,117,0,0,434,435,5,108,0,
0,435,436,5,116,0,0,436,62,1,0,0,0,437,438,5,115,0,0,438,439,5,111,
0,0,439,440,5,117,0,0,440,441,5,114,0,0,441,442,5,99,0,0,442,443,
5,101,0,0,443,64,1,0,0,0,444,445,5,114,0,0,445,446,5,101,0,0,446,
447,5,112,0,0,447,448,5,111,0,0,448,449,5,115,0,0,449,450,5,105,
0,0,450,451,5,116,0,0,451,452,5,111,0,0,452,453,5,114,0,0,453,454,
5,121,0,0,454,66,1,0,0,0,455,456,5,99,0,0,456,457,5,111,0,0,457,
458,5,109,0,0,458,459,5,109,0,0,459,460,5,105,0,0,460,461,5,116,
0,0,461,68,1,0,0,0,462,463,5,114,0,0,463,464,5,101,0,0,464,465,5,
118,0,0,465,466,5,105,0,0,466,467,5,115,0,0,467,468,5,105,0,0,468,
469,5,111,0,0,469,470,5,110,0,0,470,70,1,0,0,0,471,472,5,105,0,0,
472,473,5,100,0,0,473,72,1,0,0,0,474,475,5,100,0,0,475,476,5,111,
0,0,476,477,5,99,0,0,477,74,1,0,0,0,478,479,5,109,0,0,479,480,5,
111,0,0,480,481,5,100,0,0,481,482,5,101,0,0,482,76,1,0,0,0,483,484,
5,101,0,0,484,485,5,109,0,0,485,486,5,105,0,0,486,487,5,116,0,0,
487,488,5,115,0,0,488,78,1,0,0,0,489,490,5,114,0,0,490,491,5,101,
0,0,491,492,5,99,0,0,492,493,5,101,0,0,493,494,5,105,0,0,494,495,
5,118,0,0,495,496,5,101,0,0,496,497,5,114,0,0,497,80,1,0,0,0,498,
499,5,114,0,0,499,500,5,101,0,0,500,501,5,113,0,0,501,502,5,117,
0,0,502,503,5,105,0,0,503,504,5,114,0,0,504,505,5,101,0,0,505,506,
5,115,0,0,506,82,1,0,0,0,507,508,5,97,0,0,508,509,5,110,0,0,509,
510,5,121,0,0,510,84,1,0,0,0,511,512,5,103,0,0,512,513,5,101,0,0,
513,514,5,116,0,0,514,86,1,0,0,0,515,516,5,115,0,0,516,517,5,101,
0,0,517,518,5,116,0,0,518,88,1,0,0,0,519,520,5,119,0,0,520,521,5,
97,0,0,521,522,5,116,0,0,522,523,5,99,0,0,523,524,5,104,0,0,524,
90,1,0,0,0,525,526,5,115,0,0,526,527,5,116,0,0,527,528,5,97,0,0,
528,529,5,114,0,0,529,530,5,116,0,0,530,92,1,0,0,0,531,532,5,115,
0,0,532,533,5,116,0,0,533,534,5,111,0,0,534,535,5,112,0,0,535,94,
1,0,0,0,536,537,5,114,0,0,537,538,5,101,0,0,538,539,5,97,0,0,539,
540,5,100,0,0,540,96,1,0,0,0,541,542,5,119,0,0,542,543,5,114,0,0,
543,544,5,105,0,0,544,545,5,116,0,0,545,546,5,101,0,0,546,98,1,0,
0,0,547,548,5,114,0,0,548,549,5,101,0,0,549,550,5,115,0,0,550,551,
5,111,0,0,551,552,5,108,0,0,552,553,5,118,0,0,553,554,5,101,0,0,
554,100,1,0,0,0,555,556,5,99,0,0,556,557,5,111,0,0,557,558,5,110,
0,0,558,559,5,110,0,0,559,560,5,101,0,0,560,561,5,99,0,0,561,562,
5,116,0,0,562,102,1,0,0,0,563,564,5,100,0,0,564,565,5,105,0,0,565,
566,5,115,0,0,566,567,5,99,0,0,567,568,5,111,0,0,568,569,5,110,0,
0,569,570,5,110,0,0,570,571,5,101,0,0,571,572,5,99,0,0,572,573,5,
116,0,0,573,104,1,0,0,0,574,575,5,99,0,0,575,576,5,97,0,0,576,577,
5,108,0,0,577,578,5,108,0,0,578,106,1,0,0,0,579,580,5,119,0,0,580,
581,5,97,0,0,581,582,5,116,0,0,582,583,5,99,0,0,583,584,5,104,0,
0,584,585,5,45,0,0,585,586,5,115,0,0,586,587,5,116,0,0,587,588,5,
97,0,0,588,589,5,114,0,0,589,590,5,116,0,0,590,108,1,0,0,0,591,592,
5,119,0,0,592,593,5,97,0,0,593,594,5,116,0,0,594,595,5,99,0,0,595,
596,5,104,0,0,596,597,5,45,0,0,597,598,5,115,0,0,598,599,5,116,0,
0,599,600,5,111,0,0,600,601,5,112,0,0,601,110,1,0,0,0,602,603,5,
115,0,0,603,604,5,117,0,0,604,605,5,98,0,0,605,606,5,115,0,0,606,
607,5,99,0,0,607,608,5,114,0,0,608,609,5,105,0,0,609,610,5,98,0,
0,610,611,5,101,0,0,611,112,1,0,0,0,612,613,5,117,0,0,613,614,5,
110,0,0,614,615,5,115,0,0,615,616,5,117,0,0,616,617,5,98,0,0,617,
618,5,115,0,0,618,619,5,99,0,0,619,620,5,114,0,0,620,621,5,105,0,
0,621,622,5,98,0,0,622,623,5,101,0,0,623,114,1,0,0,0,624,625,5,111,
0,0,625,626,5,112,0,0,626,627,5,116,0,0,627,628,5,105,0,0,628,629,
5,109,0,0,629,630,5,105,0,0,630,631,5,115,0,0,631,632,5,116,0,0,
632,633,5,105,0,0,633,634,5,99,0,0,634,635,5,45,0,0,635,636,5,114,
0,0,636,637,5,101,0,0,637,638,5,103,0,0,638,639,5,105,0,0,639,640,
5,115,0,0,640,641,5,116,0,0,641,642,5,101,0,0,642,643,5,114,0,0,
643,116,1,0,0,0,644,645,5,99,0,0,645,646,5,114,0,0,646,647,5,100,
0,0,647,648,5,116,0,0,648,118,1,0,0,0,649,650,5,111,0,0,650,651,
5,112,0,0,651,652,5,116,0,0,652,653,5,105,0,0,653,654,5,111,0,0,
654,655,5,110,0,0,655,656,5,97,0,0,656,657,5,108,0,0,657,658,5,45,
0,0,658,659,5,111,0,0,659,660,5,110,0,0,660,661,5,101,0,0,661,120,
1,0,0,0,662,663,5,101,0,0,663,664,5,120,0,0,664,665,5,97,0,0,665,
666,5,99,0,0,666,667,5,116,0,0,667,668,5,108,0,0,668,669,5,121,0,
0,669,670,5,45,0,0,670,671,5,111,0,0,671,672,5,110,0,0,672,673,5,
101,0,0,673,122,1,0,0,0,674,675,5,109,0,0,675,676,5,97,0,0,676,677,
5,110,0,0,677,678,5,121,0,0,678,679,5,45,0,0,679,680,5,117,0,0,680,
681,5,110,0,0,681,682,5,105,0,0,682,683,5,113,0,0,683,684,5,117,
0,0,684,685,5,101,0,0,685,124,1,0,0,0,686,687,5,109,0,0,687,688,
5,97,0,0,688,689,5,110,0,0,689,690,5,121,0,0,690,126,1,0,0,0,691,
692,5,111,0,0,692,693,5,114,0,0,693,694,5,100,0,0,694,695,5,101,
0,0,695,696,5,114,0,0,696,697,5,101,0,0,697,698,5,100,0,0,698,128,
1,0,0,0,699,700,5,117,0,0,700,701,5,110,0,0,701,702,5,105,0,0,702,
703,5,116,0,0,703,130,1,0,0,0,704,705,5,119,0,0,705,706,5,97,0,0,
706,707,5,116,0,0,707,708,5,99,0,0,708,709,5,104,0,0,709,710,5,45,
0,0,710,711,5,104,0,0,711,712,5,97,0,0,712,713,5,110,0,0,713,714,
5,100,0,0,714,715,5,108,0,0,715,716,5,101,0,0,716,132,1,0,0,0,717,
718,5,109,0,0,718,719,5,101,0,0,719,720,5,115,0,0,720,721,5,115,
0,0,721,722,5,97,0,0,722,723,5,103,0,0,723,724,5,101,0,0,724,134,
1,0,0,0,725,726,5,97,0,0,726,727,5,116,0,0,727,728,5,111,0,0,728,
729,5,109,0,0,729,730,5,45,0,0,730,731,5,114,0,0,731,732,5,101,0,
0,732,733,5,102,0,0,733,136,1,0,0,0,734,735,5,105,0,0,735,736,5,
110,0,0,736,737,5,116,0,0,737,738,5,101,0,0,738,739,5,114,0,0,739,
740,5,102,0,0,740,741,5,97,0,0,741,742,5,99,0,0,742,743,5,101,0,
0,743,744,5,45,0,0,744,745,5,114,0,0,745,746,5,101,0,0,746,747,5,
102,0,0,747,138,1,0,0,0,748,749,5,111,0,0,749,750,5,112,0,0,750,
751,5,116,0,0,751,752,5,105,0,0,752,753,5,111,0,0,753,754,5,110,
0,0,754,755,5,97,0,0,755,756,5,108,0,0,756,140,1,0,0,0,757,758,5,
108,0,0,758,759,5,105,0,0,759,760,5,115,0,0,760,761,5,116,0,0,761,
142,1,0,0,0,762,763,5,98,0,0,763,764,5,111,0,0,764,765,5,111,0,0,
765,766,5,108,0,0,766,144,1,0,0,0,767,768,5,98,0,0,768,769,5,121,
0,0,769,770,5,116,0,0,770,771,5,101,0,0,771,772,5,115,0,0,772,146,
1,0,0,0,773,774,5,100,0,0,774,775,5,111,0,0,775,776,5,117,0,0,776,
777,5,98,0,0,777,778,5,108,0,0,778,779,5,101,0,0,779,148,1,0,0,0,
780,781,5,105,0,0,781,782,5,110,0,0,782,783,5,116,0,0,783,784,5,
51,0,0,784,785,5,50,0,0,785,150,1,0,0,0,786,787,5,105,0,0,787,788,
5,110,0,0,788,789,5,116,0,0,789,790,5,54,0,0,790,791,5,52,0,0,791,
152,1,0,0,0,792,793,5,115,0,0,793,794,5,116,0,0,794,795,5,114,0,
0,795,796,5,105,0,0,796,797,5,110,0,0,797,798,5,103,0,0,798,154,
1,0,0,0,799,800,5,117,0,0,800,801,5,105,0,0,801,802,5,110,0,0,802,
803,5,116,0,0,803,804,5,51,0,0,804,805,5,50,0,0,805,156,1,0,0,0,
806,807,5,117,0,0,807,808,5,105,0,0,808,809,5,110,0,0,809,810,5,
116,0,0,810,811,5,54,0,0,811,812,5,52,0,0,812,158,1,0,0,0,813,814,
5,116,0,0,814,815,5,114,0,0,815,816,5,117,0,0,816,817,5,101,0,0,
817,160,1,0,0,0,818,819,5,102,0,0,819,820,5,97,0,0,820,821,5,108,
0,0,821,822,5,115,0,0,822,823,5,101,0,0,823,162,1,0,0,0,824,825,
5,110,0,0,825,826,5,117,0,0,826,827,5,108,0,0,827,828,5,108,0,0,
828,164,1,0,0,0,829,830,5,45,0,0,830,831,5,62,0,0,831,166,1,0,0,
0,832,833,5,58,0,0,833,168,1,0,0,0,834,835,5,59,0,0,835,170,1,0,
0,0,836,837,5,44,0,0,837,172,1,0,0,0,838,839,5,46,0,0,839,174,1,
0,0,0,840,841,5,123,0,0,841,176,1,0,0,0,842,843,5,125,0,0,843,178,
1,0,0,0,844,845,5,91,0,0,845,180,1,0,0,0,846,847,5,93,0,0,847,182,
1,0,0,0,848,849,5,40,0,0,849,184,1,0,0,0,850,851,5,41,0,0,851,186,
1,0,0,0,852,853,5,60,0,0,853,188,1,0,0,0,854,855,5,62,0,0,855,190,
1,0,0,0,856,858,5,45,0,0,857,856,1,0,0,0,857,858,1,0,0,0,858,860,
1,0,0,0,859,861,7,0,0,0,860,859,1,0,0,0,861,862,1,0,0,0,862,860,
1,0,0,0,862,863,1,0,0,0,863,192,1,0,0,0,864,866,5,45,0,0,865,864,
1,0,0,0,865,866,1,0,0,0,866,875,1,0,0,0,867,876,5,48,0,0,868,872,
7,1,0,0,869,871,7,0,0,0,870,869,1,0,0,0,871,874,1,0,0,0,872,870,
1,0,0,0,872,873,1,0,0,0,873,876,1,0,0,0,874,872,1,0,0,0,875,867,
1,0,0,0,875,868,1,0,0,0,876,883,1,0,0,0,877,879,5,46,0,0,878,880,
7,0,0,0,879,878,1,0,0,0,880,881,1,0,0,0,881,879,1,0,0,0,881,882,
1,0,0,0,882,884,1,0,0,0,883,877,1,0,0,0,883,884,1,0,0,0,884,894,
1,0,0,0,885,887,7,2,0,0,886,888,7,3,0,0,887,886,1,0,0,0,887,888,
1,0,0,0,888,890,1,0,0,0,889,891,7,0,0,0,890,889,1,0,0,0,891,892,
1,0,0,0,892,890,1,0,0,0,892,893,1,0,0,0,893,895,1,0,0,0,894,885,
1,0,0,0,894,895,1,0,0,0,895,194,1,0,0,0,896,900,7,4,0,0,897,899,
7,5,0,0,898,897,1,0,0,0,899,902,1,0,0,0,900,898,1,0,0,0,900,901,
1,0,0,0,901,196,1,0,0,0,902,900,1,0,0,0,903,908,5,34,0,0,904,907,
3,199,99,0,905,907,8,6,0,0,906,904,1,0,0,0,906,905,1,0,0,0,907,910,
1,0,0,0,908,906,1,0,0,0,908,909,1,0,0,0,909,911,1,0,0,0,910,908,
1,0,0,0,911,912,5,34,0,0,912,198,1,0,0,0,913,921,5,92,0,0,914,922,
7,7,0,0,915,916,5,117,0,0,916,917,3,201,100,0,917,918,3,201,100,
0,918,919,3,201,100,0,919,920,3,201,100,0,920,922,1,0,0,0,921,914,
1,0,0,0,921,915,1,0,0,0,922,200,1,0,0,0,923,924,7,8,0,0,924,202,
1,0,0,0,925,926,5,47,0,0,926,927,5,47,0,0,927,931,1,0,0,0,928,930,
8,9,0,0,929,928,1,0,0,0,930,933,1,0,0,0,931,929,1,0,0,0,931,932,
1,0,0,0,932,934,1,0,0,0,933,931,1,0,0,0,934,935,6,101,0,0,935,204,
1,0,0,0,936,937,5,47,0,0,937,938,5,42,0,0,938,942,1,0,0,0,939,941,
9,0,0,0,940,939,1,0,0,0,941,944,1,0,0,0,942,943,1,0,0,0,942,940,
1,0,0,0,943,945,1,0,0,0,944,942,1,0,0,0,945,946,5,42,0,0,946,947,
5,47,0,0,947,948,1,0,0,0,948,949,6,102,0,0,949,206,1,0,0,0,950,952,
7,10,0,0,951,950,1,0,0,0,952,953,1,0,0,0,953,951,1,0,0,0,953,954,
1,0,0,0,954,955,1,0,0,0,955,956,6,103,0,0,956,208,1,0,0,0,18,0,857,
862,865,872,875,881,883,887,892,894,900,906,908,921,931,942,953,
1,6,0,0
];
private static __ATN: antlr.ATN;
File diff suppressed because it is too large Load Diff
@@ -5,9 +5,12 @@ import { AbstractParseTreeVisitor } from "antlr4ng";
import { DocumentContext } from "./QuixosCapabilityParser.js";
import { WorkspaceDeclContext } from "./QuixosCapabilityParser.js";
import { WorkspaceItemContext } from "./QuixosCapabilityParser.js";
import { ResourceImportDeclContext } from "./QuixosCapabilityParser.js";
import { ExternalAtomDeclContext } from "./QuixosCapabilityParser.js";
import { ExternalInterfaceDeclContext } from "./QuixosCapabilityParser.js";
import { ResourcePreambleContext } from "./QuixosCapabilityParser.js";
import { AtomDeclContext } from "./QuixosCapabilityParser.js";
import { InterfaceDeclContext } from "./QuixosCapabilityParser.js";
import { SourceBlockContext } from "./QuixosCapabilityParser.js";
import { InterfaceResourceDeclContext } from "./QuixosCapabilityParser.js";
import { InterfaceMemberContext } from "./QuixosCapabilityParser.js";
import { OperationMemberContext } from "./QuixosCapabilityParser.js";
import { ValueMemberContext } from "./QuixosCapabilityParser.js";
@@ -15,7 +18,7 @@ import { ValueMemberOperationContext } from "./QuixosCapabilityParser.js";
import { RelationshipMemberContext } from "./QuixosCapabilityParser.js";
import { RelationshipOperationContext } from "./QuixosCapabilityParser.js";
import { TargetConstraintContext } from "./QuixosCapabilityParser.js";
import { PackageDeclContext } from "./QuixosCapabilityParser.js";
import { PackageResourceDeclContext } from "./QuixosCapabilityParser.js";
import { PackageExportContext } from "./QuixosCapabilityParser.js";
import { PackageOperationExportContext } from "./QuixosCapabilityParser.js";
import { PackageFunctionExportContext } from "./QuixosCapabilityParser.js";
@@ -83,6 +86,30 @@ export class QuixosCapabilityVisitor<Result> extends AbstractParseTreeVisitor<Re
* @return the visitor result
*/
visitWorkspaceItem?: (ctx: WorkspaceItemContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.resourceImportDecl`.
* @param ctx the parse tree
* @return the visitor result
*/
visitResourceImportDecl?: (ctx: ResourceImportDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.externalAtomDecl`.
* @param ctx the parse tree
* @return the visitor result
*/
visitExternalAtomDecl?: (ctx: ExternalAtomDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.externalInterfaceDecl`.
* @param ctx the parse tree
* @return the visitor result
*/
visitExternalInterfaceDecl?: (ctx: ExternalInterfaceDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.resourcePreamble`.
* @param ctx the parse tree
* @return the visitor result
*/
visitResourcePreamble?: (ctx: ResourcePreambleContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.atomDecl`.
* @param ctx the parse tree
@@ -90,17 +117,11 @@ export class QuixosCapabilityVisitor<Result> extends AbstractParseTreeVisitor<Re
*/
visitAtomDecl?: (ctx: AtomDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.interfaceDecl`.
* Visit a parse tree produced by `QuixosCapabilityParser.interfaceResourceDecl`.
* @param ctx the parse tree
* @return the visitor result
*/
visitInterfaceDecl?: (ctx: InterfaceDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.sourceBlock`.
* @param ctx the parse tree
* @return the visitor result
*/
visitSourceBlock?: (ctx: SourceBlockContext) => Result;
visitInterfaceResourceDecl?: (ctx: InterfaceResourceDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.interfaceMember`.
* @param ctx the parse tree
@@ -144,11 +165,11 @@ export class QuixosCapabilityVisitor<Result> extends AbstractParseTreeVisitor<Re
*/
visitTargetConstraint?: (ctx: TargetConstraintContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.packageDecl`.
* Visit a parse tree produced by `QuixosCapabilityParser.packageResourceDecl`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPackageDecl?: (ctx: PackageDeclContext) => Result;
visitPackageResourceDecl?: (ctx: PackageResourceDeclContext) => Result;
/**
* Visit a parse tree produced by `QuixosCapabilityParser.packageExport`.
* @param ctx the parse tree
+86
View File
@@ -0,0 +1,86 @@
import childProcess from "node:child_process";
import crypto from "node:crypto";
import { mkdir, readFile, realpath } from "node:fs/promises";
import path from "node:path";
import { promisify } from "node:util";
import type { CapabilityRepositoryResolver } from "./assembly.js";
const execFile = promisify(childProcess.execFile);
const sourceKey = (kind: string, repository: string, commit: string) =>
`${kind}\0${repository}\0${commit.toLowerCase()}`;
const checkoutName = (kind: string, repository: string, commit: string) => {
const digest = crypto
.createHash("sha256")
.update(sourceKey(kind, repository, commit))
.digest("hex")
.slice(0, 24);
return `${kind}-${digest}`;
};
export const createGitCapabilityResolver = async (options: {
checkoutRoot: string;
snapshotMap?: string;
}): Promise<CapabilityRepositoryResolver> => {
await mkdir(options.checkoutRoot, { recursive: true });
const checkoutRoot = await realpath(options.checkoutRoot);
const snapshots = new Map<string, string>();
if (options.snapshotMap) {
const snapshotMapPath = await realpath(options.snapshotMap);
const document = JSON.parse(await readFile(snapshotMapPath, "utf8")) as {
resources?: Array<{
kind: string;
repository: string;
commit: string;
directory: string;
}>;
};
for (const entry of document.resources ?? []) {
if (entry.kind !== "interface" && entry.kind !== "package") {
throw new Error(`Snapshot map has unsupported resource kind ${entry.kind}`);
}
const key = sourceKey(entry.kind, entry.repository, entry.commit);
if (snapshots.has(key)) throw new Error(`Snapshot map repeats ${key}`);
const directory = path.resolve(path.dirname(snapshotMapPath), entry.directory);
snapshots.set(key, await realpath(directory));
}
}
const checkouts = new Map<string, Promise<{ directory: string }>>();
return async (source, kind) => {
const key = sourceKey(kind, source.repository, source.commit);
const snapshot = snapshots.get(key);
if (snapshot) return { directory: snapshot };
const existing = checkouts.get(key);
if (existing) return await existing;
const pending = (async () => {
const directory = path.join(
checkoutRoot,
checkoutName(kind, source.repository, source.commit),
);
await execFile("git", [
"-c",
"advice.detachedHead=false",
"clone",
"--depth",
"1",
"--single-branch",
"--branch",
`quixos-reachability/${source.commit.toLowerCase()}`,
source.repository,
directory,
]);
const { stdout } = await execFile("git", ["-C", directory, "rev-parse", "HEAD"]);
if (stdout.trim().toLowerCase() !== source.commit.toLowerCase()) {
throw new Error(
`Locked commit mismatch for ${source.repository}: ` +
`wanted ${source.commit}, fetched ${stdout.trim()}`,
);
}
return { directory };
})();
checkouts.set(key, pending);
return await pending;
};
};
+1
View File
@@ -1 +1,2 @@
export * from "./parser.js";
export * from "./assembly.js";
+457 -74
View File
@@ -27,6 +27,7 @@ import {
type InterfaceOperation,
type InterfaceOperationMode,
type InterfaceRevision,
type AtomDefinition,
type PackageExport,
type PackageReceiverRequirement,
type PackageRevision,
@@ -43,15 +44,19 @@ import { QuixosCapabilityParser,
type ConformanceDeclContext,
type DependencyBindingBlockContext,
type DependencyPortContext,
type DocumentContext,
type EdgeDeclContext,
type EdgeEndpointContext,
type InterfaceDeclContext,
type ExternalAtomDeclContext,
type ExternalInterfaceDeclContext,
type InterfaceResourceDeclContext,
type PackageConstructorExportContext,
type PackageDeclContext,
type PackageResourceDeclContext,
type PackageFunctionExportContext,
type PackageOperationExportContext,
type OperationMemberContext,
type SourceBlockContext,
type ResourceImportDeclContext,
type ResourcePreambleContext,
type StateDeclContext,
type TargetConstraintContext,
type ValueMemberContext,
@@ -61,6 +66,50 @@ import { QuixosCapabilityParser,
type WorkspaceDeclContext,
} from "./generated/QuixosCapabilityParser.js";
export type CapabilityResourceKind = "interface" | "package";
export type CapabilityResourceImport = {
kind: CapabilityResourceKind;
binding: string;
};
export type CapabilityExternalInterface = {
binding: string;
revisionId: InterfaceRevision["revisionId"];
};
export type CapabilityImportEnvironment = {
interfaces?: ReadonlyMap<string, InterfaceRevision>;
packages?: ReadonlyMap<string, PackageRevision>;
/** Complete resolved closure; direct maps above provide local authoring names. */
interfaceClosure?: readonly InterfaceRevision[];
packageClosure?: readonly PackageRevision[];
/** External nominal atoms required by imported resources. */
externalAtoms?: readonly AtomDefinition[];
/** External nominal interfaces supplied by the importing workspace. */
externalInterfaces?: readonly CapabilityExternalInterface[];
};
export type CapabilityResource =
| {
kind: "interface";
imports: CapabilityResourceImport[];
externalAtoms: AtomDefinition[];
externalInterfaces: CapabilityExternalInterface[];
revision: InterfaceRevision;
}
| {
kind: "package";
imports: CapabilityResourceImport[];
externalAtoms: AtomDefinition[];
externalInterfaces: CapabilityExternalInterface[];
revision: PackageRevision;
};
export type CapabilityResourceCompileResult =
| { ok: true; resource: CapabilityResource; diagnostics: [] }
| { ok: false; diagnostics: CapabilitySourceDiagnostic[] };
export type CapabilitySourceDiagnosticPhase =
| "syntax"
| "lowering"
@@ -81,6 +130,7 @@ export type CapabilitySourceCompileResult =
ok: true;
workspace: WorkspaceRevision;
plan: CompiledWorkspaceRevision;
imports: CapabilityResourceImport[];
diagnostics: [];
}
| {
@@ -90,6 +140,7 @@ export type CapabilitySourceCompileResult =
interface InterfaceSymbol {
revisionId: InterfaceRevision["revisionId"];
contractAvailable: boolean;
members: Map<
string,
{
@@ -220,11 +271,6 @@ const requireSymbol = <Value>(
return value;
};
const lowerSource = (context: SourceBlockContext): SourceRevision => ({
repository: stringValue(context.stringLiteral(0)),
commit: stringValue(context.stringLiteral(1)),
});
const lowerCardinality = (
context: { getText(): string } | null,
): EdgeCardinality => text(context) as EdgeCardinality;
@@ -534,7 +580,8 @@ const lowerOperationMember = (
const lowerInterface = (
state: LoweringState,
context: InterfaceDeclContext,
context: InterfaceResourceDeclContext,
source: SourceRevision,
): InterfaceRevision => {
const alias = identifier(context.identifier());
const members = context.interfaceMember().flatMap((entry) => {
@@ -572,7 +619,7 @@ const lowerInterface = (
interfaceId: capabilityId.interface(stringValue(context.stringLiteral(0))),
revisionId: symbol.revisionId,
displayName: alias,
source: lowerSource(context.sourceBlock()),
source,
members,
};
};
@@ -652,12 +699,21 @@ const lowerDependencyPort = (
context,
"interface",
);
if (target && !target.contractAvailable) {
loweringIssue(
state,
context,
"nominal-interface-port",
`Interface port ${name} needs the full ${targetName} contract; use import interface ${targetName}`,
);
return undefined;
}
return target
? {
id,
displayName: name,
requirement: {
kind: "receiver-interface",
kind: "interface",
interfaceRevisionId: target.revisionId,
},
}
@@ -815,7 +871,8 @@ const lowerPackageConstructor = (
const lowerPackage = (
state: LoweringState,
context: PackageDeclContext,
context: PackageResourceDeclContext,
source: SourceRevision,
): PackageRevision => {
const alias = identifier(context.identifier());
const exports = context.packageExport().map((exportContext) => {
@@ -837,7 +894,7 @@ const lowerPackage = (
packageId: capabilityId.package(stringValue(context.stringLiteral(0))),
revisionId: state.packages.get(alias)!.revisionId,
displayName: alias,
source: lowerSource(context.sourceBlock()),
source,
exports,
};
};
@@ -1064,7 +1121,7 @@ const lowerBoundDependencies = (
binding: { kind: "state", slotId: attachment.attachment.id, ...(via ? { via } : {}) },
}];
}
if (entry.EDGE(0)) {
if (entry.EDGE(0) && !entry.INTERFACE()) {
const attachmentName = identifier(entry.identifier(1));
const projectionName = identifier(entry.identifier(2));
const attachment = requireSymbol(
@@ -1119,13 +1176,18 @@ const lowerBoundDependencies = (
entry,
"interface",
);
const via = entry.VIA()
? traversal(identifier(entry.identifier(2)), identifier(entry.identifier(3)))
: undefined;
if (entry.VIA() && !via) return [];
return interfaceSymbol
? [
{
portId,
binding: {
kind: "receiver-interface",
kind: "interface",
interfaceRevisionId: interfaceSymbol.revisionId,
...(via ? { via } : {}),
},
},
]
@@ -1349,10 +1411,117 @@ const lowerConformance = (
};
};
const interfaceSymbolFor = (revision: InterfaceRevision): InterfaceSymbol => ({
revisionId: revision.revisionId,
contractAvailable: true,
members: new Map(revision.members.map((member) => [
member.displayName,
{
memberId: member.id,
operations: new Map(member.operations.map((operation) => [
operation.displayName,
operation.id,
])),
},
])),
});
const packageSymbolFor = (revision: PackageRevision): PackageSymbol => ({
revisionId: revision.revisionId,
exports: new Map(revision.exports.map((entry) => [
entry.displayName,
{
exportId: entry.id,
ports: new Map(entry.dependencyPorts.map((port) => [
port.displayName,
port.id,
])),
},
])),
});
const resourceImport = (
context: ResourceImportDeclContext,
): CapabilityResourceImport => ({
kind: context.INTERFACE() ? "interface" : "package",
binding: identifier(context.identifier()),
});
const registerImports = (
state: LoweringState,
contexts: readonly ResourceImportDeclContext[],
environment: CapabilityImportEnvironment,
) => contexts.map((context) => {
const imported = resourceImport(context);
if (imported.kind === "interface") {
const revision = environment.interfaces?.get(imported.binding);
if (!revision) {
loweringIssue(
state,
context,
"missing-import",
`No resolved interface is available for lock binding ${imported.binding}`,
);
} else {
declareSymbol(
state,
state.interfaces,
imported.binding,
interfaceSymbolFor(revision),
context,
"interface",
);
}
} else {
const revision = environment.packages?.get(imported.binding);
if (!revision) {
loweringIssue(
state,
context,
"missing-import",
`No resolved package is available for lock binding ${imported.binding}`,
);
} else {
declareSymbol(
state,
state.packages,
imported.binding,
packageSymbolFor(revision),
context,
"package",
);
}
}
return imported;
});
const uniqueExactRevisions = <Revision extends {
revisionId: string;
source: SourceRevision;
}>(revisions: readonly Revision[]): Revision[] => {
const seen = new Set<string>();
return revisions.filter((revision) => {
const key = `${revision.revisionId}\0${revision.source.repository}\0${revision.source.commit}`;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
};
const uniqueAtoms = (atoms: readonly AtomDefinition[]): AtomDefinition[] => {
const seen = new Set<string>();
return atoms.filter((atom) => {
if (seen.has(atom.id)) return false;
seen.add(atom.id);
return true;
});
};
const lowerWorkspace = (
state: LoweringState,
context: WorkspaceDeclContext,
): WorkspaceRevision => {
environment: CapabilityImportEnvironment,
): { workspace: WorkspaceRevision; imports: CapabilityResourceImport[] } => {
const items = context.workspaceItem();
for (const item of items) {
@@ -1368,40 +1537,13 @@ const lowerWorkspace = (
);
continue;
}
const interfaceContext = item.interfaceDecl();
if (interfaceContext) {
declareSymbol(
}
const imports = registerImports(
state,
state.interfaces,
identifier(interfaceContext.identifier()),
{
revisionId: capabilityId.interfaceRevision(
stringValue(interfaceContext.stringLiteral(1)),
),
members: new Map(),
},
interfaceContext,
"interface",
items.flatMap((item) => item.resourceImportDecl() ?? []),
environment,
);
continue;
}
const packageContext = item.packageDecl();
if (packageContext) {
declareSymbol(
state,
state.packages,
identifier(packageContext.identifier()),
{
revisionId: capabilityId.packageRevision(
stringValue(packageContext.stringLiteral(1)),
),
exports: new Map(),
},
packageContext,
"package",
);
}
}
const atoms = items.flatMap((item) => {
const atom = item.atomDecl();
@@ -1422,15 +1564,15 @@ const lowerWorkspace = (
: [];
});
const interfaceImports = items.flatMap((item) => {
const interfaceContext = item.interfaceDecl();
return interfaceContext ? [lowerInterface(state, interfaceContext)] : [];
});
const interfaceImports = uniqueExactRevisions([
...(environment.interfaceClosure ?? []),
...[...(environment.interfaces?.values() ?? [])],
]);
const packageImports = items.flatMap((item) => {
const packageContext = item.packageDecl();
return packageContext ? [lowerPackage(state, packageContext)] : [];
});
const packageImports = uniqueExactRevisions([
...(environment.packageClosure ?? []),
...[...(environment.packages?.values() ?? [])],
]);
const sharedAttachments: PersistentAttachment[] = [];
const privateAttachments = new Map<
@@ -1520,6 +1662,8 @@ const lowerWorkspace = (
});
return {
imports,
workspace: {
id: capabilityId.workspaceRevision(stringValue(context.stringLiteral(1))),
workspaceId: capabilityId.workspace(stringValue(context.stringLiteral(0))),
parentRevisionIds: [],
@@ -1530,13 +1674,14 @@ const lowerWorkspace = (
packageImports,
conformances,
constructors,
},
};
};
export const compileCapabilitySource = (
const parseDocument = (
source: string,
fileName = "<memory>",
): CapabilitySourceCompileResult => {
fileName: string,
): { tree: DocumentContext; diagnostics: CapabilitySourceDiagnostic[] } => {
const diagnostics: CapabilitySourceDiagnostic[] = [];
const listener = new SyntaxErrorListener(fileName, diagnostics);
const lexer = new QuixosCapabilityLexer(CharStream.fromString(source));
@@ -1548,27 +1693,27 @@ export const compileCapabilitySource = (
parser.removeErrorListeners();
parser.addErrorListener(listener);
const tree = parser.document();
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
return { tree, diagnostics };
};
const state: LoweringState = {
const newLoweringState = (
fileName: string,
diagnostics: CapabilitySourceDiagnostic[],
): LoweringState => ({
fileName,
diagnostics,
atoms: new Map(),
interfaces: new Map(),
packages: new Map(),
attachments: new Map(),
};
const workspace = lowerWorkspace(state, tree.workspaceDecl());
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
const compiled = compileWorkspaceRevision(workspace);
if (!compiled.ok) {
return {
ok: false,
diagnostics: compiled.issues.map((entry) => ({
});
const validationDiagnostics = (
fileName: string,
issues: ReturnType<typeof compileWorkspaceRevision> extends infer _Result
? Array<{ code: string; message: string; path: string }>
: never,
): CapabilitySourceDiagnostic[] => issues.map((entry) => ({
phase: "validation",
code: entry.code,
message: entry.message,
@@ -1576,8 +1721,246 @@ export const compileCapabilitySource = (
line: 0,
column: 0,
path: entry.path,
}));
const externalAtomsFrom = (
state: LoweringState,
contexts: readonly ExternalAtomDeclContext[],
): AtomDefinition[] => contexts.map((context) => {
const atom: AtomDefinition = {
id: capabilityId.atom(stringValue(context.stringLiteral())),
displayName: identifier(context.identifier()),
};
declareSymbol(
state,
state.atoms,
atom.displayName,
atom.id,
context,
"external atom",
);
return atom;
});
const externalInterfacesFrom = (
state: LoweringState,
contexts: readonly ExternalInterfaceDeclContext[],
): CapabilityExternalInterface[] => contexts.map((context) => {
const requirement: CapabilityExternalInterface = {
binding: identifier(context.identifier()),
revisionId: capabilityId.interfaceRevision(stringValue(context.stringLiteral())),
};
declareSymbol(
state,
state.interfaces,
requirement.binding,
{
revisionId: requirement.revisionId,
contractAvailable: false,
members: new Map(),
},
context,
"external interface",
);
return requirement;
});
const resourcePreambleParts = (contexts: readonly ResourcePreambleContext[]) => ({
imports: contexts.flatMap((context) => context.resourceImportDecl() ?? []),
atoms: contexts.flatMap((context) => context.externalAtomDecl() ?? []),
interfaces: contexts.flatMap((context) => context.externalInterfaceDecl() ?? []),
});
const resourceValidationWorkspace = (
resource: CapabilityResource,
environment: CapabilityImportEnvironment,
): WorkspaceRevision => {
const resolvedInterfaceIds = new Set([
...(environment.interfaceClosure ?? []).map((revision) => revision.revisionId),
...[...(environment.interfaces?.values() ?? [])].map((revision) => revision.revisionId),
...(resource.kind === "interface" ? [resource.revision.revisionId] : []),
]);
return ({
id: capabilityId.workspaceRevision("workspace-revision:resource-validation"),
workspaceId: capabilityId.workspace("workspace:resource-validation"),
parentRevisionIds: [],
sourceRootCommit: resource.revision.source.commit,
atoms: uniqueAtoms([
...(environment.externalAtoms ?? []),
...resource.externalAtoms,
]),
sharedAttachments: [],
interfaceImports: uniqueExactRevisions([
...(environment.interfaceClosure ?? []),
...[...(environment.interfaces?.values() ?? [])],
...(resource.kind === "interface" ? [resource.revision] : []),
...resource.externalInterfaces
.filter((requirement) => !resolvedInterfaceIds.has(requirement.revisionId))
.map((requirement): InterfaceRevision => ({
interfaceId: capabilityId.interface(`external:${requirement.revisionId}`),
revisionId: requirement.revisionId,
displayName: requirement.binding,
source: {
repository: `https://external.invalid/${encodeURIComponent(requirement.revisionId)}.git`,
commit: "0".repeat(40),
},
members: [],
})),
]),
packageImports: uniqueExactRevisions([
...(environment.packageClosure ?? []),
...[...(environment.packages?.values() ?? [])],
...(resource.kind === "package" ? [resource.revision] : []),
]),
conformances: [],
constructors: [],
});
};
export const compileCapabilityResourceSource = (
sourceText: string,
options: {
source: SourceRevision;
fileName?: string;
environment?: CapabilityImportEnvironment;
},
): CapabilityResourceCompileResult => {
const fileName = options.fileName ?? "<memory>";
const environment = options.environment ?? {};
const { tree, diagnostics } = parseDocument(sourceText, fileName);
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
const interfaceContext = tree.interfaceResourceDecl();
const packageContext = tree.packageResourceDecl();
if (!interfaceContext && !packageContext) {
return {
ok: false,
diagnostics: [{
phase: "lowering",
code: "expected-resource",
message: "Expected a standalone interface or package resource document",
fileName,
line: 1,
column: 0,
}],
};
}
return { ok: true, workspace, plan: compiled.plan, diagnostics: [] };
const state = newLoweringState(fileName, diagnostics);
const preamble = resourcePreambleParts(
(interfaceContext ?? packageContext)!.resourcePreamble(),
);
const externalAtoms = externalAtomsFrom(state, preamble.atoms);
const imports = registerImports(state, preamble.imports, environment);
const externalInterfaces = externalInterfacesFrom(state, preamble.interfaces);
let resource: CapabilityResource;
if (interfaceContext) {
const alias = identifier(interfaceContext.identifier());
declareSymbol(
state,
state.interfaces,
alias,
{
revisionId: capabilityId.interfaceRevision(
stringValue(interfaceContext.stringLiteral(1)),
),
contractAvailable: true,
members: new Map(),
},
interfaceContext,
"interface",
);
resource = {
kind: "interface",
imports,
externalAtoms,
externalInterfaces,
revision: lowerInterface(state, interfaceContext, options.source),
};
} else {
const context = packageContext!;
const alias = identifier(context.identifier());
declareSymbol(
state,
state.packages,
alias,
{
revisionId: capabilityId.packageRevision(
stringValue(context.stringLiteral(1)),
),
exports: new Map(),
},
context,
"package",
);
resource = {
kind: "package",
imports,
externalAtoms,
externalInterfaces,
revision: lowerPackage(state, context, options.source),
};
}
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
const compiled = compileWorkspaceRevision(
resourceValidationWorkspace(resource, environment),
);
if (!compiled.ok) {
return {
ok: false,
diagnostics: validationDiagnostics(fileName, compiled.issues),
};
}
return { ok: true, resource, diagnostics: [] };
};
export const compileCapabilitySource = (
source: string,
fileName = "<memory>",
environment: CapabilityImportEnvironment = {},
): CapabilitySourceCompileResult => {
const { tree, diagnostics } = parseDocument(source, fileName);
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
const workspaceContext = tree.workspaceDecl();
if (!workspaceContext) {
return {
ok: false,
diagnostics: [{
phase: "lowering",
code: "expected-workspace",
message: "Expected a workspace document",
fileName,
line: 1,
column: 0,
}],
};
}
const state = newLoweringState(fileName, diagnostics);
const lowered = lowerWorkspace(state, workspaceContext, environment);
if (diagnostics.length > 0) {
return { ok: false, diagnostics };
}
const compiled = compileWorkspaceRevision(lowered.workspace);
if (!compiled.ok) {
return {
ok: false,
diagnostics: validationDiagnostics(fileName, compiled.issues),
};
}
return {
ok: true,
workspace: lowered.workspace,
plan: compiled.plan,
imports: lowered.imports,
diagnostics: [],
};
};
+101
View File
@@ -0,0 +1,101 @@
#!/usr/bin/env node
import { writeFile } from "node:fs/promises";
import process from "node:process";
import {
compileCapabilityResourceRepository,
type ResolvedCapabilityResource,
} from "./assembly.js";
import { createGitCapabilityResolver } from "./git-resolver.js";
const usage = `usage: quixos-resource-compile --root DIRECTORY --kind interface|package
--repository URL --commit GIT_REV --checkout-root DIRECTORY
[--snapshot-map PATH] [--graph-out PATH]
Resolves a standalone resource's recursive dependency-lock graph, validates
its interface.qx or package.qx manifest, and emits the checked resource as JSON.`;
const parseArgs = (args: string[]) => {
const values = new Map<string, string>();
for (let index = 0; index < args.length; index += 2) {
const key = args[index];
const value = args[index + 1];
if (!key?.startsWith("--") || !value) throw new Error(usage);
values.set(key, value);
}
const rootDirectory = values.get("--root");
const kind = values.get("--kind");
const repository = values.get("--repository");
const commit = values.get("--commit")?.toLowerCase();
const checkoutRoot = values.get("--checkout-root");
if (!rootDirectory || !repository || !commit || !checkoutRoot ||
(kind !== "interface" && kind !== "package")) {
throw new Error(usage);
}
if (!/^([0-9a-f]{40}|[0-9a-f]{64})$/.test(commit)) {
throw new Error("--commit must be a full Git object ID");
}
return {
rootDirectory,
kind,
repository,
commit,
checkoutRoot,
snapshotMap: values.get("--snapshot-map"),
graphOut: values.get("--graph-out"),
} as const;
};
const graphEntry = (node: ResolvedCapabilityResource) => ({
key: node.key,
kind: node.kind,
source: node.source,
directory: node.directory,
resourceId: node.resource.kind === "interface"
? node.resource.revision.interfaceId
: node.resource.revision.packageId,
revisionId: node.resource.revision.revisionId,
dependencies: [...node.dependencies.entries()].map(([binding, dependency]) => ({
binding,
resourceKey: dependency.key,
})),
});
const main = async () => {
if (process.argv.includes("--help") || process.argv.includes("-h")) {
process.stdout.write(`${usage}\n`);
return;
}
const options = parseArgs(process.argv.slice(2));
const resolveResource = await createGitCapabilityResolver({
checkoutRoot: options.checkoutRoot,
snapshotMap: options.snapshotMap,
});
const compiled = await compileCapabilityResourceRepository({
rootDirectory: options.rootDirectory,
kind: options.kind,
source: {
resolver: "git",
repository: options.repository,
commit: options.commit,
},
resolveResource,
});
if (options.graphOut) {
await writeFile(options.graphOut, `${JSON.stringify({
formatVersion: 1,
quixos: compiled.lock.quixos,
root: graphEntry(compiled.resources.find((node) =>
node.source.repository === options.repository &&
node.source.commit === options.commit &&
node.kind === options.kind)!),
resources: compiled.resources.map(graphEntry),
}, null, 2)}\n`);
}
process.stdout.write(`${JSON.stringify(compiled.resource, null, 2)}\n`);
};
main().catch((error: unknown) => {
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
process.exitCode = 1;
});
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env node
import { writeFile } from "node:fs/promises";
import process from "node:process";
import { compileWorkspaceRepository } from "./assembly.js";
import { createGitCapabilityResolver } from "./git-resolver.js";
const usage = `usage: quixos-workspace-compile --root DIRECTORY --checkout-root DIRECTORY
[--snapshot-map PATH] [--graph-out PATH] [--workspace-id ID] [--workspace-revision-id ID]
[--source-root-commit GIT_REV]
Resolves a workspace's recursive resource-lock graph, clones every exact
resource revision, validates standalone interface/package manifests, and emits
the checked workspace plan as JSON.`;
const parseArgs = (args: string[]) => {
const values = new Map<string, string>();
for (let index = 0; index < args.length; index += 2) {
const key = args[index];
const value = args[index + 1];
if (!key?.startsWith("--") || !value) throw new Error(usage);
values.set(key, value);
}
const rootDirectory = values.get("--root");
const checkoutRoot = values.get("--checkout-root");
if (!rootDirectory || !checkoutRoot) throw new Error(usage);
return {
rootDirectory,
checkoutRoot,
graphOut: values.get("--graph-out"),
snapshotMap: values.get("--snapshot-map"),
workspaceId: values.get("--workspace-id"),
workspaceRevisionId: values.get("--workspace-revision-id"),
sourceRootCommit: values.get("--source-root-commit"),
};
};
const main = async () => {
if (process.argv.includes("--help") || process.argv.includes("-h")) {
process.stdout.write(`${usage}\n`);
return;
}
const options = parseArgs(process.argv.slice(2));
const resolveResource = await createGitCapabilityResolver({
checkoutRoot: options.checkoutRoot,
snapshotMap: options.snapshotMap,
});
const assembled = await compileWorkspaceRepository({
rootDirectory: options.rootDirectory,
workspaceId: options.workspaceId,
workspaceRevisionId: options.workspaceRevisionId,
sourceRootCommit: options.sourceRootCommit,
resolveResource,
});
if (options.graphOut) {
await writeFile(options.graphOut, `${JSON.stringify({
formatVersion: 1,
quixos: assembled.lock.quixos,
directResources: [...assembled.directResources.entries()].map(([bindingKey, node]) => {
const [kind, binding] = bindingKey.split("\0");
return { kind, binding, resourceKey: node.key, directory: node.directory };
}),
resources: assembled.resources.map((node) => ({
key: node.key,
kind: node.kind,
source: node.source,
directory: node.directory,
resourceId: node.resource.kind === "interface"
? node.resource.revision.interfaceId
: node.resource.revision.packageId,
revisionId: node.resource.revision.revisionId,
dependencies: [...node.dependencies.entries()].map(([binding, dependency]) => ({
binding,
resourceKey: dependency.key,
})),
})),
}, null, 2)}\n`);
}
process.stdout.write(`${JSON.stringify(assembled.workspace, null, 2)}\n`);
};
main().catch((error: unknown) => {
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
process.exitCode = 1;
});
+3 -2
View File
@@ -242,7 +242,7 @@ export type DependencyPortRequirement =
primitives: EdgePrimitive[];
}
| {
kind: "receiver-interface";
kind: "interface";
interfaceRevisionId: InterfaceRevisionId;
}
| { kind: "constructor"; atomId: AtomId };
@@ -299,8 +299,9 @@ export type DependencyBinding =
via?: EdgeTraversal;
}
| {
kind: "receiver-interface";
kind: "interface";
interfaceRevisionId: InterfaceRevisionId;
via?: EdgeTraversal;
}
| { kind: "constructor"; atomId: AtomId };
+65 -10
View File
@@ -61,7 +61,7 @@ export type CapabilityValidationIssueCode =
| "invalid-dependency-binding"
| "private-attachment-access"
| "incompatible-package-receiver"
| "unsatisfied-receiver-interface"
| "unsatisfied-interface"
| "cyclic-conformance-requirement"
| "missing-operation-binding"
| "unknown-operation-binding"
@@ -917,7 +917,7 @@ const validatePackages = (
validateConstraint(issues, port.requirement.target, `${portPath}.requirement.target`, indexes);
uniquePrimitiveList(issues, port.requirement.primitives, `${portPath}.requirement.primitives`);
break;
case "receiver-interface":
case "interface":
if (!indexes.interfaces.has(port.requirement.interfaceRevisionId)) {
issue(
issues,
@@ -976,6 +976,7 @@ const validateTraversal = (
atomId: AtomId,
traversal: { edgeTypeId: EdgeTypeId; projectionId: EdgeProjectionId },
path: string,
conformance?: Pick<Conformance, "atomId" | "interfaceRevisionId">,
) => {
const attachment = findAttachment(indexes, "edge", traversal.edgeTypeId);
if (!attachment || attachment.attachment.kind !== "edge") {
@@ -987,6 +988,7 @@ const validateTraversal = (
);
return undefined;
}
validateAttachmentAccess(issues, attachment, conformance, `${path}.edgeTypeId`);
const projection = edgeProjection(attachment.attachment, traversal.projectionId);
if (!projection) {
issue(
@@ -1085,6 +1087,7 @@ const validateBoundDependencies = (
params.atomId,
stateBinding.via,
`${path}.binding.via`,
params.conformance,
)
: undefined;
if (
@@ -1145,6 +1148,7 @@ const validateBoundDependencies = (
params.atomId,
edgeBinding.via,
`${path}.binding.via`,
params.conformance,
)
: undefined;
const originMatches = edgeBinding.via
@@ -1189,10 +1193,10 @@ const validateBoundDependencies = (
}
break;
}
case "receiver-interface": {
case "interface": {
const interfaceBinding = binding as Extract<
DependencyBinding,
{ kind: "receiver-interface" }
{ kind: "interface" }
>;
if (interfaceBinding.interfaceRevisionId !== requirement.interfaceRevisionId) {
issue(
@@ -1203,17 +1207,39 @@ const validateBoundDependencies = (
);
break;
}
const targetKey = conformanceKey(params.atomId, requirement.interfaceRevisionId);
const traversal = interfaceBinding.via
? validateTraversal(
issues,
params.indexes,
params.atomId,
interfaceBinding.via,
`${path}.binding.via`,
params.conformance,
)
: undefined;
const candidateAtoms = interfaceBinding.via
? traversal
? [...params.indexes.atoms.keys()].filter((atomId) =>
atomSatisfiesConstraint(
atomId as AtomId,
traversal.target.constraint,
params.indexes.conformances,
)) as AtomId[]
: []
: [params.atomId];
for (const atomId of candidateAtoms) {
const targetKey = conformanceKey(atomId, requirement.interfaceRevisionId);
if (!params.indexes.conformances.has(targetKey)) {
issue(
issues,
"unsatisfied-receiver-interface",
"unsatisfied-interface",
`${path}.binding.interfaceRevisionId`,
`Receiver atom ${params.atomId} does not conform to ${requirement.interfaceRevisionId}`,
`${interfaceBinding.via ? "Related" : "Receiver"} atom ${atomId} does not conform to ${requirement.interfaceRevisionId}`,
);
} else if (params.graphSourceKey) {
params.requirementGraph.get(params.graphSourceKey)?.add(targetKey);
}
}
break;
}
case "constructor": {
@@ -1276,7 +1302,7 @@ const validatePackageReceiver = (
if (!params.indexes.conformances.has(targetKey)) {
issue(
issues,
"unsatisfied-receiver-interface",
"unsatisfied-interface",
params.path,
`Atom ${params.atomId} does not conform to ${requiredInterface}`,
);
@@ -1971,6 +1997,9 @@ export const computeCapabilityClosure = (
const constructors = new Set<AtomId>();
const queued = [...roots];
const visited = new Set<string>();
const sourceConformances = new Map(
[...plan.conformances].map(([key, value]) => [key, value.source]),
);
const includeDependencies = (
atomId: AtomId,
@@ -1990,12 +2019,38 @@ export const computeCapabilityClosure = (
attachments.add(dependency.binding.via.edgeTypeId);
}
break;
case "receiver-interface":
case "interface": {
if (dependency.binding.via) {
attachments.add(dependency.binding.via.edgeTypeId);
}
const targetAtoms = dependency.binding.via
? (() => {
const attachment = plan.attachments.get(
`edge\u0000${dependency.binding.via!.edgeTypeId}`,
)?.attachment;
if (!attachment || attachment.kind !== "edge") return [];
const projection = edgeProjection(
attachment,
dependency.binding.via!.projectionId,
);
return projection
? [...plan.atoms.keys()].filter((candidate) =>
atomSatisfiesConstraint(
candidate,
projection.target.constraint,
sourceConformances,
))
: [];
})()
: [atomId];
for (const targetAtom of targetAtoms) {
queued.push({
atomId,
atomId: targetAtom,
interfaceRevisionId: dependency.binding.interfaceRevisionId,
});
}
break;
}
case "constructor": {
constructors.add(dependency.binding.atomId);
const constructor = plan.constructors.get(dependency.binding.atomId);
+6 -1
View File
@@ -18,7 +18,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/orch.proto.
*/
export const file_quixos_orch: GenFile = /*@__PURE__*/
fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCJtCiZSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhEKCW1lbWJlcl9pZBgDIAEoCSJkCidSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBITCgtjb25zdHJ1Y3RlZBgCIAEoCCLwAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkSGgoSY2xpZW50X211dGF0aW9uX2lkGAQgASgJGjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASKYAQoYSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlEhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SCgoCb2sYAyABKAgSHQoGcmVzdWx0GAQgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAUgASgJItIBChZXYXRjaENhcGFiaWxpdHlSZXF1ZXN0EikKCmNhcGFiaWxpdHkYASABKAsyFS5xdWl4b3MuQ2FwYWJpbGl0eVJlZhIRCglvYmplY3RfaWQYAiABKAkSPQoFaW5wdXQYAyADKAsyLi5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIuMBChRXYXRjaENhcGFiaWxpdHlFdmVudBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEisKCmFjdGl2YXRpb24YAiABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uEhAKCHdhdGNoX2lkGAMgASgJEhwKBXZhbHVlGAQgASgLMg0uY2FtaW5vLlZhbHVlEjcKDGRlcGVuZGVuY2llcxgFIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5Eg0KBWVycm9yGAYgASgJEg8KB2luaXRpYWwYByABKAgiFQoTR2V0V29ya3NwYWNlUmVxdWVzdCJnChRHZXRXb3Jrc3BhY2VSZXNwb25zZRIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEhoKEnNvdXJjZV9yb290X2NvbW1pdBgDIAEoCSIYChZMaXN0QWN0aXZhdGlvbnNSZXF1ZXN0Ih8KHUxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0IlAKHkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXNwb25zZRIuCgtkZXNjcmlwdG9ycxgBIAMoCzIZLnF1aXhvcy5QYWNrYWdlRGVzY3JpcHRvciIcChpMaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdCJSChtMaXN0UGFja2FnZVJ1bnRpbWVzUmVzcG9uc2USMwoIcnVudGltZXMYASADKAsyIS5xdWl4b3Mub3JjaC5QYWNrYWdlUnVudGltZVN0YXR1cyJHChdMaXN0QWN0aXZhdGlvbnNSZXNwb25zZRIsCgthY3RpdmF0aW9ucxgBIAMoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24iPwoWQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJGChdDbG9zZUFjdGl2YXRpb25SZXNwb25zZRIrCgphY3RpdmF0aW9uGAEgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiLrAQoKQWN0aXZhdGlvbhIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRINCgVzdGF0ZRgEIAEoCRIOCgZkZW1hbmQYBSABKA0SEQoJb3BlbmVkX2F0GAYgASgJEhQKDGxhc3RfdXNlZF9hdBgHIAEoCRIYChBpZGxlX2RlYWRsaW5lX2F0GAggASgJEhEKCWNsb3NlZF9hdBgJIAEoCRIUCgxjbG9zZV9yZWFzb24YCiABKAkiswIKFFBhY2thZ2VSdW50aW1lU3RhdHVzEhMKC3J1bnRpbWVfa2V5GAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSGQoRc291cmNlX3JlcG9zaXRvcnkYAyABKAkSFQoNc291cmNlX2NvbW1pdBgEIAEoCRIUCgxidWlsZF90YXJnZXQYBSABKAkSEwoLc2VydmVyX3BhdGgYBiABKAkSCwoDcGlkGAcgASgNEg0KBXN0YXRlGAggASgJEhIKCnN0YXJ0ZWRfYXQYCSABKAkSGQoRbGFzdF9oYW5kc2hha2VfYXQYCiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAsgASgJEh8KF2FkdmVydGlzZWRfZXhwb3J0X2NvdW50GAwgASgNMq4HChNPcmNoZXN0cmF0b3JSdW50aW1lEl8KEEludm9rZUNhcGFiaWxpdHkSJC5xdWl4b3Mub3JjaC5JbnZva2VDYXBhYmlsaXR5UmVxdWVzdBolLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXNwb25zZRJbCg9XYXRjaENhcGFiaWxpdHkSIy5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0GiEucXVpeG9zLm9yY2guV2F0Y2hDYXBhYmlsaXR5RXZlbnQwARJcCg9Db25zdHJ1Y3RPYmplY3QSIy5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXF1ZXN0GiQucXVpeG9zLm9yY2guQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USjAEKH1Jlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3QSMy5xdWl4b3Mub3JjaC5SZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBo0LnF1aXhvcy5vcmNoLlJlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
fileDesc("ChFxdWl4b3Mvb3JjaC5wcm90bxILcXVpeG9zLm9yY2gipQEKFkNvbnN0cnVjdE9iamVjdFJlcXVlc3QSDwoHYXRvbV9pZBgBIAEoCRI9CgVpbnB1dBgCIAMoCzIuLnF1aXhvcy5vcmNoLkNvbnN0cnVjdE9iamVjdFJlcXVlc3QuSW5wdXRFbnRyeRo7CgpJbnB1dEVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPwoXQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCJtCiZSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhEKCW1lbWJlcl9pZBgDIAEoCSJkCidSZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBITCgtjb25zdHJ1Y3RlZBgCIAEoCCLwAQoXSW52b2tlQ2FwYWJpbGl0eVJlcXVlc3QSKQoKY2FwYWJpbGl0eRgBIAEoCzIVLnF1aXhvcy5DYXBhYmlsaXR5UmVmEhEKCW9iamVjdF9pZBgCIAEoCRI+CgVpbnB1dBgDIAMoCzIvLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkSGgoSY2xpZW50X211dGF0aW9uX2lkGAQgASgJGjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASLRAQoYSW52b2tlQ2FwYWJpbGl0eVJlc3BvbnNlEhUKDWludm9jYXRpb25faWQYASABKAkSKwoKYWN0aXZhdGlvbhgCIAEoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24SCgoCb2sYAyABKAgSHQoGcmVzdWx0GAQgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAUgASgJEjcKDGRlcGVuZGVuY2llcxgGIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5ItIBChZXYXRjaENhcGFiaWxpdHlSZXF1ZXN0EikKCmNhcGFiaWxpdHkYASABKAsyFS5xdWl4b3MuQ2FwYWJpbGl0eVJlZhIRCglvYmplY3RfaWQYAiABKAkSPQoFaW5wdXQYAyADKAsyLi5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0LklucHV0RW50cnkaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIuMBChRXYXRjaENhcGFiaWxpdHlFdmVudBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEisKCmFjdGl2YXRpb24YAiABKAsyFy5xdWl4b3Mub3JjaC5BY3RpdmF0aW9uEhAKCHdhdGNoX2lkGAMgASgJEhwKBXZhbHVlGAQgASgLMg0uY2FtaW5vLlZhbHVlEjcKDGRlcGVuZGVuY2llcxgFIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5Eg0KBWVycm9yGAYgASgJEg8KB2luaXRpYWwYByABKAgiFQoTR2V0V29ya3NwYWNlUmVxdWVzdCJnChRHZXRXb3Jrc3BhY2VSZXNwb25zZRIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEhoKEnNvdXJjZV9yb290X2NvbW1pdBgDIAEoCSIYChZMaXN0QWN0aXZhdGlvbnNSZXF1ZXN0Ih8KHUxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0IlAKHkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXNwb25zZRIuCgtkZXNjcmlwdG9ycxgBIAMoCzIZLnF1aXhvcy5QYWNrYWdlRGVzY3JpcHRvciIcChpMaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdCJSChtMaXN0UGFja2FnZVJ1bnRpbWVzUmVzcG9uc2USMwoIcnVudGltZXMYASADKAsyIS5xdWl4b3Mub3JjaC5QYWNrYWdlUnVudGltZVN0YXR1cyJHChdMaXN0QWN0aXZhdGlvbnNSZXNwb25zZRIsCgthY3RpdmF0aW9ucxgBIAMoCzIXLnF1aXhvcy5vcmNoLkFjdGl2YXRpb24iPwoWQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEg4KBnJlYXNvbhgCIAEoCSJGChdDbG9zZUFjdGl2YXRpb25SZXNwb25zZRIrCgphY3RpdmF0aW9uGAEgASgLMhcucXVpeG9zLm9yY2guQWN0aXZhdGlvbiLrAQoKQWN0aXZhdGlvbhIVCg1hY3RpdmF0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRINCgVzdGF0ZRgEIAEoCRIOCgZkZW1hbmQYBSABKA0SEQoJb3BlbmVkX2F0GAYgASgJEhQKDGxhc3RfdXNlZF9hdBgHIAEoCRIYChBpZGxlX2RlYWRsaW5lX2F0GAggASgJEhEKCWNsb3NlZF9hdBgJIAEoCRIUCgxjbG9zZV9yZWFzb24YCiABKAkiswIKFFBhY2thZ2VSdW50aW1lU3RhdHVzEhMKC3J1bnRpbWVfa2V5GAEgASgJEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYAiABKAkSGQoRc291cmNlX3JlcG9zaXRvcnkYAyABKAkSFQoNc291cmNlX2NvbW1pdBgEIAEoCRIUCgxidWlsZF90YXJnZXQYBSABKAkSEwoLc2VydmVyX3BhdGgYBiABKAkSCwoDcGlkGAcgASgNEg0KBXN0YXRlGAggASgJEhIKCnN0YXJ0ZWRfYXQYCSABKAkSGQoRbGFzdF9oYW5kc2hha2VfYXQYCiABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAsgASgJEh8KF2FkdmVydGlzZWRfZXhwb3J0X2NvdW50GAwgASgNMq4HChNPcmNoZXN0cmF0b3JSdW50aW1lEl8KEEludm9rZUNhcGFiaWxpdHkSJC5xdWl4b3Mub3JjaC5JbnZva2VDYXBhYmlsaXR5UmVxdWVzdBolLnF1aXhvcy5vcmNoLkludm9rZUNhcGFiaWxpdHlSZXNwb25zZRJbCg9XYXRjaENhcGFiaWxpdHkSIy5xdWl4b3Mub3JjaC5XYXRjaENhcGFiaWxpdHlSZXF1ZXN0GiEucXVpeG9zLm9yY2guV2F0Y2hDYXBhYmlsaXR5RXZlbnQwARJcCg9Db25zdHJ1Y3RPYmplY3QSIy5xdWl4b3Mub3JjaC5Db25zdHJ1Y3RPYmplY3RSZXF1ZXN0GiQucXVpeG9zLm9yY2guQ29uc3RydWN0T2JqZWN0UmVzcG9uc2USjAEKH1Jlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3QSMy5xdWl4b3Mub3JjaC5SZXNvbHZlT3JDb25zdHJ1Y3RSZWxhdGVkT2JqZWN0UmVxdWVzdBo0LnF1aXhvcy5vcmNoLlJlc29sdmVPckNvbnN0cnVjdFJlbGF0ZWRPYmplY3RSZXNwb25zZRJTCgxHZXRXb3Jrc3BhY2USIC5xdWl4b3Mub3JjaC5HZXRXb3Jrc3BhY2VSZXF1ZXN0GiEucXVpeG9zLm9yY2guR2V0V29ya3NwYWNlUmVzcG9uc2UScQoWTGlzdFBhY2thZ2VEZXNjcmlwdG9ycxIqLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlRGVzY3JpcHRvcnNSZXF1ZXN0GisucXVpeG9zLm9yY2guTGlzdFBhY2thZ2VEZXNjcmlwdG9yc1Jlc3BvbnNlEmgKE0xpc3RQYWNrYWdlUnVudGltZXMSJy5xdWl4b3Mub3JjaC5MaXN0UGFja2FnZVJ1bnRpbWVzUmVxdWVzdBooLnF1aXhvcy5vcmNoLkxpc3RQYWNrYWdlUnVudGltZXNSZXNwb25zZRJcCg9MaXN0QWN0aXZhdGlvbnMSIy5xdWl4b3Mub3JjaC5MaXN0QWN0aXZhdGlvbnNSZXF1ZXN0GiQucXVpeG9zLm9yY2guTGlzdEFjdGl2YXRpb25zUmVzcG9uc2USXAoPQ2xvc2VBY3RpdmF0aW9uEiMucXVpeG9zLm9yY2guQ2xvc2VBY3RpdmF0aW9uUmVxdWVzdBokLnF1aXhvcy5vcmNoLkNsb3NlQWN0aXZhdGlvblJlc3BvbnNlYgZwcm90bzM", [file_camino_api, file_quixos_package, file_quixos_refs, file_quixos_runtime]);
/**
* @generated from message quixos.orch.ConstructObjectRequest
@@ -171,6 +171,11 @@ export type InvokeCapabilityResponse = Message<"quixos.orch.InvokeCapabilityResp
* @generated from field: string error = 5;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 6;
*/
dependencies: DerivedDependency[];
};
/**
+3 -3
View File
@@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/refs.proto.
*/
export const file_quixos_refs: GenFile = /*@__PURE__*/
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIs0BChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEigKHnJlY2VpdmVyX2ludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
fileDesc("ChFxdWl4b3MvcmVmcy5wcm90bxIGcXVpeG9zIkQKDUNhcGFiaWxpdHlSZWYSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAEgASgJEhQKDG9wZXJhdGlvbl9pZBgCIAEoCSJCChBQYWNrYWdlRXhwb3J0UmVmEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSEQoJZXhwb3J0X2lkGAIgASgJIsQBChJJbmplY3RlZERlcGVuZGVuY3kSDwoHcG9ydF9pZBgBIAEoCRIXCg1zdGF0ZV9zbG90X2lkGAIgASgJSAASJgoEZWRnZRgDIAEoCzIWLnF1aXhvcy5FZGdlRGVwZW5kZW5jeUgAEh8KFWludGVyZmFjZV9yZXZpc2lvbl9pZBgEIAEoCUgAEh0KE2NvbnN0cnVjdG9yX2F0b21faWQYBSABKAlIABIRCglvYmplY3RfaWQYBiABKAlCCQoHYmluZGluZyI9Cg5FZGdlRGVwZW5kZW5jeRIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCWIGcHJvdG8z");
/**
* @generated from message quixos.CapabilityRef
@@ -82,10 +82,10 @@ export type InjectedDependency = Message<"quixos.InjectedDependency"> & {
case: "edge";
} | {
/**
* @generated from field: string receiver_interface_revision_id = 4;
* @generated from field: string interface_revision_id = 4;
*/
value: string;
case: "receiverInterfaceRevisionId";
case: "interfaceRevisionId";
} | {
/**
* @generated from field: string constructor_atom_id = 5;
+6 -1
View File
@@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file quixos/runtime.proto.
*/
export const file_quixos_runtime: GenFile = /*@__PURE__*/
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJKCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkiiQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBImIKEURlcml2ZWREZXBlbmRlbmN5EgwKBGtpbmQYASABKAkSEQoJb2JqZWN0X2lkGAIgASgJEhUKDWF0dGFjaG1lbnRfaWQYAyABKAkSFQoNcHJvamVjdGlvbl9pZBgEIAEoCSKVAQoKV2F0Y2hFdmVudBIQCgh3YXRjaF9pZBgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZRI3CgxkZXBlbmRlbmNpZXMYAyADKAsyIS5xdWl4b3MucnVudGltZS5EZXJpdmVkRGVwZW5kZW5jeRINCgVlcnJvchgEIAEoCRIPCgdpbml0aWFsGAUgASgIMvABCg5QYWNrYWdlUnVudGltZRJQCglIYW5kc2hha2USIC5xdWl4b3MucnVudGltZS5IYW5kc2hha2VSZXF1ZXN0GiEucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVzcG9uc2USRwoGSW52b2tlEh0ucXVpeG9zLnJ1bnRpbWUuSW52b2tlUmVxdWVzdBoeLnF1aXhvcy5ydW50aW1lLkludm9rZVJlc3BvbnNlEkMKBVdhdGNoEhwucXVpeG9zLnJ1bnRpbWUuV2F0Y2hSZXF1ZXN0GhoucXVpeG9zLnJ1bnRpbWUuV2F0Y2hFdmVudDABYgZwcm90bzM", [file_camino_api, file_quixos_refs]);
fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASKDAQoOSW52b2tlUmVzcG9uc2USCgoCb2sYASABKAgSHQoGcmVzdWx0GAIgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAMgASgJEjcKDGRlcGVuZGVuY2llcxgEIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5IokCCgxXYXRjaFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNgoFaW5wdXQYBCADKAsyJy5xdWl4b3MucnVudGltZS5XYXRjaFJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDLwAQoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwAWIGcHJvdG8z", [file_camino_api, file_quixos_refs]);
/**
* @generated from message quixos.runtime.HandshakeRequest
@@ -115,6 +115,11 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & {
* @generated from field: string error = 3;
*/
error: string;
/**
* @generated from field: repeated quixos.runtime.DerivedDependency dependencies = 4;
*/
dependencies: DerivedDependency[];
};
/**
+2 -3
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env node
import { readFile } from "node:fs/promises";
import { parseQuixosLock } from "./parser.js";
import { loadQuixosLock } from "./loader.js";
const fileName = process.argv[2];
if (!fileName || process.argv.length !== 3) {
@@ -8,7 +7,7 @@ if (!fileName || process.argv.length !== 3) {
process.exit(2);
}
const result = parseQuixosLock(await readFile(fileName, "utf8"), fileName);
const result = await loadQuixosLock(fileName);
if (!result.ok) {
for (const diagnostic of result.diagnostics) {
console.error(
+18 -1
View File
@@ -1,6 +1,7 @@
token literal names:
null
'quixos-lock'
'fragment'
'version'
'quixos'
'source'
@@ -8,6 +9,12 @@ null
'package'
'repository'
'commit'
'policy'
'ref'
'pinned'
'track-release'
'track-development'
'import'
'{'
'}'
';'
@@ -21,6 +28,7 @@ null
token symbolic names:
null
QUIXOS_LOCK
FRAGMENT
VERSION
QUIXOS
SOURCE
@@ -28,6 +36,12 @@ INTERFACE
PACKAGE
REPOSITORY
COMMIT
POLICY
REF
PINNED
TRACK_RELEASE
TRACK_DEVELOPMENT
IMPORT
LBRACE
RBRACE
SEMI
@@ -42,11 +56,14 @@ rule names:
document
quixosEntry
resourceEntry
importEntry
resourceKind
sourceBlock
quixosSourceBlock
sourcePolicy
identifier
stringLiteral
atn:
[4, 1, 17, 53, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 21, 8, 0, 10, 0, 12, 0, 24, 9, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 0, 0, 7, 0, 2, 4, 6, 8, 10, 12, 0, 1, 1, 0, 5, 6, 46, 0, 14, 1, 0, 0, 0, 2, 28, 1, 0, 0, 0, 4, 32, 1, 0, 0, 0, 6, 37, 1, 0, 0, 0, 8, 39, 1, 0, 0, 0, 10, 48, 1, 0, 0, 0, 12, 50, 1, 0, 0, 0, 14, 15, 5, 1, 0, 0, 15, 16, 5, 2, 0, 0, 16, 17, 5, 12, 0, 0, 17, 18, 5, 9, 0, 0, 18, 22, 3, 2, 1, 0, 19, 21, 3, 4, 2, 0, 20, 19, 1, 0, 0, 0, 21, 24, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 25, 1, 0, 0, 0, 24, 22, 1, 0, 0, 0, 25, 26, 5, 10, 0, 0, 26, 27, 5, 0, 0, 1, 27, 1, 1, 0, 0, 0, 28, 29, 5, 3, 0, 0, 29, 30, 5, 4, 0, 0, 30, 31, 3, 8, 4, 0, 31, 3, 1, 0, 0, 0, 32, 33, 3, 6, 3, 0, 33, 34, 3, 10, 5, 0, 34, 35, 5, 4, 0, 0, 35, 36, 3, 8, 4, 0, 36, 5, 1, 0, 0, 0, 37, 38, 7, 0, 0, 0, 38, 7, 1, 0, 0, 0, 39, 40, 5, 9, 0, 0, 40, 41, 5, 7, 0, 0, 41, 42, 3, 12, 6, 0, 42, 43, 5, 11, 0, 0, 43, 44, 5, 8, 0, 0, 44, 45, 3, 12, 6, 0, 45, 46, 5, 11, 0, 0, 46, 47, 5, 10, 0, 0, 47, 9, 1, 0, 0, 0, 48, 49, 5, 13, 0, 0, 49, 11, 1, 0, 0, 0, 50, 51, 5, 14, 0, 0, 51, 13, 1, 0, 0, 0, 1, 22]
[4, 1, 24, 87, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 1, 0, 1, 0, 3, 0, 23, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 31, 8, 0, 10, 0, 12, 0, 34, 9, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 74, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 0, 0, 10, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 0, 2, 1, 0, 6, 7, 1, 0, 12, 14, 81, 0, 20, 1, 0, 0, 0, 2, 38, 1, 0, 0, 0, 4, 42, 1, 0, 0, 0, 6, 47, 1, 0, 0, 0, 8, 51, 1, 0, 0, 0, 10, 53, 1, 0, 0, 0, 12, 62, 1, 0, 0, 0, 14, 80, 1, 0, 0, 0, 16, 82, 1, 0, 0, 0, 18, 84, 1, 0, 0, 0, 20, 22, 5, 1, 0, 0, 21, 23, 5, 2, 0, 0, 22, 21, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 25, 5, 3, 0, 0, 25, 26, 5, 19, 0, 0, 26, 32, 5, 16, 0, 0, 27, 31, 3, 2, 1, 0, 28, 31, 3, 6, 3, 0, 29, 31, 3, 4, 2, 0, 30, 27, 1, 0, 0, 0, 30, 28, 1, 0, 0, 0, 30, 29, 1, 0, 0, 0, 31, 34, 1, 0, 0, 0, 32, 30, 1, 0, 0, 0, 32, 33, 1, 0, 0, 0, 33, 35, 1, 0, 0, 0, 34, 32, 1, 0, 0, 0, 35, 36, 5, 17, 0, 0, 36, 37, 5, 0, 0, 1, 37, 1, 1, 0, 0, 0, 38, 39, 5, 4, 0, 0, 39, 40, 5, 5, 0, 0, 40, 41, 3, 12, 6, 0, 41, 3, 1, 0, 0, 0, 42, 43, 3, 8, 4, 0, 43, 44, 3, 16, 8, 0, 44, 45, 5, 5, 0, 0, 45, 46, 3, 10, 5, 0, 46, 5, 1, 0, 0, 0, 47, 48, 5, 15, 0, 0, 48, 49, 3, 18, 9, 0, 49, 50, 5, 18, 0, 0, 50, 7, 1, 0, 0, 0, 51, 52, 7, 0, 0, 0, 52, 9, 1, 0, 0, 0, 53, 54, 5, 16, 0, 0, 54, 55, 5, 8, 0, 0, 55, 56, 3, 18, 9, 0, 56, 57, 5, 18, 0, 0, 57, 58, 5, 9, 0, 0, 58, 59, 3, 18, 9, 0, 59, 60, 5, 18, 0, 0, 60, 61, 5, 17, 0, 0, 61, 11, 1, 0, 0, 0, 62, 63, 5, 16, 0, 0, 63, 64, 5, 8, 0, 0, 64, 65, 3, 18, 9, 0, 65, 73, 5, 18, 0, 0, 66, 67, 5, 10, 0, 0, 67, 68, 3, 14, 7, 0, 68, 69, 5, 18, 0, 0, 69, 70, 5, 11, 0, 0, 70, 71, 3, 18, 9, 0, 71, 72, 5, 18, 0, 0, 72, 74, 1, 0, 0, 0, 73, 66, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, 74, 75, 1, 0, 0, 0, 75, 76, 5, 9, 0, 0, 76, 77, 3, 18, 9, 0, 77, 78, 5, 18, 0, 0, 78, 79, 5, 17, 0, 0, 79, 13, 1, 0, 0, 0, 80, 81, 7, 1, 0, 0, 81, 15, 1, 0, 0, 0, 82, 83, 5, 20, 0, 0, 83, 17, 1, 0, 0, 0, 84, 85, 5, 21, 0, 0, 85, 19, 1, 0, 0, 0, 4, 22, 30, 32, 73]
+40 -26
View File
@@ -1,28 +1,42 @@
QUIXOS_LOCK=1
VERSION=2
QUIXOS=3
SOURCE=4
INTERFACE=5
PACKAGE=6
REPOSITORY=7
COMMIT=8
LBRACE=9
RBRACE=10
SEMI=11
INTEGER=12
IDENTIFIER=13
STRING_LITERAL=14
LINE_COMMENT=15
BLOCK_COMMENT=16
WS=17
FRAGMENT=2
VERSION=3
QUIXOS=4
SOURCE=5
INTERFACE=6
PACKAGE=7
REPOSITORY=8
COMMIT=9
POLICY=10
REF=11
PINNED=12
TRACK_RELEASE=13
TRACK_DEVELOPMENT=14
IMPORT=15
LBRACE=16
RBRACE=17
SEMI=18
INTEGER=19
IDENTIFIER=20
STRING_LITERAL=21
LINE_COMMENT=22
BLOCK_COMMENT=23
WS=24
'quixos-lock'=1
'version'=2
'quixos'=3
'source'=4
'interface'=5
'package'=6
'repository'=7
'commit'=8
'{'=9
'}'=10
';'=11
'fragment'=2
'version'=3
'quixos'=4
'source'=5
'interface'=6
'package'=7
'repository'=8
'commit'=9
'policy'=10
'ref'=11
'pinned'=12
'track-release'=13
'track-development'=14
'import'=15
'{'=16
'}'=17
';'=18
File diff suppressed because one or more lines are too long
@@ -1,28 +1,42 @@
QUIXOS_LOCK=1
VERSION=2
QUIXOS=3
SOURCE=4
INTERFACE=5
PACKAGE=6
REPOSITORY=7
COMMIT=8
LBRACE=9
RBRACE=10
SEMI=11
INTEGER=12
IDENTIFIER=13
STRING_LITERAL=14
LINE_COMMENT=15
BLOCK_COMMENT=16
WS=17
FRAGMENT=2
VERSION=3
QUIXOS=4
SOURCE=5
INTERFACE=6
PACKAGE=7
REPOSITORY=8
COMMIT=9
POLICY=10
REF=11
PINNED=12
TRACK_RELEASE=13
TRACK_DEVELOPMENT=14
IMPORT=15
LBRACE=16
RBRACE=17
SEMI=18
INTEGER=19
IDENTIFIER=20
STRING_LITERAL=21
LINE_COMMENT=22
BLOCK_COMMENT=23
WS=24
'quixos-lock'=1
'version'=2
'quixos'=3
'source'=4
'interface'=5
'package'=6
'repository'=7
'commit'=8
'{'=9
'}'=10
';'=11
'fragment'=2
'version'=3
'quixos'=4
'source'=5
'interface'=6
'package'=7
'repository'=8
'commit'=9
'policy'=10
'ref'=11
'pinned'=12
'track-release'=13
'track-development'=14
'import'=15
'{'=16
'}'=17
';'=18
+126 -87
View File
@@ -5,37 +5,47 @@ import { Token } from "antlr4ng";
export class QuixosLockLexer extends antlr.Lexer {
public static readonly QUIXOS_LOCK = 1;
public static readonly VERSION = 2;
public static readonly QUIXOS = 3;
public static readonly SOURCE = 4;
public static readonly INTERFACE = 5;
public static readonly PACKAGE = 6;
public static readonly REPOSITORY = 7;
public static readonly COMMIT = 8;
public static readonly LBRACE = 9;
public static readonly RBRACE = 10;
public static readonly SEMI = 11;
public static readonly INTEGER = 12;
public static readonly IDENTIFIER = 13;
public static readonly STRING_LITERAL = 14;
public static readonly LINE_COMMENT = 15;
public static readonly BLOCK_COMMENT = 16;
public static readonly WS = 17;
public static readonly FRAGMENT = 2;
public static readonly VERSION = 3;
public static readonly QUIXOS = 4;
public static readonly SOURCE = 5;
public static readonly INTERFACE = 6;
public static readonly PACKAGE = 7;
public static readonly REPOSITORY = 8;
public static readonly COMMIT = 9;
public static readonly POLICY = 10;
public static readonly REF = 11;
public static readonly PINNED = 12;
public static readonly TRACK_RELEASE = 13;
public static readonly TRACK_DEVELOPMENT = 14;
public static readonly IMPORT = 15;
public static readonly LBRACE = 16;
public static readonly RBRACE = 17;
public static readonly SEMI = 18;
public static readonly INTEGER = 19;
public static readonly IDENTIFIER = 20;
public static readonly STRING_LITERAL = 21;
public static readonly LINE_COMMENT = 22;
public static readonly BLOCK_COMMENT = 23;
public static readonly WS = 24;
public static readonly channelNames = [
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
];
public static readonly literalNames = [
null, "'quixos-lock'", "'version'", "'quixos'", "'source'", "'interface'",
"'package'", "'repository'", "'commit'", "'{'", "'}'", "';'"
null, "'quixos-lock'", "'fragment'", "'version'", "'quixos'", "'source'",
"'interface'", "'package'", "'repository'", "'commit'", "'policy'",
"'ref'", "'pinned'", "'track-release'", "'track-development'", "'import'",
"'{'", "'}'", "';'"
];
public static readonly symbolicNames = [
null, "QUIXOS_LOCK", "VERSION", "QUIXOS", "SOURCE", "INTERFACE",
"PACKAGE", "REPOSITORY", "COMMIT", "LBRACE", "RBRACE", "SEMI", "INTEGER",
"IDENTIFIER", "STRING_LITERAL", "LINE_COMMENT", "BLOCK_COMMENT",
"WS"
null, "QUIXOS_LOCK", "FRAGMENT", "VERSION", "QUIXOS", "SOURCE",
"INTERFACE", "PACKAGE", "REPOSITORY", "COMMIT", "POLICY", "REF",
"PINNED", "TRACK_RELEASE", "TRACK_DEVELOPMENT", "IMPORT", "LBRACE",
"RBRACE", "SEMI", "INTEGER", "IDENTIFIER", "STRING_LITERAL", "LINE_COMMENT",
"BLOCK_COMMENT", "WS"
];
public static readonly modeNames = [
@@ -43,9 +53,10 @@ export class QuixosLockLexer extends antlr.Lexer {
];
public static readonly ruleNames = [
"QUIXOS_LOCK", "VERSION", "QUIXOS", "SOURCE", "INTERFACE", "PACKAGE",
"REPOSITORY", "COMMIT", "LBRACE", "RBRACE", "SEMI", "INTEGER", "IDENTIFIER",
"STRING_LITERAL", "ESC", "HEX", "LINE_COMMENT", "BLOCK_COMMENT",
"QUIXOS_LOCK", "FRAGMENT", "VERSION", "QUIXOS", "SOURCE", "INTERFACE",
"PACKAGE", "REPOSITORY", "COMMIT", "POLICY", "REF", "PINNED", "TRACK_RELEASE",
"TRACK_DEVELOPMENT", "IMPORT", "LBRACE", "RBRACE", "SEMI", "INTEGER",
"IDENTIFIER", "STRING_LITERAL", "ESC", "HEX", "LINE_COMMENT", "BLOCK_COMMENT",
"WS",
];
@@ -68,70 +79,98 @@ export class QuixosLockLexer extends antlr.Lexer {
public get modeNames(): string[] { return QuixosLockLexer.modeNames; }
public static readonly _serializedATN: number[] = [
4,0,17,181,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
4,0,24,261,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,1,0,1,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,
3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,
5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,
7,1,7,1,7,1,7,1,7,1,8,1,8,1,9,1,9,1,10,1,10,1,11,4,11,117,8,11,11,
11,12,11,118,1,12,1,12,5,12,123,8,12,10,12,12,12,126,9,12,1,13,1,
13,1,13,5,13,131,8,13,10,13,12,13,134,9,13,1,13,1,13,1,14,1,14,1,
14,1,14,1,14,1,14,1,14,1,14,3,14,146,8,14,1,15,1,15,1,16,1,16,1,
16,1,16,5,16,154,8,16,10,16,12,16,157,9,16,1,16,1,16,1,17,1,17,1,
17,1,17,5,17,165,8,17,10,17,12,17,168,9,17,1,17,1,17,1,17,1,17,1,
17,1,18,4,18,176,8,18,11,18,12,18,177,1,18,1,18,1,166,0,19,1,1,3,
13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,
19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,1,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,
3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,
5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,
7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,
9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1,
11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,
12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,
13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,
14,1,14,1,14,1,15,1,15,1,16,1,16,1,17,1,17,1,18,4,18,197,8,18,11,
18,12,18,198,1,19,1,19,5,19,203,8,19,10,19,12,19,206,9,19,1,20,1,
20,1,20,5,20,211,8,20,10,20,12,20,214,9,20,1,20,1,20,1,21,1,21,1,
21,1,21,1,21,1,21,1,21,1,21,3,21,226,8,21,1,22,1,22,1,23,1,23,1,
23,1,23,5,23,234,8,23,10,23,12,23,237,9,23,1,23,1,23,1,24,1,24,1,
24,1,24,5,24,245,8,24,10,24,12,24,248,9,24,1,24,1,24,1,24,1,24,1,
24,1,25,4,25,256,8,25,11,25,12,25,257,1,25,1,25,1,246,0,26,1,1,3,
2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,
29,0,31,0,33,15,35,16,37,17,1,0,8,1,0,48,57,3,0,65,90,95,95,97,122,
4,0,48,57,65,90,95,95,97,122,4,0,10,10,13,13,34,34,92,92,8,0,34,
34,47,47,92,92,98,98,102,102,110,110,114,114,116,116,3,0,48,57,65,
70,97,102,2,0,10,10,13,13,3,0,9,10,13,13,32,32,186,0,1,1,0,0,0,0,
3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,
1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,
1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,
1,0,0,0,1,39,1,0,0,0,3,51,1,0,0,0,5,59,1,0,0,0,7,66,1,0,0,0,9,73,
1,0,0,0,11,83,1,0,0,0,13,91,1,0,0,0,15,102,1,0,0,0,17,109,1,0,0,
0,19,111,1,0,0,0,21,113,1,0,0,0,23,116,1,0,0,0,25,120,1,0,0,0,27,
127,1,0,0,0,29,137,1,0,0,0,31,147,1,0,0,0,33,149,1,0,0,0,35,160,
1,0,0,0,37,175,1,0,0,0,39,40,5,113,0,0,40,41,5,117,0,0,41,42,5,105,
0,0,42,43,5,120,0,0,43,44,5,111,0,0,44,45,5,115,0,0,45,46,5,45,0,
0,46,47,5,108,0,0,47,48,5,111,0,0,48,49,5,99,0,0,49,50,5,107,0,0,
50,2,1,0,0,0,51,52,5,118,0,0,52,53,5,101,0,0,53,54,5,114,0,0,54,
55,5,115,0,0,55,56,5,105,0,0,56,57,5,111,0,0,57,58,5,110,0,0,58,
4,1,0,0,0,59,60,5,113,0,0,60,61,5,117,0,0,61,62,5,105,0,0,62,63,
5,120,0,0,63,64,5,111,0,0,64,65,5,115,0,0,65,6,1,0,0,0,66,67,5,115,
0,0,67,68,5,111,0,0,68,69,5,117,0,0,69,70,5,114,0,0,70,71,5,99,0,
0,71,72,5,101,0,0,72,8,1,0,0,0,73,74,5,105,0,0,74,75,5,110,0,0,75,
76,5,116,0,0,76,77,5,101,0,0,77,78,5,114,0,0,78,79,5,102,0,0,79,
80,5,97,0,0,80,81,5,99,0,0,81,82,5,101,0,0,82,10,1,0,0,0,83,84,5,
112,0,0,84,85,5,97,0,0,85,86,5,99,0,0,86,87,5,107,0,0,87,88,5,97,
0,0,88,89,5,103,0,0,89,90,5,101,0,0,90,12,1,0,0,0,91,92,5,114,0,
0,92,93,5,101,0,0,93,94,5,112,0,0,94,95,5,111,0,0,95,96,5,115,0,
0,96,97,5,105,0,0,97,98,5,116,0,0,98,99,5,111,0,0,99,100,5,114,0,
0,100,101,5,121,0,0,101,14,1,0,0,0,102,103,5,99,0,0,103,104,5,111,
0,0,104,105,5,109,0,0,105,106,5,109,0,0,106,107,5,105,0,0,107,108,
5,116,0,0,108,16,1,0,0,0,109,110,5,123,0,0,110,18,1,0,0,0,111,112,
5,125,0,0,112,20,1,0,0,0,113,114,5,59,0,0,114,22,1,0,0,0,115,117,
7,0,0,0,116,115,1,0,0,0,117,118,1,0,0,0,118,116,1,0,0,0,118,119,
1,0,0,0,119,24,1,0,0,0,120,124,7,1,0,0,121,123,7,2,0,0,122,121,1,
0,0,0,123,126,1,0,0,0,124,122,1,0,0,0,124,125,1,0,0,0,125,26,1,0,
0,0,126,124,1,0,0,0,127,132,5,34,0,0,128,131,3,29,14,0,129,131,8,
3,0,0,130,128,1,0,0,0,130,129,1,0,0,0,131,134,1,0,0,0,132,130,1,
0,0,0,132,133,1,0,0,0,133,135,1,0,0,0,134,132,1,0,0,0,135,136,5,
34,0,0,136,28,1,0,0,0,137,145,5,92,0,0,138,146,7,4,0,0,139,140,5,
117,0,0,140,141,3,31,15,0,141,142,3,31,15,0,142,143,3,31,15,0,143,
144,3,31,15,0,144,146,1,0,0,0,145,138,1,0,0,0,145,139,1,0,0,0,146,
30,1,0,0,0,147,148,7,5,0,0,148,32,1,0,0,0,149,150,5,47,0,0,150,151,
5,47,0,0,151,155,1,0,0,0,152,154,8,6,0,0,153,152,1,0,0,0,154,157,
1,0,0,0,155,153,1,0,0,0,155,156,1,0,0,0,156,158,1,0,0,0,157,155,
1,0,0,0,158,159,6,16,0,0,159,34,1,0,0,0,160,161,5,47,0,0,161,162,
5,42,0,0,162,166,1,0,0,0,163,165,9,0,0,0,164,163,1,0,0,0,165,168,
1,0,0,0,166,167,1,0,0,0,166,164,1,0,0,0,167,169,1,0,0,0,168,166,
1,0,0,0,169,170,5,42,0,0,170,171,5,47,0,0,171,172,1,0,0,0,172,173,
6,17,0,0,173,36,1,0,0,0,174,176,7,7,0,0,175,174,1,0,0,0,176,177,
1,0,0,0,177,175,1,0,0,0,177,178,1,0,0,0,178,179,1,0,0,0,179,180,
6,18,0,0,180,38,1,0,0,0,9,0,118,124,130,132,145,155,166,177,1,6,
29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,0,45,0,47,22,49,23,
51,24,1,0,8,1,0,48,57,3,0,65,90,95,95,97,122,4,0,48,57,65,90,95,
95,97,122,4,0,10,10,13,13,34,34,92,92,8,0,34,34,47,47,92,92,98,98,
102,102,110,110,114,114,116,116,3,0,48,57,65,70,97,102,2,0,10,10,
13,13,3,0,9,10,13,13,32,32,266,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,
0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,
0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,
0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,
0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,
0,51,1,0,0,0,1,53,1,0,0,0,3,65,1,0,0,0,5,74,1,0,0,0,7,82,1,0,0,0,
9,89,1,0,0,0,11,96,1,0,0,0,13,106,1,0,0,0,15,114,1,0,0,0,17,125,
1,0,0,0,19,132,1,0,0,0,21,139,1,0,0,0,23,143,1,0,0,0,25,150,1,0,
0,0,27,164,1,0,0,0,29,182,1,0,0,0,31,189,1,0,0,0,33,191,1,0,0,0,
35,193,1,0,0,0,37,196,1,0,0,0,39,200,1,0,0,0,41,207,1,0,0,0,43,217,
1,0,0,0,45,227,1,0,0,0,47,229,1,0,0,0,49,240,1,0,0,0,51,255,1,0,
0,0,53,54,5,113,0,0,54,55,5,117,0,0,55,56,5,105,0,0,56,57,5,120,
0,0,57,58,5,111,0,0,58,59,5,115,0,0,59,60,5,45,0,0,60,61,5,108,0,
0,61,62,5,111,0,0,62,63,5,99,0,0,63,64,5,107,0,0,64,2,1,0,0,0,65,
66,5,102,0,0,66,67,5,114,0,0,67,68,5,97,0,0,68,69,5,103,0,0,69,70,
5,109,0,0,70,71,5,101,0,0,71,72,5,110,0,0,72,73,5,116,0,0,73,4,1,
0,0,0,74,75,5,118,0,0,75,76,5,101,0,0,76,77,5,114,0,0,77,78,5,115,
0,0,78,79,5,105,0,0,79,80,5,111,0,0,80,81,5,110,0,0,81,6,1,0,0,0,
82,83,5,113,0,0,83,84,5,117,0,0,84,85,5,105,0,0,85,86,5,120,0,0,
86,87,5,111,0,0,87,88,5,115,0,0,88,8,1,0,0,0,89,90,5,115,0,0,90,
91,5,111,0,0,91,92,5,117,0,0,92,93,5,114,0,0,93,94,5,99,0,0,94,95,
5,101,0,0,95,10,1,0,0,0,96,97,5,105,0,0,97,98,5,110,0,0,98,99,5,
116,0,0,99,100,5,101,0,0,100,101,5,114,0,0,101,102,5,102,0,0,102,
103,5,97,0,0,103,104,5,99,0,0,104,105,5,101,0,0,105,12,1,0,0,0,106,
107,5,112,0,0,107,108,5,97,0,0,108,109,5,99,0,0,109,110,5,107,0,
0,110,111,5,97,0,0,111,112,5,103,0,0,112,113,5,101,0,0,113,14,1,
0,0,0,114,115,5,114,0,0,115,116,5,101,0,0,116,117,5,112,0,0,117,
118,5,111,0,0,118,119,5,115,0,0,119,120,5,105,0,0,120,121,5,116,
0,0,121,122,5,111,0,0,122,123,5,114,0,0,123,124,5,121,0,0,124,16,
1,0,0,0,125,126,5,99,0,0,126,127,5,111,0,0,127,128,5,109,0,0,128,
129,5,109,0,0,129,130,5,105,0,0,130,131,5,116,0,0,131,18,1,0,0,0,
132,133,5,112,0,0,133,134,5,111,0,0,134,135,5,108,0,0,135,136,5,
105,0,0,136,137,5,99,0,0,137,138,5,121,0,0,138,20,1,0,0,0,139,140,
5,114,0,0,140,141,5,101,0,0,141,142,5,102,0,0,142,22,1,0,0,0,143,
144,5,112,0,0,144,145,5,105,0,0,145,146,5,110,0,0,146,147,5,110,
0,0,147,148,5,101,0,0,148,149,5,100,0,0,149,24,1,0,0,0,150,151,5,
116,0,0,151,152,5,114,0,0,152,153,5,97,0,0,153,154,5,99,0,0,154,
155,5,107,0,0,155,156,5,45,0,0,156,157,5,114,0,0,157,158,5,101,0,
0,158,159,5,108,0,0,159,160,5,101,0,0,160,161,5,97,0,0,161,162,5,
115,0,0,162,163,5,101,0,0,163,26,1,0,0,0,164,165,5,116,0,0,165,166,
5,114,0,0,166,167,5,97,0,0,167,168,5,99,0,0,168,169,5,107,0,0,169,
170,5,45,0,0,170,171,5,100,0,0,171,172,5,101,0,0,172,173,5,118,0,
0,173,174,5,101,0,0,174,175,5,108,0,0,175,176,5,111,0,0,176,177,
5,112,0,0,177,178,5,109,0,0,178,179,5,101,0,0,179,180,5,110,0,0,
180,181,5,116,0,0,181,28,1,0,0,0,182,183,5,105,0,0,183,184,5,109,
0,0,184,185,5,112,0,0,185,186,5,111,0,0,186,187,5,114,0,0,187,188,
5,116,0,0,188,30,1,0,0,0,189,190,5,123,0,0,190,32,1,0,0,0,191,192,
5,125,0,0,192,34,1,0,0,0,193,194,5,59,0,0,194,36,1,0,0,0,195,197,
7,0,0,0,196,195,1,0,0,0,197,198,1,0,0,0,198,196,1,0,0,0,198,199,
1,0,0,0,199,38,1,0,0,0,200,204,7,1,0,0,201,203,7,2,0,0,202,201,1,
0,0,0,203,206,1,0,0,0,204,202,1,0,0,0,204,205,1,0,0,0,205,40,1,0,
0,0,206,204,1,0,0,0,207,212,5,34,0,0,208,211,3,43,21,0,209,211,8,
3,0,0,210,208,1,0,0,0,210,209,1,0,0,0,211,214,1,0,0,0,212,210,1,
0,0,0,212,213,1,0,0,0,213,215,1,0,0,0,214,212,1,0,0,0,215,216,5,
34,0,0,216,42,1,0,0,0,217,225,5,92,0,0,218,226,7,4,0,0,219,220,5,
117,0,0,220,221,3,45,22,0,221,222,3,45,22,0,222,223,3,45,22,0,223,
224,3,45,22,0,224,226,1,0,0,0,225,218,1,0,0,0,225,219,1,0,0,0,226,
44,1,0,0,0,227,228,7,5,0,0,228,46,1,0,0,0,229,230,5,47,0,0,230,231,
5,47,0,0,231,235,1,0,0,0,232,234,8,6,0,0,233,232,1,0,0,0,234,237,
1,0,0,0,235,233,1,0,0,0,235,236,1,0,0,0,236,238,1,0,0,0,237,235,
1,0,0,0,238,239,6,23,0,0,239,48,1,0,0,0,240,241,5,47,0,0,241,242,
5,42,0,0,242,246,1,0,0,0,243,245,9,0,0,0,244,243,1,0,0,0,245,248,
1,0,0,0,246,247,1,0,0,0,246,244,1,0,0,0,247,249,1,0,0,0,248,246,
1,0,0,0,249,250,5,42,0,0,250,251,5,47,0,0,251,252,1,0,0,0,252,253,
6,24,0,0,253,50,1,0,0,0,254,256,7,7,0,0,255,254,1,0,0,0,256,257,
1,0,0,0,257,255,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259,260,
6,25,0,0,260,52,1,0,0,0,9,0,198,204,210,212,225,235,246,257,1,6,
0,0
];
+381 -86
View File
@@ -11,44 +11,58 @@ type int = number;
export class QuixosLockParser extends antlr.Parser {
public static readonly QUIXOS_LOCK = 1;
public static readonly VERSION = 2;
public static readonly QUIXOS = 3;
public static readonly SOURCE = 4;
public static readonly INTERFACE = 5;
public static readonly PACKAGE = 6;
public static readonly REPOSITORY = 7;
public static readonly COMMIT = 8;
public static readonly LBRACE = 9;
public static readonly RBRACE = 10;
public static readonly SEMI = 11;
public static readonly INTEGER = 12;
public static readonly IDENTIFIER = 13;
public static readonly STRING_LITERAL = 14;
public static readonly LINE_COMMENT = 15;
public static readonly BLOCK_COMMENT = 16;
public static readonly WS = 17;
public static readonly FRAGMENT = 2;
public static readonly VERSION = 3;
public static readonly QUIXOS = 4;
public static readonly SOURCE = 5;
public static readonly INTERFACE = 6;
public static readonly PACKAGE = 7;
public static readonly REPOSITORY = 8;
public static readonly COMMIT = 9;
public static readonly POLICY = 10;
public static readonly REF = 11;
public static readonly PINNED = 12;
public static readonly TRACK_RELEASE = 13;
public static readonly TRACK_DEVELOPMENT = 14;
public static readonly IMPORT = 15;
public static readonly LBRACE = 16;
public static readonly RBRACE = 17;
public static readonly SEMI = 18;
public static readonly INTEGER = 19;
public static readonly IDENTIFIER = 20;
public static readonly STRING_LITERAL = 21;
public static readonly LINE_COMMENT = 22;
public static readonly BLOCK_COMMENT = 23;
public static readonly WS = 24;
public static readonly RULE_document = 0;
public static readonly RULE_quixosEntry = 1;
public static readonly RULE_resourceEntry = 2;
public static readonly RULE_resourceKind = 3;
public static readonly RULE_sourceBlock = 4;
public static readonly RULE_identifier = 5;
public static readonly RULE_stringLiteral = 6;
public static readonly RULE_importEntry = 3;
public static readonly RULE_resourceKind = 4;
public static readonly RULE_sourceBlock = 5;
public static readonly RULE_quixosSourceBlock = 6;
public static readonly RULE_sourcePolicy = 7;
public static readonly RULE_identifier = 8;
public static readonly RULE_stringLiteral = 9;
public static readonly literalNames = [
null, "'quixos-lock'", "'version'", "'quixos'", "'source'", "'interface'",
"'package'", "'repository'", "'commit'", "'{'", "'}'", "';'"
null, "'quixos-lock'", "'fragment'", "'version'", "'quixos'", "'source'",
"'interface'", "'package'", "'repository'", "'commit'", "'policy'",
"'ref'", "'pinned'", "'track-release'", "'track-development'", "'import'",
"'{'", "'}'", "';'"
];
public static readonly symbolicNames = [
null, "QUIXOS_LOCK", "VERSION", "QUIXOS", "SOURCE", "INTERFACE",
"PACKAGE", "REPOSITORY", "COMMIT", "LBRACE", "RBRACE", "SEMI", "INTEGER",
"IDENTIFIER", "STRING_LITERAL", "LINE_COMMENT", "BLOCK_COMMENT",
"WS"
null, "QUIXOS_LOCK", "FRAGMENT", "VERSION", "QUIXOS", "SOURCE",
"INTERFACE", "PACKAGE", "REPOSITORY", "COMMIT", "POLICY", "REF",
"PINNED", "TRACK_RELEASE", "TRACK_DEVELOPMENT", "IMPORT", "LBRACE",
"RBRACE", "SEMI", "INTEGER", "IDENTIFIER", "STRING_LITERAL", "LINE_COMMENT",
"BLOCK_COMMENT", "WS"
];
public static readonly ruleNames = [
"document", "quixosEntry", "resourceEntry", "resourceKind", "sourceBlock",
"identifier", "stringLiteral",
"document", "quixosEntry", "resourceEntry", "importEntry", "resourceKind",
"sourceBlock", "quixosSourceBlock", "sourcePolicy", "identifier",
"stringLiteral",
];
public get grammarFileName(): string { return "QuixosLock.g4"; }
@@ -72,33 +86,62 @@ export class QuixosLockParser extends antlr.Parser {
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 14;
this.state = 20;
this.match(QuixosLockParser.QUIXOS_LOCK);
this.state = 15;
this.match(QuixosLockParser.VERSION);
this.state = 16;
this.match(QuixosLockParser.INTEGER);
this.state = 17;
this.match(QuixosLockParser.LBRACE);
this.state = 18;
this.quixosEntry();
this.state = 22;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
while (_la === 5 || _la === 6) {
if (_la === 2) {
{
this.state = 21;
this.match(QuixosLockParser.FRAGMENT);
}
}
this.state = 24;
this.match(QuixosLockParser.VERSION);
this.state = 25;
this.match(QuixosLockParser.INTEGER);
this.state = 26;
this.match(QuixosLockParser.LBRACE);
this.state = 32;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 32976) !== 0)) {
{
this.state = 19;
this.state = 30;
this.errorHandler.sync(this);
switch (this.tokenStream.LA(1)) {
case QuixosLockParser.QUIXOS:
{
this.state = 27;
this.quixosEntry();
}
break;
case QuixosLockParser.IMPORT:
{
this.state = 28;
this.importEntry();
}
break;
case QuixosLockParser.INTERFACE:
case QuixosLockParser.PACKAGE:
{
this.state = 29;
this.resourceEntry();
}
break;
default:
throw new antlr.NoViableAltException(this);
}
this.state = 24;
}
this.state = 34;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
}
this.state = 25;
this.state = 35;
this.match(QuixosLockParser.RBRACE);
this.state = 26;
this.state = 36;
this.match(QuixosLockParser.EOF);
}
}
@@ -121,12 +164,12 @@ export class QuixosLockParser extends antlr.Parser {
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 28;
this.state = 38;
this.match(QuixosLockParser.QUIXOS);
this.state = 29;
this.state = 39;
this.match(QuixosLockParser.SOURCE);
this.state = 30;
this.sourceBlock();
this.state = 40;
this.quixosSourceBlock();
}
}
catch (re) {
@@ -148,13 +191,13 @@ export class QuixosLockParser extends antlr.Parser {
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 32;
this.state = 42;
this.resourceKind();
this.state = 33;
this.state = 43;
this.identifier();
this.state = 34;
this.state = 44;
this.match(QuixosLockParser.SOURCE);
this.state = 35;
this.state = 45;
this.sourceBlock();
}
}
@@ -171,16 +214,43 @@ export class QuixosLockParser extends antlr.Parser {
}
return localContext;
}
public importEntry(): ImportEntryContext {
let localContext = new ImportEntryContext(this.context, this.state);
this.enterRule(localContext, 6, QuixosLockParser.RULE_importEntry);
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 47;
this.match(QuixosLockParser.IMPORT);
this.state = 48;
this.stringLiteral();
this.state = 49;
this.match(QuixosLockParser.SEMI);
}
}
catch (re) {
if (re instanceof antlr.RecognitionException) {
this.errorHandler.reportError(this, re);
this.errorHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return localContext;
}
public resourceKind(): ResourceKindContext {
let localContext = new ResourceKindContext(this.context, this.state);
this.enterRule(localContext, 6, QuixosLockParser.RULE_resourceKind);
this.enterRule(localContext, 8, QuixosLockParser.RULE_resourceKind);
let _la: number;
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 37;
this.state = 51;
_la = this.tokenStream.LA(1);
if(!(_la === 5 || _la === 6)) {
if(!(_la === 6 || _la === 7)) {
this.errorHandler.recoverInline(this);
}
else {
@@ -204,25 +274,25 @@ export class QuixosLockParser extends antlr.Parser {
}
public sourceBlock(): SourceBlockContext {
let localContext = new SourceBlockContext(this.context, this.state);
this.enterRule(localContext, 8, QuixosLockParser.RULE_sourceBlock);
this.enterRule(localContext, 10, QuixosLockParser.RULE_sourceBlock);
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 39;
this.state = 53;
this.match(QuixosLockParser.LBRACE);
this.state = 40;
this.state = 54;
this.match(QuixosLockParser.REPOSITORY);
this.state = 41;
this.state = 55;
this.stringLiteral();
this.state = 42;
this.state = 56;
this.match(QuixosLockParser.SEMI);
this.state = 43;
this.state = 57;
this.match(QuixosLockParser.COMMIT);
this.state = 44;
this.state = 58;
this.stringLiteral();
this.state = 45;
this.state = 59;
this.match(QuixosLockParser.SEMI);
this.state = 46;
this.state = 60;
this.match(QuixosLockParser.RBRACE);
}
}
@@ -239,13 +309,102 @@ export class QuixosLockParser extends antlr.Parser {
}
return localContext;
}
public quixosSourceBlock(): QuixosSourceBlockContext {
let localContext = new QuixosSourceBlockContext(this.context, this.state);
this.enterRule(localContext, 12, QuixosLockParser.RULE_quixosSourceBlock);
let _la: number;
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 62;
this.match(QuixosLockParser.LBRACE);
this.state = 63;
this.match(QuixosLockParser.REPOSITORY);
this.state = 64;
this.stringLiteral();
this.state = 65;
this.match(QuixosLockParser.SEMI);
this.state = 73;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
if (_la === 10) {
{
this.state = 66;
this.match(QuixosLockParser.POLICY);
this.state = 67;
this.sourcePolicy();
this.state = 68;
this.match(QuixosLockParser.SEMI);
this.state = 69;
this.match(QuixosLockParser.REF);
this.state = 70;
this.stringLiteral();
this.state = 71;
this.match(QuixosLockParser.SEMI);
}
}
this.state = 75;
this.match(QuixosLockParser.COMMIT);
this.state = 76;
this.stringLiteral();
this.state = 77;
this.match(QuixosLockParser.SEMI);
this.state = 78;
this.match(QuixosLockParser.RBRACE);
}
}
catch (re) {
if (re instanceof antlr.RecognitionException) {
this.errorHandler.reportError(this, re);
this.errorHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return localContext;
}
public sourcePolicy(): SourcePolicyContext {
let localContext = new SourcePolicyContext(this.context, this.state);
this.enterRule(localContext, 14, QuixosLockParser.RULE_sourcePolicy);
let _la: number;
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 80;
_la = this.tokenStream.LA(1);
if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 28672) !== 0))) {
this.errorHandler.recoverInline(this);
}
else {
this.errorHandler.reportMatch(this);
this.consume();
}
}
}
catch (re) {
if (re instanceof antlr.RecognitionException) {
this.errorHandler.reportError(this, re);
this.errorHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return localContext;
}
public identifier(): IdentifierContext {
let localContext = new IdentifierContext(this.context, this.state);
this.enterRule(localContext, 10, QuixosLockParser.RULE_identifier);
this.enterRule(localContext, 16, QuixosLockParser.RULE_identifier);
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 48;
this.state = 82;
this.match(QuixosLockParser.IDENTIFIER);
}
}
@@ -264,11 +423,11 @@ export class QuixosLockParser extends antlr.Parser {
}
public stringLiteral(): StringLiteralContext {
let localContext = new StringLiteralContext(this.context, this.state);
this.enterRule(localContext, 12, QuixosLockParser.RULE_stringLiteral);
this.enterRule(localContext, 18, QuixosLockParser.RULE_stringLiteral);
try {
this.enterOuterAlt(localContext, 1);
{
this.state = 50;
this.state = 84;
this.match(QuixosLockParser.STRING_LITERAL);
}
}
@@ -287,21 +446,31 @@ export class QuixosLockParser extends antlr.Parser {
}
public static readonly _serializedATN: number[] = [
4,1,17,53,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,1,0,1,0,1,0,1,0,1,0,1,0,5,0,21,8,0,10,0,12,0,24,9,0,1,0,1,0,1,
0,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,4,1,4,1,
4,1,4,1,4,1,4,1,4,1,5,1,5,1,6,1,6,1,6,0,0,7,0,2,4,6,8,10,12,0,1,
1,0,5,6,46,0,14,1,0,0,0,2,28,1,0,0,0,4,32,1,0,0,0,6,37,1,0,0,0,8,
39,1,0,0,0,10,48,1,0,0,0,12,50,1,0,0,0,14,15,5,1,0,0,15,16,5,2,0,
0,16,17,5,12,0,0,17,18,5,9,0,0,18,22,3,2,1,0,19,21,3,4,2,0,20,19,
1,0,0,0,21,24,1,0,0,0,22,20,1,0,0,0,22,23,1,0,0,0,23,25,1,0,0,0,
24,22,1,0,0,0,25,26,5,10,0,0,26,27,5,0,0,1,27,1,1,0,0,0,28,29,5,
3,0,0,29,30,5,4,0,0,30,31,3,8,4,0,31,3,1,0,0,0,32,33,3,6,3,0,33,
34,3,10,5,0,34,35,5,4,0,0,35,36,3,8,4,0,36,5,1,0,0,0,37,38,7,0,0,
0,38,7,1,0,0,0,39,40,5,9,0,0,40,41,5,7,0,0,41,42,3,12,6,0,42,43,
5,11,0,0,43,44,5,8,0,0,44,45,3,12,6,0,45,46,5,11,0,0,46,47,5,10,
0,0,47,9,1,0,0,0,48,49,5,13,0,0,49,11,1,0,0,0,50,51,5,14,0,0,51,
13,1,0,0,0,1,22
4,1,24,87,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,2,7,7,7,2,8,7,8,2,9,7,9,1,0,1,0,3,0,23,8,0,1,0,1,0,1,0,1,0,1,0,
1,0,5,0,31,8,0,10,0,12,0,34,9,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,2,
1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,
1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6,3,6,74,8,
6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,8,1,8,1,9,1,9,1,9,0,0,10,0,2,4,6,
8,10,12,14,16,18,0,2,1,0,6,7,1,0,12,14,81,0,20,1,0,0,0,2,38,1,0,
0,0,4,42,1,0,0,0,6,47,1,0,0,0,8,51,1,0,0,0,10,53,1,0,0,0,12,62,1,
0,0,0,14,80,1,0,0,0,16,82,1,0,0,0,18,84,1,0,0,0,20,22,5,1,0,0,21,
23,5,2,0,0,22,21,1,0,0,0,22,23,1,0,0,0,23,24,1,0,0,0,24,25,5,3,0,
0,25,26,5,19,0,0,26,32,5,16,0,0,27,31,3,2,1,0,28,31,3,6,3,0,29,31,
3,4,2,0,30,27,1,0,0,0,30,28,1,0,0,0,30,29,1,0,0,0,31,34,1,0,0,0,
32,30,1,0,0,0,32,33,1,0,0,0,33,35,1,0,0,0,34,32,1,0,0,0,35,36,5,
17,0,0,36,37,5,0,0,1,37,1,1,0,0,0,38,39,5,4,0,0,39,40,5,5,0,0,40,
41,3,12,6,0,41,3,1,0,0,0,42,43,3,8,4,0,43,44,3,16,8,0,44,45,5,5,
0,0,45,46,3,10,5,0,46,5,1,0,0,0,47,48,5,15,0,0,48,49,3,18,9,0,49,
50,5,18,0,0,50,7,1,0,0,0,51,52,7,0,0,0,52,9,1,0,0,0,53,54,5,16,0,
0,54,55,5,8,0,0,55,56,3,18,9,0,56,57,5,18,0,0,57,58,5,9,0,0,58,59,
3,18,9,0,59,60,5,18,0,0,60,61,5,17,0,0,61,11,1,0,0,0,62,63,5,16,
0,0,63,64,5,8,0,0,64,65,3,18,9,0,65,73,5,18,0,0,66,67,5,10,0,0,67,
68,3,14,7,0,68,69,5,18,0,0,69,70,5,11,0,0,70,71,3,18,9,0,71,72,5,
18,0,0,72,74,1,0,0,0,73,66,1,0,0,0,73,74,1,0,0,0,74,75,1,0,0,0,75,
76,5,9,0,0,76,77,3,18,9,0,77,78,5,18,0,0,78,79,5,17,0,0,79,13,1,
0,0,0,80,81,7,1,0,0,81,15,1,0,0,0,82,83,5,20,0,0,83,17,1,0,0,0,84,
85,5,21,0,0,85,19,1,0,0,0,4,22,30,32,73
];
private static __ATN: antlr.ATN;
@@ -339,15 +508,33 @@ export class DocumentContext extends antlr.ParserRuleContext {
public LBRACE(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.LBRACE, 0)!;
}
public quixosEntry(): QuixosEntryContext {
return this.getRuleContext(0, QuixosEntryContext)!;
}
public RBRACE(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.RBRACE, 0)!;
}
public EOF(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.EOF, 0)!;
}
public FRAGMENT(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.FRAGMENT, 0);
}
public quixosEntry(): QuixosEntryContext[];
public quixosEntry(i: number): QuixosEntryContext | null;
public quixosEntry(i?: number): QuixosEntryContext[] | QuixosEntryContext | null {
if (i === undefined) {
return this.getRuleContexts(QuixosEntryContext);
}
return this.getRuleContext(i, QuixosEntryContext);
}
public importEntry(): ImportEntryContext[];
public importEntry(i: number): ImportEntryContext | null;
public importEntry(i?: number): ImportEntryContext[] | ImportEntryContext | null {
if (i === undefined) {
return this.getRuleContexts(ImportEntryContext);
}
return this.getRuleContext(i, ImportEntryContext);
}
public resourceEntry(): ResourceEntryContext[];
public resourceEntry(i: number): ResourceEntryContext | null;
public resourceEntry(i?: number): ResourceEntryContext[] | ResourceEntryContext | null {
@@ -380,8 +567,8 @@ export class QuixosEntryContext extends antlr.ParserRuleContext {
public SOURCE(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.SOURCE, 0)!;
}
public sourceBlock(): SourceBlockContext {
return this.getRuleContext(0, SourceBlockContext)!;
public quixosSourceBlock(): QuixosSourceBlockContext {
return this.getRuleContext(0, QuixosSourceBlockContext)!;
}
public override get ruleIndex(): number {
return QuixosLockParser.RULE_quixosEntry;
@@ -425,6 +612,32 @@ export class ResourceEntryContext extends antlr.ParserRuleContext {
}
export class ImportEntryContext extends antlr.ParserRuleContext {
public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) {
super(parent, invokingState);
}
public IMPORT(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.IMPORT, 0)!;
}
public stringLiteral(): StringLiteralContext {
return this.getRuleContext(0, StringLiteralContext)!;
}
public SEMI(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.SEMI, 0)!;
}
public override get ruleIndex(): number {
return QuixosLockParser.RULE_importEntry;
}
public override accept<Result>(visitor: QuixosLockVisitor<Result>): Result | null {
if (visitor.visitImportEntry) {
return visitor.visitImportEntry(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class ResourceKindContext extends antlr.ParserRuleContext {
public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) {
super(parent, invokingState);
@@ -495,6 +708,88 @@ export class SourceBlockContext extends antlr.ParserRuleContext {
}
export class QuixosSourceBlockContext extends antlr.ParserRuleContext {
public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) {
super(parent, invokingState);
}
public LBRACE(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.LBRACE, 0)!;
}
public REPOSITORY(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.REPOSITORY, 0)!;
}
public stringLiteral(): StringLiteralContext[];
public stringLiteral(i: number): StringLiteralContext | null;
public stringLiteral(i?: number): StringLiteralContext[] | StringLiteralContext | null {
if (i === undefined) {
return this.getRuleContexts(StringLiteralContext);
}
return this.getRuleContext(i, StringLiteralContext);
}
public SEMI(): antlr.TerminalNode[];
public SEMI(i: number): antlr.TerminalNode | null;
public SEMI(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] {
if (i === undefined) {
return this.getTokens(QuixosLockParser.SEMI);
} else {
return this.getToken(QuixosLockParser.SEMI, i);
}
}
public COMMIT(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.COMMIT, 0)!;
}
public RBRACE(): antlr.TerminalNode {
return this.getToken(QuixosLockParser.RBRACE, 0)!;
}
public POLICY(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.POLICY, 0);
}
public sourcePolicy(): SourcePolicyContext | null {
return this.getRuleContext(0, SourcePolicyContext);
}
public REF(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.REF, 0);
}
public override get ruleIndex(): number {
return QuixosLockParser.RULE_quixosSourceBlock;
}
public override accept<Result>(visitor: QuixosLockVisitor<Result>): Result | null {
if (visitor.visitQuixosSourceBlock) {
return visitor.visitQuixosSourceBlock(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class SourcePolicyContext extends antlr.ParserRuleContext {
public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) {
super(parent, invokingState);
}
public PINNED(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.PINNED, 0);
}
public TRACK_RELEASE(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.TRACK_RELEASE, 0);
}
public TRACK_DEVELOPMENT(): antlr.TerminalNode | null {
return this.getToken(QuixosLockParser.TRACK_DEVELOPMENT, 0);
}
public override get ruleIndex(): number {
return QuixosLockParser.RULE_sourcePolicy;
}
public override accept<Result>(visitor: QuixosLockVisitor<Result>): Result | null {
if (visitor.visitSourcePolicy) {
return visitor.visitSourcePolicy(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class IdentifierContext extends antlr.ParserRuleContext {
public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) {
super(parent, invokingState);
@@ -5,8 +5,11 @@ import { AbstractParseTreeVisitor } from "antlr4ng";
import { DocumentContext } from "./QuixosLockParser.js";
import { QuixosEntryContext } from "./QuixosLockParser.js";
import { ResourceEntryContext } from "./QuixosLockParser.js";
import { ImportEntryContext } from "./QuixosLockParser.js";
import { ResourceKindContext } from "./QuixosLockParser.js";
import { SourceBlockContext } from "./QuixosLockParser.js";
import { QuixosSourceBlockContext } from "./QuixosLockParser.js";
import { SourcePolicyContext } from "./QuixosLockParser.js";
import { IdentifierContext } from "./QuixosLockParser.js";
import { StringLiteralContext } from "./QuixosLockParser.js";
@@ -37,6 +40,12 @@ export class QuixosLockVisitor<Result> extends AbstractParseTreeVisitor<Result>
* @return the visitor result
*/
visitResourceEntry?: (ctx: ResourceEntryContext) => Result;
/**
* Visit a parse tree produced by `QuixosLockParser.importEntry`.
* @param ctx the parse tree
* @return the visitor result
*/
visitImportEntry?: (ctx: ImportEntryContext) => Result;
/**
* Visit a parse tree produced by `QuixosLockParser.resourceKind`.
* @param ctx the parse tree
@@ -49,6 +58,18 @@ export class QuixosLockVisitor<Result> extends AbstractParseTreeVisitor<Result>
* @return the visitor result
*/
visitSourceBlock?: (ctx: SourceBlockContext) => Result;
/**
* Visit a parse tree produced by `QuixosLockParser.quixosSourceBlock`.
* @param ctx the parse tree
* @return the visitor result
*/
visitQuixosSourceBlock?: (ctx: QuixosSourceBlockContext) => Result;
/**
* Visit a parse tree produced by `QuixosLockParser.sourcePolicy`.
* @param ctx the parse tree
* @return the visitor result
*/
visitSourcePolicy?: (ctx: SourcePolicyContext) => Result;
/**
* Visit a parse tree produced by `QuixosLockParser.identifier`.
* @param ctx the parse tree
+1
View File
@@ -1,2 +1,3 @@
export * from "./loader.js";
export * from "./parser.js";
export * from "./types.js";
+150
View File
@@ -0,0 +1,150 @@
import { lstat, readFile } from "node:fs/promises";
import path from "node:path";
import {
parseQuixosLockDocument,
type QuixosLockDiagnostic,
type QuixosLockParseResult,
} from "./parser.js";
import type {
LockedResource,
QuixosLockDocument,
QuixosRepositoryLock,
} from "./types.js";
export type QuixosLockSourceReader = (relativePath: string) => Promise<string>;
const diagnostic = (
code: string,
message: string,
fileName: string,
path?: string,
): QuixosLockDiagnostic => ({
phase: "resolution",
code,
message,
fileName,
line: 1,
column: 0,
path,
});
export const resolveQuixosLock = async (
rootSource: string,
readSource: QuixosLockSourceReader,
rootFileName = "quixos.lock",
): Promise<QuixosLockParseResult> => {
const root = parseQuixosLockDocument(rootSource, rootFileName);
if (!root.ok) return root;
if (root.document.kind !== "root") {
return {
ok: false,
diagnostics: [diagnostic(
"expected-root-lock",
"The entrypoint must be a root Quixos lock, not a fragment",
rootFileName,
)],
};
}
const diagnostics: QuixosLockDiagnostic[] = [];
const resources: LockedResource[] = [];
const sourceFiles = [rootFileName];
const visited = new Set<string>();
const active: string[] = [];
const addResources = (document: QuixosLockDocument, fileName: string) => {
for (const resource of document.resources) {
const duplicate = resources.find((entry) =>
entry.kind === resource.kind && entry.binding === resource.binding);
if (duplicate) {
diagnostics.push(diagnostic(
"duplicate-resource-binding",
`Duplicate ${resource.kind} binding ${resource.binding} across imported lock files`,
fileName,
`${resource.kind}.${resource.binding}`,
));
} else {
resources.push(resource);
}
}
};
const visit = async (importPath: string) => {
if (active.includes(importPath)) {
diagnostics.push(diagnostic(
"import-cycle",
`Lock import cycle: ${[...active, importPath].join(" -> ")}`,
importPath,
));
return;
}
if (visited.has(importPath)) return;
active.push(importPath);
let source: string;
try {
source = await readSource(importPath);
} catch (cause) {
diagnostics.push(diagnostic(
"import-read-failed",
`Could not read lock import ${importPath}: ${cause instanceof Error ? cause.message : String(cause)}`,
importPath,
));
active.pop();
return;
}
const parsed = parseQuixosLockDocument(source, importPath);
if (!parsed.ok) {
diagnostics.push(...parsed.diagnostics);
active.pop();
return;
}
if (parsed.document.kind !== "fragment") {
diagnostics.push(diagnostic(
"imported-root-lock",
`Imported file ${importPath} must begin with "quixos-lock fragment"`,
importPath,
));
active.pop();
return;
}
visited.add(importPath);
sourceFiles.push(importPath);
addResources(parsed.document, importPath);
for (const nested of parsed.document.imports) await visit(nested);
active.pop();
};
addResources(root.document, rootFileName);
for (const importPath of root.document.imports) await visit(importPath);
if (diagnostics.length) return { ok: false, diagnostics };
const lock: QuixosRepositoryLock = {
formatVersion: 1,
quixos: root.document.quixos,
resources,
sourceFiles,
};
return { ok: true, lock, diagnostics: [] };
};
export const loadQuixosLock = async (fileName: string): Promise<QuixosLockParseResult> => {
const absoluteRoot = path.resolve(fileName);
const repositoryRoot = path.dirname(absoluteRoot);
const rootName = path.basename(absoluteRoot);
const rootSource = await readFile(absoluteRoot, "utf8");
return await resolveQuixosLock(rootSource, async (relativePath) => {
let absoluteImport = repositoryRoot;
const segments = relativePath.split("/");
for (const [index, segment] of segments.entries()) {
absoluteImport = path.join(absoluteImport, segment);
const metadata = await lstat(absoluteImport);
if (metadata.isSymbolicLink()) {
throw new Error("imports must not traverse symbolic links");
}
const final = index === segments.length - 1;
if ((!final && !metadata.isDirectory()) || (final && !metadata.isFile())) {
throw new Error("imports must be ordinary files beneath ordinary directories");
}
}
return await readFile(absoluteImport, "utf8");
}, rootName);
};
+245 -9
View File
@@ -10,16 +10,19 @@ import {
import { QuixosLockLexer } from "./generated/QuixosLockLexer.js";
import {
QuixosLockParser,
type QuixosSourceBlockContext,
type SourceBlockContext,
} from "./generated/QuixosLockParser.js";
import type {
GitSource,
LockedResource,
QuixosLockDocument,
QuixosRepositoryLock,
QuixosSource,
} from "./types.js";
export type QuixosLockDiagnostic = {
phase: "syntax" | "validation";
phase: "syntax" | "validation" | "resolution";
code: string;
message: string;
fileName: string;
@@ -32,6 +35,10 @@ export type QuixosLockParseResult =
| { ok: true; lock: QuixosRepositoryLock; diagnostics: [] }
| { ok: false; diagnostics: QuixosLockDiagnostic[] };
export type QuixosLockDocumentParseResult =
| { ok: true; document: QuixosLockDocument; diagnostics: [] }
| { ok: false; diagnostics: QuixosLockDiagnostic[] };
class SyntaxErrorListener extends BaseErrorListener {
constructor(
private readonly fileName: string,
@@ -68,22 +75,72 @@ const lowerSource = (context: SourceBlockContext): GitSource => ({
commit: stringValue(context.stringLiteral(1)!).toLowerCase(),
});
const lowerQuixosSource = (context: QuixosSourceBlockContext): QuixosSource => {
const source = {
resolver: "git" as const,
repository: stringValue(context.stringLiteral(0)!),
commit: stringValue(context.stringLiteral(context.stringLiteral().length - 1)!).toLowerCase(),
};
const policyContext = context.sourcePolicy();
if (!policyContext) return source;
const policy = policyContext.PINNED()
? "pinned"
: policyContext.TRACK_RELEASE()
? "track-release"
: "track-development";
return {
...source,
policy,
ref: stringValue(context.stringLiteral(1)!),
};
};
const issue = (
diagnostics: QuixosLockDiagnostic[],
fileName: string,
code: string,
message: string,
path?: string,
line = 1,
column = 0,
) => diagnostics.push({
phase: "validation",
code,
message,
fileName,
line: 1,
column: 0,
line,
column,
path,
});
const validateImport = (
importPath: string,
index: number,
fileName: string,
diagnostics: QuixosLockDiagnostic[],
line: number,
column: number,
) => {
const path = `imports[${index}]`;
if (
!importPath
|| importPath.startsWith("/")
|| importPath.includes("\\")
|| importPath.split("/").some((segment) => !segment || segment === "." || segment === "..")
|| /^[A-Za-z][A-Za-z0-9+.-]*:/.test(importPath)
) {
issue(
diagnostics,
fileName,
"invalid-import-path",
`${path} must be a normalized relative path beneath the workspace repository root`,
path,
line,
column,
);
}
};
const validateSource = (
source: GitSource,
path: string,
@@ -141,10 +198,59 @@ const validateSource = (
}
};
export const parseQuixosLock = (
const validateQuixosSource = (
source: QuixosSource,
fileName: string,
diagnostics: QuixosLockDiagnostic[],
) => {
validateSource(source, "quixos", fileName, diagnostics);
if (!source.policy) return;
const forbiddenRefCharacters = new Set("~^:?*[\\");
const invalidRef = !source.ref
|| [...source.ref].some((character) => {
const code = character.charCodeAt(0);
return code <= 0x20 || code === 0x7f || forbiddenRefCharacters.has(character);
})
|| source.ref.startsWith("/")
|| source.ref.endsWith("/")
|| source.ref.endsWith(".")
|| source.ref.includes("..")
|| source.ref.includes("@{")
|| source.ref.includes("//");
if (invalidRef) {
issue(
diagnostics,
fileName,
"invalid-quixos-ref",
"quixos.ref must be a non-empty Git ref without whitespace or Git ref metacharacters",
"quixos.ref",
);
}
if (source.policy === "pinned") {
if (!/^([0-9a-f]{40}|[0-9a-f]{64})$/.test(source.ref)) {
issue(
diagnostics,
fileName,
"pinned-quixos-ref-not-commit",
"A pinned Quixos source must use an exact commit as its ref",
"quixos.ref",
);
} else if (source.ref.toLowerCase() !== source.commit) {
issue(
diagnostics,
fileName,
"pinned-quixos-commit-mismatch",
"A pinned Quixos source ref and resolved commit must be identical",
"quixos.commit",
);
}
}
};
export const parseQuixosLockDocument = (
source: string,
fileName = "<memory>",
): QuixosLockParseResult => {
): QuixosLockDocumentParseResult => {
const diagnostics: QuixosLockDiagnostic[] = [];
const listener = new SyntaxErrorListener(fileName, diagnostics);
const lexer = new QuixosLockLexer(CharStream.fromString(source));
@@ -167,8 +273,55 @@ export const parseQuixosLock = (
);
}
const quixos = lowerSource(tree.quixosEntry().sourceBlock());
validateSource(quixos, "quixos", fileName, diagnostics);
const fragment = Boolean(tree.FRAGMENT());
const quixosEntries = tree.quixosEntry();
let quixos: QuixosSource | undefined;
if (fragment && quixosEntries.length) {
issue(
diagnostics,
fileName,
"fragment-has-quixos-source",
"A lock fragment inherits the root document's Quixos source and must not redeclare it",
"quixos",
);
} else if (!fragment && quixosEntries.length !== 1) {
issue(
diagnostics,
fileName,
"root-quixos-source-count",
"A root lock document must contain exactly one Quixos source",
"quixos",
);
} else if (!fragment) {
quixos = lowerQuixosSource(quixosEntries[0]!.quixosSourceBlock());
validateQuixosSource(quixos, fileName, diagnostics);
}
const imports = tree.importEntry().map((context, index) => {
const importPath = stringValue(context.stringLiteral());
validateImport(
importPath,
index,
fileName,
diagnostics,
context.start?.line ?? 1,
context.start?.column ?? 0,
);
return importPath;
});
const repeatedImports = new Set<string>();
imports.forEach((importPath, index) => {
if (repeatedImports.has(importPath)) {
issue(
diagnostics,
fileName,
"duplicate-import",
`Duplicate lock import ${importPath}`,
`imports[${index}]`,
);
}
repeatedImports.add(importPath);
});
const resources: LockedResource[] = [];
const bindings = new Set<string>();
@@ -195,7 +348,52 @@ export const parseQuixosLock = (
? { ok: false, diagnostics }
: {
ok: true,
lock: { formatVersion: 1, quixos, resources },
document: fragment
? { kind: "fragment", formatVersion: 1, imports, resources }
: { kind: "root", formatVersion: 1, quixos: quixos!, imports, resources },
diagnostics: [],
};
};
export const parseQuixosLock = (
source: string,
fileName = "<memory>",
): QuixosLockParseResult => {
const parsed = parseQuixosLockDocument(source, fileName);
if (!parsed.ok) return parsed;
if (parsed.document.kind === "fragment") {
return {
ok: false,
diagnostics: [{
phase: "validation",
code: "expected-root-lock",
message: "Expected a root Quixos lock, found a lock fragment",
fileName,
line: 1,
column: 0,
}],
};
}
if (parsed.document.imports.length) {
return {
ok: false,
diagnostics: [{
phase: "resolution",
code: "imports-require-file-resolution",
message: "This lock has imports and must be loaded from its repository rather than parsed as an isolated string",
fileName,
line: 1,
column: 0,
}],
};
}
return {
ok: true,
lock: {
formatVersion: 1,
quixos: parsed.document.quixos,
resources: parsed.document.resources,
},
diagnostics: [],
};
};
@@ -207,11 +405,22 @@ const sourceLines = (source: GitSource, indentation: string): string[] => [
`${indentation}commit ${quoted(source.commit.toLowerCase())};`,
];
const quixosSourceLines = (source: QuixosSource, indentation: string): string[] => [
`${indentation}repository ${quoted(source.repository)};`,
...(source.policy
? [
`${indentation}policy ${source.policy};`,
`${indentation}ref ${quoted(source.ref)};`,
]
: []),
`${indentation}commit ${quoted(source.commit.toLowerCase())};`,
];
export const formatQuixosLock = (lock: QuixosRepositoryLock): string => {
const lines = [
"quixos-lock version 1 {",
" quixos source {",
...sourceLines(lock.quixos, " "),
...quixosSourceLines(lock.quixos, " "),
" }",
];
for (const resource of lock.resources) {
@@ -225,3 +434,30 @@ export const formatQuixosLock = (lock: QuixosRepositoryLock): string => {
lines.push("}", "");
return lines.join("\n");
};
export const formatQuixosLockDocument = (document: QuixosLockDocument): string => {
const lines = [
`quixos-lock${document.kind === "fragment" ? " fragment" : ""} version 1 {`,
];
if (document.kind === "root") {
lines.push(
" quixos source {",
...quixosSourceLines(document.quixos, " "),
" }",
);
}
for (const importPath of document.imports) {
if (lines.length > 1) lines.push("");
lines.push(` import ${quoted(importPath)};`);
}
for (const resource of document.resources) {
if (lines.length > 1) lines.push("");
lines.push(
` ${resource.kind} ${resource.binding} source {`,
...sourceLines(resource.source, " "),
" }",
);
}
lines.push("}", "");
return lines.join("\n");
};
+34 -1
View File
@@ -4,6 +4,19 @@ export type GitSource = {
commit: string;
};
export type QuixosSourcePolicy = "pinned" | "track-release" | "track-development";
// Resource repositories only need the exact Quixos commit they were authored
// against. A workspace root additionally declares how a runtime may advance
// that exact baseline.
export type QuixosSource = GitSource & ({
policy: QuixosSourcePolicy;
ref: string;
} | {
policy?: undefined;
ref?: undefined;
});
export type LockedResourceKind = "interface" | "package";
export type LockedResource = {
@@ -12,10 +25,30 @@ export type LockedResource = {
source: GitSource;
};
export type QuixosLockRootDocument = {
kind: "root";
formatVersion: 1;
quixos: QuixosSource;
imports: string[];
resources: LockedResource[];
};
export type QuixosLockFragmentDocument = {
kind: "fragment";
formatVersion: 1;
imports: string[];
resources: LockedResource[];
};
export type QuixosLockDocument =
| QuixosLockRootDocument
| QuixosLockFragmentDocument;
export type QuixosRepositoryLock = {
formatVersion: 1;
quixos: GitSource;
quixos: QuixosSource;
resources: LockedResource[];
sourceFiles?: string[];
};
export type NixGitInput = {
+184
View File
@@ -0,0 +1,184 @@
import assert from "node:assert/strict";
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import {
compileCapabilityResourceRepository,
compileWorkspaceRepository,
} from "../src/capability-language/index.js";
const quixosCommit = "1".repeat(40);
const namedCommit = "2".repeat(40);
const packageCommit = "3".repeat(40);
const lock = (resources = "") => `quixos-lock version 1 {
quixos source {
repository "https://example.test/quixos.git";
commit "${quixosCommit}";
}
${resources}
}
`;
test("workspace assembly resolves resource-owned dependencies recursively", async (context) => {
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-"));
context.after(() => rm(directory, { recursive: true, force: true }));
const root = path.join(directory, "root");
const named = path.join(directory, "named");
const runtime = path.join(directory, "runtime");
await Promise.all([mkdir(root), mkdir(named), mkdir(runtime)]);
await writeFile(path.join(root, "quixos.lock"), lock(`package Runtime source {
repository "https://example.test/package-runtime.git";
commit "${packageCommit}";
}`));
await writeFile(path.join(root, "workspace.qx"), `workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
atom Subject id "atom:subject";
import package Runtime;
}
`);
await writeFile(path.join(named, "quixos.lock"), lock());
await writeFile(path.join(named, "interface.qx"), `interface Named id "interface:named" revision "interface:named@1" {
value name id "member:named:name" : string {
get id "operation:named:name:get";
}
}
`);
await writeFile(path.join(runtime, "quixos.lock"), lock(`interface Named source {
repository "https://example.test/interface-named.git";
commit "${namedCommit}";
}`));
await writeFile(path.join(runtime, "package.qx"), `import interface Named;
package Runtime id "package:runtime" revision "package:runtime@1" {
function describe id "export:runtime:describe" : interface-ref<Named> -> string;
}
`);
const directories = new Map([
[`interface\0https://example.test/interface-named.git\0${namedCommit}`, named],
[`package\0https://example.test/package-runtime.git\0${packageCommit}`, runtime],
]);
const result = await compileWorkspaceRepository({
rootDirectory: root,
resolveResource: async (source, kind) => {
const resolved = directories.get(`${kind}\0${source.repository}\0${source.commit}`);
if (!resolved) throw new Error(`Unexpected source ${source.repository}`);
return { directory: resolved };
},
});
assert.equal(result.resources.length, 2);
assert.deepEqual(
result.workspace.interfaceImports.map((entry) => entry.revisionId),
["interface:named@1"],
);
assert.deepEqual(
result.workspace.packageImports.map((entry) => entry.revisionId),
["package:runtime@1"],
);
assert.equal(result.directResources.size, 1);
const resource = await compileCapabilityResourceRepository({
rootDirectory: runtime,
kind: "package",
source: {
resolver: "git",
repository: "https://example.test/package-runtime.git",
commit: packageCommit,
},
resolveResource: async (source, kind) => {
const resolved = directories.get(`${kind}\0${source.repository}\0${source.commit}`);
if (!resolved) throw new Error(`Unexpected source ${source.repository}`);
return { directory: resolved };
},
});
assert.equal(resource.resource.kind, "package");
assert.equal(resource.resources.length, 2);
assert.equal(resource.directResources.size, 1);
});
test("resource repositories cannot own workspace Quixos selection policy", async (context) => {
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-resource-policy-"));
context.after(() => rm(directory, { recursive: true, force: true }));
await writeFile(path.join(directory, "quixos.lock"), `quixos-lock version 1 {
quixos source {
repository "https://example.test/quixos.git";
policy track-development;
ref "dev/alice/main";
commit "${quixosCommit}";
}
}`);
await writeFile(path.join(directory, "package.qx"), `package Runtime id "package:runtime" revision "package:runtime@1" { }\n`);
await assert.rejects(
compileCapabilityResourceRepository({
rootDirectory: directory,
kind: "package",
source: {
resolver: "git",
repository: "https://example.test/package-runtime.git",
commit: packageCommit,
},
resolveResource: async () => ({ directory }),
}),
/resource locks may only declare their exact authored-against commit/,
);
});
test("resource manifests cannot hide lock dependencies", async (context) => {
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-mismatch-"));
context.after(() => rm(directory, { recursive: true, force: true }));
const root = path.join(directory, "root");
const runtime = path.join(directory, "runtime");
await Promise.all([mkdir(root), mkdir(runtime)]);
await writeFile(path.join(root, "quixos.lock"), lock(`package Runtime source {
repository "https://example.test/package-runtime.git";
commit "${packageCommit}";
}`));
await writeFile(path.join(root, "workspace.qx"), `workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
atom Subject id "atom:subject";
import package Runtime;
}
`);
await writeFile(path.join(runtime, "quixos.lock"), lock());
await writeFile(path.join(runtime, "package.qx"), `import interface Hidden;
package Runtime id "package:runtime" revision "package:runtime@1" { }
`);
await assert.rejects(
compileWorkspaceRepository({
rootDirectory: root,
resolveResource: async () => ({ directory: runtime }),
}),
/No resolved interface is available for lock binding Hidden/,
);
});
test("workspace assembly must satisfy nominal external interfaces", async (context) => {
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-external-"));
context.after(() => rm(directory, { recursive: true, force: true }));
const root = path.join(directory, "root");
const runtime = path.join(directory, "runtime");
await Promise.all([mkdir(root), mkdir(runtime)]);
await writeFile(path.join(root, "quixos.lock"), lock(`package Runtime source {
repository "https://example.test/package-runtime.git";
commit "${packageCommit}";
}`));
await writeFile(path.join(root, "workspace.qx"), `workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
atom Subject id "atom:subject";
import package Runtime;
}
`);
await writeFile(path.join(runtime, "quixos.lock"), lock());
await writeFile(path.join(runtime, "package.qx"), `external interface Named revision "interface:named@1";
package Runtime id "package:runtime" revision "package:runtime@1" { }
`);
await assert.rejects(
compileWorkspaceRepository({
rootDirectory: root,
resolveResource: async () => ({ directory: runtime }),
}),
/requires external interface Named \(interface:named@1\)/,
);
});
+137 -49
View File
@@ -2,18 +2,96 @@ import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { test } from "node:test";
import { compileCapabilitySource } from "../src/capability-language/index.js";
import {
capabilityFixturePath,
compileCapabilityResourceSource,
compileCapabilitySource,
} from "../src/capability-language/index.js";
import {
capabilityFixtureSource,
capabilityResourceSources,
compileCapabilityFixture,
fixtureId,
} from "./fixtures/capability-model.js";
test("ANTLR parses and validates a complete capability workspace", () => {
const result = compileCapabilitySource(
capabilityFixtureSource,
capabilityFixturePath,
const compileWebStudioFixture = (packageTransform = (source: string) => source) => {
const fixture = (name: string) => readFileSync(
resolve(process.cwd(), "test/fixtures", name),
"utf8",
);
const react = compileCapabilityResourceSource(
fixture("react-component.interface.qx"),
{
source: {
repository: "https://repos.quixos.org/org-quixos-web-studio/interface-react-component.git",
commit: "2".repeat(40),
},
},
);
if (!react.ok || react.resource.kind !== "interface") {
throw new Error("ReactComponent fixture did not compile");
}
const named = compileCapabilityResourceSource(
fixture("named.interface.qx"),
{
source: {
repository: "https://repos.quixos.org/quixos-test/interface-named.git",
commit: "5".repeat(40),
},
},
);
if (!named.ok || named.resource.kind !== "interface") {
throw new Error("Named fixture did not compile");
}
const has = compileCapabilityResourceSource(
fixture("has-react-component.interface.qx"),
{
source: {
repository: "https://repos.quixos.org/org-quixos-web-studio/interface-has-react-component.git",
commit: "3".repeat(40),
},
environment: {
interfaces: new Map([["ReactComponent", react.resource.revision]]),
interfaceClosure: [react.resource.revision],
},
},
);
if (!has.ok || has.resource.kind !== "interface") {
throw new Error("HasReactComponent fixture did not compile");
}
const component = compileCapabilityResourceSource(
packageTransform(fixture("component-runtime.package.qx")),
{
source: {
repository: "https://repos.quixos.org/quixos-test/package-component-runtime.git",
commit: "4".repeat(40),
},
environment: {
interfaces: new Map([["Named", named.resource.revision]]),
interfaceClosure: [named.resource.revision],
},
},
);
if (!component.ok || component.resource.kind !== "package") {
throw new Error("ComponentRuntime fixture did not compile");
}
return compileCapabilitySource(
fixture("web-studio.capabilities.qx"),
"web-studio.capabilities.qx",
{
interfaces: new Map([
["Named", named.resource.revision],
["ReactComponent", react.resource.revision],
["HasReactComponent", has.resource.revision],
]),
packages: new Map([["ComponentRuntime", component.resource.revision]]),
interfaceClosure: [named.resource.revision, react.resource.revision, has.resource.revision],
packageClosure: [component.resource.revision],
},
);
};
test("ANTLR parses and validates a complete capability workspace", () => {
const result = compileCapabilityFixture();
assert.equal(result.ok, true);
if (!result.ok) return;
assert.equal(result.workspace.workspaceId, fixtureId.workspace);
@@ -24,26 +102,24 @@ test("ANTLR parses and validates a complete capability workspace", () => {
});
test("conformances do not accept authored IDs", () => {
const result = compileCapabilitySource(
capabilityFixtureSource.replace(
const result = compileCapabilityFixture({
workspace: capabilityFixtureSource.replace(
"conform Project as Named {",
'conform Project as Named id "conformance:project:named" {',
),
"conformance-id.qx",
);
});
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) => entry.phase === "syntax"));
});
test("the v1 language has no implicit relationship materialization rule", () => {
const result = compileCapabilitySource(
capabilityFixtureSource.replace(
const result = compileCapabilityFixture({
workspace: capabilityFixtureSource.replace(
/\n}\s*$/,
'\n materialize ProjectOwner.owner if absent with Person;\n}\n',
),
"materialize.qx",
);
});
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) => entry.phase === "syntax"));
@@ -57,21 +133,23 @@ test("forward declarations make source order irrelevant", () => {
/\n}\s*$/,
'\n atom Project id "atom:project";\n atom Person id "atom:person";\n}\n',
);
assert.equal(compileCapabilitySource(source, "reordered.qx").ok, true);
assert.equal(compileCapabilityFixture({ workspace: source }).ok, true);
});
test("interfaces can declare ordinary call operations", () => {
const source = capabilityFixtureSource.replace(
" value summary id \"member:summary:summary\" : string {\n get id \"operation:summary:summary:get\";\n }",
" operation summarize id \"member:summary:summarize\" : string -> string {\n call id \"operation:summary:summarize\";\n }",
).replace(
const workspace = capabilityFixtureSource.replace(
"bind summary.get to package TodoRuntime.summaryGet",
"bind summarize.call to package TodoRuntime.summaryGet",
).replace(
);
const summary = capabilityResourceSources.summary.replace(
" value summary id \"member:summary:summary\" : string {\n get id \"operation:summary:summary:get\";\n }",
" operation summarize id \"member:summary:summarize\" : string -> string {\n call id \"operation:summary:summarize\";\n }",
);
const todo = capabilityResourceSources.todo.replace(
"operation summaryGet id \"export:todo-runtime:summary-get\" : unit -> string",
"operation summaryGet id \"export:todo-runtime:summary-get\" : string -> string",
);
const result = compileCapabilitySource(source, "operation-member.qx");
const result = compileCapabilityFixture({ workspace, summary, todo });
assert.equal(result.ok, true);
if (!result.ok) return;
const member = result.workspace.interfaceImports
@@ -86,7 +164,7 @@ test("state defaults accept recursive JSON values", () => {
shared state ProjectMetadata id "slot:project:metadata" on Project : message "example.Metadata"
policy optimistic-register default {"labels":["compiler","runtime"],"score":1.5,"enabled":true,"extra":null};`,
);
const result = compileCapabilitySource(source, "json-default.qx");
const result = compileCapabilityFixture({ workspace: source });
assert.equal(result.ok, true);
if (!result.ok) return;
const metadata = result.workspace.sharedAttachments.find(
@@ -103,25 +181,23 @@ test("state defaults accept recursive JSON values", () => {
});
test("syntax errors retain source locations", () => {
const result = compileCapabilitySource(
capabilityFixtureSource.replace("atom Project", "atom Project ???"),
"broken.qx",
);
const result = compileCapabilityFixture({
workspace: capabilityFixtureSource.replace("atom Project", "atom Project ???"),
});
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) =>
entry.phase === "syntax" && entry.fileName === "broken.qx" && entry.line > 0
entry.phase === "syntax" && entry.line > 0
));
});
test("unknown authoring names are lowering errors", () => {
const result = compileCapabilitySource(
capabilityFixtureSource.replace(
const result = compileCapabilityFixture({
workspace: capabilityFixtureSource.replace(
"to state ProjectTitle.read",
"to state NotAState.read",
),
"unknown-name.qx",
);
});
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) =>
@@ -132,13 +208,12 @@ test("unknown authoring names are lowering errors", () => {
});
test("well-formed but invalid programs report semantic paths", () => {
const result = compileCapabilitySource(
capabilityFixtureSource.replace(
const result = compileCapabilityFixture({
workspace: capabilityFixtureSource.replace(
"bind name.get to state ProjectTitle.read",
"bind name.get to state ProjectTitle.write",
),
"invalid-binding.qx",
);
});
assert.equal(result.ok, false);
if (result.ok) return;
const diagnostic = result.diagnostics.find(
@@ -150,11 +225,7 @@ test("well-formed but invalid programs report semantic paths", () => {
});
test("Web Studio sidecars declare lazy materialization and checked cross-object ports", () => {
const source = readFileSync(
resolve(process.cwd(), "test/fixtures/web-studio.capabilities.qx"),
"utf8",
);
const result = compileCapabilitySource(source, "web-studio.capabilities.qx");
const result = compileWebStudioFixture();
assert.equal(result.ok, true);
if (!result.ok) return;
@@ -175,9 +246,9 @@ test("Web Studio sidecars declare lazy materialization and checked cross-object
const binding = component?.operationBindings[0]?.binding;
assert.equal(binding?.kind, "package");
if (binding?.kind !== "package") return;
assert.deepEqual(binding.dependencies[1]?.binding, {
kind: "state",
slotId: "slot:project:name",
assert.deepEqual(binding.dependencies[0]?.binding, {
kind: "interface",
interfaceRevisionId: "interface:named@1",
via: {
edgeTypeId: "edge:project:component",
projectionId: "projection:component:subject",
@@ -186,14 +257,10 @@ test("Web Studio sidecars declare lazy materialization and checked cross-object
});
test("relationship materializers require a constructor from the host atom", () => {
const source = readFileSync(
resolve(process.cwd(), "test/fixtures/web-studio.capabilities.qx"),
"utf8",
).replace(
const result = compileWebStudioFixture((source) => source.replace(
"constructs ProjectComponent : atom-ref<Project>;",
"constructs ProjectComponent : unit;",
);
const result = compileCapabilitySource(source, "invalid-materializer.qx");
));
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) =>
@@ -201,3 +268,24 @@ test("relationship materializers require a constructor from the host atom", () =
entry.message.includes("must accept")
));
});
test("callable interface ports require a full source dependency, not a nominal reference", () => {
const result = compileCapabilityResourceSource(`
external interface Named revision "interface:named@1";
package Runtime id "package:runtime" revision "package:runtime@1" {
function readName id "export:runtime:read-name" : unit -> string requires {
interface named id "port:runtime:named" : Named;
};
}
`, {
source: {
repository: "https://repos.quixos.org/quixos-test/package-runtime.git",
commit: "6".repeat(40),
},
});
assert.equal(result.ok, false);
if (result.ok) return;
assert.ok(result.diagnostics.some((entry) =>
entry.code === "nominal-interface-port" && entry.message.includes("import interface Named")
));
});
+20 -1
View File
@@ -92,7 +92,7 @@ test("the representative v1 workspace compiles to native and package plans", ()
summary.dependencies.map((entry) => [entry.port.id, entry.binding.kind]),
[
[fixtureId.titlePort, "state"],
[fixtureId.namedPort, "receiver-interface"],
[fixtureId.namedPort, "interface"],
[fixtureId.personPort, "constructor"],
],
);
@@ -164,6 +164,25 @@ test("private attachments are visible only to their owning conformance", () => {
expectIssue(workspace, "private-attachment-access");
});
test("related-object dependency views cannot traverse another conformance's private edge", () => {
const workspace = makeValidCapabilityWorkspace();
const packageBinding = conformance(
workspace,
fixtureId.projectSummaryConformance,
).operationBindings[0]!.binding;
assert.equal(packageBinding.kind, "package");
if (packageBinding.kind !== "package") return;
const named = packageBinding.dependencies.find(
(dependency) => dependency.portId === fixtureId.namedPort,
);
assert.ok(named && named.binding.kind === "interface");
named.binding.via = {
edgeTypeId: fixtureId.projectOwner,
projectionId: fixtureId.projectOwnerProjection,
};
expectIssue(workspace, "private-attachment-access");
});
test("native state and edge providers must match operation shape", () => {
const stateWorkspace = makeValidCapabilityWorkspace();
const state = conformance(
+121 -5
View File
@@ -4,7 +4,15 @@ import {
capabilityId,
type WorkspaceRevision,
} from "../../src/capability-model/index.js";
import { compileCapabilitySource } from "../../src/capability-language/index.js";
import {
compileCapabilityResourceSource,
compileCapabilitySource,
type CapabilityImportEnvironment,
} from "../../src/capability-language/index.js";
import type {
InterfaceRevision,
PackageRevision,
} from "../../src/capability-model/index.js";
export const fixtureId = {
workspace: capabilityId.workspace("workspace:todo"),
@@ -62,11 +70,119 @@ export const capabilityFixtureSource = readFileSync(
"utf8",
);
export const makeValidCapabilityWorkspace = (): WorkspaceRevision => {
const result = compileCapabilitySource(
capabilityFixtureSource,
capabilityFixturePath,
const resourceSource = (name: string) => readFileSync(
resolve(process.cwd(), "test/fixtures", name),
"utf8",
);
export const capabilityResourceSources = {
named: resourceSource("named.interface.qx"),
owned: resourceSource("owned.interface.qx"),
summary: resourceSource("summary.interface.qx"),
todo: resourceSource("todo.package.qx"),
} as const;
const source = (repository: string, commit: string) => ({ repository, commit });
const interfaceRevision = (
resource: { kind: "interface"; revision: InterfaceRevision } |
{ kind: "package"; revision: PackageRevision },
) => {
if (resource.kind !== "interface") throw new Error("Expected interface fixture");
return resource.revision;
};
const packageRevision = (
resource: { kind: "interface"; revision: InterfaceRevision } |
{ kind: "package"; revision: PackageRevision },
) => {
if (resource.kind !== "package") throw new Error("Expected package fixture");
return resource.revision;
};
export const compileCapabilityFixture = (overrides: Partial<{
workspace: string;
named: string;
owned: string;
summary: string;
todo: string;
}> = {}) => {
const named = compileCapabilityResourceSource(
overrides.named ?? capabilityResourceSources.named,
{
source: source(
"https://repos.quixos.org/quixos-todo/interface-named.git",
"2".repeat(40),
),
fileName: "named.interface.qx",
},
);
if (!named.ok) return named;
const namedRevision = interfaceRevision(named.resource);
const namedEnvironment: CapabilityImportEnvironment = {
interfaces: new Map([["Named", namedRevision]]),
interfaceClosure: [namedRevision],
};
const owned = compileCapabilityResourceSource(
overrides.owned ?? capabilityResourceSources.owned,
{
source: source(
"https://repos.quixos.org/quixos-todo/interface-owned.git",
"3".repeat(40),
),
fileName: "owned.interface.qx",
environment: namedEnvironment,
},
);
if (!owned.ok) return owned;
const ownedRevision = interfaceRevision(owned.resource);
const summary = compileCapabilityResourceSource(
overrides.summary ?? capabilityResourceSources.summary,
{
source: source(
"https://repos.quixos.org/quixos-todo/interface-summary.git",
"4".repeat(40),
),
fileName: "summary.interface.qx",
},
);
if (!summary.ok) return summary;
const summaryRevision = interfaceRevision(summary.resource);
const todo = compileCapabilityResourceSource(
overrides.todo ?? capabilityResourceSources.todo,
{
source: source(
"https://repos.quixos.org/quixos-todo/package-todo-runtime.git",
"5".repeat(40),
),
fileName: "todo.package.qx",
environment: namedEnvironment,
},
);
if (!todo.ok) return todo;
const todoRevision = packageRevision(todo.resource);
return compileCapabilitySource(
overrides.workspace ?? capabilityFixtureSource,
capabilityFixturePath,
{
interfaces: new Map([
["Named", namedRevision],
["Owned", ownedRevision],
["Summary", summaryRevision],
]),
packages: new Map([["TodoRuntime", todoRevision]]),
interfaceClosure: [
namedRevision,
ownedRevision,
summaryRevision,
],
packageClosure: [todoRevision],
},
);
};
export const makeValidCapabilityWorkspace = (): WorkspaceRevision => {
const result = compileCapabilityFixture();
if (!result.ok) {
throw new Error(
result.diagnostics
+10
View File
@@ -0,0 +1,10 @@
import interface Named;
external atom Project id "atom:project";
external atom ProjectComponent id "atom:project-component";
package ComponentRuntime id "package:component-runtime" revision "package:component-runtime@1" {
constructor createComponent id "export:component-runtime:create-component" constructs ProjectComponent : atom-ref<Project>;
operation propsGet id "export:component-runtime:props-get" : unit -> string mode call receiver atom ProjectComponent requires {
interface project id "port:component:project" : Named;
};
}
+7
View File
@@ -0,0 +1,7 @@
import interface ReactComponent;
interface HasReactComponent id "interface:org.quixos.web-studio.has-react-component" revision "interface:org.quixos.web-studio.has-react-component@1" {
relation component id "member:org.quixos.web-studio.has-react-component:component" : optional-one interface ReactComponent {
resolve id "operation:org.quixos.web-studio.has-react-component:component:resolve";
}
}
+7
View File
@@ -0,0 +1,7 @@
interface Named id "interface:named" revision "interface:named@1" {
value name id "member:named:name" : string {
get id "operation:named:name:get";
set id "operation:named:name:set";
watch start id "operation:named:name:watch-start" stop id "operation:named:name:watch-stop";
}
}
+10
View File
@@ -0,0 +1,10 @@
import interface Named;
interface Owned id "interface:owned" revision "interface:owned@1" {
relation owner id "member:owned:owner" : exactly-one interface Named {
resolve id "operation:owned:owner:resolve";
connect id "operation:owned:owner:connect";
disconnect id "operation:owned:owner:disconnect";
watch start id "operation:owned:owner:watch-start" stop id "operation:owned:owner:watch-stop";
}
}
+5
View File
@@ -0,0 +1,5 @@
interface ReactComponent id "interface:org.quixos.web-studio.react-component" revision "interface:org.quixos.web-studio.react-component@1" {
value props id "member:org.quixos.web-studio.react-component:props" : string {
get id "operation:org.quixos.web-studio.react-component:props:get";
}
}
+5
View File
@@ -0,0 +1,5 @@
interface Summary id "interface:summary" revision "interface:summary@1" {
value summary id "member:summary:summary" : string {
get id "operation:summary:summary:get";
}
}
+4 -44
View File
@@ -2,50 +2,10 @@ workspace Todo id "workspace:todo" revision "workspace:todo@1" commit "111111111
atom Project id "atom:project" doc "A project containing work.";
atom Person id "atom:person";
interface Named id "interface:named" revision "interface:named@1" source {
repository "https://repos.quixos.org/quixos-todo/interface-named.git";
commit "2222222222222222222222222222222222222222";
} {
value name id "member:named:name" : string {
get id "operation:named:name:get";
set id "operation:named:name:set";
watch start id "operation:named:name:watch-start" stop id "operation:named:name:watch-stop";
}
}
interface Owned id "interface:owned" revision "interface:owned@1" source {
repository "https://repos.quixos.org/quixos-todo/interface-owned.git";
commit "3333333333333333333333333333333333333333";
} {
relation owner id "member:owned:owner" : exactly-one interface Named {
resolve id "operation:owned:owner:resolve";
connect id "operation:owned:owner:connect";
disconnect id "operation:owned:owner:disconnect";
watch start id "operation:owned:owner:watch-start" stop id "operation:owned:owner:watch-stop";
}
}
interface Summary id "interface:summary" revision "interface:summary@1" source {
repository "https://repos.quixos.org/quixos-todo/interface-summary.git";
commit "4444444444444444444444444444444444444444";
} {
value summary id "member:summary:summary" : string {
get id "operation:summary:summary:get";
}
}
package TodoRuntime id "package:todo-runtime" revision "package:todo-runtime@1" source {
repository "https://repos.quixos.org/quixos-todo/package-todo-runtime.git";
commit "5555555555555555555555555555555555555555";
} {
operation summaryGet id "export:todo-runtime:summary-get" : unit -> string
mode call receiver interfaces [Named] requires {
state title id "port:summary:title" : string [read];
interface named id "port:summary:named" : Named;
constructor person id "port:summary:person" : Person;
};
constructor createPerson id "export:todo-runtime:create-person" constructs Person : unit;
}
import interface Named;
import interface Owned;
import interface Summary;
import package TodoRuntime;
shared state ProjectTitle id "slot:project:title" on Project : string
policy optimistic-register default "Untitled project";
+12
View File
@@ -0,0 +1,12 @@
import interface Named;
external atom Person id "atom:person";
package TodoRuntime id "package:todo-runtime" revision "package:todo-runtime@1" {
operation summaryGet id "export:todo-runtime:summary-get" : unit -> string
mode call receiver interfaces [Named] requires {
state title id "port:summary:title" : string [read];
interface named id "port:summary:named" : Named;
constructor person id "port:summary:person" : Person;
};
constructor createPerson id "export:todo-runtime:create-person" constructs Person : unit;
}
+12 -30
View File
@@ -2,34 +2,10 @@ workspace WebStudioFixture id "workspace:web-studio-fixture" revision "workspace
atom Project id "atom:project";
atom ProjectComponent id "atom:project-component";
interface ReactComponent id "interface:org.quixos.web-studio.react-component" revision "interface:org.quixos.web-studio.react-component@1" source {
repository "https://repos.quixos.org/org-quixos-web-studio/interface-react-component.git";
commit "2222222222222222222222222222222222222222";
} {
value props id "member:org.quixos.web-studio.react-component:props" : string {
get id "operation:org.quixos.web-studio.react-component:props:get";
}
}
interface HasReactComponent id "interface:org.quixos.web-studio.has-react-component" revision "interface:org.quixos.web-studio.has-react-component@1" source {
repository "https://repos.quixos.org/org-quixos-web-studio/interface-has-react-component.git";
commit "3333333333333333333333333333333333333333";
} {
relation component id "member:org.quixos.web-studio.has-react-component:component" : optional-one interface ReactComponent {
resolve id "operation:org.quixos.web-studio.has-react-component:component:resolve";
}
}
package ComponentRuntime id "package:component-runtime" revision "package:component-runtime@1" source {
repository "https://repos.quixos.org/quixos-test/package-component-runtime.git";
commit "4444444444444444444444444444444444444444";
} {
constructor createComponent id "export:component-runtime:create-component" constructs ProjectComponent : atom-ref<Project>;
operation propsGet id "export:component-runtime:props-get" : unit -> string mode call receiver atom ProjectComponent requires {
edge subject id "port:component:subject" : exactly-one atom Project [resolve];
state projectName id "port:component:project-name" : string [read];
};
}
import interface Named;
import interface ReactComponent;
import interface HasReactComponent;
import package ComponentRuntime;
shared state ProjectName id "slot:project:name" on Project : string
policy optimistic-register default "Untitled project";
@@ -38,14 +14,20 @@ workspace WebStudioFixture id "workspace:web-studio-fixture" revision "workspace
atom Project projection component id "projection:project:component" optional-one;
}
conform Project as Named {
bind name.get to state ProjectName.read;
bind name.set to state ProjectName.write;
bind name.watch-start to state ProjectName.watch-start;
bind name.watch-stop to state ProjectName.watch-stop;
}
conform Project as HasReactComponent {
bind component.resolve to edge ProjectComponentEdge.component.resolve;
materialize component if absent using constructor ProjectComponent via edge ProjectComponentEdge.subject;
}
conform ProjectComponent as ReactComponent {
bind props.get to package ComponentRuntime.propsGet with {
subject to edge ProjectComponentEdge.subject;
projectName to state ProjectName via edge ProjectComponentEdge.subject;
project to interface Named via edge ProjectComponentEdge.subject;
};
}
+183
View File
@@ -1,9 +1,16 @@
import assert from "node:assert/strict";
import { mkdtemp, mkdir, rm, symlink, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import {
formatQuixosLock,
formatQuixosLockDocument,
loadQuixosLock,
nixGitInput,
parseQuixosLock,
parseQuixosLockDocument,
resolveQuixosLock,
retentionTagForCommit,
} from "../src/resource-lock/index.js";
@@ -13,6 +20,8 @@ const packageCommit = "3".repeat(64);
const fixture = `quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
policy track-development;
ref "dev/alice/main";
commit "${quixosCommit}";
}
@@ -34,6 +43,8 @@ test("parses and canonically formats a Git-only repository lock", () => {
if (!parsed.ok) return;
assert.equal(parsed.lock.formatVersion, 1);
assert.equal(parsed.lock.quixos.commit, quixosCommit);
assert.equal(parsed.lock.quixos.policy, "track-development");
assert.equal(parsed.lock.quixos.ref, "dev/alice/main");
assert.deepEqual(
parsed.lock.resources.map(({ kind, binding }) => ({ kind, binding })),
[
@@ -48,6 +59,29 @@ test("parses and canonically formats a Git-only repository lock", () => {
});
});
test("validates pinned Quixos selections without imposing policy on resource locks", () => {
const mismatch = parseQuixosLockDocument(`quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
policy pinned;
ref "${namedCommit}";
commit "${quixosCommit}";
}
}`);
assert.equal(mismatch.ok, false);
if (!mismatch.ok) {
assert.equal(mismatch.diagnostics[0]?.code, "pinned-quixos-commit-mismatch");
}
const resourceBaseline = parseQuixosLockDocument(`quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
commit "${quixosCommit}";
}
}`);
assert.equal(resourceBaseline.ok, true);
});
test("derives immutable retention and Nix inputs without storing extra identity", () => {
const source = {
resolver: "git" as const,
@@ -92,3 +126,152 @@ test("rejects mutable revisions, embedded credentials, and duplicate bindings",
]),
);
});
test("resolves root-relative lock fragments into one deterministic resource closure", async () => {
const root = `quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
commit "${quixosCommit}";
}
import "locks/web-studio.lock";
import "locks/domain.lock";
package RootRuntime source {
repository "https://repos.example/alice/package-root.git";
commit "${packageCommit}";
}
}`;
const sources = new Map([
["locks/web-studio.lock", `quixos-lock fragment version 1 {
import "locks/shared.lock";
interface Placeable source {
repository "https://repos.example/alice/interface-placeable.git";
commit "${namedCommit}";
}
}`],
["locks/shared.lock", `quixos-lock fragment version 1 {
interface Named source {
repository "https://repos.example/alice/interface-named.git";
commit "${namedCommit}";
}
}`],
["locks/domain.lock", `quixos-lock fragment version 1 {
package TodoRuntime source {
repository "https://repos.example/alice/package-todo.git";
commit "${packageCommit}";
}
}`],
]);
const result = await resolveQuixosLock(root, async (relativePath) => {
const source = sources.get(relativePath);
if (!source) throw new Error("missing fixture");
return source;
});
assert.equal(result.ok, true);
if (!result.ok) return;
assert.deepEqual(result.lock.sourceFiles, [
"quixos.lock",
"locks/web-studio.lock",
"locks/shared.lock",
"locks/domain.lock",
]);
assert.deepEqual(result.lock.resources.map(({ kind, binding }) => ({ kind, binding })), [
{ kind: "package", binding: "RootRuntime" },
{ kind: "interface", binding: "Placeable" },
{ kind: "interface", binding: "Named" },
{ kind: "package", binding: "TodoRuntime" },
]);
});
test("lock fragments format canonically and cannot redeclare the Quixos source", () => {
const document = {
kind: "fragment" as const,
formatVersion: 1 as const,
imports: ["locks/shared.lock"],
resources: [{
kind: "interface" as const,
binding: "Named",
source: {
resolver: "git" as const,
repository: "https://repos.example/alice/interface-named.git",
commit: namedCommit,
},
}],
};
assert.deepEqual(parseQuixosLockDocument(formatQuixosLockDocument(document)), {
ok: true,
document,
diagnostics: [],
});
const invalid = parseQuixosLockDocument(`quixos-lock fragment version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
commit "${quixosCommit}";
}
}`, "bad.lock");
assert.equal(invalid.ok, false);
if (!invalid.ok) assert.equal(invalid.diagnostics[0]?.code, "fragment-has-quixos-source");
});
test("lock imports reject traversal, cycles, root documents, and cross-file binding collisions", async () => {
const invalidPath = parseQuixosLockDocument(`quixos-lock fragment version 1 {
import "../outside.lock";
}`, "bad-path.lock");
assert.equal(invalidPath.ok, false);
if (!invalidPath.ok) assert.equal(invalidPath.diagnostics[0]?.code, "invalid-import-path");
const root = `quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
commit "${quixosCommit}";
}
import "a.lock";
import "root-again.lock";
interface Named source {
repository "https://repos.example/alice/interface-named.git";
commit "${namedCommit}";
}
}`;
const sources = new Map([
["a.lock", `quixos-lock fragment version 1 {
import "b.lock";
interface Named source {
repository "https://repos.example/alice/interface-named-copy.git";
commit "${namedCommit}";
}
}`],
["b.lock", `quixos-lock fragment version 1 { import "a.lock"; }`],
["root-again.lock", root],
]);
const result = await resolveQuixosLock(root, async (relativePath) => sources.get(relativePath) ?? "");
assert.equal(result.ok, false);
if (!result.ok) {
assert.deepEqual(new Set(result.diagnostics.map(({ code }) => code)), new Set([
"duplicate-resource-binding",
"import-cycle",
"imported-root-lock",
]));
}
});
test("file loading rejects a symlink in any import path component", async (context) => {
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-lock-test-"));
context.after(() => rm(directory, { recursive: true, force: true }));
const outside = path.join(directory, "outside");
await mkdir(outside);
await writeFile(path.join(outside, "fragment.lock"), "quixos-lock fragment version 1 {}\n");
await symlink(outside, path.join(directory, "linked"), "dir");
await writeFile(path.join(directory, "quixos.lock"), `quixos-lock version 1 {
quixos source {
repository "https://gitea.example/quixos/quixos.git";
commit "${quixosCommit}";
}
import "linked/fragment.lock";
}`);
const result = await loadQuixosLock(path.join(directory, "quixos.lock"));
assert.equal(result.ok, false);
if (!result.ok) {
assert.equal(result.diagnostics[0]?.code, "import-read-failed");
assert.match(result.diagnostics[0]?.message ?? "", /symbolic links/);
}
});
+2
View File
@@ -54,6 +54,8 @@ __metadata:
quixos-capability-compile: dist/src/capability-language/cli.js
quixos-descriptor-check: dist/src/descriptor-check.js
quixos-lock-check: dist/src/resource-lock/cli.js
quixos-resource-compile: dist/src/capability-language/resource-cli.js
quixos-workspace-compile: dist/src/capability-language/workspace-cli.js
languageName: unknown
linkType: soft