@shapeshift-labs/frontier-lang-compiler 0.2.70 → 0.2.71

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.
@@ -140,14 +140,18 @@ export function createLightweightNativeImport(input) {
140
140
  kind: 'import',
141
141
  status: 'passed',
142
142
  path: input.sourcePath,
143
- summary: `Lightweight declaration scan found ${symbols.length} symbol(s) and ${dependencies.summary.total} dependency edge(s).`,
144
- metadata: { parser, dependencyRelations: dependencies.summary.total }
143
+ summary: `Lightweight declaration scan found ${symbols.length} symbol(s), ${dependencies.summary.total} dependency edge(s), and ${dependencies.summary.controlFlow + dependencies.summary.effects + dependencies.summary.mutations} semantic fact(s).`,
144
+ metadata: { parser, dependencyRelations: dependencies.summary.total, semanticFacts: {
145
+ controlFlow: dependencies.summary.controlFlow,
146
+ effects: dependencies.summary.effects,
147
+ mutations: dependencies.summary.mutations
148
+ } }
145
149
  }],
146
150
  metadata: {
147
151
  parser,
148
152
  coverage: 'declarations-only',
149
153
  dependencyRelations: dependencies.summary,
150
- unsupported: ['full expression AST', 'type checking', 'control flow', 'comments and formatting preservation']
154
+ unsupported: ['full expression AST', 'type checking', 'full control-flow graph', 'comments and formatting preservation']
151
155
  }
152
156
  });
153
157
 
@@ -164,6 +168,12 @@ export function createLightweightNativeImport(input) {
164
168
  declarationCount: declarations.length,
165
169
  dependencyRelationCount: dependencies.summary.total,
166
170
  dependencyOccurrenceCount: dependencies.occurrences.length,
171
+ semanticFactCount: dependencies.summary.controlFlow + dependencies.summary.effects + dependencies.summary.mutations,
172
+ semanticFactSummary: {
173
+ controlFlow: dependencies.summary.controlFlow,
174
+ effects: dependencies.summary.effects,
175
+ mutations: dependencies.summary.mutations
176
+ },
167
177
  ...(input.sourcePreservation ? {
168
178
  sourcePreservationId: input.sourcePreservation.id,
169
179
  sourcePreservationSummary: input.sourcePreservation.summary
@@ -11,6 +11,7 @@ export function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
11
11
  ...relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['controlflow', 'cfg', 'flow'])),
12
12
  ...facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['controlflow', 'cfg', 'flow']))
13
13
  ];
14
+ const effectRecords = facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['effect', 'mutation', 'sideeffect']));
14
15
  return {
15
16
  declarations: occurrences.filter((occurrence) => occurrence?.role === 'definition' || occurrence?.role === 'declaration').length,
16
17
  references: occurrences.filter((occurrence) => {
@@ -18,6 +19,7 @@ export function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
18
19
  return role && role !== 'definition' && role !== 'declaration';
19
20
  }).length + referenceRelations.length,
20
21
  types: typeFacts.length + typedSymbols.length,
21
- controlFlow: controlFlowRecords.length
22
+ controlFlow: controlFlowRecords.length,
23
+ effects: effectRecords.length
22
24
  };
23
25
  }
@@ -24,7 +24,10 @@ export function lightweightDependencyRelations(input, declarations, documentId)
24
24
  summary: {
25
25
  total: records.relations.length,
26
26
  calls: records.relations.filter((relation) => relation.predicate === 'calls').length,
27
- uses: records.relations.filter((relation) => relation.predicate === 'uses').length
27
+ uses: records.relations.filter((relation) => relation.predicate === 'uses').length,
28
+ controlFlow: records.facts.filter((fact) => fact.predicate === 'controlFlow').length,
29
+ effects: records.facts.filter((fact) => fact.predicate === 'effect').length,
30
+ mutations: records.facts.filter((fact) => fact.predicate === 'mutation').length
28
31
  }
29
32
  };
30
33
  }
