@shapeshift-labs/frontier-lang-parser 0.3.71 → 0.3.73
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/metadata.js
CHANGED
|
@@ -264,6 +264,13 @@ function mergeResourceGraphBlocks(blocks) {
|
|
|
264
264
|
lifetimeRelationIds: blocks.flatMap((block) => ids(block.graph?.lifetimeRelations)),
|
|
265
265
|
borrowScopeIds: blocks.flatMap((block) => ids(block.graph?.borrowScopes)),
|
|
266
266
|
unsafeBoundaryIds: blocks.flatMap((block) => ids(block.graph?.unsafeBoundaries)),
|
|
267
|
+
memoryRegionIds: blocks.flatMap((block) => ids(block.graph?.memoryRegions)),
|
|
268
|
+
dataLayoutIds: blocks.flatMap((block) => ids(block.graph?.dataLayouts)),
|
|
269
|
+
pointerEdgeIds: blocks.flatMap((block) => ids(block.graph?.pointerEdges)),
|
|
270
|
+
memoryAccessIds: blocks.flatMap((block) => ids(block.graph?.memoryAccesses)),
|
|
271
|
+
abiBoundaryIds: blocks.flatMap((block) => ids(block.graph?.abiBoundaries)),
|
|
272
|
+
trapIds: blocks.flatMap((block) => ids(block.graph?.traps)),
|
|
273
|
+
undefinedBehaviorIds: blocks.flatMap((block) => ids(block.graph?.undefinedBehaviors)),
|
|
267
274
|
conflictIds: blocks.flatMap((block) => ids(block.graph?.conflicts)),
|
|
268
275
|
proofObligationIds: blocks.flatMap((block) => ids(block.graph?.proofObligations)),
|
|
269
276
|
summary: {
|
|
@@ -280,9 +287,20 @@ function mergeResourceGraphBlocks(blocks) {
|
|
|
280
287
|
lifetimeRelationCount: sum(blocks, 'lifetimeRelations'),
|
|
281
288
|
borrowScopeCount: sum(blocks, 'borrowScopes'),
|
|
282
289
|
unsafeBoundaryCount: sum(blocks, 'unsafeBoundaries'),
|
|
290
|
+
memoryRegionCount: sum(blocks, 'memoryRegions'),
|
|
291
|
+
dataLayoutCount: sum(blocks, 'dataLayouts'),
|
|
292
|
+
pointerEdgeCount: sum(blocks, 'pointerEdges'),
|
|
293
|
+
memoryAccessCount: sum(blocks, 'memoryAccesses'),
|
|
294
|
+
abiBoundaryCount: sum(blocks, 'abiBoundaries'),
|
|
295
|
+
trapCount: sum(blocks, 'traps'),
|
|
296
|
+
undefinedBehaviorCount: sum(blocks, 'undefinedBehaviors'),
|
|
297
|
+
lowLevelPrimitiveCount: sum(blocks, 'lowLevelPrimitives'),
|
|
283
298
|
conflictCount: sum(blocks, 'conflicts'),
|
|
284
299
|
proofObligationCount: sum(blocks, 'proofObligations'),
|
|
285
|
-
unsafeBoundariesWithoutProof: sum(blocks, 'unsafeBoundariesWithoutProof')
|
|
300
|
+
unsafeBoundariesWithoutProof: sum(blocks, 'unsafeBoundariesWithoutProof'),
|
|
301
|
+
failClosedTrapCount: sum(blocks, 'failClosedTraps'),
|
|
302
|
+
trapWithoutProofCount: sum(blocks, 'trapsWithoutProof'),
|
|
303
|
+
undefinedBehaviorWithoutProofCount: sum(blocks, 'undefinedBehaviorsWithoutProof')
|
|
286
304
|
},
|
|
287
305
|
metadata: { authoredResourceGraphBlockIds: blocks.map((block) => block.id) }
|
|
288
306
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function parseLowLevelResourceRecord(kind, common, name, text) {
|
|
2
|
+
if (kind === 'memoryRegion') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), memoryKind: word('memoryKind', text) ?? word('kind', text) ?? name, regionKind: word('regionKind', text), addressSpace: word('addressSpace', text) ?? word('space', text), address: word('address', text) ?? word('baseAddress', text), sizeBytes: number('sizeBytes', text) ?? number('size', text), alignmentBytes: number('alignmentBytes', text) ?? number('alignment', text), pointerWidth: number('pointerWidth', text), endian: word('endian', text) ?? word('endianness', text), volatile: flag('volatile', text), atomic: flag('atomic', text), shared: flag('shared', text) });
|
|
3
|
+
if (kind === 'dataLayout') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), typeId: word('type', text) ?? word('typeId', text), structId: word('struct', text) ?? word('structId', text), fieldId: word('field', text) ?? word('fieldId', text), bitfieldId: word('bitfield', text) ?? word('bitfieldId', text), layoutKind: word('layoutKind', text) ?? word('kind', text), repr: word('repr', text), abi: word('abi', text), endian: word('endian', text) ?? word('endianness', text), sizeBytes: number('sizeBytes', text) ?? number('size', text), alignmentBytes: number('alignmentBytes', text) ?? number('alignment', text), offsetBytes: number('offsetBytes', text) ?? number('offset', text), bitWidth: number('bitWidth', text) ?? number('width', text), fieldOrder: list(text, 'fieldOrder', 'fields'), constraintKinds: list(text, 'constraint', 'constraints', 'constraintKind', 'constraintKinds') });
|
|
4
|
+
if (kind === 'pointerEdge') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), targetResourceId: word('targetResource', text) ?? word('targetResourceId', text) ?? word('target', text), ownerId: word('owner', text) ?? word('ownerId', text), lifetimeRegionId: word('lifetime', text) ?? word('lifetimeRegion', text) ?? word('lifetimeRegionId', text), pointerKind: word('pointerKind', text) ?? word('kind', text) ?? 'pointer', addressSpace: word('addressSpace', text) ?? word('space', text), pointerWidth: number('pointerWidth', text), aliasKind: word('aliasKind', text), mode: word('mode', text), provenance: word('provenance', text), nullable: flag('nullable', text), mutable: flag('mutable', text) });
|
|
5
|
+
if (kind === 'memoryAccess') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), accessKind: word('accessKind', text) ?? word('kind', text) ?? name, operationKind: word('operation', text) ?? word('operationKind', text), memoryOrder: word('memoryOrder', text) ?? word('ordering', text), lockId: word('lock', text) ?? word('lockId', text), synchronizationKey: word('sync', text) ?? word('synchronizationKey', text), reads: list(text, 'read', 'reads'), writes: list(text, 'write', 'writes'), volatile: flag('volatile', text), atomic: flag('atomic', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing' });
|
|
6
|
+
if (kind === 'abiBoundary') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), callableId: word('callable', text) ?? word('callableId', text), functionId: word('function', text) ?? word('functionId', text), boundaryKind: word('boundaryKind', text) ?? word('kind', text) ?? 'abi-boundary', abi: word('abi', text), abiKind: word('abiKind', text), callingConvention: word('callingConvention', text) ?? word('convention', text), pointerWidth: number('pointerWidth', text), endian: word('endian', text) ?? word('endianness', text), ffiBoundary: word('ffiBoundary', text), proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing' });
|
|
7
|
+
if (kind === 'trap') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), ownerId: word('owner', text) ?? word('ownerId', text), loanId: word('loan', text) ?? word('loanId', text), pointerEdgeId: word('pointer', text) ?? word('pointerEdge', text) ?? word('pointerEdgeId', text), memoryAccessId: word('memoryAccess', text) ?? word('memoryAccessId', text), unsafeBoundaryId: word('unsafeBoundary', text) ?? word('unsafeBoundaryId', text), operationKind: word('operation', text) ?? word('operationKind', text), instructionId: word('instruction', text) ?? word('instructionId', text), callableId: word('callable', text) ?? word('callableId', text), trapKind: word('trapKind', text) ?? word('kind', text) ?? name, trapCode: word('trapCode', text) ?? word('code', text), reasonCode: word('reasonCode', text) ?? word('code', text), condition: quoted('condition', text) ?? word('condition', text), status: word('status', text) ?? 'needs-proof', severity: word('severity', text) ?? 'error', proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', message: quoted('message', text), failClosed: common.failClosed ?? true, semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
|
|
8
|
+
if (kind === 'undefinedBehavior') return cleanRecord({ ...common, resourceId: word('resource', text) ?? word('resourceId', text), ownerId: word('owner', text) ?? word('ownerId', text), loanId: word('loan', text) ?? word('loanId', text), pointerEdgeId: word('pointer', text) ?? word('pointerEdge', text) ?? word('pointerEdgeId', text), memoryAccessId: word('memoryAccess', text) ?? word('memoryAccessId', text), unsafeBoundaryId: word('unsafeBoundary', text) ?? word('unsafeBoundaryId', text), operationKind: word('operation', text) ?? word('operationKind', text), undefinedBehaviorKind: word('undefinedBehaviorKind', text) ?? word('behaviorKind', text) ?? word('kind', text) ?? name, language: word('language', text), reasonCode: word('reasonCode', text) ?? word('code', text), condition: quoted('condition', text) ?? word('condition', text), status: word('status', text) ?? 'needs-proof', severity: word('severity', text) ?? 'error', proofStatus: word('proofStatus', text) ?? word('status', text) ?? 'missing', message: quoted('message', text), failClosed: common.failClosed ?? true, semanticEquivalenceClaim: false, runtimeEquivalenceClaim: false });
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function word(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
|
|
13
|
+
function quoted(label, text) { return new RegExp("(?:^|\\s)" + label + "\\s+[\"']([^\"']+)[\"']").exec(text)?.[1]?.trim(); }
|
|
14
|
+
function flag(label, text) { return new RegExp('(?:^|\\s)' + label + '(?:\\s|$)').test(text) || undefined; }
|
|
15
|
+
function number(label, text) { const value = word(label, text); return value === undefined ? undefined : Number(value); }
|
|
16
|
+
function list(text, ...labels) {
|
|
17
|
+
for (const label of labels) {
|
|
18
|
+
const value = new RegExp('(?:^|\\s)' + label + '\\s+([^\\s]+)').exec(text)?.[1]?.trim();
|
|
19
|
+
if (value) return value.split(/[|,]/).map((item) => item.trim()).filter(Boolean);
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
function cleanRecord(record) {
|
|
24
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0)));
|
|
25
|
+
}
|
package/dist/resource-graph.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createRowIdentityTracker } from './row-identity.js';
|
|
2
|
+
import { parseLowLevelResourceRecord } from './resource-graph-low-level.js';
|
|
2
3
|
|
|
3
4
|
const GROUPS = {
|
|
4
5
|
resource: 'resources',
|
|
@@ -12,6 +13,13 @@ const GROUPS = {
|
|
|
12
13
|
lifetimeRelation: 'lifetimeRelations',
|
|
13
14
|
borrowScope: 'borrowScopes',
|
|
14
15
|
unsafeBoundary: 'unsafeBoundaries',
|
|
16
|
+
memoryRegion: 'memoryRegions',
|
|
17
|
+
dataLayout: 'dataLayouts',
|
|
18
|
+
pointerEdge: 'pointerEdges',
|
|
19
|
+
memoryAccess: 'memoryAccesses',
|
|
20
|
+
abiBoundary: 'abiBoundaries',
|
|
21
|
+
trap: 'traps',
|
|
22
|
+
undefinedBehavior: 'undefinedBehaviors',
|
|
15
23
|
conflict: 'conflicts',
|
|
16
24
|
proofObligation: 'proofObligations'
|
|
17
25
|
};
|
|
@@ -41,6 +49,13 @@ export function parseResourceGraphBlock(block) {
|
|
|
41
49
|
borrowScopes: [],
|
|
42
50
|
borrowScopeRegions: [],
|
|
43
51
|
unsafeBoundaries: [],
|
|
52
|
+
memoryRegions: [],
|
|
53
|
+
dataLayouts: [],
|
|
54
|
+
pointerEdges: [],
|
|
55
|
+
memoryAccesses: [],
|
|
56
|
+
abiBoundaries: [],
|
|
57
|
+
traps: [],
|
|
58
|
+
undefinedBehaviors: [],
|
|
44
59
|
conflicts: [],
|
|
45
60
|
proofObligations: [],
|
|
46
61
|
parser: { status: 'authored', errors: rowIdentity.errors },
|
|
@@ -54,14 +69,14 @@ export function parseResourceGraphBlock(block) {
|
|
|
54
69
|
metadata: { name }
|
|
55
70
|
};
|
|
56
71
|
|
|
57
|
-
for (const
|
|
58
|
-
const line =
|
|
72
|
+
for (const authoredLine of readAuthoredLines(block)) {
|
|
73
|
+
const line = authoredLine.text;
|
|
59
74
|
if (!line || line.startsWith('#') || isGraphPropertyLine(line)) continue;
|
|
60
75
|
const match = /^([A-Za-z_$][\w$-]*)\s+([A-Za-z_$][\w$-]*)(.*)$/.exec(line);
|
|
61
76
|
if (!match) continue;
|
|
62
77
|
const [, rowKind, rowName, rest] = match;
|
|
63
78
|
const normalized = normalizeRowKind(rowKind);
|
|
64
|
-
const record = parseResourceRecord(normalized, rowName, rest, graph);
|
|
79
|
+
const record = parseResourceRecord(normalized, rowName, rest, graph, authoredLine);
|
|
65
80
|
const group = GROUPS[normalized];
|
|
66
81
|
if (record && group) rowIdentity.push(graph[group], record, { rowKind, normalizedRowKind: normalized, name: rowName });
|
|
67
82
|
}
|
|
@@ -73,9 +88,13 @@ export function parseResourceGraphBlock(block) {
|
|
|
73
88
|
resourceIds: ids(graph.resources),
|
|
74
89
|
ownerIds: ids(graph.owners),
|
|
75
90
|
lifetimeRegionIds: ids(graph.lifetimeRegions),
|
|
91
|
+
trapIds: ids(graph.traps),
|
|
92
|
+
undefinedBehaviorIds: ids(graph.undefinedBehaviors),
|
|
93
|
+
failClosedTrapIds: ids(graph.traps.filter((record) => record.failClosed)),
|
|
94
|
+
lowLevelPrimitiveIds: ids([...graph.memoryRegions, ...graph.dataLayouts, ...graph.pointerEdges, ...graph.memoryAccesses, ...graph.abiBoundaries, ...graph.traps, ...graph.undefinedBehaviors]),
|
|
76
95
|
sourcePaths: unique(allRecords(graph).map((record) => record.sourcePath)),
|
|
77
96
|
evidenceIds: unique([...graph.evidenceIds, ...allRecords(graph).flatMap((record) => record.evidenceIds ?? [])]),
|
|
78
|
-
blockerReasonCodes: unique(graph.conflicts.map((record) => record.reasonCode))
|
|
97
|
+
blockerReasonCodes: unique([...graph.conflicts, ...graph.traps, ...graph.undefinedBehaviors].map((record) => record.reasonCode))
|
|
79
98
|
};
|
|
80
99
|
|
|
81
100
|
return {
|
|
@@ -90,8 +109,8 @@ export function parseResourceGraphBlock(block) {
|
|
|
90
109
|
};
|
|
91
110
|
}
|
|
92
111
|
|
|
93
|
-
function parseResourceRecord(kind, name, text, graph) {
|
|
94
|
-
const common = commonRecord(kind, name, text, graph);
|
|
112
|
+
function parseResourceRecord(kind, name, text, graph, authoredLine = {}) {
|
|
113
|
+
const common = commonRecord(kind, name, text, graph, authoredLine);
|
|
95
114
|
if (kind === 'resource') return cleanRecord({ ...common, resourceKind: readInlineWord('resourceKind', text) ?? readInlineWord('kind', text) ?? name, ownerId: readInlineWord('owner', text) ?? readInlineWord('ownerId', text), ownerName: readInlineWord('ownerName', text) });
|
|
96
115
|
if (kind === 'owner') return cleanRecord({ ...common, ownerKind: readInlineWord('ownerKind', text) ?? readInlineWord('kind', text) ?? 'owner' });
|
|
97
116
|
if (kind === 'loan') return cleanRecord({ ...common, resourceId: readInlineWord('resource', text) ?? readInlineWord('resourceId', text), ownerId: readInlineWord('owner', text) ?? readInlineWord('ownerId', text), lifetimeRegionId: readInlineWord('lifetime', text) ?? readInlineWord('lifetimeRegion', text) ?? readInlineWord('lifetimeRegionId', text), mode: readInlineWord('mode', text) ?? 'unknown', access: readInlineWord('access', text) });
|
|
@@ -103,18 +122,28 @@ function parseResourceRecord(kind, name, text, graph) {
|
|
|
103
122
|
if (kind === 'lifetimeRelation') return cleanRecord({ ...common, relationKind: readInlineWord('relationKind', text) ?? readInlineWord('kind', text) ?? 'outlives', fromLifetimeId: readInlineWord('fromLifetime', text) ?? readInlineWord('fromLifetimeId', text) ?? readInlineWord('from', text), toLifetimeId: readInlineWord('toLifetime', text) ?? readInlineWord('toLifetimeId', text) ?? readInlineWord('to', text), from: readInlineWord('from', text), to: readInlineWord('to', text) });
|
|
104
123
|
if (kind === 'borrowScope') return cleanRecord({ ...common, scopeKind: readInlineWord('scopeKind', text) ?? readInlineWord('kind', text) ?? 'borrow-scope', constraintKind: readInlineWord('constraintKind', text), constraintKinds: readInlineList(text, 'constraint', 'constraints', 'constraintKind', 'constraintKinds') ?? [], ownershipKind: readInlineWord('ownershipKind', text), lifetimeKind: readInlineWord('lifetimeKind', text), controlFlowKind: readInlineWord('controlFlowKind', text), sourceControlFlowId: readInlineWord('sourceControlFlow', text) ?? readInlineWord('sourceControlFlowId', text), lifetimeRegionId: readInlineWord('lifetime', text) ?? readInlineWord('lifetimeRegion', text) ?? readInlineWord('lifetimeRegionId', text), resourceId: readInlineWord('resource', text) ?? readInlineWord('resourceId', text) });
|
|
105
124
|
if (kind === 'unsafeBoundary') return cleanRecord({ ...common, resourceId: readInlineWord('resource', text) ?? readInlineWord('resourceId', text), unsafeBoundary: true, proofStatus: readInlineWord('proofStatus', text) ?? readInlineWord('status', text) ?? 'missing', kind: readInlineWord('kind', text) });
|
|
125
|
+
const lowLevelRecord = parseLowLevelResourceRecord(kind, common, name, text);
|
|
126
|
+
if (lowLevelRecord) return lowLevelRecord;
|
|
106
127
|
if (kind === 'conflict') return cleanRecord({ ...common, resourceId: readInlineWord('resource', text) ?? readInlineWord('resourceId', text), ownerId: readInlineWord('owner', text) ?? readInlineWord('ownerId', text), loanId: readInlineWord('loan', text) ?? readInlineWord('loanId', text), aliasId: readInlineWord('alias', text) ?? readInlineWord('aliasId', text), unsafeBoundaryId: readInlineWord('unsafeBoundary', text) ?? readInlineWord('unsafeBoundaryId', text), reasonCode: readInlineWord('reasonCode', text), message: readInlineQuoted('message', text), status: readInlineWord('status', text) ?? 'open', severity: readInlineWord('severity', text) ?? 'error' });
|
|
107
128
|
if (kind === 'proofObligation') return cleanRecord({ ...common, resourceId: readInlineWord('resource', text) ?? readInlineWord('resourceId', text), conflictId: readInlineWord('conflict', text) ?? readInlineWord('conflictId', text), kind: readInlineWord('kind', text), status: readInlineWord('status', text) ?? 'open', statement: readInlineQuoted('statement', text) });
|
|
108
129
|
return undefined;
|
|
109
130
|
}
|
|
110
131
|
|
|
111
|
-
function commonRecord(kind, name, text, graph) {
|
|
132
|
+
function commonRecord(kind, name, text, graph, authoredLine = {}) {
|
|
112
133
|
return cleanRecord({
|
|
113
134
|
recordKind: recordKind(kind),
|
|
114
135
|
id: idFrom(text, `${recordPrefix(kind)}_${name}`),
|
|
115
136
|
name,
|
|
116
137
|
sourcePath: readInlineWord('sourcePath', text) ?? readInlineWord('path', text) ?? graph.sourcePath,
|
|
117
138
|
sourceHash: readInlineWord('sourceHash', text) ?? graph.sourceHash,
|
|
139
|
+
sourceSpan: authoredLine.sourceSpan,
|
|
140
|
+
authoredSourceSpan: authoredLine.sourceSpan,
|
|
141
|
+
sourceMapIds: readInlineList(text, 'sourceMap', 'sourceMaps', 'sourceMapId', 'sourceMapIds'),
|
|
142
|
+
sourceMapMappingIds: readInlineList(text, 'sourceMapMapping', 'sourceMapMappings', 'sourceMapMappingId', 'sourceMapMappingIds'),
|
|
143
|
+
proofEvidenceIds: readInlineList(text, 'proofEvidence', 'proofEvidenceId', 'proofEvidenceIds'),
|
|
144
|
+
proofObligationIds: readInlineList(text, 'proofObligation', 'proofObligations', 'proofObligationId', 'proofObligationIds', 'obligation', 'obligations'),
|
|
145
|
+
missingEvidence: readInlineList(text, 'missingEvidence'),
|
|
146
|
+
failClosed: readInlineFlag('failClosed', text),
|
|
118
147
|
evidenceIds: readInlineList(text, 'evidence', 'evidenceIds') ?? graph.evidenceIds,
|
|
119
148
|
metadata: { authoredName: name }
|
|
120
149
|
});
|
|
@@ -134,11 +163,22 @@ function summarize(graph) {
|
|
|
134
163
|
lifetimeRelations: graph.lifetimeRelations.length,
|
|
135
164
|
borrowScopes: graph.borrowScopes.length,
|
|
136
165
|
unsafeBoundaries: graph.unsafeBoundaries.length,
|
|
166
|
+
memoryRegions: graph.memoryRegions.length,
|
|
167
|
+
dataLayouts: graph.dataLayouts.length,
|
|
168
|
+
pointerEdges: graph.pointerEdges.length,
|
|
169
|
+
memoryAccesses: graph.memoryAccesses.length,
|
|
170
|
+
abiBoundaries: graph.abiBoundaries.length,
|
|
171
|
+
traps: graph.traps.length,
|
|
172
|
+
undefinedBehaviors: graph.undefinedBehaviors.length,
|
|
173
|
+
lowLevelPrimitives: graph.memoryRegions.length + graph.dataLayouts.length + graph.pointerEdges.length + graph.memoryAccesses.length + graph.abiBoundaries.length + graph.traps.length + graph.undefinedBehaviors.length,
|
|
137
174
|
conflicts: graph.conflicts.length,
|
|
138
175
|
proofObligations: graph.proofObligations.length,
|
|
139
176
|
unsafeBoundariesWithoutProof: graph.unsafeBoundaries.filter((record) => record.proofStatus !== 'passed').length,
|
|
177
|
+
failClosedTraps: graph.traps.filter((record) => record.failClosed).length,
|
|
178
|
+
trapsWithoutProof: graph.traps.filter((record) => record.proofStatus !== 'passed').length,
|
|
179
|
+
undefinedBehaviorsWithoutProof: graph.undefinedBehaviors.filter((record) => record.proofStatus !== 'passed').length,
|
|
140
180
|
parseErrors: graph.parser?.errors?.length ?? 0,
|
|
141
|
-
reasonCodes: unique(graph.conflicts.map((record) => record.reasonCode))
|
|
181
|
+
reasonCodes: unique([...graph.conflicts, ...graph.traps, ...graph.undefinedBehaviors].map((record) => record.reasonCode))
|
|
142
182
|
};
|
|
143
183
|
}
|
|
144
184
|
|
|
@@ -155,6 +195,13 @@ function allRecords(graph) {
|
|
|
155
195
|
...graph.lifetimeRelations,
|
|
156
196
|
...graph.borrowScopes,
|
|
157
197
|
...graph.unsafeBoundaries,
|
|
198
|
+
...graph.memoryRegions,
|
|
199
|
+
...graph.dataLayouts,
|
|
200
|
+
...graph.pointerEdges,
|
|
201
|
+
...graph.memoryAccesses,
|
|
202
|
+
...graph.abiBoundaries,
|
|
203
|
+
...graph.traps,
|
|
204
|
+
...graph.undefinedBehaviors,
|
|
158
205
|
...graph.conflicts,
|
|
159
206
|
...graph.proofObligations
|
|
160
207
|
];
|
|
@@ -165,6 +212,13 @@ function normalizeRowKind(kind) {
|
|
|
165
212
|
if (kind === 'outlives' || kind === 'lifetimeRelation' || kind === 'lifeRelation') return 'lifetimeRelation';
|
|
166
213
|
if (kind === 'borrow' || kind === 'borrowScope' || kind === 'borrowRegion') return 'borrowScope';
|
|
167
214
|
if (kind === 'unsafe' || kind === 'unsafeBoundary') return 'unsafeBoundary';
|
|
215
|
+
if (kind === 'memory' || kind === 'memoryRegion' || kind === 'region') return 'memoryRegion';
|
|
216
|
+
if (kind === 'layout' || kind === 'dataLayout') return 'dataLayout';
|
|
217
|
+
if (kind === 'pointer' || kind === 'ptr' || kind === 'address') return 'pointerEdge';
|
|
218
|
+
if (kind === 'access' || kind === 'memoryAccess' || kind === 'atomic' || kind === 'volatile') return 'memoryAccess';
|
|
219
|
+
if (kind === 'abi' || kind === 'abiBoundary' || kind === 'callBoundary') return 'abiBoundary';
|
|
220
|
+
if (kind === 'traps') return 'trap';
|
|
221
|
+
if (kind === 'undefined' || kind === 'ub' || kind === 'undefinedBehavior' || kind === 'undefinedBehaviour') return 'undefinedBehavior';
|
|
168
222
|
if (kind === 'proof' || kind === 'obligation' || kind === 'proofObligation') return 'proofObligation';
|
|
169
223
|
return kind;
|
|
170
224
|
}
|
|
@@ -174,6 +228,12 @@ function recordKind(kind) {
|
|
|
174
228
|
if (kind === 'lifetimeRelation') return 'lifetime-relation';
|
|
175
229
|
if (kind === 'borrowScope') return 'borrow-scope';
|
|
176
230
|
if (kind === 'unsafeBoundary') return 'unsafe-boundary';
|
|
231
|
+
if (kind === 'memoryRegion') return 'memory-region';
|
|
232
|
+
if (kind === 'dataLayout') return 'data-layout';
|
|
233
|
+
if (kind === 'pointerEdge') return 'pointer-edge';
|
|
234
|
+
if (kind === 'memoryAccess') return 'memory-access';
|
|
235
|
+
if (kind === 'abiBoundary') return 'abi-boundary';
|
|
236
|
+
if (kind === 'undefinedBehavior') return 'undefined-behavior';
|
|
177
237
|
if (kind === 'proofObligation') return 'proof-obligation';
|
|
178
238
|
return kind;
|
|
179
239
|
}
|
|
@@ -195,6 +255,7 @@ function readListLine(label, body) {
|
|
|
195
255
|
}
|
|
196
256
|
function readInlineWord(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
|
|
197
257
|
function readInlineQuoted(label, text) { return new RegExp("(?:^|\\s)" + label + "\\s+[\"']([^\"']+)[\"']").exec(text)?.[1]?.trim(); }
|
|
258
|
+
function readInlineFlag(label, text) { return new RegExp('(?:^|\\s)' + label + '(?:\\s|$)').test(text) || undefined; }
|
|
198
259
|
function readInlineNumber(label, text) {
|
|
199
260
|
const value = readInlineWord(label, text);
|
|
200
261
|
return value === undefined ? undefined : Number(value);
|
|
@@ -208,6 +269,21 @@ function readInlineList(text, ...labels) {
|
|
|
208
269
|
}
|
|
209
270
|
function ids(records = []) { return records.map((record) => record?.id).filter(Boolean); }
|
|
210
271
|
function unique(values = []) { return [...new Set(values.filter(Boolean))]; }
|
|
272
|
+
function readAuthoredLines(block) {
|
|
273
|
+
const lines = block.body.split('\n');
|
|
274
|
+
const records = [];
|
|
275
|
+
let lineStart = block.syntax?.bodyStartOffset ?? 0;
|
|
276
|
+
for (const rawLine of lines) {
|
|
277
|
+
const rawEnd = lineStart + rawLine.length;
|
|
278
|
+
const leading = /^\s*/.exec(rawLine)?.[0].length ?? 0;
|
|
279
|
+
const trailing = /\s*$/.exec(rawLine)?.[0].length ?? 0;
|
|
280
|
+
const startOffset = lineStart + leading;
|
|
281
|
+
const endOffset = Math.max(startOffset, rawEnd - trailing);
|
|
282
|
+
records.push({ text: rawLine.trim(), sourceSpan: typeof block.sourceSpan === 'function' ? block.sourceSpan(startOffset, endOffset) : undefined });
|
|
283
|
+
lineStart = rawEnd + 1;
|
|
284
|
+
}
|
|
285
|
+
return records;
|
|
286
|
+
}
|
|
211
287
|
function cleanRecord(record) {
|
|
212
288
|
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0)));
|
|
213
289
|
}
|
|
@@ -16,8 +16,8 @@ export const ROW_SYNTAX_CONFIG = Object.freeze({
|
|
|
16
16
|
runtimeCapabilities: rowConfig('runtimeCapabilityRow', 'runtime_capability_row', runtimeRows, normalizeRuntimeCapabilityRow),
|
|
17
17
|
runtimeCapabilityMatrix: rowConfig('runtimeCapabilityRow', 'runtime_capability_row', runtimeRows, normalizeRuntimeCapabilityRow),
|
|
18
18
|
runtimeHosts: rowConfig('runtimeCapabilityRow', 'runtime_capability_row', runtimeRows, normalizeRuntimeCapabilityRow),
|
|
19
|
-
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 conflict proof proofObligation obligation'), normalizeResourceGraphRow),
|
|
20
|
-
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 conflict proof proofObligation obligation'), normalizeResourceGraphRow),
|
|
19
|
+
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 trap traps undefined undefinedBehavior undefinedBehaviour ub conflict proof proofObligation obligation'), normalizeResourceGraphRow),
|
|
20
|
+
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 trap traps undefined undefinedBehavior undefinedBehaviour ub conflict proof proofObligation obligation'), normalizeResourceGraphRow),
|
|
21
21
|
applicationSurface: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
|
|
22
22
|
appHost: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
|
|
23
23
|
plugin: rowConfig('applicationSurfaceRow', 'application_surface_row', appRows, normalizeApplicationSurfaceRow),
|
|
@@ -79,6 +79,13 @@ function normalizeResourceGraphRow(rowKind) {
|
|
|
79
79
|
if (rowKind === 'lifeRelation') return 'lifetimeRelation';
|
|
80
80
|
if (rowKind === 'borrowRegion') return 'borrowScope';
|
|
81
81
|
if (rowKind === 'unsafe') return 'unsafeBoundary';
|
|
82
|
+
if (rowKind === 'memory' || rowKind === 'region') return 'memoryRegion';
|
|
83
|
+
if (rowKind === 'layout') return 'dataLayout';
|
|
84
|
+
if (rowKind === 'pointer' || rowKind === 'ptr' || rowKind === 'address') return 'pointerEdge';
|
|
85
|
+
if (rowKind === 'access' || rowKind === 'atomic' || rowKind === 'volatile') return 'memoryAccess';
|
|
86
|
+
if (rowKind === 'abi' || rowKind === 'callBoundary') return 'abiBoundary';
|
|
87
|
+
if (rowKind === 'traps') return 'trap';
|
|
88
|
+
if (rowKind === 'undefined' || rowKind === 'undefinedBehaviour' || rowKind === 'ub') return 'undefinedBehavior';
|
|
82
89
|
if (rowKind === 'proof' || rowKind === 'proofObligation') return 'obligation';
|
|
83
90
|
return rowKind;
|
|
84
91
|
}
|