import * as path from "jsr:@std/path"; import { Parser } from "./parser/parser.ts"; import * as ast from "./ast/mod.ts"; import { Ctx } from "./ctx.ts"; import { File } from "./ctx.ts"; export type Pack = { rootMod: Mod; }; export type Mod = null; export interface PackEmitter { emit(pack: Pack): void; } export class PackCompiler { public constructor( private entryFilePath: string, private emitter: PackEmitter, ) {} public compile() { } } type _P = { file: File }; export class FileTreeCollector implements ast.Visitor<[_P]> { private subFilePromise = Promise.resolve(); public constructor( private ctx: Ctx, private superFile: File | undefined, private ident: string, private absPath: string, private relPath: string, ) {} public async collect(): Promise { const text = await Deno.readTextFile(this.absPath); const file = this.ctx.addFile( this.ident, this.absPath, this.relPath, this.superFile, text, ); const fileAst = new Parser(file, text).parse(); this.ctx.addFileAst(file, fileAst); ast.visitFile(this, fileAst, { file }); await this.subFilePromise; } visitModFileStmt( stmt: ast.Stmt, kind: ast.ModFileStmt, { file }: _P, ): ast.VisitRes { const { ident, filePath: relPath } = kind; const absPath = path.join(path.dirname(this.absPath), relPath); this.subFilePromise = this.subFilePromise .then(() => { if (this.ctx.fileHasChildWithIdent(file, ident)) { this.ctx.report({ severity: "fatal", msg: `module '${ident}' already declared`, file, span: stmt.span, }); } return new FileTreeCollector( this.ctx, file, ident, absPath, relPath, ) .collect(); }); return "stop"; } }