@@ -67,6 +70,7 @@ function scanDeclarationDependencies(input, documentId, scan, identifiers, lines
67
70
  const state = { inBlockComment: false };
68
71
  for (let lineNumber = scan.startLine; lineNumber <= scan.endLine; lineNumber += 1) {
69
72
  const scanLine = maskDependencyLine(input, lines[lineNumber - 1]?.line ?? '', state);
73
+ addLightweightSemanticFacts(input, documentId, scan.declaration, scanLine, lineNumber, records);
70
74
  for (const match of scanLine.matchAll(/[A-Za-z_$][\w$]*/g)) {
71
75
  const name = match[0];
72
76
  if (!isDependencyIdentifier(name) || !identifiers.has(name)) continue;
@@ -83,6 +87,68 @@ function scanDeclarationDependencies(input, documentId, scan, identifiers, lines
83
87
  }
84
88
  }
85
89
 
90
+ function addLightweightSemanticFacts(input, documentId, declaration, line, lineNumber, records) {
91
+ const text = String(line ?? '').trim();
92
+ if (!text) return;
93
+ for (const item of lightweightControlFlowKinds(text)) {
94
+ addFactRecord(input, documentId, declaration, 'controlFlow', item, lineNumber, records);
95
+ }
96
+ for (const item of lightweightEffectKinds(text)) {
97
+ addFactRecord(input, documentId, declaration, 'effect', item, lineNumber, records);
98
+ }
99
+ for (const item of lightweightMutationKinds(text)) {
100
+ addFactRecord(input, documentId, declaration, 'mutation', item, lineNumber, records);
101
+ }
102
+ }
103
+
104
+ function lightweightControlFlowKinds(line) {
105
+ const kinds = [];
106
+ if (/\b(if|else|switch|case|default)\b/.test(line)) kinds.push('branch');
107
+ if (/\b(for|while|do)\b/.test(line)) kinds.push('loop');
108
+ if (/\b(return|yield)\b/.test(line)) kinds.push('exit');
109
+ if (/\b(throw|catch|finally|try)\b/.test(line)) kinds.push('exception');
110
+ if (/\b(await|async)\b/.test(line)) kinds.push('async');
111
+ return kinds;
112
+ }
113
+
114
+ function lightweightEffectKinds(line) {
115
+ const kinds = [];
116
+ if (/\bawait\b|import\s*\(/.test(line)) kinds.push('async');
117
+ if (/\b(fetch|XMLHttpRequest|WebSocket|EventSource)\s*\(/.test(line)) kinds.push('network');
118
+ if (/\b(localStorage|sessionStorage|indexedDB|caches|cookie)\b/.test(line)) kinds.push('storage');
119
+ if (/\b(setTimeout|setInterval|requestAnimationFrame|queueMicrotask)\s*\(/.test(line)) kinds.push('scheduler');
120
+ if (/\b(console|process|Deno|Bun)\s*\./.test(line)) kinds.push('host');
121
+ if (/\b(document|window|navigator|location|history)\s*\./.test(line)) kinds.push('browser');
122
+ return kinds;
123
+ }
124
+
125
+ function lightweightMutationKinds(line) {
126
+ const kinds = [];
127
+ if (/\bdelete\s+[A-Za-z_$][\w$.[\]]*/.test(line)) kinds.push('delete');
128
+ if (/(?:^|[^=!<>])=(?!=|>)/.test(line)) kinds.push('assignment');
129
+ if (/\+\+|--|(?:\+=|-=|\*=|\/=|%=|\|\|=|&&=|\?\?=)/.test(line)) kinds.push('update');
130
+ if (/\.(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\s*\(/.test(line)) kinds.push('mutating-call');
131
+ return kinds;
132
+ }
133
+
134
+ function addFactRecord(input, documentId, declaration, predicate, factKind, lineNumber, records) {
135
+ const key = `${declaration.symbolId}|${predicate}|${factKind}|${lineNumber}`;
136
+ if (records.seen.has(key)) return;
137
+ records.seen.add(key);
138
+ records.facts.push({
139
+ id: `fact_${idFragment(declaration.symbolId)}_${predicate}_${idFragment(factKind)}_${lineNumber}`,
140
+ predicate,
141
+ subjectId: declaration.symbolId,
142
+ value: {
143
+ kind: factKind,
144
+ line: lineNumber,
145
+ sourcePath: input.sourcePath,
146
+ documentId,
147
+ confidence: 'lexical-source-scan'
148
+ }
149
+ });
150
+ }
151
+
86
152
  function addDependencyRecord(input, documentId, caller, target, occurrence, records) {
87
153
  const predicate = isCallReference(occurrence.line, occurrence.startColumn + occurrence.name.length - 1) ? 'calls' : 'uses';
88
154
  const key = `${caller.symbolId}|${predicate}|${target.symbolId}|${occurrence.lineNumber}|${occurrence.startColumn}`;
@@ -11,6 +11,7 @@ import {
11
11
  function semanticImportSidecarEntry(imported, index, options) {
12
12
  const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
13
13
  const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
14
+ const semanticFacts = semanticIndex?.facts ?? [];
14
15
  const sourceMaps = imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [];
15
16
  const sourceMapMappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
16
17
  const sourcePreservationRecords = collectKernelSourcePreservationFromImport(imported);
@@ -18,6 +19,7 @@ function semanticImportSidecarEntry(imported, index, options) {
18
19
  const proofSpec = summarizeProofSpecLayer(imported?.universalAst?.proof ?? imported?.proof);
19
20
  const paradigmSemantics = summarizeParadigmSemanticsLayer(imported?.universalAst?.paradigmSemantics ?? imported?.paradigmSemantics);
20
21
  const dependencies = summarizeSemanticImportDependencyRelations(semanticIndex?.relations ?? []);
22
+ const factSummary = summarizeSemanticFacts(semanticFacts);
21
23
  const readiness = semanticImportEntryReadiness(imported);
22
24
  const mappingsBySymbolId = new Map();
23
25
  for (const mapping of sourceMapMappings) {
@@ -72,6 +74,9 @@ function semanticImportSidecarEntry(imported, index, options) {
72
74
  paradigmSemantics,
73
75
  dependencyRelationCount: dependencies.total,
74
76
  dependencyPredicates: dependencies.predicates,
77
+ semanticFactCount: semanticFacts.length,
78
+ semanticFactPredicates: factSummary.predicates,
79
+ semanticFactSummary: factSummary.byPredicate,
75
80
  readiness,
76
81
  emptySemanticIndex: symbols.length === 0,
77
82
  regionTaxonomy,
@@ -90,4 +95,14 @@ function semanticImportEntryReadiness(imported) {
90
95
  return readiness ?? 'needs-review';
91
96
  }
92
97
 
98
+ function summarizeSemanticFacts(facts) {
99
+ const byPredicate = {};
100
+ for (const fact of facts ?? []) {
101
+ const predicate = String(fact?.predicate ?? '').trim();
102
+ if (!predicate) continue;
103
+ byPredicate[predicate] = (byPredicate[predicate] ?? 0) + 1;
104
+ }
105
+ return { byPredicate, predicates: Object.keys(byPredicate).sort() };
106
+ }
107
+
93
108
  export { semanticImportSidecarEntry };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.70",
3
+ "version": "0.2.71",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",