mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 12:46:31 +00:00
94a57029c0
This reverts commit 7ca1ff1e25
.
138 lines
3.8 KiB
TypeScript
138 lines
3.8 KiB
TypeScript
import { AstCreator, Mod, Stmt } from "./ast.ts";
|
|
import { Checker } from "./checker.ts";
|
|
import { CompoundAssignDesugarer } from "./desugar/compound_assign.ts";
|
|
import { SpecialLoopDesugarer } from "./desugar/special_loop.ts";
|
|
import { Reporter } from "./info.ts";
|
|
import { Lexer } from "./lexer.ts";
|
|
import { Monomorphizer } from "./mono.ts";
|
|
import { FnNamesMap, Lowerer } from "./lowerer.ts";
|
|
import { Parser } from "./parser.ts";
|
|
import { Resolver } from "./resolver.ts";
|
|
import { AstVisitor, VisitRes, visitStmts } from "./ast_visitor.ts";
|
|
|
|
import * as path from "jsr:@std/path";
|
|
import { Pos } from "./token.ts";
|
|
|
|
export type CompileResult = {
|
|
program: number[];
|
|
fnNames: FnNamesMap;
|
|
};
|
|
|
|
export class Compiler {
|
|
private astCreator = new AstCreator();
|
|
private reporter;
|
|
|
|
public constructor(private startFilePath: string) {
|
|
this.reporter = new Reporter(this.startFilePath);
|
|
}
|
|
|
|
public async compile(): Promise<CompileResult> {
|
|
const mod = new ModTree(
|
|
this.startFilePath,
|
|
this.astCreator,
|
|
this.reporter,
|
|
).resolve();
|
|
|
|
new SpecialLoopDesugarer(this.astCreator).desugar(mod.ast);
|
|
|
|
new Resolver(this.reporter).resolve(mod.ast);
|
|
|
|
new CompoundAssignDesugarer(this.astCreator).desugar(mod.ast);
|
|
|
|
new Checker(this.reporter).check(mod.ast);
|
|
|
|
if (this.reporter.errorOccured()) {
|
|
console.error("Errors occurred, stopping compilation.");
|
|
Deno.exit(1);
|
|
}
|
|
|
|
const { monoFns, callMap } = new Monomorphizer(mod.ast).monomorphize();
|
|
|
|
const lastPos = await lastPosInTextFile(this.startFilePath);
|
|
|
|
const lowerer = new Lowerer(monoFns, callMap, lastPos);
|
|
const { program, fnNames } = lowerer.lower();
|
|
//lowerer.printProgram();
|
|
|
|
return { program, fnNames };
|
|
}
|
|
}
|
|
|
|
export class ModTree implements AstVisitor<[string]> {
|
|
constructor(
|
|
private entryFilePath: string,
|
|
private astCreator: AstCreator,
|
|
private reporter: Reporter,
|
|
) {}
|
|
|
|
public resolve(): Mod {
|
|
const entryAst = this.parseFile(this.entryFilePath);
|
|
|
|
visitStmts(entryAst, this, this.entryFilePath);
|
|
|
|
return { filePath: this.entryFilePath, ast: entryAst };
|
|
}
|
|
|
|
private parseFile(filePath: string): Stmt[] {
|
|
const text = Deno.readTextFileSync(filePath);
|
|
|
|
const lexer = new Lexer(text, this.reporter);
|
|
|
|
const parser = new Parser(lexer, this.astCreator, this.reporter);
|
|
const ast = parser.parse();
|
|
|
|
return ast;
|
|
}
|
|
|
|
visitModBlockStmt(stmt: Stmt, filePath: string): VisitRes {
|
|
if (stmt.kind.type !== "mod_block") {
|
|
throw new Error();
|
|
}
|
|
const { ident, stmts: ast } = stmt.kind;
|
|
stmt.kind = {
|
|
type: "mod",
|
|
ident,
|
|
mod: { filePath, ast },
|
|
};
|
|
visitStmts(ast, this, filePath);
|
|
return "stop";
|
|
}
|
|
|
|
visitModFileStmt(stmt: Stmt, filePath: string): VisitRes {
|
|
if (stmt.kind.type !== "mod_file") {
|
|
throw new Error();
|
|
}
|
|
const { ident, filePath: modFilePath } = stmt.kind;
|
|
const ast = this.parseFile(
|
|
path.join(path.dirname(filePath), modFilePath),
|
|
);
|
|
stmt.kind = {
|
|
type: "mod",
|
|
ident,
|
|
mod: { filePath, ast },
|
|
};
|
|
visitStmts(ast, this, filePath);
|
|
return "stop";
|
|
}
|
|
}
|
|
|
|
async function lastPosInTextFile(filePath: string): Promise<Pos> {
|
|
const text = await Deno.readTextFile(filePath);
|
|
|
|
let index = 0;
|
|
let line = 1;
|
|
let col = 1;
|
|
|
|
while (index < text.length) {
|
|
if (text[index] == "\n") {
|
|
line += 1;
|
|
col = 1;
|
|
} else {
|
|
col += 1;
|
|
}
|
|
index += 1;
|
|
}
|
|
|
|
return { index, line, col };
|
|
}
|