@shapeshift-labs/frontier-lang-compiler 0.2.12 → 0.2.13

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
@@ -171,6 +171,9 @@ const project = await importNativeProject({
171
171
  console.log(imported.universalAst.sourceMaps.length);
172
172
  console.log(project.semanticIndex.symbols.length);
173
173
  console.log(imported.adapter.coverage.exactness);
174
+ console.log(imported.adapter.coverage.capabilityEvidence.declared.exactness);
175
+ console.log(imported.adapter.coverage.capabilityEvidence.observed.sourceRanges);
176
+ console.log(imported.adapter.coverage.capabilityEvidence.gaps);
174
177
  console.log(imported.adapter.coverage.semanticCoverage.level);
175
178
  console.log(project.metadata.sourcePreservationSummary.total);
176
179
  ```
@@ -184,6 +187,8 @@ The built-in adapter factories are dependency-light wrappers for caller-owned pa
184
187
 
185
188
  Adapter summaries include a structured `coverage` record so merge queues can distinguish exact parser AST imports from declaration scans. The record declares exactness, parser token/trivia support, diagnostics support, source-range and generated-range support, and semantic coverage. Built-in wrappers normalize native AST/CST nodes and declaration-level semantic indexes; they do not claim resolved references, types, control flow, generated ranges, or token/trivia fidelity unless the host adapter supplies that evidence.
186
189
 
190
+ Coverage records also keep declared, observed, and effective capability evidence separate. `coverage.capabilityEvidence.gaps` highlights missing exact AST, token/trivia, parser diagnostics, source range, generated range, reference, type, and control-flow evidence for the current adapter/import. `observedOnly` means the import produced evidence the adapter did not declare, while `declaredOnly` means the adapter declared support that this run did not exercise.
191
+
187
192
  ## Related Packages
188
193
 
189
194
  The published Frontier package family is generated from one shared package catalog so READMEs stay in sync across packages:
package/bench/smoke.mjs CHANGED
@@ -96,6 +96,10 @@ console.log(JSON.stringify({
96
96
  nativeImportDurationMs: Number(importDurationMs.toFixed(2)),
97
97
  coverageMatrixLanguages: coverageMatrix.summary.languages,
98
98
  coverageMatrixImports: coverageMatrix.summary.imports,
99
+ adapterCoverageSummaries: coverageMatrix.summary.adapterCoverage.total,
100
+ adapterCoverageSourceRanges: coverageMatrix.summary.adapterCoverage.effective.sourceRanges ?? 0,
101
+ adapterCoverageTokenGaps: coverageMatrix.summary.adapterCoverage.gaps.tokens ?? 0,
102
+ adapterCoverageReferenceGaps: coverageMatrix.summary.adapterCoverage.gaps.references ?? 0,
99
103
  coverageMatrixDurationMs: Number(matrixDurationMs.toFixed(2)),
100
104
  sourcePreservationRecords: preservationRecords.length,
101
105
  sourcePreservationTokens: preservationTokens,
package/dist/index.d.ts CHANGED
@@ -174,6 +174,28 @@ export interface NativeImportLanguageProfile {
174
174
  readonly notes: readonly string[];
175
175
  }
176
176
 
177
+ export interface NativeImporterAdapterCoverageAggregate {
178
+ readonly total: number;
179
+ readonly declared: Readonly<Record<string, number>>;
180
+ readonly observed: Readonly<Record<string, number>>;
181
+ readonly effective: Readonly<Record<string, number>>;
182
+ readonly gaps: Readonly<Record<string, number>>;
183
+ readonly declaredOnly: Readonly<Record<string, number>>;
184
+ readonly observedOnly: Readonly<Record<string, number>>;
185
+ readonly summaries: readonly {
186
+ readonly adapterId?: string;
187
+ readonly language?: FrontierSourceLanguage | string;
188
+ readonly parser?: string;
189
+ readonly exactness?: NativeImporterAdapterExactness;
190
+ readonly declared: readonly string[];
191
+ readonly observed: readonly string[];
192
+ readonly effective: readonly string[];
193
+ readonly gaps: readonly string[];
194
+ readonly declaredOnly: readonly string[];
195
+ readonly observedOnly: readonly string[];
196
+ }[];
197
+ }
198
+
177
199
  export interface NativeImportCoverageLanguage {
178
200
  readonly language: FrontierSourceLanguage;
179
201
  readonly aliases: readonly string[];
@@ -184,6 +206,7 @@ export interface NativeImportCoverageLanguage {
184
206
  readonly knownLossKinds: readonly NativeImportKnownLossKind[];
185
207
  readonly defaultReadiness: SemanticMergeReadiness;
186
208
  readonly notes: readonly string[];
209
+ readonly adapterCoverage: NativeImporterAdapterCoverageAggregate;
187
210
  readonly imports: {
188
211
  readonly total: number;
189
212
  readonly parsers: readonly string[];
@@ -214,6 +237,7 @@ export interface NativeImportCoverageMatrix {
214
237
  readonly losses: number;
215
238
  readonly byReadiness: Readonly<Record<string, number>>;
216
239
  readonly lossKinds: Readonly<Record<string, number>>;
240
+ readonly adapterCoverage: NativeImporterAdapterCoverageAggregate;
217
241
  };
218
242
  readonly metadata: {
219
243
  readonly compileTargets: readonly FrontierCompileTarget[];
@@ -618,14 +642,97 @@ export interface NativeImporterAdapterSemanticCoverage {
618
642
  readonly controlFlow: boolean;
619
643
  }
620
644
 
645
+ export interface NativeImporterAdapterCoverageSnapshot {
646
+ readonly exactness: NativeImporterAdapterExactness;
647
+ readonly exactAst: boolean;
648
+ readonly tokens: boolean;
649
+ readonly trivia: boolean;
650
+ readonly diagnostics: boolean;
651
+ readonly sourceRanges: boolean;
652
+ readonly generatedRanges: boolean;
653
+ readonly semanticCoverage: NativeImporterAdapterSemanticCoverage;
654
+ }
655
+
621
656
  export interface NativeImporterAdapterCoverageObserved {
657
+ readonly exactness?: NativeImporterAdapterExactness;
658
+ readonly exactAst?: boolean;
659
+ readonly tokens?: boolean;
660
+ readonly tokenCount?: number;
661
+ readonly trivia?: boolean;
662
+ readonly triviaCount?: number;
622
663
  readonly diagnostics: number;
664
+ readonly parserDiagnostics?: number;
665
+ readonly diagnosticErrors?: number;
666
+ readonly diagnosticWarnings?: number;
667
+ readonly diagnosticInfos?: number;
623
668
  readonly losses: number;
624
669
  readonly nativeAstNodes: number;
625
670
  readonly semanticSymbols: number;
671
+ readonly semanticReferences?: number;
672
+ readonly semanticTypes?: number;
673
+ readonly semanticControlFlow?: number;
674
+ readonly references?: boolean;
675
+ readonly types?: boolean;
676
+ readonly controlFlow?: boolean;
626
677
  readonly sourceMapMappings: number;
627
678
  readonly sourceRanges: boolean;
679
+ readonly sourceRangeNodes?: number;
680
+ readonly sourceRangeMappings?: number;
628
681
  readonly generatedRanges: boolean;
682
+ readonly generatedRangeMappings?: number;
683
+ readonly semanticCoverage?: NativeImporterAdapterSemanticCoverage;
684
+ }
685
+
686
+ export interface NativeImporterAdapterCoverageCapabilityRow {
687
+ readonly capability: string;
688
+ readonly declared: boolean;
689
+ readonly observed: boolean;
690
+ readonly effective: boolean;
691
+ readonly count: number;
692
+ readonly status: 'declared-and-observed' | 'declared-unobserved' | 'observed-undeclared' | 'absent';
693
+ }
694
+
695
+ export interface NativeImporterAdapterCoverageCapabilityEvidence {
696
+ readonly declared: NativeImporterAdapterCoverageSnapshot;
697
+ readonly observed: NativeImporterAdapterCoverageObserved;
698
+ readonly effective: NativeImporterAdapterCoverageSnapshot;
699
+ readonly capabilities: readonly NativeImporterAdapterCoverageCapabilityRow[];
700
+ readonly gaps: readonly string[];
701
+ readonly declaredOnly: readonly string[];
702
+ readonly observedOnly: readonly string[];
703
+ readonly parserDiagnostics: {
704
+ readonly declared: boolean;
705
+ readonly observed: boolean;
706
+ readonly count: number;
707
+ readonly errors: number;
708
+ readonly warnings: number;
709
+ readonly infos: number;
710
+ };
711
+ readonly sourceRanges: {
712
+ readonly declared: boolean;
713
+ readonly observed: boolean;
714
+ readonly nativeAstNodes: number;
715
+ readonly sourceRangeNodes: number;
716
+ readonly sourceMapMappings: number;
717
+ readonly sourceRangeMappings: number;
718
+ readonly generatedRangeMappings: number;
719
+ };
720
+ readonly tokensTrivia: {
721
+ readonly tokens: { readonly declared: boolean; readonly observed: boolean; readonly count: number };
722
+ readonly trivia: { readonly declared: boolean; readonly observed: boolean; readonly count: number };
723
+ };
724
+ readonly semantic: {
725
+ readonly level: {
726
+ readonly declared: string;
727
+ readonly observed: string;
728
+ readonly effective: string;
729
+ };
730
+ readonly declarations: NativeImporterAdapterCoverageCapabilityRow;
731
+ readonly symbols: NativeImporterAdapterCoverageCapabilityRow;
732
+ readonly references: NativeImporterAdapterCoverageCapabilityRow;
733
+ readonly types: NativeImporterAdapterCoverageCapabilityRow;
734
+ readonly controlFlow: NativeImporterAdapterCoverageCapabilityRow;
735
+ };
629
736
  }
630
737
 
631
738
  export interface NativeImporterAdapterCoverageSummary {
@@ -638,11 +745,13 @@ export interface NativeImporterAdapterCoverageSummary {
638
745
  readonly generatedRanges: boolean;
639
746
  readonly semanticCoverage: NativeImporterAdapterSemanticCoverage;
640
747
  readonly notes: readonly string[];
748
+ readonly declared?: NativeImporterAdapterCoverageSnapshot;
641
749
  readonly observed?: NativeImporterAdapterCoverageObserved;
750
+ readonly capabilityEvidence?: NativeImporterAdapterCoverageCapabilityEvidence;
642
751
  }
643
752
 
644
753
  export type NativeImporterAdapterCoverageInput =
645
- Omit<Partial<NativeImporterAdapterCoverageSummary>, 'semanticCoverage' | 'observed'> & {
754
+ Omit<Partial<NativeImporterAdapterCoverageSummary>, 'semanticCoverage' | 'observed' | 'declared' | 'capabilityEvidence'> & {
646
755
  readonly semanticCoverage?: Partial<NativeImporterAdapterSemanticCoverage>;
647
756
  readonly observed?: Partial<NativeImporterAdapterCoverageObserved>;
648
757
  };
package/dist/index.js CHANGED
@@ -493,6 +493,7 @@ export function createNativeImportCoverageMatrix(input = {}) {
493
493
  for (const [kind, count] of Object.entries(entry.imports.lossKinds)) {
494
494
  totals.lossKinds[kind] = (totals.lossKinds[kind] ?? 0) + count;
495
495
  }
496
+ totals.adapterCoverage = mergeNativeImporterAdapterCoverageAggregates(totals.adapterCoverage, entry.adapterCoverage);
496
497
  return totals;
497
498
  }, {
498
499
  languages: 0,
@@ -504,7 +505,8 @@ export function createNativeImportCoverageMatrix(input = {}) {
504
505
  sourceMapMappings: 0,
505
506
  losses: 0,
506
507
  byReadiness: {},
507
- lossKinds: {}
508
+ lossKinds: {},
509
+ adapterCoverage: emptyNativeImporterAdapterCoverageAggregate()
508
510
  });
509
511
  return {
510
512
  kind: 'frontier.lang.nativeImportCoverageMatrix',
@@ -3440,6 +3442,10 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3440
3442
  : profile.supportsLightweightScan ? profile.defaultReadiness : 'blocked';
3441
3443
  const importedParsers = uniqueStrings(matchingImports.map((imported) => imported?.nativeAst?.parser ?? imported?.parser ?? imported?.metadata?.parser).filter(Boolean));
3442
3444
  const sourceMaps = matchingImports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? []);
3445
+ const adapterCoverage = summarizeNativeImporterAdapterCoverageEntries([
3446
+ ...matchingImports.map((imported) => nativeImporterAdapterCoverageEntryFromImport(imported)).filter(Boolean),
3447
+ ...matchingAdapters.map((adapter) => nativeImporterAdapterCoverageEntryFromAdapter(adapter)).filter(Boolean)
3448
+ ]);
3443
3449
  return {
3444
3450
  language: profile.language,
3445
3451
  aliases: profile.aliases,
@@ -3450,6 +3456,7 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3450
3456
  knownLossKinds: uniqueStrings([...(profile.knownLossKinds ?? []), ...Object.keys(lossSummary.byKind)]),
3451
3457
  defaultReadiness: profile.defaultReadiness,
3452
3458
  notes: profile.notes,
3459
+ adapterCoverage,
3453
3460
  imports: {
3454
3461
  total: matchingImports.length,
3455
3462
  parsers: importedParsers,
@@ -3465,6 +3472,125 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3465
3472
  };
3466
3473
  }
3467
3474
 
3475
+ function nativeImporterAdapterCoverageEntryFromImport(imported) {
3476
+ const coverage = imported?.adapter?.coverage
3477
+ ?? imported?.metadata?.adapterCoverage
3478
+ ?? imported?.nativeAst?.metadata?.adapterCoverage
3479
+ ?? imported?.nativeSource?.metadata?.adapterCoverage;
3480
+ if (!coverage) return undefined;
3481
+ return {
3482
+ adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? imported?.nativeAst?.metadata?.adapterId,
3483
+ language: imported?.adapter?.language ?? imported?.language ?? imported?.nativeAst?.language,
3484
+ parser: imported?.adapter?.parser ?? imported?.nativeAst?.parser ?? imported?.nativeSource?.parser,
3485
+ coverage
3486
+ };
3487
+ }
3488
+
3489
+ function nativeImporterAdapterCoverageEntryFromAdapter(adapter) {
3490
+ if (!adapter) return undefined;
3491
+ const summary = normalizeNativeImporterAdapter(adapter);
3492
+ return {
3493
+ adapterId: summary.id,
3494
+ language: summary.language,
3495
+ parser: summary.parser,
3496
+ coverage: summary.coverage
3497
+ };
3498
+ }
3499
+
3500
+ function summarizeNativeImporterAdapterCoverageEntries(entries = []) {
3501
+ const aggregate = emptyNativeImporterAdapterCoverageAggregate();
3502
+ for (const entry of entries) {
3503
+ const coverage = normalizeNativeImporterAdapterCoverageForEvidence(entry.coverage);
3504
+ const capabilityEvidence = coverage.capabilityEvidence;
3505
+ const summary = {
3506
+ adapterId: entry.adapterId,
3507
+ language: entry.language,
3508
+ parser: entry.parser,
3509
+ exactness: coverage.exactness,
3510
+ declared: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'declared'),
3511
+ observed: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'observed'),
3512
+ effective: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'effective'),
3513
+ gaps: capabilityEvidence.gaps,
3514
+ declaredOnly: capabilityEvidence.declaredOnly,
3515
+ observedOnly: capabilityEvidence.observedOnly
3516
+ };
3517
+ aggregate.total += 1;
3518
+ aggregate.summaries.push(summary);
3519
+ incrementCoverageCapabilityCounts(aggregate.declared, summary.declared);
3520
+ incrementCoverageCapabilityCounts(aggregate.observed, summary.observed);
3521
+ incrementCoverageCapabilityCounts(aggregate.effective, summary.effective);
3522
+ incrementCoverageCapabilityCounts(aggregate.gaps, summary.gaps);
3523
+ incrementCoverageCapabilityCounts(aggregate.declaredOnly, summary.declaredOnly);
3524
+ incrementCoverageCapabilityCounts(aggregate.observedOnly, summary.observedOnly);
3525
+ }
3526
+ return {
3527
+ ...aggregate,
3528
+ summaries: Object.freeze(aggregate.summaries)
3529
+ };
3530
+ }
3531
+
3532
+ function normalizeNativeImporterAdapterCoverageForEvidence(coverage = {}) {
3533
+ if (coverage.capabilityEvidence) return coverage;
3534
+ const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
3535
+ const observed = normalizeNativeImporterAdapterObservedCoverage(coverage.observed, declared);
3536
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
3537
+ return {
3538
+ ...coverage,
3539
+ ...effective,
3540
+ declared,
3541
+ observed,
3542
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
3543
+ };
3544
+ }
3545
+
3546
+ function emptyNativeImporterAdapterCoverageAggregate() {
3547
+ return {
3548
+ total: 0,
3549
+ declared: {},
3550
+ observed: {},
3551
+ effective: {},
3552
+ gaps: {},
3553
+ declaredOnly: {},
3554
+ observedOnly: {},
3555
+ summaries: []
3556
+ };
3557
+ }
3558
+
3559
+ function mergeNativeImporterAdapterCoverageAggregates(left, right) {
3560
+ const merged = emptyNativeImporterAdapterCoverageAggregate();
3561
+ for (const aggregate of [left, right]) {
3562
+ if (!aggregate) continue;
3563
+ merged.total += aggregate.total ?? 0;
3564
+ incrementCoverageCapabilityCounts(merged.declared, aggregate.declared ?? {});
3565
+ incrementCoverageCapabilityCounts(merged.observed, aggregate.observed ?? {});
3566
+ incrementCoverageCapabilityCounts(merged.effective, aggregate.effective ?? {});
3567
+ incrementCoverageCapabilityCounts(merged.gaps, aggregate.gaps ?? {});
3568
+ incrementCoverageCapabilityCounts(merged.declaredOnly, aggregate.declaredOnly ?? {});
3569
+ incrementCoverageCapabilityCounts(merged.observedOnly, aggregate.observedOnly ?? {});
3570
+ merged.summaries.push(...(aggregate.summaries ?? []));
3571
+ }
3572
+ return {
3573
+ ...merged,
3574
+ summaries: Object.freeze(merged.summaries)
3575
+ };
3576
+ }
3577
+
3578
+ function capabilityNamesByBoolean(rows, property) {
3579
+ return rows.filter((row) => row[property]).map((row) => row.capability);
3580
+ }
3581
+
3582
+ function incrementCoverageCapabilityCounts(target, capabilities) {
3583
+ if (Array.isArray(capabilities)) {
3584
+ for (const capability of capabilities) {
3585
+ target[capability] = (target[capability] ?? 0) + 1;
3586
+ }
3587
+ return;
3588
+ }
3589
+ for (const [capability, count] of Object.entries(capabilities ?? {})) {
3590
+ target[capability] = (target[capability] ?? 0) + count;
3591
+ }
3592
+ }
3593
+
3468
3594
  function semanticImportSidecarEntry(imported, index, options) {
3469
3595
  const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
3470
3596
  const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
@@ -4828,7 +4954,7 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
4828
4954
  const sourceRanges = Boolean(value.sourceRanges ?? hasCapability('sourceRanges', 'sourceRange', 'ranges', 'sourceMaps'));
4829
4955
  const generatedRanges = Boolean(value.generatedRanges ?? hasCapability('generatedRanges', 'generatedRange', 'generatedSourceMaps'));
4830
4956
  const diagnostics = Boolean(value.diagnostics ?? hasCapability('diagnostics', 'parserDiagnostics'));
4831
- return Object.freeze({
4957
+ const declared = freezeNativeImporterAdapterCoverageSnapshot({
4832
4958
  exactness: String(value.exactness ?? inferredAdapterExactness(exactAst, capabilities)),
4833
4959
  exactAst,
4834
4960
  tokens: Boolean(value.tokens ?? hasCapability('tokens', 'tokenStream')),
@@ -4840,13 +4966,21 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
4840
4966
  capabilities,
4841
4967
  sourceRanges,
4842
4968
  generatedRanges
4843
- }),
4969
+ })
4970
+ });
4971
+ const observed = normalizeNativeImporterAdapterObservedCoverage(value.observed, declared);
4972
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
4973
+ return Object.freeze({
4974
+ ...effective,
4975
+ declared,
4976
+ observed,
4844
4977
  notes: uniqueStrings(value.notes ?? inferredAdapterCoverageNotes(context, {
4845
4978
  exactAst,
4846
4979
  sourceRanges,
4847
4980
  generatedRanges,
4848
4981
  diagnostics
4849
- }))
4982
+ })),
4983
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
4850
4984
  });
4851
4985
  }
4852
4986
 
@@ -4856,31 +4990,297 @@ function observeNativeImporterAdapterCoverage(coverage, parseResult = {}, contex
4856
4990
  const sourceMapMappings = parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? []) ?? parseResult.mappings ?? [];
4857
4991
  const semanticIndex = parseResult.semanticIndex;
4858
4992
  const semanticSymbols = semanticIndex?.symbols?.length ?? 0;
4859
- const observedSourceRanges = nodeList.some((node) => Boolean(node?.span)) || sourceMapMappings.some((mapping) => Boolean(mapping?.sourceSpan));
4860
- const observedGeneratedRanges = sourceMapMappings.some((mapping) => Boolean(mapping?.generatedSpan));
4861
- const observedSemanticCoverage = normalizeNativeImporterSemanticCoverage({
4862
- ...coverage.semanticCoverage,
4863
- level: semanticSymbols
4864
- ? maxSemanticCoverageLevel(coverage.semanticCoverage?.level, 'declaration-index')
4865
- : coverage.semanticCoverage?.level,
4866
- declarations: coverage.semanticCoverage?.declarations || semanticSymbols > 0,
4867
- symbols: coverage.semanticCoverage?.symbols || semanticSymbols > 0
4868
- }, {});
4993
+ const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
4994
+ const observed = observeNativeImporterAdapterCoverageDetails(parseResult, context, {
4995
+ declared,
4996
+ nodeList,
4997
+ sourceMapMappings,
4998
+ semanticIndex,
4999
+ semanticSymbols
5000
+ });
5001
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
4869
5002
  return Object.freeze({
4870
5003
  ...coverage,
4871
- diagnostics: coverage.diagnostics || (context.diagnostics?.length ?? 0) > 0,
4872
- sourceRanges: coverage.sourceRanges || observedSourceRanges,
4873
- generatedRanges: coverage.generatedRanges || observedGeneratedRanges,
4874
- semanticCoverage: observedSemanticCoverage,
4875
- observed: {
4876
- diagnostics: context.diagnostics?.length ?? 0,
4877
- losses: context.losses?.length ?? 0,
4878
- nativeAstNodes: nodeList.length,
4879
- semanticSymbols,
4880
- sourceMapMappings: sourceMapMappings.length,
4881
- sourceRanges: observedSourceRanges,
4882
- generatedRanges: observedGeneratedRanges
4883
- }
5004
+ ...effective,
5005
+ declared,
5006
+ observed,
5007
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
5008
+ });
5009
+ }
5010
+
5011
+ function adapterCoverageSnapshotFromSummary(coverage = {}) {
5012
+ return freezeNativeImporterAdapterCoverageSnapshot({
5013
+ exactness: coverage.exactness ?? 'unknown',
5014
+ exactAst: coverage.exactAst,
5015
+ tokens: coverage.tokens,
5016
+ trivia: coverage.trivia,
5017
+ diagnostics: coverage.diagnostics,
5018
+ sourceRanges: coverage.sourceRanges,
5019
+ generatedRanges: coverage.generatedRanges,
5020
+ semanticCoverage: coverage.semanticCoverage
5021
+ });
5022
+ }
5023
+
5024
+ function freezeNativeImporterAdapterCoverageSnapshot(value = {}) {
5025
+ return Object.freeze({
5026
+ exactness: String(value.exactness ?? 'unknown'),
5027
+ exactAst: Boolean(value.exactAst),
5028
+ tokens: Boolean(value.tokens),
5029
+ trivia: Boolean(value.trivia),
5030
+ diagnostics: Boolean(value.diagnostics),
5031
+ sourceRanges: Boolean(value.sourceRanges),
5032
+ generatedRanges: Boolean(value.generatedRanges),
5033
+ semanticCoverage: normalizeNativeImporterSemanticCoverage(value.semanticCoverage, {})
5034
+ });
5035
+ }
5036
+
5037
+ function normalizeNativeImporterAdapterObservedCoverage(value = {}, declared = {}) {
5038
+ const diagnostics = Number(value.diagnostics ?? value.parserDiagnostics ?? 0) || 0;
5039
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5040
+ ...(value.semanticCoverage ?? {}),
5041
+ declarations: value.semanticCoverage?.declarations ?? value.declarations,
5042
+ symbols: value.semanticCoverage?.symbols ?? value.symbols,
5043
+ references: value.semanticCoverage?.references ?? value.references,
5044
+ types: value.semanticCoverage?.types ?? value.types,
5045
+ controlFlow: value.semanticCoverage?.controlFlow ?? value.controlFlow
5046
+ }, {});
5047
+ const nativeAstNodes = Number(value.nativeAstNodes ?? 0) || 0;
5048
+ const exactness = String(value.exactness ?? observedAdapterExactness(declared, nativeAstNodes));
5049
+ return Object.freeze({
5050
+ exactness,
5051
+ exactAst: Boolean(value.exactAst ?? (declared.exactAst && nativeAstNodes > 0)),
5052
+ tokens: Boolean(value.tokens),
5053
+ tokenCount: Number(value.tokenCount ?? 0) || 0,
5054
+ trivia: Boolean(value.trivia),
5055
+ triviaCount: Number(value.triviaCount ?? 0) || 0,
5056
+ diagnostics,
5057
+ parserDiagnostics: diagnostics,
5058
+ diagnosticErrors: Number(value.diagnosticErrors ?? 0) || 0,
5059
+ diagnosticWarnings: Number(value.diagnosticWarnings ?? 0) || 0,
5060
+ diagnosticInfos: Number(value.diagnosticInfos ?? 0) || 0,
5061
+ losses: Number(value.losses ?? 0) || 0,
5062
+ nativeAstNodes,
5063
+ semanticSymbols: Number(value.semanticSymbols ?? 0) || 0,
5064
+ semanticReferences: Number(value.semanticReferences ?? 0) || 0,
5065
+ semanticTypes: Number(value.semanticTypes ?? 0) || 0,
5066
+ semanticControlFlow: Number(value.semanticControlFlow ?? 0) || 0,
5067
+ references: Boolean(value.references ?? semanticCoverage.references),
5068
+ types: Boolean(value.types ?? semanticCoverage.types),
5069
+ controlFlow: Boolean(value.controlFlow ?? semanticCoverage.controlFlow),
5070
+ sourceMapMappings: Number(value.sourceMapMappings ?? 0) || 0,
5071
+ sourceRanges: Boolean(value.sourceRanges),
5072
+ sourceRangeNodes: Number(value.sourceRangeNodes ?? 0) || 0,
5073
+ sourceRangeMappings: Number(value.sourceRangeMappings ?? 0) || 0,
5074
+ generatedRanges: Boolean(value.generatedRanges),
5075
+ generatedRangeMappings: Number(value.generatedRangeMappings ?? 0) || 0,
5076
+ semanticCoverage
5077
+ });
5078
+ }
5079
+
5080
+ function observeNativeImporterAdapterCoverageDetails(parseResult = {}, context = {}, observedContext = {}) {
5081
+ const declared = observedContext.declared ?? {};
5082
+ const nodeList = observedContext.nodeList ?? Object.values(parseResult.nativeAst?.nodes ?? parseResult.nodes ?? {});
5083
+ const sourceMapMappings = observedContext.sourceMapMappings
5084
+ ?? parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? [])
5085
+ ?? parseResult.mappings
5086
+ ?? [];
5087
+ const semanticIndex = observedContext.semanticIndex ?? parseResult.semanticIndex;
5088
+ const semanticSymbols = observedContext.semanticSymbols ?? semanticIndex?.symbols?.length ?? 0;
5089
+ const diagnostics = context.diagnostics ?? [];
5090
+ const diagnosticErrors = diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
5091
+ const diagnosticWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;
5092
+ const diagnosticInfos = diagnostics.filter((diagnostic) => diagnostic.severity === 'info').length;
5093
+ const sourceRangeNodes = nodeList.filter((node) => Boolean(node?.span)).length;
5094
+ const sourceRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.sourceSpan)).length;
5095
+ const generatedRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.generatedSpan)).length;
5096
+ const preservation = adapterCoverageSourcePreservation(parseResult);
5097
+ const tokenCount = preservation?.summary?.tokens ?? preservation?.tokens?.length ?? 0;
5098
+ const triviaCount = preservation?.summary?.trivia ?? preservation?.trivia?.length ?? 0;
5099
+ const semanticEvidence = observeNativeImporterSemanticEvidence(semanticIndex);
5100
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5101
+ level: maxSemanticCoverageLevel(
5102
+ semanticSymbols || semanticEvidence.declarations
5103
+ ? 'declaration-index'
5104
+ : 'native-ast',
5105
+ semanticEvidence.references || semanticEvidence.types || semanticEvidence.controlFlow
5106
+ ? 'semantic-index'
5107
+ : semanticSymbols ? 'declaration-index' : 'native-ast'
5108
+ ),
5109
+ declarations: semanticSymbols > 0 || semanticEvidence.declarations > 0,
5110
+ symbols: semanticSymbols > 0,
5111
+ references: semanticEvidence.references > 0,
5112
+ types: semanticEvidence.types > 0,
5113
+ controlFlow: semanticEvidence.controlFlow > 0
5114
+ }, {});
5115
+ return normalizeNativeImporterAdapterObservedCoverage({
5116
+ exactness: observedAdapterExactness(declared, nodeList.length),
5117
+ exactAst: Boolean(declared.exactAst && nodeList.length > 0),
5118
+ tokens: tokenCount > 0,
5119
+ tokenCount,
5120
+ trivia: triviaCount > 0,
5121
+ triviaCount,
5122
+ diagnostics: diagnostics.length,
5123
+ parserDiagnostics: diagnostics.length,
5124
+ diagnosticErrors,
5125
+ diagnosticWarnings,
5126
+ diagnosticInfos,
5127
+ losses: context.losses?.length ?? 0,
5128
+ nativeAstNodes: nodeList.length,
5129
+ semanticSymbols,
5130
+ semanticReferences: semanticEvidence.references,
5131
+ semanticTypes: semanticEvidence.types,
5132
+ semanticControlFlow: semanticEvidence.controlFlow,
5133
+ references: semanticEvidence.references > 0,
5134
+ types: semanticEvidence.types > 0,
5135
+ controlFlow: semanticEvidence.controlFlow > 0,
5136
+ sourceMapMappings: sourceMapMappings.length,
5137
+ sourceRanges: sourceRangeNodes > 0 || sourceRangeMappings > 0,
5138
+ sourceRangeNodes,
5139
+ sourceRangeMappings,
5140
+ generatedRanges: generatedRangeMappings > 0,
5141
+ generatedRangeMappings,
5142
+ semanticCoverage
5143
+ }, declared);
5144
+ }
5145
+
5146
+ function adapterCoverageSourcePreservation(parseResult = {}) {
5147
+ return parseResult.sourcePreservation
5148
+ ?? parseResult.nativeAst?.metadata?.sourcePreservation
5149
+ ?? parseResult.nativeAstMetadata?.sourcePreservation
5150
+ ?? parseResult.metadata?.sourcePreservation;
5151
+ }
5152
+
5153
+ function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
5154
+ const occurrences = semanticIndex?.occurrences ?? [];
5155
+ const relations = semanticIndex?.relations ?? [];
5156
+ const facts = semanticIndex?.facts ?? [];
5157
+ const symbols = semanticIndex?.symbols ?? [];
5158
+ const referenceRelations = relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['reference', 'call', 'read', 'write', 'use']));
5159
+ const typeFacts = facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['type', 'declaredtype', 'inferredtype', 'typeof']));
5160
+ const typedSymbols = symbols.filter((symbol) => Boolean(symbol?.declaredType ?? symbol?.inferredType ?? symbol?.typeId ?? symbol?.valueType));
5161
+ const controlFlowRecords = [
5162
+ ...relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['controlflow', 'cfg', 'flow'])),
5163
+ ...facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['controlflow', 'cfg', 'flow']))
5164
+ ];
5165
+ return {
5166
+ declarations: occurrences.filter((occurrence) => occurrence?.role === 'definition' || occurrence?.role === 'declaration').length,
5167
+ references: occurrences.filter((occurrence) => {
5168
+ const role = String(occurrence?.role ?? '').toLowerCase();
5169
+ return role && role !== 'definition' && role !== 'declaration';
5170
+ }).length + referenceRelations.length,
5171
+ types: typeFacts.length + typedSymbols.length,
5172
+ controlFlow: controlFlowRecords.length
5173
+ };
5174
+ }
5175
+
5176
+ function semanticPredicateMatches(value, fragments) {
5177
+ const predicate = String(value ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '');
5178
+ return fragments.some((fragment) => predicate.includes(fragment));
5179
+ }
5180
+
5181
+ function observedAdapterExactness(declared = {}, nativeAstNodes = 0) {
5182
+ if (!nativeAstNodes) return 'unknown';
5183
+ if (declared.exactAst) return declared.exactness ?? 'exact-parser-ast';
5184
+ return 'adapter-reported-native-ast';
5185
+ }
5186
+
5187
+ function effectiveNativeImporterAdapterCoverage(declared, observed) {
5188
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5189
+ level: maxSemanticCoverageLevel(declared.semanticCoverage?.level, observed.semanticCoverage?.level),
5190
+ declarations: declared.semanticCoverage?.declarations || observed.semanticCoverage?.declarations,
5191
+ symbols: declared.semanticCoverage?.symbols || observed.semanticCoverage?.symbols,
5192
+ references: declared.semanticCoverage?.references || observed.semanticCoverage?.references,
5193
+ types: declared.semanticCoverage?.types || observed.semanticCoverage?.types,
5194
+ controlFlow: declared.semanticCoverage?.controlFlow || observed.semanticCoverage?.controlFlow
5195
+ }, {});
5196
+ return freezeNativeImporterAdapterCoverageSnapshot({
5197
+ exactness: effectiveAdapterExactness(declared, observed),
5198
+ exactAst: declared.exactAst || observed.exactAst,
5199
+ tokens: declared.tokens || observed.tokens,
5200
+ trivia: declared.trivia || observed.trivia,
5201
+ diagnostics: declared.diagnostics || observed.parserDiagnostics > 0,
5202
+ sourceRanges: declared.sourceRanges || observed.sourceRanges,
5203
+ generatedRanges: declared.generatedRanges || observed.generatedRanges,
5204
+ semanticCoverage
5205
+ });
5206
+ }
5207
+
5208
+ function effectiveAdapterExactness(declared, observed) {
5209
+ if (declared.exactAst || observed.exactAst) return declared.exactness ?? 'exact-parser-ast';
5210
+ if (observed.nativeAstNodes > 0) return observed.exactness ?? 'adapter-reported-native-ast';
5211
+ return declared.exactness ?? 'unknown';
5212
+ }
5213
+
5214
+ function nativeImporterAdapterCapabilityEvidence(declared, observed, effective) {
5215
+ const capabilityRows = [
5216
+ adapterCoverageCapabilityRow('exactAst', declared.exactAst, observed.exactAst, effective.exactAst, observed.nativeAstNodes),
5217
+ adapterCoverageCapabilityRow('tokens', declared.tokens, observed.tokens, effective.tokens, observed.tokenCount),
5218
+ adapterCoverageCapabilityRow('trivia', declared.trivia, observed.trivia, effective.trivia, observed.triviaCount),
5219
+ adapterCoverageCapabilityRow('parserDiagnostics', declared.diagnostics, observed.parserDiagnostics > 0, effective.diagnostics, observed.parserDiagnostics),
5220
+ adapterCoverageCapabilityRow('sourceRanges', declared.sourceRanges, observed.sourceRanges, effective.sourceRanges, observed.sourceRangeNodes + observed.sourceRangeMappings),
5221
+ adapterCoverageCapabilityRow('generatedRanges', declared.generatedRanges, observed.generatedRanges, effective.generatedRanges, observed.generatedRangeMappings),
5222
+ adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
5223
+ adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
5224
+ adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
5225
+ adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
5226
+ adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
5227
+ ];
5228
+ const reviewCapabilities = new Set(['exactAst', 'tokens', 'trivia', 'parserDiagnostics', 'sourceRanges', 'generatedRanges', 'references', 'types', 'controlFlow']);
5229
+ return Object.freeze({
5230
+ declared,
5231
+ observed,
5232
+ effective,
5233
+ capabilities: Object.freeze(capabilityRows),
5234
+ gaps: Object.freeze(capabilityRows.filter((row) => reviewCapabilities.has(row.capability) && !row.effective).map((row) => row.capability)),
5235
+ declaredOnly: Object.freeze(capabilityRows.filter((row) => row.declared && !row.observed).map((row) => row.capability)),
5236
+ observedOnly: Object.freeze(capabilityRows.filter((row) => !row.declared && row.observed).map((row) => row.capability)),
5237
+ parserDiagnostics: Object.freeze({
5238
+ declared: declared.diagnostics,
5239
+ observed: observed.parserDiagnostics > 0,
5240
+ count: observed.parserDiagnostics,
5241
+ errors: observed.diagnosticErrors,
5242
+ warnings: observed.diagnosticWarnings,
5243
+ infos: observed.diagnosticInfos
5244
+ }),
5245
+ sourceRanges: Object.freeze({
5246
+ declared: declared.sourceRanges,
5247
+ observed: observed.sourceRanges,
5248
+ nativeAstNodes: observed.nativeAstNodes,
5249
+ sourceRangeNodes: observed.sourceRangeNodes,
5250
+ sourceMapMappings: observed.sourceMapMappings,
5251
+ sourceRangeMappings: observed.sourceRangeMappings,
5252
+ generatedRangeMappings: observed.generatedRangeMappings
5253
+ }),
5254
+ tokensTrivia: Object.freeze({
5255
+ tokens: Object.freeze({ declared: declared.tokens, observed: observed.tokens, count: observed.tokenCount }),
5256
+ trivia: Object.freeze({ declared: declared.trivia, observed: observed.trivia, count: observed.triviaCount })
5257
+ }),
5258
+ semantic: Object.freeze({
5259
+ level: Object.freeze({
5260
+ declared: declared.semanticCoverage.level,
5261
+ observed: observed.semanticCoverage.level,
5262
+ effective: effective.semanticCoverage.level
5263
+ }),
5264
+ declarations: adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
5265
+ symbols: adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
5266
+ references: adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
5267
+ types: adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
5268
+ controlFlow: adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
5269
+ })
5270
+ });
5271
+ }
5272
+
5273
+ function adapterCoverageCapabilityRow(capability, declared, observed, effective, count = 0) {
5274
+ const status = declared && observed
5275
+ ? 'declared-and-observed'
5276
+ : declared ? 'declared-unobserved' : observed ? 'observed-undeclared' : 'absent';
5277
+ return Object.freeze({
5278
+ capability,
5279
+ declared: Boolean(declared),
5280
+ observed: Boolean(observed),
5281
+ effective: Boolean(effective),
5282
+ count: Number(count ?? 0) || 0,
5283
+ status
4884
5284
  });
4885
5285
  }
4886
5286
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",