slige/compiler/main.ts

102 lines
2.6 KiB
TypeScript
Raw Normal View History

2025-01-22 21:40:29 +00:00
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 = {
2025-01-22 13:09:27 +00:00
rootMod: Mod;
};
2025-01-22 21:40:29 +00:00
export type Mod = null;
2025-01-22 13:09:27 +00:00
2025-01-22 21:40:29 +00:00
export interface PackEmitter {
2025-01-22 13:09:27 +00:00
emit(pack: Pack): void;
}
2025-01-22 21:40:29 +00:00
export class PackCompiler {
2025-01-23 13:19:27 +00:00
private ctx = new Ctx();
2025-01-22 13:09:27 +00:00
public constructor(
private entryFilePath: string,
private emitter: PackEmitter,
) {}
public compile() {
2025-01-23 13:19:27 +00:00
FileTreeAstCollector
.fromEntryFile(this.ctx, this.entryFilePath)
.collect();
2025-01-22 13:09:27 +00:00
}
}
2025-01-22 21:40:29 +00:00
type _P = { file: File };
2025-01-23 13:19:27 +00:00
export class FileTreeAstCollector implements ast.Visitor<[_P]> {
2025-01-22 21:40:29 +00:00
private subFilePromise = Promise.resolve();
2025-01-23 13:19:27 +00:00
private constructor(
2025-01-22 21:40:29 +00:00
private ctx: Ctx,
private superFile: File | undefined,
private ident: string,
private absPath: string,
private relPath: string,
) {}
2025-01-23 13:19:27 +00:00
public static fromEntryFile(
ctx: Ctx,
entryFilePath: string,
): FileTreeAstCollector {
return new FileTreeAstCollector(
ctx,
undefined,
"root",
entryFilePath,
entryFilePath,
);
}
2025-01-22 21:40:29 +00:00
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;
}
2025-01-23 13:19:27 +00:00
visitModFileItem(
item: ast.Item,
kind: ast.ModFileItem,
2025-01-22 21:40:29 +00:00
{ file }: _P,
): ast.VisitRes {
2025-01-23 13:19:27 +00:00
const { ident: { text: ident }, filePath: relPath } = kind;
2025-01-22 21:40:29 +00:00
const absPath = path.join(path.dirname(this.absPath), relPath);
this.subFilePromise = this.subFilePromise
.then(() => {
if (this.ctx.fileHasChildWithIdent(file, ident)) {
2025-01-23 09:18:33 +00:00
this.ctx.report({
severity: "fatal",
msg: `module '${ident}' already declared`,
file,
2025-01-23 13:19:27 +00:00
span: item.span,
2025-01-23 09:18:33 +00:00
});
2025-01-23 13:19:27 +00:00
Deno.exit(1);
2025-01-22 21:40:29 +00:00
}
2025-01-23 13:19:27 +00:00
return new FileTreeAstCollector(
2025-01-22 21:40:29 +00:00
this.ctx,
file,
ident,
absPath,
relPath,
)
.collect();
});
return "stop";
}
2025-01-22 13:09:27 +00:00
}