slige/compiler/main.ts
2025-01-23 10:18:33 +01:00

82 lines
2.1 KiB
TypeScript

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<void> {
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,
});
}
return new FileTreeCollector(
this.ctx,
file,
ident,
absPath,
relPath,
)
.collect();
});
return "stop";
}
}