import * as ast from "./ast/mod.ts"; import { Diag } from "./diagnostics.ts"; export class Ctx { private fileIds = new Ids(); private files = new Map, FileInfo>(); private diags: Diag[] = []; public fileHasChildWithIdent(file: File, childIdent: string): boolean { return this.files.get(id(file))! .subFiles.has(childIdent); } public addFile( ident: string, absPath: string, relPath: string, superFile: File | undefined, text: string, ): File { const file = this.fileIds.nextThenStep(); this.files.set(id(file), { ident, absPath, relPath, superFile, subFiles: new Map(), text, }); if (superFile) { this.files.get(id(superFile))! .subFiles.set(ident, file); } return file; } public addFileAst(file: File, ast: ast.File) { this.files.get(id(file))!.ast = ast; } public fileInfo(file: File): FileInfo { this.files.get(id(file))!; } public reportFatal(file: File, msg: string) { console.error(`fatal: ${msg}`); this.reportImmediately(file, msg); } public enableReportImmediately = false; public enableStacktrace = false; private reportImmediately(file: File, msg: string) { if (!this.enableReportImmediately) { return; } if (!this.enableStacktrace) { return; } class StackTracer extends Error { constructor() { super("StackTracer"); } } try { //throw new ReportNotAnError(); } catch (error) { if (!(error instanceof StackTracer)) { throw error; } console.log( error.stack?.replace( "Error: StackTracer", "Stack trace:", ) ?? error, ); } } } export type File = IdBase; export type FileInfo = { ident: string; absPath: string; relPath: string; superFile?: File; subFiles: Map; text: string; ast?: ast.File; }; export type IdBase = { id: number }; export type Id = IdType["id"]; export const id = (id: IdType): Id => id.id; export class Ids { private next = 0; public nextThenStep(): IdType { const id = this.next; this.next += 1; return { id } as IdType; } }