@shapeshift-labs/frontier-lang-parser 0.3.31 → 0.3.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -367,7 +367,7 @@ target rust @id("target_rust") {
367
367
  }
368
368
  ```
369
369
 
370
- The parser stores these rows on the target node metadata as `projectionContracts` and `projectionLayers`. They are target-lowering evidence, not proof of equivalence: `autoMergeClaim` and `semanticEquivalenceClaim` remain false.
370
+ The parser stores these rows on the target node metadata as `projectionContracts` and `projectionLayers`, then aggregates them into `metadata.targetProjections` and mirrors that aggregate under `metadata.universalAst.targetProjections` with target ids, target languages, emit paths, adapter ids, represented/missing layers, evidence ids, proof evidence ids, loss ids, and missing evidence. They are target-lowering evidence, not proof of equivalence: `autoMergeClaim` and `semanticEquivalenceClaim` remain false on rows and aggregates.
371
371
 
372
372
  ## Authored decision graph syntax
373
373
 
@@ -473,7 +473,7 @@ conversion TodoJavascriptToRust @id("conversion_todo_js_rust") {
473
473
 
474
474
  `sourceRuntime` and `targetRuntime` become runtime maps. `runtimeRequirement` rows become proof obligations for host/runtime capabilities, including authored `requiredSignals` denominators such as source hashes, target hashes, probe ids, runtime commands, telemetry hashes, and capability-specific trace hashes. `proofEvidence` and `evidence` attach evidence ids, but the compiler still requires bound evidence records before a proof obligation is satisfied. `dialect` and `extern` rows preserve dialect-specific constructs, projection readiness, loss/evidence ids, and binding metadata without requiring the authored Frontier file to drop down to raw JSON.
475
475
 
476
- `constraint` rows accept every universal conversion constraint family used by route admission, including hyphenated spellings such as `module-constraint`, `scope-binding`, `memory-model`, `effect-constraint`, `control-flow`, `borrow-scope`, `borrow-checker`, `host-environment`, `callable-boundary`, `adt-pattern`, `data-layout`, `numeric-semantics`, `text-semantics`, `collection-semantics`, `serialization-semantics`, `dependency-semantics`, `object-model`, and `protocol`. The parser preserves family-specific fields such as module specifiers, package conditions, binding/reference ids, memory ordering, locks, capabilities, host permissions, callable signatures, pattern exhaustiveness, ABI/layout hints, numeric/text/collection behavior, wire formats, dependency lockfile evidence, and effect adapters as authored evidence inputs. Record-level targets use explicit labels such as `effectTarget` so `role target` rows cannot be mistaken for an authored target field. These rows do not prove translation equivalence; they make the required proof surface explicit for downstream gates and admission records.
476
+ `constraint` rows accept every universal conversion constraint family used by route admission, including hyphenated spellings such as `module-constraint`, `scope-binding`, `memory-model`, `effect-constraint`, `control-flow`, `borrow-scope`, `borrow-checker`, `host-environment`, `callable-boundary`, `adt-pattern`, `data-layout`, `layout-style`, `layout`, `style`, `numeric-semantics`, `text-semantics`, `collection-semantics`, `serialization-semantics`, `dependency-semantics`, `object-model`, and `protocol`. The parser preserves family-specific fields such as module specifiers, package conditions, binding/reference ids, memory ordering, locks, capabilities, host permissions, callable signatures, pattern exhaustiveness, ABI/layout hints, selector/style/cascade/layout evidence, numeric/text/collection behavior, wire formats, dependency lockfile evidence, and effect adapters as authored evidence inputs. Constraint entries and family-specific records can also carry `sourceMap`, `sourceMapMapping`, `proofObligation`, `proofEvidence`, `missingEvidence`, and `failClosed` so downstream compiler, merge, and admission tooling can keep source-bound denominators visible. Record-level targets use explicit labels such as `effectTarget` so `role target` rows cannot be mistaken for an authored target field. These rows do not prove translation equivalence; they make the required proof surface explicit for downstream gates and admission records.
477
477
 
478
478
  ## Authored runtime capability syntax
479
479
 
@@ -8,6 +8,7 @@ const FAMILY_ROWS = [
8
8
  ['callableBoundary', 'callableBoundaryConstraints', 'sourceCallables', 'targetCallables', ['callableBoundaryConstraint', 'callable-boundary', 'callable-boundary-constraint'], { extraSourceKeys: ['sourceCallableBoundaryRecords'], extraTargetKeys: ['targetCallableBoundaryRecords'] }],
9
9
  ['adtPattern', 'adtPatternConstraints', 'sourcePatterns', 'targetPatterns', ['adtPatternConstraint', 'adt-pattern', 'adt-pattern-constraint'], { extraSourceKeys: ['sourceAdtPatternRecords'], extraTargetKeys: ['targetAdtPatternRecords'] }],
10
10
  ['dataLayout', 'dataLayoutConstraints', 'sourceLayouts', 'targetLayouts', ['dataLayoutConstraint', 'data-layout', 'data-layout-constraint'], { extraSourceKeys: ['sourceDataLayoutRecords'], extraTargetKeys: ['targetDataLayoutRecords'] }],
11
+ ['layoutStyle', 'layoutStyleConstraints', 'sourceLayoutStyles', 'targetLayoutStyles', ['layoutStyleConstraint', 'layout-style', 'layout-style-constraint', 'layout', 'layoutConstraint', 'layout-constraint', 'style', 'styleConstraint', 'style-constraint', 'css-style', 'css-rule', 'style-layout', 'render-layout'], { extraSourceKeys: ['sourceLayoutStyleRecords'], extraTargetKeys: ['targetLayoutStyleRecords'] }],
11
12
  ['effect', 'effectConstraints', 'sourceEffects', 'targetEffects', ['effectConstraint', 'effect-constraint']],
12
13
  ['concurrencyModel', 'concurrencyModelConstraints', 'sourceConcurrencyModels', 'targetConcurrencyModels', ['concurrencyModelConstraint', 'concurrency-model', 'concurrency-model-constraint'], { extraSourceKeys: ['sourceConcurrencyModelRecords'], extraTargetKeys: ['targetConcurrencyModelRecords'] }],
13
14
  ['errorModel', 'errorModelConstraints', 'sourceErrors', 'targetErrors', ['errorModelConstraint', 'error-model', 'error-model-constraint'], { extraSourceKeys: ['sourceErrorModelRecords'], extraTargetKeys: ['targetErrorModelRecords'] }],
@@ -48,7 +49,7 @@ const WORD_FIELDS = [
48
49
  ['controlFlowKind'], ['sourceControlFlowId'], ['sourceId', 'from', 'sourceId'], ['targetId', 'to', 'targetId'], ['label'],
49
50
  ['conditionHash'], ['orderingKey', 'orderingKey', 'orderKey'], ['lifetimeKind'], ['lifetimeRegionId', 'lifetimeRegion', 'lifetimeRegionId'],
50
51
  ['regionKind'], ['resourceId', 'resource', 'resourceId'],
51
- ['functionName'], ['methodName'], ['callableName'], ['callableKind'], ['callSignatureHash'],
52
+ ['functionName'], ['methodName'], ['callableName'], ['callableKind'], ['callSignatureHash'], ['restParameter', 'restParameter', 'rest'],
52
53
  ['receiverKind', 'receiverKind', 'receiver'], ['thisBinding'], ['selfBinding'], ['returnKind', 'returnKind', 'returnType'],
53
54
  ['asyncKind', 'asyncKind', 'asyncMode'], ['generatorKind', 'generatorKind', 'yieldKind'], ['callbackKind'],
54
55
  ['closureCapture', 'closureCapture', 'captureKind'], ['overloadSet', 'overloadSet', 'overloads'],
@@ -57,7 +58,7 @@ const WORD_FIELDS = [
57
58
  ['symbolKind'], ['relationKind'], ['representationKind'], ['typeId', 'typeId', 'nodeId'], ['nodeId'], ['structId'], ['unionId'],
58
59
  ['enumId'], ['fieldId'], ['bitfieldId'], ['endianness', 'endianness', 'endian'], ['repr', 'repr', 'reprAttribute'],
59
60
  ['numericKind', 'numericKind', 'numberKind'], ['numberKind'], ['numericTypeName'], ['signedness'], ['overflowMode', 'overflowMode', 'overflowBehavior'],
60
- ['divisionMode', 'divisionMode', 'integerDivisionMode'], ['moduloMode', 'moduloMode', 'remainderMode'], ['floatPrecision'], ['roundingMode'],
61
+ ['divisionMode', 'divisionMode', 'integerDivisionMode'], ['moduloMode', 'moduloMode', 'remainderMode'], ['floatFormat'], ['floatPrecision'], ['roundingMode'],
61
62
  ['separatorPolicy'], ['coercionKind', 'coercionKind', 'conversionKind'], ['conversionKind'], ['literalKind'],
62
63
  ['textKind', 'textKind', 'stringKind'], ['stringKind'], ['stringTypeName'], ['encoding', 'encoding', 'charset', 'codepage'],
63
64
  ['charset'], ['codepage'], ['codeUnit', 'codeUnit', 'codeUnitWidth'], ['indexingUnit', 'indexingUnit', 'indexUnit'],
@@ -83,15 +84,19 @@ const WORD_FIELDS = [
83
84
  ['buildTool', 'buildTool', 'builder'], ['packageManagerVersion', 'packageManagerVersion', 'managerVersion'],
84
85
  ['offlineCache', 'offlineCache', 'cachePolicy'], ['dedupeHoist', 'dedupeHoist', 'hoistPolicy'], ['provenance', 'provenance', 'sourceProvenance'],
85
86
  ['trust', 'trust', 'supplyChainTrust'], ['concurrencyKind'], ['constructId', 'constructId', 'taskId', 'threadId', 'actorId', 'channelId'],
86
- ['taskId'], ['threadId'], ['executor', 'executor', 'queue', 'runtime'], ['executorId'], ['isolationKey'], ['cancellationKey', 'cancellationKey', 'signalId', 'contextId'],
87
+ ['taskId'], ['threadId'], ['scheduler'], ['executor', 'executor', 'queue', 'runtime'], ['executorId'], ['isolationKey'], ['cancellationKey', 'cancellationKey', 'signalId', 'contextId'],
87
88
  ['signalId'], ['contextId'], ['errorKind'], ['errorType', 'errorType', 'exceptionType', 'resultType'], ['exceptionType'], ['resultType'],
88
89
  ['boundaryId', 'boundaryId', 'catchId', 'handlerId'], ['catchId'], ['handlerId'], ['evaluationKind', 'evaluationKind', 'expressionKind'],
89
90
  ['expressionKind'], ['expressionId', 'expressionId', 'nodeId'], ['operator'], ['evaluationOrder', 'evaluationOrder', 'order'],
90
91
  ['expansionKind', 'expansionKind', 'macroKind', 'templateKind', 'decoratorKind', 'generatorKind'], ['macroKind'], ['templateKind'],
91
92
  ['decoratorKind'], ['expansionId'], ['generatorId'], ['generatedSourcePath'], ['expandedHash', 'expandedHash', 'generatedHash'],
92
- ['generatedHash'], ['classId'], ['classKind'], ['prototypeId'], ['mixinId'], ['constructorId'], ['inheritanceKind'], ['referenceSemantics'],
93
+ ['generatedHash'], ['classId'], ['classKind'], ['prototypeId'], ['mixinId'], ['methodId'], ['constructorId'], ['inheritanceKind'], ['referenceSemantics'],
93
94
  ['valueSemantics'], ['protocolKind'], ['protocolName'], ['traitName'], ['interfaceName'], ['subjectName', 'subjectName', 'receiverName', 'implementedFor'],
94
- ['implementedFor'], ['sourcePath', 'sourcePath', 'path'], ['sourceHash'], ['target', 'effectTarget', 'targetResource']
95
+ ['implementedFor'], ['sourcePath', 'sourcePath', 'path'], ['sourceHash'], ['selector'], ['value'], ['styleProperty', 'styleProperty', 'property', 'cssProperty'],
96
+ ['cssProperty', 'cssProperty', 'styleProperty', 'property'], ['computedValue'], ['cascadeLayer'], ['specificity'], ['mediaQuery'],
97
+ ['containerQuery'], ['boxModel'], ['display'], ['position'], ['zIndex'], ['writingMode'], ['direction'], ['viewport'], ['renderTreeId'],
98
+ ['styleRuleId'], ['computedStyleHash'], ['layoutSnapshotHash'], ['bitmapHash'], ['accessibilityTreeHash'], ['focusOrderHash'],
99
+ ['target', 'effectTarget', 'targetResource']
95
100
  ];
96
101
  const LIST_FIELDS = [
97
102
  ['factKinds', 'fact', 'facts', 'factKind', 'factKinds'], ['importAttributes', 'importAttribute', 'importAttributes', 'assertion', 'assertions'],
@@ -108,14 +113,20 @@ const LIST_FIELDS = [
108
113
  ['devDependencies'], ['features', 'features', 'extras', 'flags'], ['lifecycleScripts', 'lifecycleScripts', 'scripts'],
109
114
  ['requirementNames', 'requirementNames', 'requirements', 'methods', 'members'], ['associatedTypeNames', 'associatedTypeNames', 'associatedTypes'],
110
115
  ['boundNames', 'boundNames', 'bounds', 'traitBounds', 'protocolBounds', 'whereBounds'], ['implementationKinds', 'implementationKinds', 'implKinds', 'implementations'],
111
- ['dispatchKinds', 'dispatchKinds', 'dispatchModes'], ['coherenceKinds', 'coherenceKinds', 'coherenceRules'], ['evidenceIds', 'evidence', 'evidenceIds']
116
+ ['dispatchKinds', 'dispatchKinds', 'dispatchModes'], ['coherenceKinds', 'coherenceKinds', 'coherenceRules'],
117
+ ['sourceMapIds', 'sourceMap', 'sourceMaps', 'sourceMapId', 'sourceMapIds'],
118
+ ['sourceMapMappingIds', 'sourceMapMapping', 'sourceMapMappings', 'sourceMapMappingId', 'sourceMapMappingIds'],
119
+ ['proofObligationIds', 'proofObligation', 'proofObligations', 'proofObligationId', 'proofObligationIds', 'obligation', 'obligations'],
120
+ ['proofEvidenceIds', 'proofEvidence', 'proofEvidenceId', 'proofEvidenceIds'],
121
+ ['missingEvidence', 'missingEvidence', 'missingEvidenceIds'],
122
+ ['evidenceIds', 'evidence', 'evidenceIds']
112
123
  ];
113
124
  const NUMBER_FIELDS = [
114
125
  ['arity'], ['size'], ['alignment'], ['parameterCount'], ['requiredParameterCount'], ['optionalParameterCount'],
115
126
  ['sizeBytes'], ['alignmentBytes'], ['offsetBytes'], ['pointerWidth'], ['integerWidth'], ['bitWidth'], ['width'],
116
127
  ['codeUnitWidth'], ['indexBase']
117
128
  ];
118
- const FLAG_FIELDS = ['nullable', 'optional', 'publicContract', 'closure', 'captured', 'writeExpr', 'mutable', 'shadowed', 'hoisted', 'typeOnly', 'isTypeReference', 'isValueReference', 'shared', 'volatile', 'atomic', 'adapterRequired', 'async', 'generator', 'exceptional', 'cancellable', 'variadic', 'signed', 'nan', 'infinity', 'deterministic', 'streaming', 'framing', 'copyOnWrite', 'multipleInheritance', 'reflection', 'staticDispatch', 'virtual', 'spawn', 'await', 'structured', 'reentrant', 'cancelable'];
129
+ const FLAG_FIELDS = ['nullable', 'optional', 'publicContract', 'closure', 'captured', 'writeExpr', 'mutable', 'shadowed', 'hoisted', 'typeOnly', 'isTypeReference', 'isValueReference', 'shared', 'volatile', 'atomic', 'adapterRequired', 'async', 'generator', 'exceptional', 'cancellable', 'variadic', 'signed', 'nan', 'infinity', 'deterministic', 'streaming', 'framing', 'copyOnWrite', 'multipleInheritance', 'reflection', 'staticDispatch', 'virtual', 'spawn', 'await', 'structured', 'reentrant', 'cancelable', 'failClosed'];
119
130
 
120
131
  export const FAMILIES = Object.freeze(Object.fromEntries(FAMILY_ROWS.flatMap(([name, field, sourceKey, targetKey, aliases = [], extra = {}]) => {
121
132
  const config = { field, sourceKey, targetKey, ...extra };
@@ -88,10 +88,15 @@ function addConstraint(plan, family, name, text) {
88
88
  sourceLanguage: readInlineWord('sourceLanguage', text) ?? plan.sourceLanguage,
89
89
  target: readInlineWord('targetLanguage', text) ?? plan.targets[0],
90
90
  mode: readInlineWord('mode', text),
91
+ sourceMapIds: readInlineList(text, 'sourceMap', 'sourceMaps', 'sourceMapId', 'sourceMapIds'),
92
+ sourceMapMappingIds: readInlineList(text, 'sourceMapMapping', 'sourceMapMappings', 'sourceMapMappingId', 'sourceMapMappingIds'),
93
+ proofObligationIds: readInlineList(text, 'proofObligation', 'proofObligations', 'proofObligationId', 'proofObligationIds', 'obligation', 'obligations'),
94
+ proofEvidenceIds: readInlineList(text, 'proofEvidence', 'proofEvidenceId', 'proofEvidenceIds'),
91
95
  evidenceIds: readInlineList(text, 'evidence', 'evidenceIds'),
92
96
  missingEvidence: readInlineList(text, 'missingEvidence'),
93
97
  blockers: readInlineList(text, 'blocker', 'blockers'),
94
98
  review: readInlineList(text, 'review'),
99
+ failClosed: readInlineFlag('failClosed', text),
95
100
  metadata: { name, family, authoredConversionBlockId: plan.id }
96
101
  });
97
102
  const recordKey = role === 'target' ? config.targetKey : config.sourceKey;
@@ -113,6 +118,12 @@ function resourceGraphFromRecord(record, entry) {
113
118
  sourcePath: record.sourcePath,
114
119
  sourceHash: record.sourceHash,
115
120
  evidenceIds,
121
+ sourceMapIds: record.sourceMapIds ?? entry.sourceMapIds,
122
+ sourceMapMappingIds: record.sourceMapMappingIds ?? entry.sourceMapMappingIds,
123
+ proofObligationIds: record.proofObligationIds ?? entry.proofObligationIds,
124
+ proofEvidenceIds: record.proofEvidenceIds ?? entry.proofEvidenceIds,
125
+ missingEvidence: record.missingEvidence ?? entry.missingEvidence,
126
+ failClosed: record.failClosed ?? entry.failClosed,
116
127
  resources: [{
117
128
  id: resourceId,
118
129
  resourceKind: record.resourceKind ?? record.kind ?? record.constraintKind,
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ export function parseFrontierSource(source, options = {}) {
32
32
  const packageManifestBlocks = [];
33
33
  const canvasSurfaceBlocks = [];
34
34
  const applicationSurfaceBlocks = [];
35
- const runtimeCapabilityBlocks = [];
35
+ const runtimeCapabilityBlocks = [], targetProjectionTargets = [];
36
36
  const documentId = options.id ?? readId(source) ?? 'mod_frontier';
37
37
  const documentName = options.name ?? readName(source) ?? 'FrontierModule';
38
38
  for (const block of readBlocks(source)) {
@@ -51,7 +51,7 @@ export function parseFrontierSource(source, options = {}) {
51
51
  nodes.push(parsed.node);
52
52
  nativeSourceBlocks.push(parsed);
53
53
  }
54
- if (block.kind === 'target') nodes.push(parseTarget(block));
54
+ if (block.kind === 'target') { const parsed = parseTarget(block); nodes.push(parsed); if (parsed.metadata?.authoredTargetProjection) targetProjectionTargets.push(parsed); }
55
55
  if (block.kind === 'proof') proofBlocks.push(parseProofBlock(block));
56
56
  if (block.kind === 'paradigm' || block.kind === 'paradigmSemantics') paradigmBlocks.push(parseParadigmBlock(block));
57
57
  if (block.kind === 'operations' || block.kind === 'semanticOperations') operationBlocks.push(parseSemanticOperationsBlock(block));
@@ -66,7 +66,7 @@ export function parseFrontierSource(source, options = {}) {
66
66
  if (block.kind === 'applicationSurface' || block.kind === 'appHost' || block.kind === 'plugin' || block.kind === 'pluginSurface' || block.kind === 'pluginContract') applicationSurfaceBlocks.push(parseApplicationSurfaceBlock(block));
67
67
  if (block.kind === 'runtimeCapabilities' || block.kind === 'runtimeCapabilityMatrix' || block.kind === 'runtimeHosts') runtimeCapabilityBlocks.push(parseRuntimeCapabilityBlock(block));
68
68
  }
69
- const metadata = createParsedMetadata({ proofBlocks, paradigmBlocks, operationBlocks, conversionBlocks, constraintSpaceBlocks, decisionGraphBlocks, dialectRegistryBlocks, interlinguaBlocks, resourceGraphBlocks, nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks });
69
+ const metadata = createParsedMetadata({ proofBlocks, paradigmBlocks, operationBlocks, conversionBlocks, constraintSpaceBlocks, decisionGraphBlocks, dialectRegistryBlocks, interlinguaBlocks, resourceGraphBlocks, nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks, targetProjectionTargets });
70
70
  return createDocument({ id: documentId, name: documentName, nodes, ...(metadata ? { metadata } : {}) });
71
71
  }
72
72
 
package/dist/metadata.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { mergeDialectRegistryBlocks } from './dialect-registry.js';
2
2
  import { mergeApplicationSurfaceBlocks } from './application-surface.js';
3
3
  import { mergeRuntimeCapabilityBlocks } from './runtime-capability.js';
4
+ import { mergeTargetProjectionTargets } from './target-projection-aggregate.js';
4
5
 
5
6
  const PROOF_GROUPS = ['contracts', 'refinements', 'invariants', 'termination', 'temporal', 'obligations', 'artifacts', 'assumptions'];
6
7
  const PARADIGM_GROUPS = [
@@ -9,7 +10,7 @@ const PARADIGM_GROUPS = [
9
10
  'clockModels', 'objectModels', 'macroExpansions', 'reflectionBoundaries', 'loweringRecords'
10
11
  ];
11
12
 
12
- export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], operationBlocks = [], conversionBlocks = [], constraintSpaceBlocks = [], decisionGraphBlocks = [], dialectRegistryBlocks = [], interlinguaBlocks = [], resourceGraphBlocks = [], nativeSourceBlocks = [], packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = [] } = {}) {
13
+ export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], operationBlocks = [], conversionBlocks = [], constraintSpaceBlocks = [], decisionGraphBlocks = [], dialectRegistryBlocks = [], interlinguaBlocks = [], resourceGraphBlocks = [], nativeSourceBlocks = [], packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = [], targetProjectionTargets = [] } = {}) {
13
14
  const metadata = {};
14
15
  if (proofBlocks.length) metadata.proof = mergeProofBlocks(proofBlocks);
15
16
  if (paradigmBlocks.length) metadata.paradigmSemantics = mergeParadigmBlocks(paradigmBlocks);
@@ -27,8 +28,9 @@ export function createParsedMetadata({ proofBlocks = [], paradigmBlocks = [], op
27
28
  metadata.runtimeCapabilities = mergeRuntimeCapabilityBlocks(runtimeCapabilityBlocks);
28
29
  metadata.runtimeCapabilityMatrix = metadata.runtimeCapabilities;
29
30
  }
30
- if (nativeSourceBlocks.some((block) => block.sourceMaps.length || block.mergeCandidates.length || block.evidence.length) || packageManifestBlocks.length || canvasSurfaceBlocks.length || applicationSurfaceBlocks.length || runtimeCapabilityBlocks.length) {
31
- metadata.universalAst = mergeUniversalAstBlocks(nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks);
31
+ if (targetProjectionTargets.length) metadata.targetProjections = mergeTargetProjectionTargets(targetProjectionTargets);
32
+ if (nativeSourceBlocks.some((block) => block.sourceMaps.length || block.mergeCandidates.length || block.evidence.length) || packageManifestBlocks.length || canvasSurfaceBlocks.length || applicationSurfaceBlocks.length || runtimeCapabilityBlocks.length || targetProjectionTargets.length) {
33
+ metadata.universalAst = mergeUniversalAstBlocks(nativeSourceBlocks, packageManifestBlocks, canvasSurfaceBlocks, applicationSurfaceBlocks, runtimeCapabilityBlocks, metadata.targetProjections);
32
34
  }
33
35
  return Object.keys(metadata).length ? metadata : undefined;
34
36
  }
@@ -99,7 +101,7 @@ function mergeConstraintSpaceBlocks(blocks) {
99
101
  };
100
102
  }
101
103
 
102
- function mergeUniversalAstBlocks(blocks, packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = []) {
104
+ function mergeUniversalAstBlocks(blocks, packageManifestBlocks = [], canvasSurfaceBlocks = [], applicationSurfaceBlocks = [], runtimeCapabilityBlocks = [], targetProjections) {
103
105
  return {
104
106
  id: blocks.length === 1 ? `universalAst:${blocks[0].node.id}` : 'universalAst:source',
105
107
  nativeSourceIds: blocks.map((block) => block.node.id),
@@ -111,6 +113,7 @@ function mergeUniversalAstBlocks(blocks, packageManifestBlocks = [], canvasSurfa
111
113
  canvasSurfaces: canvasSurfaceBlocks,
112
114
  applicationSurfaces: applicationSurfaceBlocks,
113
115
  runtimeCapabilities: runtimeCapabilityBlocks,
116
+ ...(targetProjections ? { targetProjections, targetProjectionTargetIds: targetProjections.targetIds, targetProjectionContractIds: targetProjections.projectionContractIds, targetProjectionLayerIds: targetProjections.projectionLayerIds } : {}),
114
117
  packageManifestIds: ids(packageManifestBlocks),
115
118
  canvasSurfaceIds: ids(canvasSurfaceBlocks),
116
119
  applicationSurfaceIds: ids(applicationSurfaceBlocks),
@@ -120,7 +123,8 @@ function mergeUniversalAstBlocks(blocks, packageManifestBlocks = [], canvasSurfa
120
123
  authoredPackageManifestIds: ids(packageManifestBlocks),
121
124
  authoredCanvasSurfaceIds: ids(canvasSurfaceBlocks),
122
125
  authoredApplicationSurfaceIds: ids(applicationSurfaceBlocks),
123
- authoredRuntimeCapabilityIds: ids(runtimeCapabilityBlocks)
126
+ authoredRuntimeCapabilityIds: ids(runtimeCapabilityBlocks),
127
+ ...(targetProjections ? { authoredTargetProjectionTargetIds: targetProjections.targetIds } : {})
124
128
  }
125
129
  };
126
130
  }
@@ -0,0 +1,75 @@
1
+ export function mergeTargetProjectionTargets(targets = []) {
2
+ const entries = targets.map(targetProjectionEntry).filter(Boolean);
3
+ if (!entries.length) return undefined;
4
+ const contracts = entries.flatMap((entry) => entry.projectionContracts ?? []);
5
+ const layers = entries.flatMap((entry) => entry.projectionLayers ?? []);
6
+ return {
7
+ id: entries.length === 1 ? `targetProjections:${entries[0].id}` : 'targetProjections:source',
8
+ targets: entries,
9
+ targetIds: ids(entries),
10
+ targetLanguages: uniqueStrings(entries.map((entry) => entry.target?.language)),
11
+ emitPaths: uniqueStrings(entries.map((entry) => entry.target?.emitPath)),
12
+ projectionContracts: contracts,
13
+ projectionLayers: layers,
14
+ projectionContractIds: ids(contracts),
15
+ projectionLayerIds: ids(layers),
16
+ representedLayerKinds: uniqueStrings(contracts.flatMap((entry) => entry.representedLayerKinds ?? [])),
17
+ missingLayerKinds: uniqueStrings(contracts.flatMap((entry) => entry.missingLayerKinds ?? [])),
18
+ evidenceIds: uniqueStrings(entries.flatMap((entry) => entry.evidenceIds ?? [])),
19
+ proofEvidenceIds: uniqueStrings(entries.flatMap((entry) => entry.proofEvidenceIds ?? [])),
20
+ lossIds: uniqueStrings(entries.flatMap((entry) => entry.lossIds ?? [])),
21
+ missingEvidence: uniqueStrings(entries.flatMap((entry) => entry.missingEvidence ?? [])),
22
+ summary: {
23
+ targetCount: entries.length,
24
+ projectionContractCount: contracts.length,
25
+ projectionLayerCount: layers.length,
26
+ missingEvidenceCount: uniqueStrings(entries.flatMap((entry) => entry.missingEvidence ?? [])).length,
27
+ lossCount: uniqueStrings(entries.flatMap((entry) => entry.lossIds ?? [])).length
28
+ },
29
+ claims: { semanticEquivalenceClaim: false, autoMergeClaim: false },
30
+ metadata: { authoredTargetProjectionTargetIds: ids(entries) }
31
+ };
32
+ }
33
+
34
+ function targetProjectionEntry(node = {}) {
35
+ const metadata = node.metadata;
36
+ if (!metadata?.authoredTargetProjection) return undefined;
37
+ const projectionContracts = enrichRows(metadata.projectionContracts, node);
38
+ const projectionLayers = enrichRows(metadata.projectionLayers, node);
39
+ return cleanObject({
40
+ id: node.id,
41
+ kind: 'frontier.lang.targetProjectionTarget',
42
+ name: node.name,
43
+ target: node.target,
44
+ projectionContracts,
45
+ projectionLayers,
46
+ projectionContractIds: ids(projectionContracts),
47
+ projectionLayerIds: ids(projectionLayers),
48
+ representedLayerKinds: uniqueStrings(projectionContracts.flatMap((entry) => entry.representedLayerKinds ?? [])),
49
+ missingLayerKinds: uniqueStrings(projectionContracts.flatMap((entry) => entry.missingLayerKinds ?? [])),
50
+ evidenceIds: metadata.evidenceIds,
51
+ proofEvidenceIds: metadata.proofEvidenceIds,
52
+ lossIds: metadata.lossIds,
53
+ missingEvidence: metadata.missingEvidence,
54
+ claims: { semanticEquivalenceClaim: false, autoMergeClaim: false },
55
+ metadata: { authoredTargetProjection: true, targetNodeId: node.id, targetLanguage: node.target?.language ?? node.name }
56
+ });
57
+ }
58
+
59
+ function enrichRows(rows = [], node = {}) {
60
+ return rows.map((row) => cleanObject({
61
+ targetId: node.id,
62
+ targetName: node.name,
63
+ targetLanguage: node.target?.language ?? node.name,
64
+ packageName: node.target?.packageName,
65
+ emitPath: node.target?.emitPath,
66
+ moduleFormat: node.target?.moduleFormat,
67
+ ...row,
68
+ semanticEquivalenceClaim: false,
69
+ autoMergeClaim: false
70
+ }));
71
+ }
72
+
73
+ function ids(records = []) { return records.map((record) => record?.id).filter(Boolean); }
74
+ function uniqueStrings(values = []) { return [...new Set(values.filter(Boolean))]; }
75
+ function cleanObject(object) { return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-parser",
3
- "version": "0.3.31",
3
+ "version": "0.3.33",
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/conversion-constraint-fields-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/target-projection-aggregate-smoke.mjs && node test/conversion-constraint-fields-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",
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",