62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import { expect } from "vitest";
|
|
|
|
import type {
|
|
JavaScriptSemanticBinding,
|
|
JavaScriptSemanticIr,
|
|
} from "../../../src/domain/javascriptSemanticIr.js";
|
|
|
|
export const programScope = (ir: JavaScriptSemanticIr) => {
|
|
const scope = ir.scopes.find(({ kind }) => kind === "program");
|
|
if (scope === undefined) throw new Error("Missing program scope");
|
|
return scope;
|
|
};
|
|
|
|
export const bindingsNamed = (
|
|
ir: JavaScriptSemanticIr,
|
|
name: string,
|
|
): JavaScriptSemanticBinding[] =>
|
|
ir.bindings.filter(({ name: candidate }) => candidate === name);
|
|
|
|
export const onlyBinding = (
|
|
ir: JavaScriptSemanticIr,
|
|
name: string,
|
|
): JavaScriptSemanticBinding => {
|
|
const bindings = bindingsNamed(ir, name);
|
|
expect(bindings).toHaveLength(1);
|
|
const binding = bindings[0];
|
|
if (binding === undefined) throw new Error(`Missing binding ${name}`);
|
|
return binding;
|
|
};
|
|
|
|
export const onlyCallable = (ir: JavaScriptSemanticIr, name: string) => {
|
|
const callables = ir.callables.filter(
|
|
({ name: candidate }) => candidate === name,
|
|
);
|
|
if (callables.length !== 1 || callables[0] === undefined)
|
|
throw new Error(`Expected one callable named ${name}`);
|
|
return callables[0];
|
|
};
|
|
|
|
export const topLevelBinding = (
|
|
ir: JavaScriptSemanticIr,
|
|
name: string,
|
|
): JavaScriptSemanticBinding => {
|
|
const scopeId = programScope(ir).scopeId;
|
|
const binding = ir.bindings.find(
|
|
({ name: candidate, scopeId: candidateScope }) =>
|
|
candidate === name && candidateScope === scopeId,
|
|
);
|
|
if (binding === undefined)
|
|
throw new Error(`Missing top-level binding ${name}`);
|
|
return binding;
|
|
};
|
|
|
|
export const origin = (binding: JavaScriptSemanticBinding) => {
|
|
expect(binding.provenance.status).toBe("module");
|
|
expect(binding.provenance.origins).toHaveLength(1);
|
|
const value = binding.provenance.origins[0];
|
|
if (value === undefined)
|
|
throw new Error(`Missing origin for ${binding.name}`);
|
|
return value;
|
|
};
|