@shapeshift-labs/frontier-lang-parser 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -4
- package/dist/index.js +33 -5
- package/dist/proof.js +120 -0
- package/dist/view.js +103 -0
- package/examples/todo.frontier +21 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -20,7 +20,10 @@ The published Frontier package family is generated from one shared package catal
|
|
|
20
20
|
- [`@shapeshift-labs/frontier-schema`](https://www.npmjs.com/package/@shapeshift-labs/frontier-schema): JSON Schema validation, Frontier profile generation, CloudEvent envelopes, and query/table schema helpers.
|
|
21
21
|
- [`@shapeshift-labs/frontier-migrations`](https://www.npmjs.com/package/@shapeshift-labs/frontier-migrations): Boundary-first data migrations, import normalization, plugin/API version mapping, versioned envelopes, graph diagnostics, patch path rewrites, dry-run reports, and current-shape rehydration.
|
|
22
22
|
- [`@shapeshift-labs/frontier-event-log`](https://www.npmjs.com/package/@shapeshift-labs/frontier-event-log): Bounded event logs, replay cursors, consumer acknowledgements, keyed compaction, checkpoints, and Frontier patch event records.
|
|
23
|
+
- [`@shapeshift-labs/frontier-run`](https://www.npmjs.com/package/@shapeshift-labs/frontier-run): Append-only distributed run graphs, causal event DAGs, evidence nodes, lanes, leases, refs, segments, dashboard projections, and admission decision records for Frontier agent work.
|
|
24
|
+
- [`@shapeshift-labs/frontier-lease`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lease): Runtime-neutral semantic, file, package, and repository lease claims with fencing tokens, expiry, conflict checks, apply validation, and replayable evidence for Frontier collaboration.
|
|
23
25
|
- [`@shapeshift-labs/frontier-inspect`](https://www.npmjs.com/package/@shapeshift-labs/frontier-inspect): Cross-package inspection/evidence bundles, registry graph snapshots, feature/resource impact reports, timeline/event normalization, redaction, JSONL import/export, and AI-readable app feature maps.
|
|
26
|
+
- [`@shapeshift-labs/frontier-runtime-proof`](https://www.npmjs.com/package/@shapeshift-labs/frontier-runtime-proof): Runtime-neutral proof capsules, source-bound runtime telemetry, and admission evidence helpers for Frontier merge and review workflows.
|
|
24
27
|
- [`@shapeshift-labs/frontier-scheduler`](https://www.npmjs.com/package/@shapeshift-labs/frontier-scheduler): Deterministic work scheduling, lanes, cancellation, backpressure, frame policies, replay snapshots, and work graphs.
|
|
25
28
|
- [`@shapeshift-labs/frontier-logging`](https://www.npmjs.com/package/@shapeshift-labs/frontier-logging): Opt-in structured logging, browser telemetry, scheduled sinks, file sinks, exporters, benchmark traces, and Frontier patch/update summaries.
|
|
26
29
|
- [`@shapeshift-labs/frontier-mutation`](https://www.npmjs.com/package/@shapeshift-labs/frontier-mutation): Explicit mutation and selector plans compiled to Frontier patches or CRDT operations.
|
|
@@ -35,23 +38,30 @@ The published Frontier package family is generated from one shared package catal
|
|
|
35
38
|
- [`@shapeshift-labs/frontier-worker`](https://www.npmjs.com/package/@shapeshift-labs/frontier-worker): Serializable worker and edge task descriptors for Frontier apps, including queues, idempotency keys, retry and timeout policy, declared reads/writes/effects, snapshots, patch outputs, produced assets, execution records, logs, trace links, proof hashes, dedupe indexes, and registry graph output.
|
|
36
39
|
- [`@shapeshift-labs/frontier-queue`](https://www.npmjs.com/package/@shapeshift-labs/frontier-queue): Serializable durable queue state, leases, retries, dedupe keys, patch-carrying jobs, dead-letter records, replay evidence, and queue inspection for Frontier apps.
|
|
37
40
|
- [`@shapeshift-labs/frontier-swarm`](https://www.npmjs.com/package/@shapeshift-labs/frontier-swarm): Hierarchical swarm plans, lanes, compute profiles, ownership policy, semantic ownership regions, task queues, event streams, run records, merge bundles, merge indexes, queue overlays, merge admission, coordinator dashboards, changed-path checks, and proof artifacts for Frontier agent work.
|
|
38
|
-
- [`@shapeshift-labs/frontier-swarm-
|
|
41
|
+
- [`@shapeshift-labs/frontier-swarm-git`](https://www.npmjs.com/package/@shapeshift-labs/frontier-swarm-git): Node Git, workspace, patch, changed-path, write-fence, package-link repair, patch check, HEAD read, blob hash, and apply-ledger adapter for Frontier swarm runners.
|
|
42
|
+
- [`@shapeshift-labs/frontier-swarm-codex`](https://www.npmjs.com/package/@shapeshift-labs/frontier-swarm-codex): Node Codex CLI adapter for Frontier swarm plans, including prompt rendering, worktree and snapshot workspaces, Codex argument compatibility, browser resource allocation, JSONL capture, verification commands, pid-backed stop, collect/apply workflows, merge indexes, queue overlays, merge bundles, normalized job evidence, coordinator query artifacts, result artifacts, and run-log sync adapters.
|
|
43
|
+
- [`@shapeshift-labs/frontier-loom-ui`](https://www.npmjs.com/package/@shapeshift-labs/frontier-loom-ui): Read-only Loom and Frontier operator dashboard for workspace-lifetime progress, active agents, queue state, evidence/admission status, run events, run-log sync projections, semantic leases, gate executions, git apply/workspace evidence, and coordinator steering intent files.
|
|
39
44
|
- [`@shapeshift-labs/frontier-lang-kernel`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-kernel): Runtime-neutral semantic source graph, type/lattice/extern declarations, patch bundles, replay, hashing, evidence records, and merge-admission kernel for Frontier Lang.
|
|
40
45
|
- [`@shapeshift-labs/frontier-lang-checker`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-checker): Checker and diagnostics for Frontier Lang semantic documents, including type symbols, effects, regions, lattice laws, CRDT metadata, and patch evidence.
|
|
41
46
|
- [`@shapeshift-labs/frontier-lang-typescript`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-typescript): TypeScript projection adapter for Frontier Lang semantic documents, including type/entity/state/action/extern declarations and CRDT lattice descriptors.
|
|
42
47
|
- [`@shapeshift-labs/frontier-lang-javascript`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-javascript): JavaScript projection adapter for Frontier Lang semantic documents, including ESM action stubs and schema/lattice descriptors.
|
|
48
|
+
- [`@shapeshift-labs/frontier-lang-jsx`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-jsx): Runtime-neutral JSX semantic merge evidence for Frontier Lang, including element identity, prop records, keyed children, spread props, source spans, and fail-closed renderer/runtime proof gaps.
|
|
49
|
+
- [`@shapeshift-labs/frontier-lang-svg`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-svg): Runtime-neutral SVG semantic merge evidence for Frontier Lang, including element identity, local id definitions, url/href reference graphs, source spans, and fail-closed paint/runtime proof gaps.
|
|
50
|
+
- [`@shapeshift-labs/frontier-lang-package`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-package): Runtime-neutral package manifest semantic merge evidence for Frontier Lang, including dependency, script, export/import, bin, workspace, package-manager, source-span, and fail-closed install/runtime proof gaps.
|
|
51
|
+
- [`@shapeshift-labs/frontier-lang-html`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-html): HTML semantic merge evidence and projection adapter for Frontier Lang semantic documents, including element tree identity, attributes, text/comment spans, source maps, and fail-closed browser/runtime proof gaps.
|
|
52
|
+
- [`@shapeshift-labs/frontier-lang-css`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-css): CSS semantic merge evidence and projection adapter for Frontier Lang semantic documents, including selector specificity, declaration/cascade keys, custom properties, `@property` and `@page` descriptor evidence, CSS Modules/ICSS export and composition evidence, source maps, and fail-closed browser cascade/render proof gaps.
|
|
43
53
|
- [`@shapeshift-labs/frontier-lang-rust`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-rust): Rust projection adapter for Frontier Lang semantic documents, including structs, aliases, and action stubs.
|
|
44
54
|
- [`@shapeshift-labs/frontier-lang-python`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-python): Python projection adapter for Frontier Lang semantic documents, including dataclasses, typed patch records, and action stubs.
|
|
45
55
|
- [`@shapeshift-labs/frontier-lang-c`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-c): C header projection adapter for Frontier Lang semantic documents, including structs and action prototypes.
|
|
46
|
-
- [`@shapeshift-labs/frontier-lang-compiler`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-compiler): Compiler facade for Frontier Lang source documents, including parse, check, hash, diagnostics, universal AST envelopes, proof/paradigm semantic summaries, projection to TypeScript, JavaScript, Rust, Python, and C, and native source-import adapters for semantic merge evidence.
|
|
56
|
+
- [`@shapeshift-labs/frontier-lang-compiler`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-compiler): Compiler facade for Frontier Lang source documents, including parse, check, hash, diagnostics, universal AST envelopes, proof/paradigm semantic summaries, projection to TypeScript, JavaScript, JSX, TSX, SVG, HTML, CSS, package manifests, Rust, Python, and C, and native source-import adapters for semantic merge evidence.
|
|
47
57
|
- [`@shapeshift-labs/frontier-lang-swift`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-swift): Swift source-language importer package for Frontier Lang semantic documents, including package-level metadata, SwiftSyntax adapter helpers, native import results, and semantic sidecar generation for SwiftSyntax/SwiftParser-shaped syntax trees.
|
|
48
58
|
- [`@shapeshift-labs/frontier-lang-kotlin`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-kotlin): Kotlin PSI source-language importer package for Frontier Lang semantic documents, including package-level metadata, Kotlin PSI adapter helpers, native import results, and semantic sidecar generation for Kotlin PSI/KtFile-shaped syntax trees.
|
|
49
59
|
- [`@shapeshift-labs/frontier-lang-java`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-java): Java source-language importer package for Frontier Lang semantic documents, including package-level metadata, Java AST adapter helpers, native import results, and semantic sidecar generation for javac/JDT/JavaParser-shaped ASTs.
|
|
50
60
|
- [`@shapeshift-labs/frontier-lang-go`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-go): Go source-language importer package for Frontier Lang semantic documents, including package-level metadata, Go AST adapter helpers, native import results, and semantic sidecar generation for go/ast File or Package trees.
|
|
51
61
|
- [`@shapeshift-labs/frontier-lang-csharp`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-csharp): C# Roslyn source-language importer package for Frontier Lang semantic documents, including package-level metadata, Roslyn adapter helpers, native import results, and semantic sidecar generation for SyntaxTree/SyntaxNode-shaped ASTs.
|
|
52
62
|
- [`@shapeshift-labs/frontier-lang-clang`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-clang): Clang AST source-language importer package for Frontier Lang semantic documents, including package-level metadata, Clang AST JSON adapter helpers, native import results, and semantic sidecar generation for C/C++ translation units.
|
|
53
|
-
- [`@shapeshift-labs/frontier-lang-cli`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-cli): Command line interface for parsing, checking, hashing, and
|
|
54
|
-
- [`@shapeshift-labs/frontier-lang`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang): Umbrella package for Frontier Lang kernel, parser, checker, compiler facade, universal AST helpers, projection adapters, and source-language importer adapters.
|
|
63
|
+
- [`@shapeshift-labs/frontier-lang-cli`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang-cli): Command line interface for parsing, checking, hashing, emitting, native source import/projection, semantic slicing, and corpus roundtrip evidence for Frontier Lang projects.
|
|
64
|
+
- [`@shapeshift-labs/frontier-lang`](https://www.npmjs.com/package/@shapeshift-labs/frontier-lang): Umbrella package for Frontier Lang kernel, parser, checker, compiler facade, universal AST helpers, projection adapters, HTML/CSS semantic merge evidence adapters, and source-language importer adapters.
|
|
55
65
|
- [`@shapeshift-labs/frontier-kv`](https://www.npmjs.com/package/@shapeshift-labs/frontier-kv): Serializable in-memory key/value state for Frontier apps, including TTL, versioned compare-and-set, batched patch mutations, scans, watchers, snapshots, JSONL event evidence, and replay verification.
|
|
56
66
|
- [`@shapeshift-labs/frontier-kv-locks`](https://www.npmjs.com/package/@shapeshift-labs/frontier-kv-locks): Lease-style lock records on top of Frontier KV, including acquire, renew, release, fencing tokens, expiration, owner evidence, and replayable lock events.
|
|
57
67
|
- [`@shapeshift-labs/frontier-kv-rate-limit`](https://www.npmjs.com/package/@shapeshift-labs/frontier-kv-rate-limit): Patch-native rate limit buckets for Frontier KV, including fixed windows, sliding windows, token buckets, deterministic refill, consume evidence, and reset records.
|
|
@@ -96,6 +106,7 @@ The published Frontier package family is generated from one shared package catal
|
|
|
96
106
|
- [`@shapeshift-labs/frontier-realtime-server`](https://www.npmjs.com/package/@shapeshift-labs/frontier-realtime-server): Authoritative realtime room, tick, command validation, rate-limit, session, and snapshot-history runtime.
|
|
97
107
|
- [`@shapeshift-labs/frontier-realtime-websocket`](https://www.npmjs.com/package/@shapeshift-labs/frontier-realtime-websocket): WebSocket client, wire, and Node room-server transport for Frontier realtime.
|
|
98
108
|
- [`@shapeshift-labs/frontier-game`](https://www.npmjs.com/package/@shapeshift-labs/frontier-game): Game-facing entity, component, player, room, ownership, spatial interest, rollback, physics, and replication helpers above realtime.
|
|
109
|
+
- [`@shapeshift-labs/loom`](https://www.npmjs.com/package/@shapeshift-labs/loom): Repo-level semantic collaboration CLI for .loom workspaces, including init, scan, status, graph snapshots, projection plans, Frontier Lang delegation, Frontier Swarm delegation, run-log sync command delegation, and Frontier Framework delegation.
|
|
99
110
|
|
|
100
111
|
Package source repositories:
|
|
101
112
|
|
|
@@ -112,7 +123,10 @@ Package source repositories:
|
|
|
112
123
|
- [`siliconjungle/-shapeshift-labs-frontier-schema`](https://github.com/siliconjungle/-shapeshift-labs-frontier-schema)
|
|
113
124
|
- [`siliconjungle/-shapeshift-labs-frontier-migrations`](https://github.com/siliconjungle/-shapeshift-labs-frontier-migrations)
|
|
114
125
|
- [`siliconjungle/-shapeshift-labs-frontier-event-log`](https://github.com/siliconjungle/-shapeshift-labs-frontier-event-log)
|
|
126
|
+
- [`siliconjungle/-shapeshift-labs-frontier-run`](https://github.com/siliconjungle/-shapeshift-labs-frontier-run)
|
|
127
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lease`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lease)
|
|
115
128
|
- [`siliconjungle/-shapeshift-labs-frontier-inspect`](https://github.com/siliconjungle/-shapeshift-labs-frontier-inspect)
|
|
129
|
+
- [`siliconjungle/-shapeshift-labs-frontier-runtime-proof`](https://github.com/siliconjungle/-shapeshift-labs-frontier-runtime-proof)
|
|
116
130
|
- [`siliconjungle/-shapeshift-labs-frontier-scheduler`](https://github.com/siliconjungle/-shapeshift-labs-frontier-scheduler)
|
|
117
131
|
- [`siliconjungle/-shapeshift-labs-frontier-logging`](https://github.com/siliconjungle/-shapeshift-labs-frontier-logging)
|
|
118
132
|
- [`siliconjungle/-shapeshift-labs-frontier-mutation`](https://github.com/siliconjungle/-shapeshift-labs-frontier-mutation)
|
|
@@ -127,12 +141,19 @@ Package source repositories:
|
|
|
127
141
|
- [`siliconjungle/-shapeshift-labs-frontier-worker`](https://github.com/siliconjungle/-shapeshift-labs-frontier-worker)
|
|
128
142
|
- [`siliconjungle/-shapeshift-labs-frontier-queue`](https://github.com/siliconjungle/-shapeshift-labs-frontier-queue)
|
|
129
143
|
- [`siliconjungle/-shapeshift-labs-frontier-swarm`](https://github.com/siliconjungle/-shapeshift-labs-frontier-swarm)
|
|
144
|
+
- [`siliconjungle/-shapeshift-labs-frontier-swarm-git`](https://github.com/siliconjungle/-shapeshift-labs-frontier-swarm-git)
|
|
130
145
|
- [`siliconjungle/-shapeshift-labs-frontier-swarm-codex`](https://github.com/siliconjungle/-shapeshift-labs-frontier-swarm-codex)
|
|
146
|
+
- [`siliconjungle/frontier-loom-ui`](https://github.com/siliconjungle/frontier-loom-ui)
|
|
131
147
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-kernel`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-kernel)
|
|
132
148
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-parser`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-parser)
|
|
133
149
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-checker`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-checker)
|
|
134
150
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-typescript`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-typescript)
|
|
135
151
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-javascript`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-javascript)
|
|
152
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lang-jsx`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-jsx)
|
|
153
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lang-svg`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-svg)
|
|
154
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lang-package`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-package)
|
|
155
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lang-html`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-html)
|
|
156
|
+
- [`siliconjungle/-shapeshift-labs-frontier-lang-css`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-css)
|
|
136
157
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-rust`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-rust)
|
|
137
158
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-python`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-python)
|
|
138
159
|
- [`siliconjungle/-shapeshift-labs-frontier-lang-c`](https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-c)
|
|
@@ -189,6 +210,7 @@ Package source repositories:
|
|
|
189
210
|
- [`siliconjungle/-shapeshift-labs-frontier-realtime-server`](https://github.com/siliconjungle/-shapeshift-labs-frontier-realtime-server)
|
|
190
211
|
- [`siliconjungle/-shapeshift-labs-frontier-realtime-websocket`](https://github.com/siliconjungle/-shapeshift-labs-frontier-realtime-websocket)
|
|
191
212
|
- [`siliconjungle/-shapeshift-labs-frontier-game`](https://github.com/siliconjungle/-shapeshift-labs-frontier-game)
|
|
213
|
+
- [`siliconjungle/-shapeshift-labs-loom`](https://github.com/siliconjungle/-shapeshift-labs-loom)
|
|
192
214
|
|
|
193
215
|
## Install
|
|
194
216
|
|
package/dist/index.js
CHANGED
|
@@ -6,20 +6,26 @@ import {
|
|
|
6
6
|
entityNode,
|
|
7
7
|
externNode,
|
|
8
8
|
latticeNode,
|
|
9
|
+
migrationNode,
|
|
9
10
|
nativeSourceNode,
|
|
10
11
|
stateNode,
|
|
11
12
|
targetNode,
|
|
12
13
|
typeNode
|
|
13
14
|
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
15
|
+
import { parseProofBlock } from './proof.js';
|
|
16
|
+
import { parseViewBlock } from './view.js';
|
|
14
17
|
|
|
15
18
|
export function parseFrontierSource(source, options = {}) {
|
|
16
19
|
const nodes = [];
|
|
20
|
+
const proofBlocks = [];
|
|
17
21
|
const documentId = options.id ?? readId(source) ?? 'mod_frontier';
|
|
18
22
|
const documentName = options.name ?? readName(source) ?? 'FrontierModule';
|
|
19
23
|
for (const block of readBlocks(source)) {
|
|
20
24
|
if (block.kind === 'entity') nodes.push(parseEntity(block));
|
|
21
25
|
if (block.kind === 'state') nodes.push(parseState(block));
|
|
22
26
|
if (block.kind === 'action') nodes.push(parseAction(block));
|
|
27
|
+
if (block.kind === 'view') nodes.push(parseViewBlock(block));
|
|
28
|
+
if (block.kind === 'migration') nodes.push(parseMigration(block));
|
|
23
29
|
if (block.kind === 'capability') nodes.push(parseCapability(block));
|
|
24
30
|
if (block.kind === 'effect') nodes.push(parseEffect(block));
|
|
25
31
|
if (block.kind === 'type') nodes.push(parseType(block));
|
|
@@ -27,19 +33,18 @@ export function parseFrontierSource(source, options = {}) {
|
|
|
27
33
|
if (block.kind === 'lattice') nodes.push(parseLattice(block));
|
|
28
34
|
if (block.kind === 'nativeSource') nodes.push(parseNativeSource(block));
|
|
29
35
|
if (block.kind === 'target') nodes.push(parseTarget(block));
|
|
36
|
+
if (block.kind === 'proof') proofBlocks.push(parseProofBlock(block));
|
|
30
37
|
}
|
|
31
|
-
return createDocument({ id: documentId, name: documentName, nodes });
|
|
38
|
+
return createDocument({ id: documentId, name: documentName, nodes, ...(proofBlocks.length ? { metadata: { proof: mergeProofBlocks(proofBlocks) } } : {}) });
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
export function parseFrontierFile(name, source) {
|
|
35
|
-
return parseFrontierSource(source, { name: name.replace(/\.frontier$/, '') });
|
|
36
|
-
}
|
|
41
|
+
export function parseFrontierFile(name, source) { return parseFrontierSource(source, { name: name.replace(/\.frontier$/, '') }); }
|
|
37
42
|
|
|
38
43
|
function readName(source) { return /module\s+([A-Za-z_$][\w$]*)/.exec(source)?.[1]; }
|
|
39
44
|
function readId(source) { return /module\s+[A-Za-z_$][\w$]*\s+@id\(\s*["']([^"']+)["']\s*\)/.exec(source)?.[1]; }
|
|
40
45
|
function readBlocks(source) {
|
|
41
46
|
const blocks = [];
|
|
42
|
-
const header = /\b(entity|state|action|capability|effect|type|extern|lattice|nativeSource|target)\s+([^{}]+)\{/g;
|
|
47
|
+
const header = /\b(entity|state|action|view|migration|capability|effect|type|extern|lattice|nativeSource|target|proof)\s+([^{}]+)\{/g;
|
|
43
48
|
let match;
|
|
44
49
|
while ((match = header.exec(source))) {
|
|
45
50
|
let depth = 1; let index = header.lastIndex;
|
|
@@ -49,6 +54,15 @@ function readBlocks(source) {
|
|
|
49
54
|
}
|
|
50
55
|
return blocks;
|
|
51
56
|
}
|
|
57
|
+
const PROOF_GROUPS = ['contracts', 'refinements', 'invariants', 'termination', 'temporal', 'obligations', 'artifacts', 'assumptions'];
|
|
58
|
+
function mergeProofBlocks(blocks) {
|
|
59
|
+
const proof = {
|
|
60
|
+
id: blocks.length === 1 ? blocks[0].id : 'proof:source',
|
|
61
|
+
metadata: { authoredProofBlockIds: blocks.map((block) => block.id) }
|
|
62
|
+
};
|
|
63
|
+
for (const group of PROOF_GROUPS) proof[group] = blocks.flatMap((block) => block[group] ?? []);
|
|
64
|
+
return proof;
|
|
65
|
+
}
|
|
52
66
|
function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
|
|
53
67
|
function nameFrom(header) { return /^([A-Za-z_$][\w$]*)/.exec(header)?.[1] ?? 'Unnamed'; }
|
|
54
68
|
function parseEntity(block) {
|
|
@@ -97,6 +111,10 @@ function parseAction(block) {
|
|
|
97
111
|
uses: readList('uses', block.body)
|
|
98
112
|
});
|
|
99
113
|
}
|
|
114
|
+
function parseMigration(block) {
|
|
115
|
+
const name = nameFrom(block.header);
|
|
116
|
+
return migrationNode({ id: idFrom(block.header, `migration_${name}`), name, fromVersion: readWord('fromVersion', block.body) ?? readWord('from', block.body) ?? 'unknown', toVersion: readWord('toVersion', block.body) ?? readWord('to', block.body) ?? 'unknown', changes: readChangeRecords(block.body), invariants: readList('invariants', block.body) });
|
|
117
|
+
}
|
|
100
118
|
function parseEffect(block) {
|
|
101
119
|
const name = nameFrom(block.header);
|
|
102
120
|
return effectNode({
|
|
@@ -246,6 +264,16 @@ function readUnsupportedTargets(body) {
|
|
|
246
264
|
}
|
|
247
265
|
return unsupported.length ? unsupported : undefined;
|
|
248
266
|
}
|
|
267
|
+
function readChangeRecords(body) {
|
|
268
|
+
const changes = [];
|
|
269
|
+
const re = /^\s*change\s+([A-Za-z][\w-]*)(?:\s+([^\n]+))?/gm;
|
|
270
|
+
let match;
|
|
271
|
+
while ((match = re.exec(body))) {
|
|
272
|
+
const statement = match[2]?.trim();
|
|
273
|
+
changes.push({ id: `change_${changes.length}`, kind: match[1], ...(statement ? { statement, target: statement.split(/\s+/)[0] } : {}) });
|
|
274
|
+
}
|
|
275
|
+
return changes;
|
|
276
|
+
}
|
|
249
277
|
function parseMerge(text) {
|
|
250
278
|
const kind = /merge\s+([A-Za-z][\w-]*)/.exec(text)?.[1];
|
|
251
279
|
if (!kind) return undefined;
|
package/dist/proof.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const CONTRACT_GROUPS = {
|
|
2
|
+
contract: 'contracts',
|
|
3
|
+
refinement: 'refinements',
|
|
4
|
+
invariant: 'invariants',
|
|
5
|
+
termination: 'termination',
|
|
6
|
+
temporal: 'temporal'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function parseProofBlock(block) {
|
|
10
|
+
const name = nameFrom(block.header);
|
|
11
|
+
const proof = {
|
|
12
|
+
id: idFrom(block.header, `proof_${name}`),
|
|
13
|
+
contracts: [],
|
|
14
|
+
refinements: [],
|
|
15
|
+
invariants: [],
|
|
16
|
+
termination: [],
|
|
17
|
+
temporal: [],
|
|
18
|
+
obligations: [],
|
|
19
|
+
artifacts: [],
|
|
20
|
+
assumptions: [],
|
|
21
|
+
metadata: { name }
|
|
22
|
+
};
|
|
23
|
+
for (const rawLine of block.body.split('\n')) {
|
|
24
|
+
const line = rawLine.trim();
|
|
25
|
+
if (!line || line.startsWith('#')) continue;
|
|
26
|
+
const match = /^(contract|refinement|invariant|termination|temporal|obligation|artifact|assumption)\s+([A-Za-z_$][\w$-]*)(.*)$/.exec(line);
|
|
27
|
+
if (!match) continue;
|
|
28
|
+
const [, section, recordName, rest] = match;
|
|
29
|
+
const group = CONTRACT_GROUPS[section];
|
|
30
|
+
if (group) proof[group].push(parseProofContract(section, recordName, rest));
|
|
31
|
+
if (section === 'obligation') proof.obligations.push(parseProofObligation(recordName, rest));
|
|
32
|
+
if (section === 'artifact') proof.artifacts.push(parseProofArtifact(recordName, rest));
|
|
33
|
+
if (section === 'assumption') proof.assumptions.push(parseProofAssumption(recordName, rest));
|
|
34
|
+
}
|
|
35
|
+
return omitEmptyArrays(proof);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseProofContract(section, name, text) {
|
|
39
|
+
return cleanRecord({
|
|
40
|
+
id: idFrom(text, `proof_${section}_${name}`),
|
|
41
|
+
kind: readInlineWord('kind', text) ?? section,
|
|
42
|
+
subjectKind: readInlineWord('subjectKind', text),
|
|
43
|
+
subjectId: readInlineWord('subject', text) ?? readInlineWord('subjectId', text),
|
|
44
|
+
expression: readInlineQuoted('expression', text),
|
|
45
|
+
statement: readInlineQuoted('statement', text),
|
|
46
|
+
language: readInlineWord('language', text),
|
|
47
|
+
sourceMapId: readInlineWord('sourceMap', text) ?? readInlineWord('sourceMapId', text),
|
|
48
|
+
sourceMapMappingId: readInlineWord('sourceMapMapping', text) ?? readInlineWord('sourceMapMappingId', text),
|
|
49
|
+
evidenceIds: readInlineList(text, 'evidence', 'evidenceIds'),
|
|
50
|
+
lossIds: readInlineList(text, 'loss', 'lossIds'),
|
|
51
|
+
metadata: { name }
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function parseProofObligation(name, text) {
|
|
56
|
+
return cleanRecord({
|
|
57
|
+
id: idFrom(text, `proof_obligation_${name}`),
|
|
58
|
+
kind: readInlineWord('kind', text),
|
|
59
|
+
status: readInlineWord('status', text),
|
|
60
|
+
subjectKind: readInlineWord('subjectKind', text),
|
|
61
|
+
subjectId: readInlineWord('subject', text) ?? readInlineWord('subjectId', text),
|
|
62
|
+
expression: readInlineQuoted('expression', text),
|
|
63
|
+
statement: readInlineQuoted('statement', text),
|
|
64
|
+
contractIds: readInlineList(text, 'contract', 'contracts', 'contractIds'),
|
|
65
|
+
assumptionIds: readInlineList(text, 'assumption', 'assumptions', 'assumptionIds'),
|
|
66
|
+
artifactIds: readInlineList(text, 'artifact', 'artifacts', 'artifactIds'),
|
|
67
|
+
evidenceIds: readInlineList(text, 'evidence', 'evidenceIds'),
|
|
68
|
+
lossIds: readInlineList(text, 'loss', 'lossIds'),
|
|
69
|
+
solver: readInlineWord('solver', text),
|
|
70
|
+
staleAgainstHash: readInlineWord('staleAgainstHash', text),
|
|
71
|
+
metadata: { name }
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseProofArtifact(name, text) {
|
|
76
|
+
return cleanRecord({
|
|
77
|
+
id: idFrom(text, `proof_artifact_${name}`),
|
|
78
|
+
kind: readInlineWord('kind', text),
|
|
79
|
+
status: readInlineWord('status', text),
|
|
80
|
+
path: readInlineWord('path', text),
|
|
81
|
+
hash: readInlineWord('hash', text),
|
|
82
|
+
command: readInlineQuoted('command', text),
|
|
83
|
+
prover: readInlineWord('prover', text),
|
|
84
|
+
obligationIds: readInlineList(text, 'obligation', 'obligations', 'obligationIds'),
|
|
85
|
+
assumptionIds: readInlineList(text, 'assumption', 'assumptions', 'assumptionIds'),
|
|
86
|
+
evidenceIds: readInlineList(text, 'evidence', 'evidenceIds'),
|
|
87
|
+
summary: readInlineQuoted('summary', text),
|
|
88
|
+
metadata: { name }
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function parseProofAssumption(name, text) {
|
|
93
|
+
return cleanRecord({
|
|
94
|
+
id: idFrom(text, `proof_assumption_${name}`),
|
|
95
|
+
scope: readInlineWord('scope', text),
|
|
96
|
+
subjectKind: readInlineWord('subjectKind', text),
|
|
97
|
+
subjectId: readInlineWord('subject', text) ?? readInlineWord('subjectId', text),
|
|
98
|
+
description: readInlineQuoted('description', text),
|
|
99
|
+
evidenceIds: readInlineList(text, 'evidence', 'evidenceIds'),
|
|
100
|
+
metadata: { name }
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function idFrom(text, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(text)?.[1] ?? fallback; }
|
|
105
|
+
function nameFrom(header) { return /^([A-Za-z_$][\w$]*)/.exec(header)?.[1] ?? 'Proof'; }
|
|
106
|
+
function readInlineWord(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
|
|
107
|
+
function readInlineQuoted(label, text) { return new RegExp("(?:^|\\s)" + label + "\\s+[\"']([^\"']+)[\"']").exec(text)?.[1]?.trim(); }
|
|
108
|
+
function readInlineList(text, ...labels) {
|
|
109
|
+
for (const label of labels) {
|
|
110
|
+
const value = new RegExp('(?:^|\\s)' + label + '\\s+([^\\s]+)').exec(text)?.[1]?.trim();
|
|
111
|
+
if (value) return value.split(/[|,]/).map((item) => item.trim()).filter(Boolean);
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
function cleanRecord(record) {
|
|
116
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0)));
|
|
117
|
+
}
|
|
118
|
+
function omitEmptyArrays(record) {
|
|
119
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => !Array.isArray(value) || value.length > 0));
|
|
120
|
+
}
|
package/dist/view.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { viewNode } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
|
|
3
|
+
export function parseViewBlock(block) {
|
|
4
|
+
const name = nameFrom(block.header);
|
|
5
|
+
const topLevelBody = stripNestedBlocks('render', block.body);
|
|
6
|
+
const props = readViewProps(topLevelBody);
|
|
7
|
+
const events = readViewEvents(topLevelBody);
|
|
8
|
+
const renders = readRenderNodes(block.body);
|
|
9
|
+
return viewNode({
|
|
10
|
+
id: idFrom(block.header, `view_${name}`),
|
|
11
|
+
name,
|
|
12
|
+
reads: readList('reads', topLevelBody),
|
|
13
|
+
dispatches: readList('dispatches', topLevelBody) ?? readList('dispatch', topLevelBody),
|
|
14
|
+
props: props.length ? props : undefined,
|
|
15
|
+
events: events.length ? events : undefined,
|
|
16
|
+
renders: renders.length ? renders : undefined
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function readViewProps(body) {
|
|
21
|
+
const props = [];
|
|
22
|
+
const re = /^\s*prop\s+([A-Za-z_$][\w$.-]*)(?:\s+@id\(\s*["']([^"']+)["']\s*\))?\s*:\s*([^\n]+)$/gm;
|
|
23
|
+
let match;
|
|
24
|
+
while ((match = re.exec(body))) props.push({ id: match[2] ?? `view_prop_${match[1]}`, name: match[1], type: parseTypeExpression(match[3].replace(/\s+optional\s*$/, '').trim()), optional: /\soptional\s*$/.test(match[3]) || undefined });
|
|
25
|
+
return props;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readViewEvents(body) {
|
|
29
|
+
const events = [];
|
|
30
|
+
const re = /^\s*event\s+([A-Za-z_$][\w$.-]*)(?:\s+@id\(\s*["']([^"']+)["']\s*\))?([^\n]*)$/gm;
|
|
31
|
+
let match;
|
|
32
|
+
while ((match = re.exec(body))) events.push({ id: match[2] ?? `view_event_${match[1]}`, name: match[1], action: readInlineWord('action', match[3]), input: parseOptionalTypeExpression(readInlineWord('input', match[3])) });
|
|
33
|
+
return events;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readRenderNodes(body) {
|
|
37
|
+
return readNestedBlocks('render', body).map((block) => {
|
|
38
|
+
const tagName = nameFrom(block.header);
|
|
39
|
+
const props = readRenderProps(block.body);
|
|
40
|
+
const events = readRenderEvents(block.body);
|
|
41
|
+
return {
|
|
42
|
+
id: idFrom(block.header, `render_${tagName}`),
|
|
43
|
+
kind: readInlineWord('kind', block.header) ?? 'element',
|
|
44
|
+
tagName,
|
|
45
|
+
identityKey: readLine('identity', block.body) ?? readLine('key', block.body),
|
|
46
|
+
text: readQuotedLine('text', block.body),
|
|
47
|
+
props: props.length ? props : undefined,
|
|
48
|
+
events: events.length ? events : undefined
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readRenderProps(body) {
|
|
54
|
+
const props = [];
|
|
55
|
+
const re = /^\s*prop\s+([A-Za-z_$][\w$.-]*)\s+([^\n]+)$/gm;
|
|
56
|
+
let match;
|
|
57
|
+
while ((match = re.exec(body))) props.push({ name: match[1], ...readRenderValue(match[2]) });
|
|
58
|
+
return props;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function readRenderEvents(body) {
|
|
62
|
+
const events = [];
|
|
63
|
+
const re = /^\s*on\s+([A-Za-z_$][\w$.-]*)\s+([A-Za-z_$][\w$.-]*)/gm;
|
|
64
|
+
let match;
|
|
65
|
+
while ((match = re.exec(body))) events.push({ name: match[1], action: match[2] });
|
|
66
|
+
return events;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function readNestedBlocks(kind, source) {
|
|
70
|
+
const blocks = [];
|
|
71
|
+
const header = new RegExp('\\b' + kind + '\\s+([^{}]+)\\{', 'g');
|
|
72
|
+
let match;
|
|
73
|
+
while ((match = header.exec(source))) {
|
|
74
|
+
let depth = 1; let index = header.lastIndex;
|
|
75
|
+
while (index < source.length && depth > 0) { const ch = source[index++]; if (ch === '{') depth++; if (ch === '}') depth--; }
|
|
76
|
+
blocks.push({ kind, header: match[1].trim(), body: source.slice(header.lastIndex, index - 1), start: match.index, end: index });
|
|
77
|
+
header.lastIndex = index;
|
|
78
|
+
}
|
|
79
|
+
return blocks;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function stripNestedBlocks(kind, source) {
|
|
83
|
+
let text = source;
|
|
84
|
+
for (const block of readNestedBlocks(kind, source).reverse()) text = text.slice(0, block.start) + text.slice(block.end);
|
|
85
|
+
return text;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
|
|
89
|
+
function nameFrom(header) { return /^([A-Za-z_$][\w$]*)/.exec(header)?.[1] ?? 'Unnamed'; }
|
|
90
|
+
function readList(label, body) { const line = new RegExp('^\\s*' + label + '\\s+([^\\n]+)', 'm').exec(body)?.[1]; return line ? line.split(',').map((item) => item.trim()).filter(Boolean) : undefined; }
|
|
91
|
+
function readLine(label, body) { return new RegExp('^\\s*' + label + '\\s+([^\\n]+)', 'm').exec(body)?.[1]?.trim(); }
|
|
92
|
+
function readQuotedLine(label, body) { return new RegExp(`^\\s*${label}\\s+["']([^"']+)["']`, 'm').exec(body)?.[1]; }
|
|
93
|
+
function readInlineWord(label, text = '') { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
|
|
94
|
+
function readRenderValue(value) { const quoted = /^["']([^"']+)["']$/.exec(value.trim()); return quoted ? { value: quoted[1] } : { expression: value.trim() }; }
|
|
95
|
+
function parseOptionalTypeExpression(value) { return value ? parseTypeExpression(value.trim()) : undefined; }
|
|
96
|
+
function parseTypeExpression(value) {
|
|
97
|
+
const text = value.trim();
|
|
98
|
+
if (/^Set<.+>$/.test(text)) return { kind: 'set', item: parseTypeExpression(text.slice(4, -1)) };
|
|
99
|
+
if (/^List<.+>$/.test(text)) return { kind: 'list', item: parseTypeExpression(text.slice(5, -1)) };
|
|
100
|
+
const map = /^Map<(.+),\s*(.+)>$/.exec(text);
|
|
101
|
+
if (map) return { kind: 'map', key: parseTypeExpression(map[1]), value: parseTypeExpression(map[2]) };
|
|
102
|
+
return text;
|
|
103
|
+
}
|
package/examples/todo.frontier
CHANGED
|
@@ -2,4 +2,25 @@ module TodoApp @id("mod_todo") {
|
|
|
2
2
|
entity Todo @id("ent_todo") {
|
|
3
3
|
title @id("field_title"): Text { merge conflict }
|
|
4
4
|
}
|
|
5
|
+
state TodoDb @id("state_todo") {
|
|
6
|
+
todos @id("collection_todos"): Map<TodoId, Todo> { merge byKey law commutative }
|
|
7
|
+
}
|
|
8
|
+
view TodoList @id("view_todo_list") {
|
|
9
|
+
reads TodoDb.todos
|
|
10
|
+
dispatches action_add
|
|
11
|
+
prop disabled @id("view_prop_disabled"): Boolean
|
|
12
|
+
event save @id("view_event_save") action action_add input TodoInput
|
|
13
|
+
render Button @id("render_save_button") {
|
|
14
|
+
identity save
|
|
15
|
+
text "Save"
|
|
16
|
+
prop disabled disabled
|
|
17
|
+
on press save
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
migration TodoV1ToV2 @id("migration_todo_v1_v2") {
|
|
21
|
+
from 1
|
|
22
|
+
to 2
|
|
23
|
+
change addField Todo.title
|
|
24
|
+
invariants title_present
|
|
25
|
+
}
|
|
5
26
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shapeshift-labs/frontier-lang-parser",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Parser for the first Frontier Lang .frontier syntax slice.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"repository": {
|
|
46
46
|
"type": "git",
|
|
47
|
-
"url": "git+
|
|
47
|
+
"url": "git+ssh://git@github.com/siliconjungle/-shapeshift-labs-frontier-lang-parser.git"
|
|
48
48
|
},
|
|
49
49
|
"bugs": {
|
|
50
50
|
"url": "https://github.com/siliconjungle/-shapeshift-labs-frontier-lang-parser/issues"
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@shapeshift-labs/frontier-lang-kernel": "0.3.
|
|
57
|
+
"@shapeshift-labs/frontier-lang-kernel": "0.3.12"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"typescript": "^5.9.3"
|