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

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/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',
@@ -227,9 +227,9 @@ function readGenericRowSyntaxChildren(source, block, options, config) {
227
227
  for (const line of readBodyLines(source, block)) {
228
228
  if (!line.text || line.text.startsWith('#')) continue;
229
229
  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; }
230
+ if (!row) { if (unknownGenericRowsFailClosed(config)) children.push(genericUnknownRowChild(source, block, options, line, config, undefined, undefined, unsupportedGenericRowReason(config))); continue; }
231
231
  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; }
232
+ if (!config.rowKinds.has(rowKind)) { if (unknownGenericRowsFailClosed(config)) children.push(genericUnknownRowChild(source, block, options, line, config, rowKind, name, unsupportedGenericRowReason(config))); continue; }
233
233
  const normalizedRowKind = config.normalize?.(rowKind) ?? rowKind;
234
234
  const id = idFrom(rest, `${config.idPrefix}_${safeId(normalizedRowKind)}_${safeId(name)}`);
235
235
  let recognized = true;
@@ -268,13 +268,16 @@ function genericUnknownRowChild(source, block, options, line, config, rowKind, n
268
268
  const resolvedName = name ?? rowKind ?? 'unknown';
269
269
  return cleanRecord({
270
270
  kind: config.childKind === 'gateAdmissionEvidenceRow' ? 'gateAdmissionUnknownRow' : 'genericUnknownRow', rowKind,
271
- normalizedRowKind: 'unknown', name: resolvedName, id: `gate_admission_unknown_${safeId(rowKind ?? 'row')}_${line.startOffset}`,
271
+ normalizedRowKind: 'unknown', name: resolvedName, id: `${config.idPrefix}_unknown_${safeId(rowKind ?? 'row')}_${line.startOffset}`,
272
272
  header: line.text, startOffset: line.startOffset, endOffset: line.endOffset, location: sourcePosition(source, line.startOffset),
273
273
  parentKind: block.kind, parentId: block.id, parentName: block.name, moduleId: block.moduleId, moduleName: block.moduleName,
274
274
  sourceSpan: sourceSpan(source, block, line.startOffset, line.endOffset, options), recognized: false, reason
275
275
  });
276
276
  }
277
277
 
278
+ function unknownGenericRowsFailClosed(config) { return config.childKind === 'gateAdmissionEvidenceRow' || config.childKind === 'machineGraphRow'; }
279
+ function unsupportedGenericRowReason(config) { return config.childKind === 'machineGraphRow' ? 'unsupported-machine-graph-row' : 'unsupported-gate-admission-row'; }
280
+
278
281
  function readBodyLines(source, block) { return readTextLines(source, block.bodyStartOffset, block.bodyEndOffset); }
279
282
 
280
283
  function readTextLines(source, startOffset, endOffset) {
@@ -294,10 +297,7 @@ function readTextLines(source, startOffset, endOffset) {
294
297
  return records;
295
298
  }
296
299
 
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
- }
300
+ 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
301
 
302
302
  function sourceSpan(source, block, startOffset, endOffset, options = {}) {
303
303
  return cleanRecord({
@@ -315,6 +315,4 @@ function sourceSpan(source, block, startOffset, endOffset, options = {}) {
315
315
  function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
316
316
  function readInlineWord(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
317
317
  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
- }
318
+ 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';
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.76",
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/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",