@shapeshift-labs/frontier-lang-compiler 0.2.48 → 0.2.50
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 +25 -0
- package/bench/native-transform-suite.mjs +19 -0
- package/bench/smoke.mjs +7 -0
- package/dist/declarations/runtime.d.ts +12 -0
- package/dist/declarations/universal-conversion-artifacts.d.ts +148 -0
- package/dist/declarations/universal-conversion-plan.d.ts +203 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/internal/index-impl/createUniversalConversionPlan.js +5 -0
- package/dist/internal/index-impl/queryUniversalConversionPlan.js +5 -0
- package/dist/universal-conversion-artifact-query.js +60 -0
- package/dist/universal-conversion-artifacts.js +287 -0
- package/dist/universal-conversion-plan-merge-refs.js +125 -0
- package/dist/universal-conversion-plan-scoring.js +134 -0
- package/dist/universal-conversion-plan.js +279 -0
- package/package.json +1 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import {
|
|
2
|
+
idFragment,
|
|
3
|
+
maxSemanticMergeReadiness,
|
|
4
|
+
normalizeNativeLanguageId,
|
|
5
|
+
uniqueStrings
|
|
6
|
+
} from './native-import-utils.js';
|
|
7
|
+
import {
|
|
8
|
+
nativeLanguageCompileTarget,
|
|
9
|
+
normalizeProjectionMatrixTargets
|
|
10
|
+
} from './coverage-matrix-profiles.js';
|
|
11
|
+
import { createUniversalCapabilityMatrix } from './universal-capability-matrix.js';
|
|
12
|
+
import {
|
|
13
|
+
conversionMergeRefs,
|
|
14
|
+
importsForConversionLanguage
|
|
15
|
+
} from './universal-conversion-plan-merge-refs.js';
|
|
16
|
+
import {
|
|
17
|
+
conversionMergeScore,
|
|
18
|
+
conversionScoreComponents
|
|
19
|
+
} from './universal-conversion-plan-scoring.js';
|
|
20
|
+
|
|
21
|
+
export function createUniversalConversionPlan(input = {}, context = {}) {
|
|
22
|
+
const generatedAt = input.generatedAt ?? Date.now();
|
|
23
|
+
const id = input.id ?? conversionPlanId(input, generatedAt);
|
|
24
|
+
const matrix = input.universalCapabilityMatrix?.kind === 'frontier.lang.universalCapabilityMatrix'
|
|
25
|
+
? input.universalCapabilityMatrix
|
|
26
|
+
: createUniversalCapabilityMatrix({ ...input, generatedAt }, context);
|
|
27
|
+
const targets = conversionTargets(input, matrix, context);
|
|
28
|
+
const evidence = input.evidence ?? [];
|
|
29
|
+
const routes = (matrix.languages ?? []).flatMap((language) => targets.map((target) => conversionRoute(language, target, {
|
|
30
|
+
evidence,
|
|
31
|
+
generatedAt,
|
|
32
|
+
imports: input.imports ?? [],
|
|
33
|
+
matrix
|
|
34
|
+
}, id)));
|
|
35
|
+
return {
|
|
36
|
+
kind: 'frontier.lang.universalConversionPlan',
|
|
37
|
+
version: 1,
|
|
38
|
+
id,
|
|
39
|
+
generatedAt,
|
|
40
|
+
routes,
|
|
41
|
+
summary: conversionPlanSummary(routes),
|
|
42
|
+
matrices: {
|
|
43
|
+
universalCapability: matrix,
|
|
44
|
+
projectionReadiness: matrix.matrices?.projectionReadiness,
|
|
45
|
+
projectionTargets: matrix.matrices?.projectionTargets
|
|
46
|
+
},
|
|
47
|
+
metadata: {
|
|
48
|
+
compileTargets: targets,
|
|
49
|
+
requiredFeatures: matrix.metadata?.requiredFeatures ?? [],
|
|
50
|
+
autoMergeClaim: false,
|
|
51
|
+
semanticEquivalenceClaim: false,
|
|
52
|
+
note: 'Conversion plans rank source-to-target routes and missing evidence for agent coordination. They do not prove semantic equivalence or grant auto-merge.'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function queryUniversalConversionPlan(planOrInput = {}, query = {}, context = {}) {
|
|
58
|
+
const plan = planOrInput?.kind === 'frontier.lang.universalConversionPlan'
|
|
59
|
+
? planOrInput
|
|
60
|
+
: createUniversalConversionPlan(planOrInput, context);
|
|
61
|
+
const sourceLanguage = normalizeNativeLanguageId(query.sourceLanguage ?? query.language);
|
|
62
|
+
const target = normalizeProjectionMatrixTargets(query.target ? [query.target] : [])[0];
|
|
63
|
+
const routes = (plan.routes ?? []).filter((route) => {
|
|
64
|
+
if (sourceLanguage && !route.languageIds.includes(sourceLanguage)) return false;
|
|
65
|
+
if (target && route.target !== target) return false;
|
|
66
|
+
if (query.mode && route.mode !== query.mode) return false;
|
|
67
|
+
if (query.readiness && route.readiness !== query.readiness) return false;
|
|
68
|
+
if (query.admissionAction && route.admissionAction !== query.admissionAction) return false;
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
kind: 'frontier.lang.universalConversionPlanQuery',
|
|
73
|
+
version: 1,
|
|
74
|
+
found: routes.length > 0,
|
|
75
|
+
routes,
|
|
76
|
+
bestRoute: routes.slice().sort((a, b) => b.mergeScore.sortKey - a.mergeScore.sortKey)[0],
|
|
77
|
+
reasons: routes.length ? [] : [`No conversion route matched source=${query.sourceLanguage ?? query.language ?? '*'} target=${query.target ?? '*'}.`]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function conversionTargets(input, matrix, context) {
|
|
82
|
+
const explicit = normalizeProjectionMatrixTargets(input.targets ?? []);
|
|
83
|
+
if (explicit.length) return explicit;
|
|
84
|
+
const matrixTargets = normalizeProjectionMatrixTargets(matrix.metadata?.compileTargets ?? []);
|
|
85
|
+
if (matrixTargets.length) return matrixTargets;
|
|
86
|
+
return normalizeProjectionMatrixTargets(context.compileTargets ?? []);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function conversionRoute(language, target, input, planId) {
|
|
90
|
+
const sourceTarget = nativeLanguageCompileTarget(language.language, language.aliases) ?? normalizeNativeLanguageId(language.language);
|
|
91
|
+
const targetCell = (language.projection?.targets ?? []).find((entry) => entry.target === target);
|
|
92
|
+
const readinessCell = projectionReadinessCell(input.matrix, language, target);
|
|
93
|
+
const mode = conversionMode(language, target, sourceTarget, targetCell);
|
|
94
|
+
const blockers = conversionBlockers(language, targetCell, mode);
|
|
95
|
+
const review = conversionReviewReasons(language, targetCell, mode);
|
|
96
|
+
const readiness = blockers.length
|
|
97
|
+
? 'blocked'
|
|
98
|
+
: maxSemanticMergeReadiness(language.readiness, targetCell?.readiness ?? readinessCell?.readiness ?? 'needs-review');
|
|
99
|
+
const components = conversionScoreComponents(language, targetCell, readiness, mode, input.evidence);
|
|
100
|
+
const mergeScore = conversionMergeScore({ readiness, mode, components, blockers, review });
|
|
101
|
+
const id = `conversion_${idFragment(language.language)}_to_${idFragment(target)}`;
|
|
102
|
+
const routeImports = importsForConversionLanguage(input.imports, language);
|
|
103
|
+
return {
|
|
104
|
+
id,
|
|
105
|
+
sourceLanguage: language.language,
|
|
106
|
+
languageIds: uniqueStrings([language.language, ...(language.aliases ?? [])].map(normalizeNativeLanguageId)),
|
|
107
|
+
target,
|
|
108
|
+
mode,
|
|
109
|
+
routeAction: conversionRouteAction(mode, targetCell, readiness),
|
|
110
|
+
admissionAction: mergeScore.action,
|
|
111
|
+
priority: conversionPriority(mergeScore.action, readiness, mode),
|
|
112
|
+
readiness,
|
|
113
|
+
lossClass: mode === 'preserve-source' ? 'exactSourceProjection' : targetCell?.lossClass ?? 'missingAdapter',
|
|
114
|
+
adapter: targetCell?.adapter,
|
|
115
|
+
adapterKind: targetCell?.adapterKind,
|
|
116
|
+
sourceProjection: language.projection?.sourceProjection,
|
|
117
|
+
projectionReadiness: readinessCell,
|
|
118
|
+
evidence: conversionEvidence(language, targetCell),
|
|
119
|
+
missingEvidence: conversionMissingEvidence(language, targetCell, mode),
|
|
120
|
+
blockers,
|
|
121
|
+
review,
|
|
122
|
+
tasks: conversionTasks(language, target, mode, blockers, review),
|
|
123
|
+
mergeScore,
|
|
124
|
+
mergeRefs: conversionMergeRefs({
|
|
125
|
+
planId,
|
|
126
|
+
routeId: id,
|
|
127
|
+
imports: routeImports,
|
|
128
|
+
readiness,
|
|
129
|
+
admissionStatus: mergeScore.action
|
|
130
|
+
}),
|
|
131
|
+
autoMergeClaim: false,
|
|
132
|
+
semanticEquivalenceClaim: false,
|
|
133
|
+
metadata: {
|
|
134
|
+
generatedAt: input.generatedAt,
|
|
135
|
+
note: 'Route readiness is merge-review evidence for a conversion attempt, not proof that emitted target code is semantically equivalent.'
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function conversionPlanId(input, generatedAt) {
|
|
141
|
+
const languages = uniqueStrings((input.imports ?? []).map((imported) => imported?.language ?? imported?.nativeAst?.language));
|
|
142
|
+
const targets = normalizeProjectionMatrixTargets(input.targets ?? []);
|
|
143
|
+
return `universal_conversion_plan_${idFragment([...languages, 'to', ...targets, String(generatedAt)].join('_'))}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function conversionMode(language, target, sourceTarget, targetCell) {
|
|
147
|
+
const exactSourceImports = language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0;
|
|
148
|
+
if (target === sourceTarget && exactSourceImports > 0) return 'preserve-source';
|
|
149
|
+
if (targetCell?.lossClass === 'targetAdapterProjection') return 'target-adapter';
|
|
150
|
+
if (targetCell?.lossClass === 'nativeSourceStubs') return 'stub-only';
|
|
151
|
+
if (targetCell?.lossClass === 'unsupportedTargetFeatures') return 'target-adapter';
|
|
152
|
+
if ((language.imports?.symbols ?? 0) > 0 && targetCell?.lossClass === 'missingAdapter') return 'semantic-index-only';
|
|
153
|
+
return 'blocked';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function conversionBlockers(language, targetCell, mode) {
|
|
157
|
+
return uniqueStrings([
|
|
158
|
+
...(language.imports.total === 0 ? ['No source import exists for this language.'] : []),
|
|
159
|
+
...(mode === 'blocked' ? ['No viable preserve, adapter, stub, or semantic-index conversion route exists.'] : []),
|
|
160
|
+
...(targetCell?.lossClass === 'missingAdapter' && mode !== 'semantic-index-only' ? [targetCell.reason] : []),
|
|
161
|
+
...(language.blockers ?? []).filter((reason) => !reason.includes('Missing native-to-target projection adapter'))
|
|
162
|
+
]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function conversionReviewReasons(language, targetCell, mode) {
|
|
166
|
+
return uniqueStrings([
|
|
167
|
+
...(language.review ?? []),
|
|
168
|
+
...(targetCell?.reason ? [targetCell.reason] : []),
|
|
169
|
+
...(mode === 'stub-only' ? ['Route can emit declaration stubs only; executable semantics require a target adapter.'] : []),
|
|
170
|
+
...(mode === 'semantic-index-only' ? ['Route has semantic index evidence but no target code projection adapter.'] : []),
|
|
171
|
+
...(mode === 'target-adapter' ? ['Host target adapter evidence must be reviewed before accepting emitted target code.'] : [])
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function projectionReadinessCell(matrix, language, target) {
|
|
176
|
+
const ids = uniqueStrings([language.language, ...(language.aliases ?? [])].map(normalizeNativeLanguageId));
|
|
177
|
+
return (matrix.matrices?.projectionReadiness?.languages ?? [])
|
|
178
|
+
.find((row) => ids.includes(normalizeNativeLanguageId(row.language)))
|
|
179
|
+
?.targets?.find((entry) => entry.target === target);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function conversionRouteAction(mode, targetCell, readiness) {
|
|
183
|
+
if (mode === 'blocked') return 'blocked';
|
|
184
|
+
if (mode === 'preserve-source') return 'preserve-source';
|
|
185
|
+
if (mode === 'stub-only') return 'emit-stub';
|
|
186
|
+
if (mode === 'semantic-index-only') return 'add-target-adapter';
|
|
187
|
+
if (targetCell?.lossClass === 'unsupportedTargetFeatures') return 'attach-adapter-evidence';
|
|
188
|
+
return 'run-target-adapter';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function conversionPriority(action, readiness, mode) {
|
|
192
|
+
if (action === 'reject' || readiness === 'blocked') return 'blocker';
|
|
193
|
+
if (mode === 'semantic-index-only' || readiness === 'needs-review') return 'high';
|
|
194
|
+
if (mode === 'stub-only' || readiness === 'ready-with-losses') return 'normal';
|
|
195
|
+
return 'low';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function conversionEvidence(language, targetCell) {
|
|
199
|
+
return {
|
|
200
|
+
imports: language.imports.total,
|
|
201
|
+
importReadiness: language.imports.readiness,
|
|
202
|
+
symbols: language.imports.symbols,
|
|
203
|
+
sourceMaps: language.imports.sourceMaps,
|
|
204
|
+
sourceMapMappings: language.imports.sourceMapMappings,
|
|
205
|
+
losses: language.imports.losses,
|
|
206
|
+
parserRows: language.parser.rows,
|
|
207
|
+
mergeReadyParsers: language.parser.mergeReadyParsers.length,
|
|
208
|
+
exactSourceImports: language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0,
|
|
209
|
+
declarationImports: language.projection?.sourceProjection?.stubs?.evidence?.importsWithDeclarations ?? 0,
|
|
210
|
+
targetSupported: targetCell?.supported === true,
|
|
211
|
+
targetAdapter: targetCell?.adapter,
|
|
212
|
+
targetLossKinds: targetCell?.lossKinds ?? []
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function conversionMissingEvidence(language, targetCell, mode) {
|
|
217
|
+
return uniqueStrings([
|
|
218
|
+
...(language.imports.total ? [] : ['source-import']),
|
|
219
|
+
...(language.imports.symbols ? [] : ['semantic-index']),
|
|
220
|
+
...(language.imports.sourceMapMappings ? [] : ['source-map']),
|
|
221
|
+
...(language.parser.mergeReadyParsers.length ? [] : ['merge-ready-parser']),
|
|
222
|
+
...((language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0) ? [] : ['source-preservation-hash']),
|
|
223
|
+
...(mode === 'target-adapter' && !targetCell?.adapter ? ['target-adapter-evidence'] : []),
|
|
224
|
+
...(mode === 'semantic-index-only' || targetCell?.lossClass === 'missingAdapter' ? ['target-adapter'] : []),
|
|
225
|
+
...(mode === 'stub-only' ? ['executable-target-semantics'] : []),
|
|
226
|
+
['proof-or-replay-evidence']
|
|
227
|
+
]);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function conversionTasks(language, target, mode, blockers, review) {
|
|
231
|
+
return uniqueStrings([
|
|
232
|
+
...(language.imports.total ? [] : [`import ${language.language} source before planning ${target} output`]),
|
|
233
|
+
...(language.imports.symbols ? [] : [`attach semantic index for ${language.language}`]),
|
|
234
|
+
...(language.parser.mergeReadyParsers.length ? [] : [`provide merge-ready parser evidence for ${language.language}`]),
|
|
235
|
+
...(mode === 'semantic-index-only' || mode === 'blocked' ? [`add ${language.language} to ${target} target adapter`] : []),
|
|
236
|
+
...(mode === 'stub-only' ? [`replace ${target} declaration stubs with executable adapter output`] : []),
|
|
237
|
+
...(mode === 'target-adapter' ? [`run and verify ${language.language} to ${target} target adapter`] : []),
|
|
238
|
+
...(blockers.length || review.length ? [`collect proof, replay, or oracle evidence for ${language.language} to ${target}`] : [])
|
|
239
|
+
]);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function conversionPlanSummary(routes) {
|
|
243
|
+
const summary = {
|
|
244
|
+
routes: routes.length,
|
|
245
|
+
byMode: {},
|
|
246
|
+
byReadiness: {},
|
|
247
|
+
byAdmissionAction: {},
|
|
248
|
+
readyRoutes: 0,
|
|
249
|
+
reviewRoutes: 0,
|
|
250
|
+
blockedRoutes: 0,
|
|
251
|
+
preserveSourceRoutes: 0,
|
|
252
|
+
targetAdapterRoutes: 0,
|
|
253
|
+
stubOnlyRoutes: 0,
|
|
254
|
+
semanticIndexOnlyRoutes: 0,
|
|
255
|
+
missingEvidence: 0,
|
|
256
|
+
blockers: 0,
|
|
257
|
+
reviewReasons: 0,
|
|
258
|
+
autoMergeClaims: 0,
|
|
259
|
+
semanticEquivalenceClaims: 0
|
|
260
|
+
};
|
|
261
|
+
for (const route of routes) {
|
|
262
|
+
summary.byMode[route.mode] = (summary.byMode[route.mode] ?? 0) + 1;
|
|
263
|
+
summary.byReadiness[route.readiness] = (summary.byReadiness[route.readiness] ?? 0) + 1;
|
|
264
|
+
summary.byAdmissionAction[route.admissionAction] = (summary.byAdmissionAction[route.admissionAction] ?? 0) + 1;
|
|
265
|
+
if (route.readiness === 'ready') summary.readyRoutes += 1;
|
|
266
|
+
if (route.readiness === 'needs-review' || route.readiness === 'ready-with-losses') summary.reviewRoutes += 1;
|
|
267
|
+
if (route.readiness === 'blocked') summary.blockedRoutes += 1;
|
|
268
|
+
if (route.mode === 'preserve-source') summary.preserveSourceRoutes += 1;
|
|
269
|
+
if (route.mode === 'target-adapter') summary.targetAdapterRoutes += 1;
|
|
270
|
+
if (route.mode === 'stub-only') summary.stubOnlyRoutes += 1;
|
|
271
|
+
if (route.mode === 'semantic-index-only') summary.semanticIndexOnlyRoutes += 1;
|
|
272
|
+
summary.missingEvidence += route.missingEvidence.length;
|
|
273
|
+
summary.blockers += route.blockers.length;
|
|
274
|
+
summary.reviewReasons += route.review.length;
|
|
275
|
+
if (route.autoMergeClaim) summary.autoMergeClaims += 1;
|
|
276
|
+
if (route.semanticEquivalenceClaim) summary.semanticEquivalenceClaims += 1;
|
|
277
|
+
}
|
|
278
|
+
return summary;
|
|
279
|
+
}
|
package/package.json
CHANGED