/** * The one pipeline from Agency source text to a `CompilationUnit`. * * Every path that checks names goes through here, so a new step is added * once. Callers differ only through `PrepareOptions`; see * docs/dev/compiler/prepare-program.md. */ import type { AgencyConfig } from "../config/config.js"; import type { AgencyProgram } from "../types.js"; import type { SourceLocation } from "../types/base.js"; import { type CompilationUnit } from "../compilationUnit.js"; import { type ParseAgencyErrorData } from "../parser.js"; import { SymbolTable } from "../symbolTable.js"; import type { SpliceDiagnostic } from "./splice/types.js"; export type ParseFailure = { stage: "parse"; message: string; errorData?: ParseAgencyErrorData; }; /** `vet` refused the program. */ export type VetFailure = { stage: "vet"; message: string; }; export type SpliceFailure = { stage: "splice"; splice: SpliceDiagnostic; }; /** A failed symbol table build, re-export, or import. `error` is whatever * was thrown, which is not always an ImportResolutionError. */ export type ImportFailure = { stage: "imports"; error: unknown; }; /** A `callback("onX") { ... }` block the lifting pass refuses. */ export type LiftFailure = { stage: "lift"; message: string; loc?: SourceLocation; }; /** A decorator tag that cannot lower: an unknown name, a def decorating * itself, or a tag on anything but a top-level def. */ export type DecoratorFailure = { stage: "decorators"; message: string; loc?: SourceLocation; }; export type PipelineDiagnostic = ParseFailure | VetFailure | SpliceFailure | ImportFailure | LiftFailure | DecoratorFailure; export type PrepareOptions = { /** Prepend the prelude import to the text before parsing. The editor * passes false so positions match the buffer; the prelude import is then * added to the parsed program instead. Default true. */ applyTemplate?: boolean; /** Honor `import test { ... }`. Only the editor and the test runner may; * anything that compiles code to run it must not. Default false. */ allowTestImports?: boolean; /** Continue past a splice that will not expand or an import that will not * resolve, so the rest of the file is still checked. An editor and the * analysis commands want this. A build does not. Default false. */ keepGoing?: boolean; /** The editor uses a shorter limit than the build. */ spliceWallClockMs?: number; /** Leave a relative import alone instead of resolving it. For source * checked at a made-up path, where `./helper.agency` cannot resolve and * saying so would blame the user for the caller's own limitation. * Default false. */ ignoreRelativeImports?: boolean; /** A table the caller already built, for example one shared across files. */ symbolTable?: SymbolTable; /** Reasons to refuse this program, or none. Runs on the program as written, * before any generator does, and again once splices have expanded, * because a generator can emit imports of its own. */ vet?: (program: AgencyProgram) => string[]; }; export type PreparedProgram = { ok: true; program: AgencyProgram; info: CompilationUnit; symbolTable: SymbolTable; /** The parse as written, before any step rewrote it. The linter reads this. */ parsed: AgencyProgram; /** Empty unless `keepGoing` let the pipeline past a failure. */ diagnostics: PipelineDiagnostic[]; }; export type PrepareFailure = { ok: false; diagnostics: PipelineDiagnostic[]; }; export type PrepareResult = PreparedProgram | PrepareFailure; export declare function prepareProgram(source: string, filePath: string, config: AgencyConfig, options?: PrepareOptions): PrepareResult; /** Rethrow what an "imports" failure caught. For callers whose contract is * that a bad import throws. */ export declare function throwImportFailures(diagnostics: PipelineDiagnostic[]): void; /** One failure as a line of text that names its file, for callers that * report errors as strings. Leave `filePath` out when the path means nothing * to the reader, such as a temporary file. */ export declare function describeDiagnostic(found: PipelineDiagnostic, filePath?: string): string;