@shapeshift-labs/frontier-lang-parser 0.3.75 → 0.3.77

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 CHANGED
@@ -97,6 +97,12 @@ The published Frontier package family is generated from one shared package catal
97
97
  - [`@shapeshift-labs/frontier-documentation`](https://www.npmjs.com/package/@shapeshift-labs/frontier-documentation): Frontier-native documentation manifests, generated documentation books, package/API/source discovery, Vite virtual modules, standalone browser docs shells, inspector bridges, search indexes, and documentation harness evidence for Frontier apps and packages.
98
98
  - [`@shapeshift-labs/frontier-ast-walk`](https://www.npmjs.com/package/@shapeshift-labs/frontier-ast-walk): Dependency-light source graph, import/export/declaration/call analysis, Frontier package-use discovery, and business-logic placement findings for Frontier tools, apps, docs, fuzzers, benchmarks, and agent evidence.
99
99
  - [`@shapeshift-labs/frontier-history`](https://www.npmjs.com/package/@shapeshift-labs/frontier-history): Serializable temporal explanation and causality records for Frontier apps, including field-change explanations, action/workflow/policy/effect/trace/test provenance, audit windows, undo planning, registry/provenance graph output, JSONL replay bundles, and proof hashes.
100
+ - [`@shapeshift-labs/frontier-explain`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain): Renderer-neutral interactive explanation contracts for Frontier apps, including explanation manifests, narrative graphs, figure specs, model/state records, controls, semantic trace and replay records, structure projections, invariants, accessibility metadata, provenance, and evidence/probe contracts.
101
+ - [`@shapeshift-labs/frontier-explain-graph`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain-graph): Graph, grid, tree, table, matrix, and algorithm/data-structure explanation builders for Frontier interactive explanations, including stable projections, worklist/frontier panels, pseudocode links, operation vocabularies, trace fixtures, counters, and invariant witnesses.
102
+ - [`@shapeshift-labs/frontier-explain-sim`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain-sim): Simulation explanation contracts for Frontier interactive explanations, including deterministic clocks, phases, sampled fields, constraint records, particle/advection frames, curve samples, plot materialization records, and replayable simulation evidence without owning domain-specific solvers.
103
+ - [`@shapeshift-labs/frontier-explain-render`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain-render): Renderer-neutral materialization for Frontier explanations, including frame records, mark/layer/label layout records, hit regions, linked representation frames, static fallback frames, coordinate spaces, cameras, and renderer adapter records.
104
+ - [`@shapeshift-labs/frontier-explain-test`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain-test): Reusable test and evidence contracts for Frontier explanations, including deterministic replay checks, figure probes, control replay plans, accessibility expectations, static fallback checks, trace assertions, visual evidence records, and evidence summaries.
105
+ - [`@shapeshift-labs/frontier-explain-author`](https://www.npmjs.com/package/@shapeshift-labs/frontier-explain-author): Serializable authoring contracts for Frontier explanations, including explanation documents, narrative graphs, control presets, citation/provenance records, authoring diagnostics, stale-link checks, gallery records, and publication planning records.
100
106
  - [`@shapeshift-labs/frontier-application`](https://www.npmjs.com/package/@shapeshift-labs/frontier-application): Serializable whole-application graph and impact queries for Frontier apps, including features, owners, packages, routes, views, actions, mutations, state paths, effects, workers, assets, tests, traces, policies, workflows, migrations, benchmarks, registry graph output, feature maps, JSONL bundles, and proof hashes.
101
107
  - [`@shapeshift-labs/frontier-linter`](https://www.npmjs.com/package/@shapeshift-labs/frontier-linter): Serializable Frontier lint rules, diagnostics, fixes, reports, and fast rule execution for package catalogs, registry graphs, application maps, manifests, traces, policies, workflows, workers, assets, tests, benchmarks, and source snippets.
102
108
  - [`@shapeshift-labs/frontier-framework`](https://www.npmjs.com/package/@shapeshift-labs/frontier-framework): High-level app framework package for Frontier applications, including configuration, CLI scaffolding, Vite builds, monorepo layout, TSX route builds, split frontend/backend deploy artifacts, backend-neutral Fetch handler and sync transport contracts, runtime data-source migrations, devtools, harness gates, agent MCP/tool manifests, CI evidence gates, workflow manifests, SARIF/linter output, replay scripts, and evidence manifest output.
@@ -204,6 +210,12 @@ Package source repositories:
204
210
  - [`siliconjungle/-shapeshift-labs-frontier-documentation`](https://github.com/siliconjungle/-shapeshift-labs-frontier-documentation)
205
211
  - [`siliconjungle/-shapeshift-labs-frontier-ast-walk`](https://github.com/siliconjungle/-shapeshift-labs-frontier-ast-walk)
206
212
  - [`siliconjungle/-shapeshift-labs-frontier-history`](https://github.com/siliconjungle/-shapeshift-labs-frontier-history)
213
+ - [`siliconjungle/-shapeshift-labs-frontier-explain`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain)
214
+ - [`siliconjungle/-shapeshift-labs-frontier-explain-graph`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain-graph)
215
+ - [`siliconjungle/-shapeshift-labs-frontier-explain-sim`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain-sim)
216
+ - [`siliconjungle/-shapeshift-labs-frontier-explain-render`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain-render)
217
+ - [`siliconjungle/-shapeshift-labs-frontier-explain-test`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain-test)
218
+ - [`siliconjungle/-shapeshift-labs-frontier-explain-author`](https://github.com/siliconjungle/-shapeshift-labs-frontier-explain-author)
207
219
  - [`siliconjungle/-shapeshift-labs-frontier-application`](https://github.com/siliconjungle/-shapeshift-labs-frontier-application)
208
220
  - [`siliconjungle/-shapeshift-labs-frontier-linter`](https://github.com/siliconjungle/-shapeshift-labs-frontier-linter)
209
221
  - [`siliconjungle/-shapeshift-labs-frontier-framework`](https://github.com/siliconjungle/-shapeshift-labs-frontier-framework)
package/dist/index.d.ts CHANGED
@@ -29,6 +29,14 @@ export interface FrontierSourceChildSyntaxRecord {
29
29
  readonly id?: string;
30
30
  readonly family?: string;
31
31
  readonly role?: string;
32
+ readonly parentRenderId?: string;
33
+ readonly typeSource?: string;
34
+ readonly action?: string;
35
+ readonly value?: string;
36
+ readonly values?: readonly string[];
37
+ readonly expression?: string;
38
+ readonly viewRenderKind?: string;
39
+ readonly optional?: boolean;
32
40
  readonly reason?: string;
33
41
  readonly header: string;
34
42
  readonly startOffset: number;
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { parseDecisionGraphBlock } from './decision-graph.js';
8
8
  import { parseDialectRegistryBlock } from './dialect-registry.js';
9
9
  import { parseGateAdmissionEvidenceBlock } from './gate-admission-evidence.js';
10
10
  import { parseInterlinguaBlock } from './interlingua.js';
11
+ import { parseMachineGraphBlock } from './machine-graph.js';
11
12
  import { createParsedMetadata } from './metadata.js';
12
13
  import { parseEntityBlock, parseStateBlock, readTypeFields } from './member-records.js';
13
14
  import { parseSemanticEditRecordsBlock } from './semantic-edit-records.js';
@@ -38,7 +39,7 @@ export function parseFrontierSource(source, options = {}) {
38
39
  const gateAdmissionEvidenceBlocks = [];
39
40
  const dialectRegistryBlocks = [];
40
41
  const interlinguaBlocks = [];
41
- const resourceGraphBlocks = [];
42
+ const resourceGraphBlocks = [], machineGraphBlocks = [];
42
43
  const nativeSourceBlocks = [];
43
44
  const packageManifestBlocks = [];
44
45
  const canvasSurfaceBlocks = [];
@@ -74,12 +75,13 @@ export function parseFrontierSource(source, options = {}) {
74
75
  if (block.kind === 'dialectRegistry' || block.kind === 'universalDialectRegistry') dialectRegistryBlocks.push(parseDialectRegistryBlock(block));
75
76
  if (block.kind === 'interlingua' || block.kind === 'universalInterlingua') interlinguaBlocks.push(parseInterlinguaBlock(block));
76
77
  if (block.kind === 'resourceGraph' || block.kind === 'semanticResourceGraph') resourceGraphBlocks.push(parseResourceGraphBlock(block));
78
+ if (block.kind === 'machineGraph' || block.kind === 'executionGraph' || block.kind === 'lowLevelGraph') machineGraphBlocks.push(parseMachineGraphBlock(block));
77
79
  if (block.kind === 'packageManifest' || block.kind === 'packageGraph' || block.kind === 'packageSurface') packageManifestBlocks.push(parsePackageManifestBlock(block));
78
80
  if (block.kind === 'canvasSurface' || block.kind === 'canvasGraph') canvasSurfaceBlocks.push(parseCanvasSurfaceBlock(block));
79
81
  if (block.kind === 'applicationSurface' || block.kind === 'appHost' || block.kind === 'plugin' || block.kind === 'pluginSurface' || block.kind === 'pluginContract') applicationSurfaceBlocks.push(parseApplicationSurfaceBlock(block));
80
82
  if (block.kind === 'runtimeCapabilities' || block.kind === 'runtimeCapabilityMatrix' || block.kind === 'runtimeHosts') runtimeCapabilityBlocks.push(parseRuntimeCapabilityBlock(block));
81
83
  }
82
- const metadata = createParsedMetadata({ proofBlocks, paradigmBlocks, operationBlocks, semanticEditBlocks, conversionBlocks, constraintSpaceBlocks, decisionGraphBlocks, gateAdmissionEvidenceBlocks, dialectRegistryBlocks, interlinguaBlocks, resourceGraphBlocks, nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks, targetProjectionTargets });
84
+ const metadata = createParsedMetadata({ proofBlocks, paradigmBlocks, operationBlocks, semanticEditBlocks, conversionBlocks, constraintSpaceBlocks, decisionGraphBlocks, gateAdmissionEvidenceBlocks, dialectRegistryBlocks, interlinguaBlocks, resourceGraphBlocks, machineGraphBlocks, nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks, targetProjectionTargets });
83
85
  return createDocument({ id: documentId, name: documentName, nodes, ...(metadata ? { metadata } : {}) });
84
86
  }
85
87
 
@@ -0,0 +1,66 @@
1
+ export function mergeMachineGraphBlocks(blocks) {
2
+ const graphs = blocks.map((block) => block.graph).filter(Boolean);
3
+ const records = blocks.flatMap((block) => block.records ?? []);
4
+ return {
5
+ id: blocks.length === 1 ? blocks[0].id : 'machineGraphs:source',
6
+ graphs,
7
+ machineGraphs: graphs,
8
+ records,
9
+ graphIds: ids(graphs),
10
+ recordIds: ids(records),
11
+ labelIds: blocks.flatMap((block) => ids(block.graph?.labels)),
12
+ directiveIds: blocks.flatMap((block) => ids(block.graph?.directives)),
13
+ registerIds: blocks.flatMap((block) => ids(block.graph?.registers)),
14
+ flagIds: blocks.flatMap((block) => ids(block.graph?.flags)),
15
+ basicBlockIds: blocks.flatMap((block) => ids(block.graph?.basicBlocks)),
16
+ instructionIds: blocks.flatMap((block) => ids(block.graph?.instructions)),
17
+ operandIds: blocks.flatMap((block) => ids(block.graph?.operands)),
18
+ memoryEffectIds: blocks.flatMap((block) => ids(block.graph?.memoryEffects)),
19
+ controlEdgeIds: blocks.flatMap((block) => ids(block.graph?.controlEdges)),
20
+ branchIds: blocks.flatMap((block) => ids(block.graph?.branches)),
21
+ callIds: blocks.flatMap((block) => ids(block.graph?.calls)),
22
+ returnIds: blocks.flatMap((block) => ids(block.graph?.returns)),
23
+ interruptIds: blocks.flatMap((block) => ids(block.graph?.interrupts)),
24
+ proofObligationIds: blocks.flatMap((block) => ids(block.graph?.proofObligations)),
25
+ proofGapCodes: unique(blocks.flatMap((block) => block.graph?.query?.proofGapCodes ?? [])),
26
+ evidenceIds: unique(blocks.flatMap((block) => block.graph?.query?.evidenceIds ?? [])),
27
+ proofEvidenceIds: unique(blocks.flatMap((block) => block.graph?.query?.proofEvidenceIds ?? [])),
28
+ sourceMapIds: unique(blocks.flatMap((block) => block.graph?.query?.sourceMapIds ?? [])),
29
+ sourceMapMappingIds: unique(blocks.flatMap((block) => block.graph?.query?.sourceMapMappingIds ?? [])),
30
+ conflictKeys: unique(blocks.flatMap((block) => block.graph?.query?.conflictKeys ?? [])),
31
+ summary: summary(blocks, records),
32
+ metadata: { authoredMachineGraphBlockIds: blocks.map((block) => block.id) }
33
+ };
34
+ }
35
+
36
+ function summary(blocks, records) {
37
+ return {
38
+ graphCount: blocks.length,
39
+ recordCount: records.length,
40
+ labelCount: sum(blocks, 'labels'),
41
+ directiveCount: sum(blocks, 'directives'),
42
+ registerCount: sum(blocks, 'registers'),
43
+ flagCount: sum(blocks, 'flags'),
44
+ basicBlockCount: sum(blocks, 'basicBlocks'),
45
+ instructionCount: sum(blocks, 'instructions'),
46
+ operandCount: sum(blocks, 'operands'),
47
+ memoryEffectCount: sum(blocks, 'memoryEffects'),
48
+ controlEdgeCount: sum(blocks, 'controlEdges'),
49
+ branchCount: sum(blocks, 'branches'),
50
+ callCount: sum(blocks, 'calls'),
51
+ returnCount: sum(blocks, 'returns'),
52
+ interruptCount: sum(blocks, 'interrupts'),
53
+ proofObligationCount: sum(blocks, 'proofObligations'),
54
+ proofGapCount: sum(blocks, 'proofGaps'),
55
+ evidenceCount: sum(blocks, 'evidence'),
56
+ memoryEffectsWithoutProof: sum(blocks, 'memoryEffectsWithoutProof'),
57
+ controlEdgesWithoutProof: sum(blocks, 'controlEdgesWithoutProof'),
58
+ branchesWithoutProof: sum(blocks, 'branchesWithoutProof'),
59
+ callsWithoutProof: sum(blocks, 'callsWithoutProof'),
60
+ interruptsWithoutProof: sum(blocks, 'interruptsWithoutProof')
61
+ };
62
+ }
63
+
64
+ function ids(records = []) { return records.map((record) => record?.id).filter(Boolean); }
65
+ function unique(values = []) { return [...new Set(values.filter(Boolean))]; }
66
+ function sum(blocks, key) { return blocks.reduce((total, block) => total + (block.summary?.[key] ?? 0), 0); }
@@ -0,0 +1,307 @@
1
+ import { createRowIdentityTracker } from './row-identity.js';
2
+
3
+ const GROUPS = {
4
+ label: 'labels',
5
+ directive: 'directives',
6
+ register: 'registers',
7
+ flag: 'flags',
8
+ basicBlock: 'basicBlocks',
9
+ instruction: 'instructions',
10
+ operand: 'operands',
11
+ memoryEffect: 'memoryEffects',
12
+ controlEdge: 'controlEdges',
13
+ branch: 'branches',
14
+ call: 'calls',
15
+ return: 'returns',
16
+ interrupt: 'interrupts',
17
+ proofObligation: 'proofObligations',
18
+ proofGap: 'proofGaps',
19
+ evidence: 'evidence'
20
+ };
21
+
22
+ export function parseMachineGraphBlock(block) {
23
+ const name = nameFrom(block.header);
24
+ const rowIdentity = createRowIdentityTracker();
25
+ const graph = {
26
+ kind: 'frontier.lang.machineGraph',
27
+ version: 1,
28
+ id: idFrom(block.header, `machine_graph_${name}`),
29
+ architecture: readLine('architecture', block.body) ?? readLine('arch', block.body),
30
+ dialect: readLine('dialect', block.body),
31
+ sourceLanguage: readLine('sourceLanguage', block.body) ?? readLine('language', block.body),
32
+ sourcePath: readLine('sourcePath', block.body) ?? readLine('path', block.body),
33
+ sourceHash: readLine('sourceHash', block.body),
34
+ status: readLine('status', block.body) ?? 'partial',
35
+ evidenceIds: readListLine('evidence', block.body) ?? readListLine('evidenceIds', block.body) ?? [],
36
+ labels: [],
37
+ directives: [],
38
+ registers: [],
39
+ flags: [],
40
+ basicBlocks: [],
41
+ instructions: [],
42
+ operands: [],
43
+ memoryEffects: [],
44
+ controlEdges: [],
45
+ branches: [],
46
+ calls: [],
47
+ returns: [],
48
+ interrupts: [],
49
+ proofObligations: [],
50
+ proofGaps: [],
51
+ evidence: [],
52
+ parser: { status: 'authored', errors: rowIdentity.errors },
53
+ claims: {
54
+ autoMergeClaim: false,
55
+ semanticEquivalenceClaim: false,
56
+ binaryEquivalenceClaim: false,
57
+ timingEquivalenceClaim: false,
58
+ runtimeEquivalenceClaim: false
59
+ },
60
+ metadata: { name }
61
+ };
62
+
63
+ for (const authoredLine of readAuthoredLines(block)) {
64
+ const line = authoredLine.text;
65
+ if (!line || line.startsWith('#') || isGraphPropertyLine(line)) continue;
66
+ const match = /^([A-Za-z_$][\w$-]*)\s+([A-Za-z_$@./:*+-][\w$./@:*+-]*)(.*)$/.exec(line);
67
+ if (!match) continue;
68
+ const [, rowKind, rowName, rest] = match;
69
+ const normalized = normalizeMachineRowKind(rowKind);
70
+ const record = parseMachineRecord(normalized, rowName, rest, graph, authoredLine);
71
+ const group = GROUPS[normalized];
72
+ if (record && group) rowIdentity.push(graph[group], record, { rowKind, normalizedRowKind: normalized, name: rowName });
73
+ }
74
+
75
+ graph.summary = summarizeMachineGraph(graph);
76
+ graph.status = deriveMachineGraphStatus(graph.status, graph.summary);
77
+ graph.query = {
78
+ labelIds: ids(graph.labels),
79
+ directiveIds: ids(graph.directives),
80
+ registerIds: ids(graph.registers),
81
+ flagIds: ids(graph.flags),
82
+ basicBlockIds: ids(graph.basicBlocks),
83
+ instructionIds: ids(graph.instructions),
84
+ operandIds: ids(graph.operands),
85
+ memoryEffectIds: ids(graph.memoryEffects),
86
+ controlEdgeIds: ids(graph.controlEdges),
87
+ branchIds: ids(graph.branches),
88
+ callIds: ids(graph.calls),
89
+ returnIds: ids(graph.returns),
90
+ interruptIds: ids(graph.interrupts),
91
+ controlFlowEdgeIds: ids([...graph.controlEdges, ...graph.branches, ...graph.calls, ...graph.returns, ...graph.interrupts]),
92
+ proofObligationIds: ids(graph.proofObligations),
93
+ proofGapCodes: unique(graph.proofGaps.map((record) => record.code)),
94
+ evidenceIds: unique([...graph.evidenceIds, ...ids(graph.evidence), ...allMachineRecords(graph).flatMap((record) => record.evidenceIds ?? [])]),
95
+ proofEvidenceIds: unique(allMachineRecords(graph).flatMap((record) => record.proofEvidenceIds ?? [])),
96
+ sourceMapIds: unique(allMachineRecords(graph).flatMap((record) => record.sourceMapIds ?? [])),
97
+ sourceMapMappingIds: unique(allMachineRecords(graph).flatMap((record) => record.sourceMapMappingIds ?? [])),
98
+ conflictKeys: unique(allMachineRecords(graph).map((record) => record.conflictKey)),
99
+ blockerReasonCodes: machineBlockerReasonCodes(graph)
100
+ };
101
+
102
+ return {
103
+ id: graph.id,
104
+ graph,
105
+ records: allMachineRecords(graph),
106
+ summary: {
107
+ graphCount: 1,
108
+ ...graph.summary
109
+ },
110
+ metadata: { name }
111
+ };
112
+ }
113
+
114
+ function parseMachineRecord(kind, name, text, graph, authoredLine = {}) {
115
+ const common = commonRecord(kind, name, text, graph, authoredLine);
116
+ if (kind === 'label') return cleanRecord({ ...common, labelKind: word('kind', text) ?? 'label', address: word('address', text) ?? word('addr', text), symbol: word('symbol', text) ?? name, exported: flag('exported', text) });
117
+ if (kind === 'directive') return cleanRecord({ ...common, directiveKind: word('kind', text) ?? word('directiveKind', text) ?? name, value: quoted('value', text) ?? word('value', text), arguments: list(text, 'argument', 'arguments', 'arg', 'args') });
118
+ if (kind === 'register') return cleanRecord({ ...common, registerName: word('register', text) ?? word('registerName', text) ?? name, registerKind: word('kind', text) ?? word('registerKind', text), widthBits: number('widthBits', text) ?? number('width', text), bank: word('bank', text), aliases: list(text, 'alias', 'aliases'), role: word('role', text) });
119
+ if (kind === 'flag') return cleanRecord({ ...common, flagName: word('flag', text) ?? word('flagName', text) ?? name, flagKind: word('kind', text) ?? word('flagKind', text), bit: number('bit', text), registerId: word('register', text) ?? word('registerId', text) });
120
+ if (kind === 'basicBlock') return cleanRecord({ ...common, blockKind: word('kind', text) ?? word('blockKind', text), entryInstructionId: word('entryInstruction', text) ?? word('entryInstructionId', text), exitInstructionId: word('exitInstruction', text) ?? word('exitInstructionId', text), instructionIds: list(text, 'instruction', 'instructions', 'instructionId', 'instructionIds'), successorIds: list(text, 'successor', 'successors', 'successorId', 'successorIds'), predecessorIds: list(text, 'predecessor', 'predecessors', 'predecessorId', 'predecessorIds'), address: word('address', text) ?? word('addr', text), proofStatus: word('proofStatus', text) ?? word('status', text) });
121
+ if (kind === 'instruction') return cleanRecord({ ...common, mnemonic: word('mnemonic', text) ?? word('op', text) ?? name, opcode: word('opcode', text), instructionKind: word('kind', text) ?? word('instructionKind', text), operationKind: word('operation', text) ?? word('operationKind', text), address: word('address', text) ?? word('addr', text), addressMode: word('addressMode', text) ?? word('mode', text), sizeBytes: number('sizeBytes', text) ?? number('size', text), cycles: number('cycles', text), reads: list(text, 'read', 'reads'), writes: list(text, 'write', 'writes'), flagsRead: list(text, 'flagRead', 'flagsRead'), flagsWritten: list(text, 'flagWrite', 'flagsWritten'), registerIds: list(text, 'register', 'registers', 'registerId', 'registerIds'), memoryEffectIds: list(text, 'memoryEffect', 'memoryEffects', 'memoryEffectId', 'memoryEffectIds'), controlFlow: word('controlFlow', text), branchTarget: word('branchTarget', text), callTarget: word('callTarget', text), proofStatus: word('proofStatus', text) ?? word('status', text), semanticEquivalenceClaim: false, binaryEquivalenceClaim: false, timingEquivalenceClaim: false });
122
+ if (kind === 'operand') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), operandIndex: number('index', text) ?? number('operandIndex', text), operandKind: word('kind', text) ?? word('operandKind', text), value: quoted('value', text) ?? word('value', text), registerIds: list(text, 'register', 'registers', 'registerId', 'registerIds'), memoryReference: quoted('memoryReference', text) ?? word('memoryReference', text) ?? word('memory', text), address: word('address', text) ?? word('addr', text), addressMode: word('addressMode', text) ?? word('mode', text), immediate: word('immediate', text), widthBits: number('widthBits', text) ?? number('width', text) });
123
+ if (kind === 'memoryEffect') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), resourceId: word('resource', text) ?? word('resourceId', text), memoryKind: word('memoryKind', text), effectKind: word('effectKind', text) ?? word('kind', text) ?? name, address: word('address', text) ?? word('addr', text), addressSpace: word('addressSpace', text) ?? word('space', text), widthBits: number('widthBits', text) ?? number('width', text), memoryOrder: word('memoryOrder', text) ?? word('ordering', text), reads: list(text, 'read', 'reads'), writes: list(text, 'write', 'writes'), bank: word('bank', text), volatile: flag('volatile', text), atomic: flag('atomic', text), io: flag('io', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
124
+ if (kind === 'controlEdge') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), fromInstructionId: word('fromInstruction', text) ?? word('fromInstructionId', text) ?? word('from', text), toInstructionId: word('toInstruction', text) ?? word('toInstructionId', text) ?? word('to', text), fromBlockId: word('fromBlock', text) ?? word('fromBlockId', text), toBlockId: word('toBlock', text) ?? word('toBlockId', text), targetId: word('target', text) ?? word('targetId', text), edgeKind: word('edgeKind', text) ?? word('kind', text) ?? name, condition: quoted('condition', text) ?? word('condition', text), flagIds: list(text, 'flag', 'flags', 'flagId', 'flagIds', 'conditionFlag', 'conditionFlags'), callTarget: word('callTarget', text), returnTarget: word('returnTarget', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
125
+ if (kind === 'branch') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), fromInstructionId: word('fromInstruction', text) ?? word('fromInstructionId', text) ?? word('from', text), toInstructionId: word('toInstruction', text) ?? word('toInstructionId', text), targetId: word('target', text) ?? word('targetId', text) ?? word('to', text), branchKind: word('kind', text) ?? word('branchKind', text), condition: quoted('condition', text) ?? word('condition', text), flagIds: list(text, 'flag', 'flags', 'flagId', 'flagIds'), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
126
+ if (kind === 'call') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), targetId: word('target', text) ?? word('targetId', text), callableId: word('callable', text) ?? word('callableId', text), callingConvention: word('callingConvention', text) ?? word('convention', text), stackEffect: word('stackEffect', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
127
+ if (kind === 'return') return cleanRecord({ ...common, instructionId: word('instruction', text) ?? word('instructionId', text), fromCallableId: word('fromCallable', text) ?? word('fromCallableId', text) ?? word('from', text), stackEffect: word('stackEffect', text), proofStatus: word('proofStatus', text) ?? word('status', text) });
128
+ if (kind === 'interrupt') return cleanRecord({ ...common, vector: word('vector', text), handlerId: word('handler', text) ?? word('handlerId', text), interruptKind: word('kind', text) ?? word('interruptKind', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
129
+ if (kind === 'proofObligation') return cleanRecord({ ...common, subjectId: word('subject', text) ?? word('subjectId', text), subjectKind: word('subjectKind', text), obligationKind: word('obligationKind', text) ?? word('kind', text) ?? name, status: word('status', text) ?? 'missing', statement: quoted('statement', text) ?? quoted('summary', text), evidenceIds: list(text, 'evidence', 'evidenceIds') ?? common.evidenceIds, missingEvidence: list(text, 'missingEvidence') ?? common.missingEvidence, semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
130
+ if (kind === 'proofGap') return cleanRecord({ ...common, code: word('code', text) ?? word('reasonCode', text) ?? name, status: word('status', text) ?? 'missing', summary: quoted('summary', text) ?? quoted('message', text), failClosed: common.failClosed ?? true, semanticEquivalenceClaim: false, binaryEquivalenceClaim: false, timingEquivalenceClaim: false, runtimeEquivalenceClaim: false });
131
+ if (kind === 'evidence') return cleanRecord({ ...common, evidenceKind: word('kind', text) ?? word('evidenceKind', text), status: word('status', text) ?? 'unknown', path: word('path', text), command: quoted('command', text) ?? word('command', text), sourceHash: word('sourceHash', text), traceHash: word('traceHash', text), binaryHash: word('binaryHash', text) });
132
+ return undefined;
133
+ }
134
+
135
+ function commonRecord(kind, name, text, graph, authoredLine = {}) {
136
+ return cleanRecord({
137
+ recordKind: recordKind(kind),
138
+ id: idFrom(text, `${recordPrefix(kind)}_${name}`),
139
+ name,
140
+ sourcePath: word('sourcePath', text) ?? word('path', text) ?? graph.sourcePath,
141
+ sourceHash: word('sourceHash', text) ?? graph.sourceHash,
142
+ sourceSpan: authoredLine.sourceSpan,
143
+ authoredSourceSpan: authoredLine.sourceSpan,
144
+ evidenceIds: list(text, 'evidence', 'evidenceIds') ?? graph.evidenceIds,
145
+ proofEvidenceIds: list(text, 'proofEvidence', 'proofEvidenceId', 'proofEvidenceIds'),
146
+ proofObligationIds: list(text, 'proofObligation', 'proofObligations', 'proofObligationId', 'proofObligationIds', 'obligation', 'obligations'),
147
+ missingEvidence: list(text, 'missingEvidence'),
148
+ sourceMapIds: list(text, 'sourceMap', 'sourceMaps', 'sourceMapId', 'sourceMapIds'),
149
+ sourceMapMappingIds: list(text, 'sourceMapMapping', 'sourceMapMappings', 'sourceMapMappingId', 'sourceMapMappingIds'),
150
+ semanticNodeId: word('semanticNode', text) ?? word('semanticNodeId', text),
151
+ semanticSymbolId: word('semanticSymbol', text) ?? word('semanticSymbolId', text),
152
+ conflictKey: word('conflictKey', text),
153
+ reasonCode: word('reasonCode', text) ?? word('code', text),
154
+ failClosed: flag('failClosed', text),
155
+ metadata: { authoredName: name }
156
+ });
157
+ }
158
+
159
+ function summarizeMachineGraph(graph) {
160
+ return {
161
+ records: allMachineRecords(graph).length,
162
+ labels: graph.labels.length,
163
+ directives: graph.directives.length,
164
+ registers: graph.registers.length,
165
+ flags: graph.flags.length,
166
+ basicBlocks: graph.basicBlocks.length,
167
+ instructions: graph.instructions.length,
168
+ operands: graph.operands.length,
169
+ memoryEffects: graph.memoryEffects.length,
170
+ controlEdges: graph.controlEdges.length,
171
+ branches: graph.branches.length,
172
+ calls: graph.calls.length,
173
+ returns: graph.returns.length,
174
+ interrupts: graph.interrupts.length,
175
+ proofObligations: graph.proofObligations.length,
176
+ proofGaps: graph.proofGaps.length,
177
+ evidence: graph.evidence.length,
178
+ memoryEffectsWithoutProof: graph.memoryEffects.filter((record) => record.proofStatus !== 'passed').length,
179
+ controlEdgesWithoutProof: graph.controlEdges.filter((record) => record.proofStatus !== 'passed').length,
180
+ branchesWithoutProof: graph.branches.filter((record) => record.proofStatus !== 'passed').length,
181
+ callsWithoutProof: graph.calls.filter((record) => record.proofStatus !== 'passed').length,
182
+ interruptsWithoutProof: graph.interrupts.filter((record) => record.proofStatus !== 'passed').length,
183
+ parseErrors: graph.parser?.errors?.length ?? 0,
184
+ reasonCodes: unique([...unprovedMachineRecords(graph), ...graph.proofGaps].map((record) => record.reasonCode ?? record.code))
185
+ };
186
+ }
187
+
188
+ function deriveMachineGraphStatus(authoredStatus, summary) {
189
+ if (
190
+ summary.proofGaps > 0 ||
191
+ summary.memoryEffectsWithoutProof > 0 ||
192
+ summary.controlEdgesWithoutProof > 0 ||
193
+ summary.branchesWithoutProof > 0 ||
194
+ summary.callsWithoutProof > 0 ||
195
+ summary.interruptsWithoutProof > 0
196
+ ) return 'blocked';
197
+ return authoredStatus ?? 'partial';
198
+ }
199
+
200
+ function machineBlockerReasonCodes(graph) {
201
+ return unique([...unprovedMachineRecords(graph), ...graph.proofGaps].map((record) => record.reasonCode ?? record.code));
202
+ }
203
+
204
+ function unprovedMachineRecords(graph) {
205
+ return [
206
+ ...graph.memoryEffects,
207
+ ...graph.controlEdges,
208
+ ...graph.branches,
209
+ ...graph.calls,
210
+ ...graph.interrupts
211
+ ].filter((record) => record.proofStatus !== 'passed');
212
+ }
213
+
214
+ function allMachineRecords(graph) {
215
+ return [
216
+ ...graph.labels,
217
+ ...graph.directives,
218
+ ...graph.registers,
219
+ ...graph.flags,
220
+ ...graph.basicBlocks,
221
+ ...graph.instructions,
222
+ ...graph.operands,
223
+ ...graph.memoryEffects,
224
+ ...graph.controlEdges,
225
+ ...graph.branches,
226
+ ...graph.calls,
227
+ ...graph.returns,
228
+ ...graph.interrupts,
229
+ ...graph.proofObligations,
230
+ ...graph.proofGaps,
231
+ ...graph.evidence
232
+ ];
233
+ }
234
+
235
+ export function normalizeMachineRowKind(kind) {
236
+ if (kind === 'reg') return 'register';
237
+ if (kind === 'block') return 'basicBlock';
238
+ if (kind === 'inst' || kind === 'instr' || kind === 'op' || kind === 'opcode') return 'instruction';
239
+ if (kind === 'arg') return 'operand';
240
+ if (kind === 'mem' || kind === 'memory' || kind === 'memoryAccess' || kind === 'effect' || kind === 'load' || kind === 'store' || kind === 'atomic' || kind === 'fence' || kind === 'memoryEffect') return 'memoryEffect';
241
+ if (kind === 'edge') return 'controlEdge';
242
+ if (kind === 'ret') return 'return';
243
+ if (kind === 'irq' || kind === 'exception') return 'interrupt';
244
+ if (kind === 'proof' || kind === 'obligation') return 'proofObligation';
245
+ if (kind === 'gap' || kind === 'proofGap') return 'proofGap';
246
+ if (kind === 'proofEvidence') return 'evidence';
247
+ return kind;
248
+ }
249
+
250
+ function recordKind(kind) {
251
+ if (kind === 'memoryEffect') return 'memory-effect';
252
+ if (kind === 'proofGap') return 'proof-gap';
253
+ return kind;
254
+ }
255
+
256
+ function recordPrefix(kind) {
257
+ return recordKind(kind).replace(/-/g, '_');
258
+ }
259
+
260
+ function isGraphPropertyLine(line) {
261
+ const property = /^(architecture|arch|dialect|sourceLanguage|language|sourcePath|path|sourceHash|status|evidence|evidenceIds)\s+/.exec(line)?.[1];
262
+ if (!property) return false;
263
+ if ((property === 'evidence' || property === 'evidenceIds') && /@id\(/.test(line)) return false;
264
+ return true;
265
+ }
266
+
267
+ function idFrom(text, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(text)?.[1] ?? fallback; }
268
+ function nameFrom(header) { return /^([A-Za-z_$][\w$]*)/.exec(header)?.[1] ?? 'MachineGraph'; }
269
+ function readLine(label, body) { return new RegExp('^\\s*' + label + '\\s+([^\\n]+)', 'm').exec(body)?.[1]?.trim(); }
270
+ function readListLine(label, body) {
271
+ const line = readLine(label, body);
272
+ return line ? line.split(/[|,]/).map((item) => item.trim()).filter(Boolean) : undefined;
273
+ }
274
+ function word(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
275
+ function quoted(label, text) { return new RegExp("(?:^|\\s)" + label + "\\s+[\"']([^\"']+)[\"']").exec(text)?.[1]?.trim(); }
276
+ function flag(label, text) { return new RegExp('(?:^|\\s)' + label + '(?:\\s|$)').test(text) || undefined; }
277
+ function number(label, text) {
278
+ const value = word(label, text);
279
+ return value === undefined ? undefined : Number(value);
280
+ }
281
+ function list(text, ...labels) {
282
+ for (const label of labels) {
283
+ const value = new RegExp('(?:^|\\s)' + label + '\\s+([^\\s]+)').exec(text)?.[1]?.trim();
284
+ if (value) return value.split(/[|,]/).map((item) => item.trim()).filter(Boolean);
285
+ }
286
+ return undefined;
287
+ }
288
+ function ids(records = []) { return records.map((record) => record?.id).filter(Boolean); }
289
+ function unique(values = []) { return [...new Set(values.filter(Boolean))]; }
290
+ function readAuthoredLines(block) {
291
+ const lines = block.body.split('\n');
292
+ const records = [];
293
+ let lineStart = block.syntax?.bodyStartOffset ?? 0;
294
+ for (const rawLine of lines) {
295
+ const rawEnd = lineStart + rawLine.length;
296
+ const leading = /^\s*/.exec(rawLine)?.[0].length ?? 0;
297
+ const trailing = /\s*$/.exec(rawLine)?.[0].length ?? 0;
298
+ const startOffset = lineStart + leading;
299
+ const endOffset = Math.max(startOffset, rawEnd - trailing);
300
+ records.push({ text: rawLine.trim(), sourceSpan: typeof block.sourceSpan === 'function' ? block.sourceSpan(startOffset, endOffset) : undefined });
301
+ lineStart = rawEnd + 1;
302
+ }
303
+ return records;
304
+ }
305
+ function cleanRecord(record) {
306
+ return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0)));
307
+ }
package/dist/metadata.js CHANGED
@@ -5,7 +5,7 @@ import { mergeTargetProjectionTargets } from './target-projection-aggregate.js';
5
5
  import { mergeConversionBlocks } from './conversion-metadata.js';
6
6
  import { mergeSemanticEditBlocks } from './semantic-edit-metadata.js';
7
7
  import { mergeGateAdmissionEvidenceBlocks } from './gate-admission-evidence.js';
8
-
8
+ import { mergeMachineGraphBlocks } from './machine-graph-metadata.js';
9
9
  const PROOF_GROUPS = ['contracts', 'refinements', 'invariants', 'termination', 'temporal', 'obligations', 'artifacts', 'assumptions'];
10
10
  const PARADIGM_GROUPS = [
11
11
  'bindingScopes', 'bindings', 'patterns', 'typeConstraints', 'evaluationModels', 'memoryLocations', 'effectRegions',
@@ -13,7 +13,7 @@ const PARADIGM_GROUPS = [
13
13
  'clockModels', 'objectModels', 'macroExpansions', 'reflectionBoundaries', 'loweringRecords'
14
14
  ];
15
15
 
16
- export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], operationBlocks = [], semanticEditBlocks = [], conversionBlocks = [], constraintSpaceBlocks = [], decisionGraphBlocks = [], gateAdmissionEvidenceBlocks = [], dialectRegistryBlocks = [], interlinguaBlocks = [], resourceGraphBlocks = [], nativeSourceBlocks = [], packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = [], targetProjectionTargets = [] } = {}) {
16
+ export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], operationBlocks = [], semanticEditBlocks = [], conversionBlocks = [], constraintSpaceBlocks = [], decisionGraphBlocks = [], gateAdmissionEvidenceBlocks = [], dialectRegistryBlocks = [], interlinguaBlocks = [], resourceGraphBlocks = [], machineGraphBlocks = [], nativeSourceBlocks = [], packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = [], targetProjectionTargets = [] } = {}) {
17
17
  const metadata = {};
18
18
  if (proofBlocks.length) metadata.proof = mergeProofBlocks(proofBlocks);
19
19
  if (paradigmBlocks.length) metadata.paradigmSemantics = mergeParadigmBlocks(paradigmBlocks);
@@ -26,6 +26,7 @@ export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], op
26
26
  if (dialectRegistryBlocks.length) metadata.dialects = mergeDialectRegistryBlocks(dialectRegistryBlocks);
27
27
  if (interlinguaBlocks.length) metadata.universalInterlingua = mergeInterlinguaBlocks(interlinguaBlocks);
28
28
  if (resourceGraphBlocks.length) metadata.semanticResourceGraphs = mergeResourceGraphBlocks(resourceGraphBlocks);
29
+ if (machineGraphBlocks.length) metadata.machineGraphs = mergeMachineGraphBlocks(machineGraphBlocks);
29
30
  if (packageManifestBlocks.length) metadata.packageManifests = mergePackageManifestBlocks(packageManifestBlocks);
30
31
  if (canvasSurfaceBlocks.length) metadata.canvasSurfaces = mergeCanvasSurfaceBlocks(canvasSurfaceBlocks);
31
32
  if (applicationSurfaceBlocks.length) metadata.applicationSurfaces = mergeApplicationSurfaceBlocks(applicationSurfaceBlocks);
@@ -33,6 +33,9 @@ export const FrontierSourceBlockKinds = Object.freeze([
33
33
  'universalInterlingua',
34
34
  'resourceGraph',
35
35
  'semanticResourceGraph',
36
+ 'machineGraph',
37
+ 'executionGraph',
38
+ 'lowLevelGraph',
36
39
  'packageManifest',
37
40
  'packageGraph',
38
41
  'packageSurface',
@@ -1,9 +1,9 @@
1
1
  import { readActionSyntaxChildren } from './action-syntax-children.js';
2
2
  import { ROW_SYNTAX_CONFIG } from './source-syntax-row-config.js';
3
3
  import { readTypeExpressionSyntaxChildren } from './source-syntax-type-expressions.js';
4
+ import { readViewSyntaxChildren } from './source-syntax-view-children.js';
4
5
  import { inspectTypeExpressionSyntax } from './type-expressions.js';
5
6
  import { inspectVariantPayload } from './type-variants.js';
6
-
7
7
  const ROW_NAME_PATTERN = '([A-Za-z_$@./:*+-][\\w$./@:*+-]*)';
8
8
 
9
9
  export function readSourceSyntaxChildren(source, block, options = {}) {
@@ -31,6 +31,8 @@ export function readSourceSyntaxChildren(source, block, options = {}) {
31
31
  duplicateNameReason: 'duplicate-state-collection-name',
32
32
  duplicateIdReason: 'duplicate-state-collection-id'
33
33
  });
34
+ } else if (block.kind === 'view') {
35
+ children = readViewSyntaxChildren(source, block, options);
34
36
  } else {
35
37
  const rowConfig = ROW_SYNTAX_CONFIG[block.kind];
36
38
  if (rowConfig) children = readGenericRowSyntaxChildren(source, block, options, rowConfig);
@@ -227,9 +229,9 @@ function readGenericRowSyntaxChildren(source, block, options, config) {
227
229
  for (const line of readBodyLines(source, block)) {
228
230
  if (!line.text || line.text.startsWith('#')) continue;
229
231
  const row = rowPattern.exec(line.text);
230
- if (!row) { if (config.childKind === 'gateAdmissionEvidenceRow') children.push(genericUnknownRowChild(source, block, options, line, config, undefined, undefined, 'unsupported-gate-admission-row')); continue; }
232
+ if (!row) { if (unknownGenericRowsFailClosed(config)) children.push(genericUnknownRowChild(source, block, options, line, config, undefined, undefined, unsupportedGenericRowReason(config))); continue; }
231
233
  const [, rowKind, name, rest] = row;
232
- if (!config.rowKinds.has(rowKind)) { if (config.childKind === 'gateAdmissionEvidenceRow') children.push(genericUnknownRowChild(source, block, options, line, config, rowKind, name, 'unsupported-gate-admission-row')); continue; }
234
+ if (!config.rowKinds.has(rowKind)) { if (unknownGenericRowsFailClosed(config)) children.push(genericUnknownRowChild(source, block, options, line, config, rowKind, name, unsupportedGenericRowReason(config))); continue; }
233
235
  const normalizedRowKind = config.normalize?.(rowKind) ?? rowKind;
234
236
  const id = idFrom(rest, `${config.idPrefix}_${safeId(normalizedRowKind)}_${safeId(name)}`);
235
237
  let recognized = true;
@@ -268,13 +270,16 @@ function genericUnknownRowChild(source, block, options, line, config, rowKind, n
268
270
  const resolvedName = name ?? rowKind ?? 'unknown';
269
271
  return cleanRecord({
270
272
  kind: config.childKind === 'gateAdmissionEvidenceRow' ? 'gateAdmissionUnknownRow' : 'genericUnknownRow', rowKind,
271
- normalizedRowKind: 'unknown', name: resolvedName, id: `gate_admission_unknown_${safeId(rowKind ?? 'row')}_${line.startOffset}`,
273
+ normalizedRowKind: 'unknown', name: resolvedName, id: `${config.idPrefix}_unknown_${safeId(rowKind ?? 'row')}_${line.startOffset}`,
272
274
  header: line.text, startOffset: line.startOffset, endOffset: line.endOffset, location: sourcePosition(source, line.startOffset),
273
275
  parentKind: block.kind, parentId: block.id, parentName: block.name, moduleId: block.moduleId, moduleName: block.moduleName,
274
276
  sourceSpan: sourceSpan(source, block, line.startOffset, line.endOffset, options), recognized: false, reason
275
277
  });
276
278
  }
277
279
 
280
+ function unknownGenericRowsFailClosed(config) { return config.childKind === 'gateAdmissionEvidenceRow' || config.childKind === 'machineGraphRow'; }
281
+ function unsupportedGenericRowReason(config) { return config.childKind === 'machineGraphRow' ? 'unsupported-machine-graph-row' : 'unsupported-gate-admission-row'; }
282
+
278
283
  function readBodyLines(source, block) { return readTextLines(source, block.bodyStartOffset, block.bodyEndOffset); }
279
284
 
280
285
  function readTextLines(source, startOffset, endOffset) {
@@ -294,10 +299,7 @@ function readTextLines(source, startOffset, endOffset) {
294
299
  return records;
295
300
  }
296
301
 
297
- function sourcePosition(source, offset) {
298
- const lines = source.slice(0, offset).split('\n');
299
- return { line: lines.length, column: lines[lines.length - 1].length + 1, offset };
300
- }
302
+ function sourcePosition(source, offset) { const lines = source.slice(0, offset).split('\n'); return { line: lines.length, column: lines[lines.length - 1].length + 1, offset }; }
301
303
 
302
304
  function sourceSpan(source, block, startOffset, endOffset, options = {}) {
303
305
  return cleanRecord({
@@ -315,6 +317,4 @@ function sourceSpan(source, block, startOffset, endOffset, options = {}) {
315
317
  function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
316
318
  function readInlineWord(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
317
319
  function safeId(value) { return String(value).replace(/[^A-Za-z0-9_$-]+/g, '_').replace(/^_+|_+$/g, '') || 'row'; }
318
- function cleanRecord(record) {
319
- return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0)));
320
- }
320
+ function cleanRecord(record) { return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))); }
@@ -3,6 +3,7 @@ const canvasRows = words('element command state stateWrite trace gap proofGap ev
3
3
  const constraintRows = words('variable var constraint hard soft preference prefer collapse admission');
4
4
  const dialectRows = words('dialect record extern');
5
5
  const interlinguaRows = words('layer constraint edge obligation proofObligation proof lowering lower source sourceLift lift evidence');
6
+ const machineRows = words('label directive register reg flag conditionFlag basicBlock block instruction inst instr op opcode operand arg memoryEffect memoryAccess load store atomic fence memory mem effect controlEdge edge branch call return ret interrupt irq exception proof proofObligation obligation gap proofGap evidence proofEvidence');
6
7
  const packageRows = words('metadata dependency script export gap proofGap evidence proofEvidence');
7
8
  const runtimeRows = words('host runtimeHost hostProfile sourceHost targetHost capability hostCapability hostBinding binding requirement runtimeRequirement requiredRuntime evidence proofEvidence gap proofGap');
8
9
  const semanticEditRows = words('script semanticEditScript projection semanticEditProjection replay semanticEditReplay');
@@ -18,6 +19,9 @@ export const ROW_SYNTAX_CONFIG = Object.freeze({
18
19
  runtimeHosts: rowConfig('runtimeCapabilityRow', 'runtime_capability_row', runtimeRows, normalizeRuntimeCapabilityRow),
19
20
  resourceGraph: rowConfig('resourceGraphRow', 'resource_graph_row', words('resource owner loan alias move drop escape lifetime lifetimeRegion life outlives lifetimeRelation lifeRelation borrow borrowScope borrowRegion unsafe unsafeBoundary memory memoryRegion region layout dataLayout pointer ptr address access memoryAccess atomic volatile abi abiBoundary callBoundary sync synchronization synchronisation synchronizationEdge synchronisationEdge happensBefore hb fence fenceEdge barrier barrierEdge trap traps undefined undefinedBehavior undefinedBehaviour ub conflict proof proofObligation obligation'), normalizeResourceGraphRow),
20
21
  semanticResourceGraph: rowConfig('resourceGraphRow', 'resource_graph_row', words('resource owner loan alias move drop escape lifetime lifetimeRegion life outlives lifetimeRelation lifeRelation borrow borrowScope borrowRegion unsafe unsafeBoundary memory memoryRegion region layout dataLayout pointer ptr address access memoryAccess atomic volatile abi abiBoundary callBoundary sync synchronization synchronisation synchronizationEdge synchronisationEdge happensBefore hb fence fenceEdge barrier barrierEdge trap traps undefined undefinedBehavior undefinedBehaviour ub conflict proof proofObligation obligation'), normalizeResourceGraphRow),
22
+ machineGraph: rowConfig('machineGraphRow', 'machine_graph_row', machineRows, normalizeMachineGraphRow),
23
+ executionGraph: rowConfig('machineGraphRow', 'machine_graph_row', machineRows, normalizeMachineGraphRow),
24
+ lowLevelGraph: rowConfig('machineGraphRow', 'machine_graph_row', machineRows, normalizeMachineGraphRow),
21
25
  applicationSurface: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
22
26
  appHost: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
23
27
  plugin: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
@@ -91,6 +95,22 @@ function normalizeResourceGraphRow(rowKind) {
91
95
  return rowKind;
92
96
  }
93
97
 
98
+ function normalizeMachineGraphRow(rowKind) {
99
+ if (rowKind === 'reg') return 'register';
100
+ if (rowKind === 'conditionFlag') return 'flag';
101
+ if (rowKind === 'block') return 'basicBlock';
102
+ if (rowKind === 'inst' || rowKind === 'instr' || rowKind === 'op' || rowKind === 'opcode') return 'instruction';
103
+ if (rowKind === 'arg') return 'operand';
104
+ if (rowKind === 'memory' || rowKind === 'mem' || rowKind === 'memoryAccess' || rowKind === 'effect' || rowKind === 'load' || rowKind === 'store' || rowKind === 'atomic' || rowKind === 'fence') return 'memoryEffect';
105
+ if (rowKind === 'edge') return 'controlEdge';
106
+ if (rowKind === 'ret') return 'return';
107
+ if (rowKind === 'irq' || rowKind === 'exception') return 'interrupt';
108
+ if (rowKind === 'proof' || rowKind === 'obligation') return 'proofObligation';
109
+ if (rowKind === 'gap') return 'proofGap';
110
+ if (rowKind === 'proofEvidence') return 'evidence';
111
+ return rowKind;
112
+ }
113
+
94
114
  function normalizeApplicationSurfaceRow(rowKind) {
95
115
  if (rowKind === 'provide' || rowKind === 'provides') return 'provided-surface';
96
116
  if (rowKind === 'required' || rowKind === 'requires' || rowKind === 'require') return 'required-capability';
@@ -0,0 +1,152 @@
1
+ export function readViewSyntaxChildren(source, block, options = {}) {
2
+ const children = [];
3
+ const ranges = readRenderRanges(source.slice(block.bodyStartOffset, block.bodyEndOffset), block.bodyStartOffset);
4
+ for (const line of readBodyLines(source, block.bodyStartOffset, block.bodyEndOffset)) {
5
+ if (!line.text || line.text.startsWith('#') || inRange(line.startOffset, ranges)) continue;
6
+ const child = viewRowChild(source, block, options, line);
7
+ children.push(child ?? unknownViewChild(source, block, options, line, 'unsupported-view-row'));
8
+ }
9
+ for (const range of ranges) {
10
+ children.push(renderHeaderChild(source, block, options, range));
11
+ const nested = ranges.filter((candidate) => candidate.parentRenderId === range.id);
12
+ for (const line of readBodyLines(source, range.bodyStartOffset, range.bodyEndOffset)) {
13
+ if (!line.text || line.text.startsWith('#') || inRange(line.startOffset, nested)) continue;
14
+ const child = renderRowChild(source, block, options, line, range);
15
+ children.push(child ?? unknownViewChild(source, block, options, line, 'unsupported-view-render-row', range.id));
16
+ }
17
+ }
18
+ return children;
19
+ }
20
+
21
+ function viewRowChild(source, block, options, line) {
22
+ const reads = /^(reads?)\s+(.+)$/.exec(line.text);
23
+ if (reads) return childRecord(source, block, options, line, { kind: 'viewRead', rowKind: reads[1], name: reads[2].trim(), id: `view_read_${safeId(block.name)}_${line.startOffset}`, values: readList(reads[2]) });
24
+ const dispatch = /^(dispatch(?:es)?)\s+(.+)$/.exec(line.text);
25
+ if (dispatch) return childRecord(source, block, options, line, { kind: 'viewDispatch', rowKind: dispatch[1], name: dispatch[2].trim(), id: `view_dispatch_${safeId(block.name)}_${line.startOffset}`, values: readList(dispatch[2]) });
26
+ const prop = /^prop\s+([A-Za-z_$][\w$.-]*)(?:\s+@id\(\s*["']([^"']+)["']\s*\))?\s*:\s*(.+)$/.exec(line.text);
27
+ if (prop) return childRecord(source, block, options, line, { kind: 'viewProp', rowKind: 'prop', name: prop[1], id: prop[2] ?? `view_prop_${prop[1]}`, typeSource: prop[3].replace(/\s+optional\s*$/, '').trim(), optional: /\soptional\s*$/.test(prop[3]) || undefined });
28
+ const event = /^event\s+([A-Za-z_$][\w$.-]*)(?:\s+@id\(\s*["']([^"']+)["']\s*\))?(.*)$/.exec(line.text);
29
+ if (event) return childRecord(source, block, options, line, { kind: 'viewEvent', rowKind: 'event', name: event[1], id: event[2] ?? `view_event_${event[1]}`, action: readInlineWord('action', event[3]), typeSource: readInlineType('input', event[3]) });
30
+ return undefined;
31
+ }
32
+
33
+ function renderHeaderChild(source, block, options, range) {
34
+ return childRecord(source, block, options, range, {
35
+ kind: 'viewRender',
36
+ rowKind: 'render',
37
+ name: range.name,
38
+ id: range.id,
39
+ viewRenderKind: readInlineWord('kind', range.header) ?? 'element',
40
+ parentRenderId: range.parentRenderId
41
+ });
42
+ }
43
+
44
+ function renderRowChild(source, block, options, line, range) {
45
+ const identity = /^(identity|key)\s+(.+)$/.exec(line.text);
46
+ if (identity) return childRecord(source, block, options, line, { kind: 'viewRenderIdentity', rowKind: identity[1], name: identity[2].trim(), id: `${range.id}_${identity[1]}`, value: identity[2].trim(), parentRenderId: range.id });
47
+ const text = /^text\s+(.+)$/.exec(line.text);
48
+ if (text) return childRecord(source, block, options, line, { kind: 'viewRenderText', rowKind: 'text', name: 'text', id: `${range.id}_text`, ...readRenderValue(text[1]), parentRenderId: range.id });
49
+ const attr = /^(component|tag|tagName|kind)\s+(.+)$/.exec(line.text);
50
+ if (attr) return childRecord(source, block, options, line, { kind: 'viewRenderAttribute', rowKind: attr[1], name: attr[1], id: `${range.id}_${safeId(attr[1])}`, value: attr[2].trim(), parentRenderId: range.id });
51
+ const prop = /^prop\s+([A-Za-z_$][\w$.-]*)\s+(.+)$/.exec(line.text);
52
+ if (prop) return childRecord(source, block, options, line, { kind: 'viewRenderProp', rowKind: 'prop', name: prop[1], id: `${range.id}_prop_${safeId(prop[1])}`, ...readRenderValue(prop[2]), parentRenderId: range.id });
53
+ const event = /^on\s+([A-Za-z_$][\w$.-]*)\s+([A-Za-z_$][\w$.-]*)/.exec(line.text);
54
+ if (event) return childRecord(source, block, options, line, { kind: 'viewRenderEvent', rowKind: 'on', name: event[1], id: `${range.id}_on_${safeId(event[1])}`, action: event[2], parentRenderId: range.id });
55
+ const child = /^(children?|child)\s+(.+)$/.exec(line.text);
56
+ if (child) return childRecord(source, block, options, line, { kind: 'viewRenderChildren', rowKind: child[1], name: 'children', id: `${range.id}_children`, values: readList(child[2]), parentRenderId: range.id });
57
+ return undefined;
58
+ }
59
+
60
+ function readRenderRanges(body, baseOffset, parentRenderId) {
61
+ const ranges = [];
62
+ for (const range of readTopLevelRenderRanges(body, baseOffset, parentRenderId)) {
63
+ ranges.push(range, ...readRenderRanges(body.slice(range.bodyStartOffset - baseOffset, range.bodyEndOffset - baseOffset), range.bodyStartOffset, range.id));
64
+ }
65
+ return ranges;
66
+ }
67
+
68
+ function readTopLevelRenderRanges(body, baseOffset, parentRenderId) {
69
+ const structure = scanStructure(body), ranges = [];
70
+ const header = /(^|\n)\s*render\s+([^{}\n]+)\{/g;
71
+ let match;
72
+ while ((match = header.exec(body))) {
73
+ const start = match.index + match[1].length + (/^\s*/.exec(body.slice(match.index + match[1].length))?.[0].length ?? 0);
74
+ const open = header.lastIndex - 1;
75
+ if (!structure.codeOffsets[start] || !structure.codeOffsets[open] || structure.depthBefore[start] !== 0) continue;
76
+ const close = structure.bracePairs.get(open);
77
+ if (close === undefined) continue;
78
+ const headerText = (match[2] ?? '').trim(), name = nameFrom(headerText);
79
+ ranges.push({ header: headerText, name, id: idFrom(headerText, `render_${name}`), startOffset: baseOffset + start, endOffset: baseOffset + close + 1, bodyStartOffset: baseOffset + open + 1, bodyEndOffset: baseOffset + close, parentRenderId });
80
+ header.lastIndex = close + 1;
81
+ }
82
+ return ranges;
83
+ }
84
+
85
+ function childRecord(source, block, options, line, input) {
86
+ return cleanRecord({
87
+ ...input,
88
+ normalizedRowKind: input.normalizedRowKind ?? input.rowKind,
89
+ header: line.header ?? line.text ?? source.slice(line.startOffset, line.endOffset).trim(),
90
+ startOffset: line.startOffset,
91
+ endOffset: line.endOffset,
92
+ location: sourcePosition(source, line.startOffset),
93
+ parentKind: block.kind,
94
+ parentId: block.id,
95
+ parentName: block.name,
96
+ moduleId: block.moduleId,
97
+ moduleName: block.moduleName,
98
+ sourceSpan: sourceSpan(source, block, line.startOffset, line.endOffset, options),
99
+ recognized: input.recognized ?? true
100
+ });
101
+ }
102
+
103
+ function unknownViewChild(source, block, options, line, reason, parentRenderId) {
104
+ const rowKind = /^([A-Za-z_$][\w$-]*)\b/.exec(line.text)?.[1];
105
+ return childRecord(source, block, options, line, { kind: 'viewUnknownRow', rowKind, normalizedRowKind: 'unknown', name: rowKind ?? 'unknown', id: `view_unknown_${safeId(rowKind ?? 'row')}_${line.startOffset}`, parentRenderId, recognized: false, reason });
106
+ }
107
+
108
+ function readBodyLines(source, startOffset, endOffset) {
109
+ const lines = source.slice(startOffset, endOffset).split('\n');
110
+ const records = [];
111
+ let lineStart = startOffset;
112
+ for (const rawLine of lines) {
113
+ const rawEnd = lineStart + rawLine.length, leading = /^\s*/.exec(rawLine)?.[0].length ?? 0, trailing = /\s*$/.exec(rawLine)?.[0].length ?? 0;
114
+ const start = lineStart + leading, end = Math.max(start, rawEnd - trailing);
115
+ records.push({ text: rawLine.trim(), startOffset: start, endOffset: end });
116
+ lineStart = rawEnd + 1;
117
+ }
118
+ return records;
119
+ }
120
+
121
+ function scanStructure(source) {
122
+ const depthBefore = new Int32Array(source.length + 1), codeOffsets = new Uint8Array(source.length), stack = [], bracePairs = new Map();
123
+ let depth = 0, state = 'code', quote = '';
124
+ for (let index = 0; index < source.length; index++) {
125
+ depthBefore[index] = depth;
126
+ const char = source[index], next = source[index + 1];
127
+ if (state === 'line-comment') { if (char === '\n') state = 'code'; continue; }
128
+ if (state === 'block-comment') { if (char === '*' && next === '/') { index++; state = 'code'; } continue; }
129
+ if (state === 'string') { if (char === '\\') { index++; continue; } if (char === quote) state = 'code'; continue; }
130
+ codeOffsets[index] = 1;
131
+ if (char === '#') { state = 'line-comment'; continue; }
132
+ if (char === '"' || char === "'" || char === '`') { state = 'string'; quote = char; continue; }
133
+ if (char === '/' && next === '*') { index++; state = 'block-comment'; continue; }
134
+ if (char === '/' && next === '/') { index++; state = 'line-comment'; continue; }
135
+ if (char === '{') { stack.push(index); depth++; continue; }
136
+ if (char === '}') { const open = stack.pop(); if (open !== undefined) { depth = Math.max(0, depth - 1); bracePairs.set(open, index); } }
137
+ }
138
+ depthBefore[source.length] = depth;
139
+ return { depthBefore, codeOffsets, bracePairs };
140
+ }
141
+
142
+ function inRange(offset, ranges) { return ranges.some((range) => offset >= range.startOffset && offset < range.endOffset); }
143
+ function readList(value) { return value.split(',').map((item) => item.trim()).filter(Boolean); }
144
+ function readInlineWord(label, text = '') { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
145
+ function readInlineType(label, text = '') { return new RegExp('(?:^|\\s)' + label + '\\s+(.+)$').exec(text)?.[1]?.trim(); }
146
+ function readRenderValue(value) { const quoted = /^["']([^"']+)["']$/.exec(value.trim()); return quoted ? { value: quoted[1] } : { expression: value.trim() }; }
147
+ function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
148
+ function nameFrom(header) { return /^([A-Za-z_$][\w$.-]*)/.exec(header)?.[1] ?? 'Unnamed'; }
149
+ function sourcePosition(source, offset) { const lines = source.slice(0, offset).split('\n'); return { line: lines.length, column: lines[lines.length - 1].length + 1, offset }; }
150
+ function sourceSpan(source, block, startOffset, endOffset, options = {}) { return cleanRecord({ sourceId: options.documentId, path: options.sourcePath, blockId: block.id, blockKind: block.kind, startOffset, endOffset, start: sourcePosition(source, startOffset), end: sourcePosition(source, endOffset) }); }
151
+ function safeId(value) { return String(value).replace(/[^A-Za-z0-9_$-]+/g, '_').replace(/^_+|_+$/g, '') || 'row'; }
152
+ function cleanRecord(record) { return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-parser",
3
- "version": "0.3.75",
3
+ "version": "0.3.77",
4
4
  "description": "Parser for the first Frontier Lang .frontier syntax slice.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "scripts": {
24
24
  "build": "node scripts/build.mjs",
25
- "test": "npm run build && node test/smoke.mjs && node test/member-identity-smoke.mjs && node test/generic-row-parse-identity-smoke.mjs && node test/type-variant-payload-smoke.mjs && node test/type-generic-ref-smoke.mjs && node test/type-parameter-constraints-smoke.mjs && node test/type-structural-expression-smoke.mjs && node test/action-body-smoke.mjs && node test/action-structured-literals-smoke.mjs && node test/action-return-smoke.mjs && node test/action-else-smoke.mjs && node test/action-match-smoke.mjs && node test/action-for-in-smoke.mjs && node test/action-repeat-smoke.mjs && node test/action-call-smoke.mjs && node test/semantic-operation-edit-smoke.mjs && node test/target-projection-aggregate-smoke.mjs && node test/conversion-constraint-fields-smoke.mjs && node test/conversion-evidence-smoke.mjs && node test/gate-admission-evidence-smoke.mjs && node test/package-canvas-surface-smoke.mjs && node test/view-render-graph-smoke.mjs && node test/resource-graph-smoke.mjs && node test/interlingua-smoke.mjs && node test/dialect-registry-smoke.mjs",
25
+ "test": "npm run build && node test/smoke.mjs && node test/member-identity-smoke.mjs && node test/generic-row-parse-identity-smoke.mjs && node test/type-variant-payload-smoke.mjs && node test/type-generic-ref-smoke.mjs && node test/type-parameter-constraints-smoke.mjs && node test/type-structural-expression-smoke.mjs && node test/action-body-smoke.mjs && node test/action-structured-literals-smoke.mjs && node test/action-return-smoke.mjs && node test/action-else-smoke.mjs && node test/action-match-smoke.mjs && node test/action-for-in-smoke.mjs && node test/action-repeat-smoke.mjs && node test/action-call-smoke.mjs && node test/semantic-operation-edit-smoke.mjs && node test/target-projection-aggregate-smoke.mjs && node test/conversion-constraint-fields-smoke.mjs && node test/conversion-evidence-smoke.mjs && node test/gate-admission-evidence-smoke.mjs && node test/package-canvas-surface-smoke.mjs && node test/view-render-graph-smoke.mjs && node test/view-source-syntax-smoke.mjs && node test/resource-graph-smoke.mjs && node test/machine-graph-smoke.mjs && node test/interlingua-smoke.mjs && node test/dialect-registry-smoke.mjs",
26
26
  "typecheck": "node ./node_modules/typescript/bin/tsc --noEmit -p test/tsconfig.json",
27
27
  "fuzz": "npm run build && node fuzz/smoke.mjs",
28
28
  "bench": "npm run build && node bench/smoke.mjs",