This commit is contained in:
parent
d908ff30e0
commit
4d7998eb9f
@ -1,6 +1,71 @@
|
||||
export class Reporter {
|
||||
report() {}
|
||||
private reports: Report[] = [];
|
||||
private errorOccured = false;
|
||||
|
||||
report(report: Report) {
|
||||
if (report.severity === "error") {
|
||||
this.errorOccured = true;
|
||||
}
|
||||
this.reports.push(report);
|
||||
}
|
||||
|
||||
ok(): boolean {
|
||||
return !this.errorOccured;
|
||||
}
|
||||
|
||||
printAll() {
|
||||
for (const report of this.reports) {
|
||||
printReport(report);
|
||||
}
|
||||
}
|
||||
|
||||
abort(): never {
|
||||
this.printAll();
|
||||
console.error("fatal: a fatal error occured");
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
ofFile(file: FileInfo): FileReporter {
|
||||
return new FileReporter(this, file);
|
||||
}
|
||||
}
|
||||
|
||||
export class FileReporter {
|
||||
constructor(
|
||||
private reporter: Reporter,
|
||||
private file: FileInfo,
|
||||
) {}
|
||||
|
||||
error(loc: Loc, message: string) {
|
||||
this.reporter.report({
|
||||
severity: "error",
|
||||
file: this.file,
|
||||
loc,
|
||||
message,
|
||||
});
|
||||
}
|
||||
info(loc: Loc, message: string) {
|
||||
this.reporter.report({
|
||||
severity: "info",
|
||||
file: this.file,
|
||||
loc,
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
||||
abort(): never {
|
||||
this.reporter.abort();
|
||||
}
|
||||
}
|
||||
|
||||
export type Report = {
|
||||
severity: Severity;
|
||||
file: FileInfo;
|
||||
loc: Loc;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type Severity = "error" | "info";
|
||||
|
||||
export type Loc = {
|
||||
idx: number;
|
||||
@ -13,14 +78,9 @@ export type FileInfo = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
export function printDiagnostics(
|
||||
filename: string,
|
||||
loc: Loc,
|
||||
severity: "error" | "info",
|
||||
message: string,
|
||||
text?: string,
|
||||
) {
|
||||
const line = loc.line;
|
||||
function printReport(report: Report) {
|
||||
const { severity, file: { filename, text }, message, loc } = report;
|
||||
const { line, col } = loc;
|
||||
|
||||
const severityColor = ({
|
||||
"error": "red",
|
||||
@ -49,12 +109,12 @@ export function printDiagnostics(
|
||||
`${" ".repeat(lineNumberText.length)}%c|\n` +
|
||||
`${lineNumberText}|%c${lineText}\n` +
|
||||
`${" ".repeat(lineNumberText.length)}%c|` +
|
||||
`%c${"~".repeat(lineText.length)}\n` +
|
||||
`${" ".repeat(col - 1)}%c^\n` +
|
||||
`${" ".repeat(lineNumberText.length)}%c|%c`,
|
||||
"color: cyan;",
|
||||
"color: lightwhite;",
|
||||
"color: cyan;",
|
||||
`color: ${severityColor};`,
|
||||
`color: ${severityColor}; font-weight: bold;`,
|
||||
"color: cyan;",
|
||||
"",
|
||||
);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import * as ast from "../ast.ts";
|
||||
import { Loc, printDiagnostics } from "../diagnostics.ts";
|
||||
import { FileReporter, Loc } from "../diagnostics.ts";
|
||||
import { Ty } from "../ty.ts";
|
||||
import { builtins } from "./builtins.ts";
|
||||
import { ResolveMap } from "./resolve.ts";
|
||||
@ -14,10 +14,8 @@ export class Checker {
|
||||
private nodeTys = new Map<number, Ty>();
|
||||
|
||||
constructor(
|
||||
private filename: string,
|
||||
private text: string,
|
||||
private file: ast.Node,
|
||||
private resols: ResolveMap,
|
||||
private reporter: FileReporter,
|
||||
) {}
|
||||
|
||||
check(node: ast.Node): Ty {
|
||||
@ -338,27 +336,15 @@ export class Checker {
|
||||
}
|
||||
|
||||
private error(loc: Loc, message: string) {
|
||||
printDiagnostics(
|
||||
this.filename,
|
||||
loc,
|
||||
"error",
|
||||
message,
|
||||
this.text,
|
||||
);
|
||||
this.reporter.error(loc, message);
|
||||
}
|
||||
|
||||
private info(loc: Loc, message: string) {
|
||||
printDiagnostics(
|
||||
this.filename,
|
||||
loc,
|
||||
"info",
|
||||
message,
|
||||
this.text,
|
||||
);
|
||||
this.reporter.info(loc, message);
|
||||
}
|
||||
|
||||
private fail(): never {
|
||||
Deno.exit(1);
|
||||
this.reporter.abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import * as ast from "../ast.ts";
|
||||
import { Loc, printDiagnostics } from "../diagnostics.ts";
|
||||
import { FileReporter, Loc } from "../diagnostics.ts";
|
||||
|
||||
export function parse(
|
||||
filename: string,
|
||||
text: string,
|
||||
reporter: FileReporter,
|
||||
): ast.Node {
|
||||
return new Parser(filename, text).parseFile();
|
||||
return new Parser(text, reporter).parseFile();
|
||||
}
|
||||
|
||||
export class Parser {
|
||||
@ -15,8 +15,8 @@ export class Parser {
|
||||
private prevTok: Tok | null = null;
|
||||
|
||||
constructor(
|
||||
private filename: string,
|
||||
private text: string,
|
||||
private reporter: FileReporter,
|
||||
) {
|
||||
this.toks = tokenize(text);
|
||||
}
|
||||
@ -334,9 +334,8 @@ export class Parser {
|
||||
}
|
||||
|
||||
private error(message: string, loc: Loc): never {
|
||||
printDiagnostics(this.filename, loc, "error", message, this.text);
|
||||
throw new Error();
|
||||
Deno.exit(1);
|
||||
this.reporter.error(loc, message);
|
||||
this.reporter.abort();
|
||||
}
|
||||
|
||||
private eat(type: string): boolean {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import * as ast from "../ast.ts";
|
||||
import { printDiagnostics } from "../diagnostics.ts";
|
||||
import { FileReporter } from "../diagnostics.ts";
|
||||
import { builtins } from "./builtins.ts";
|
||||
|
||||
export class ResolveMap {
|
||||
@ -33,9 +33,8 @@ export type Sym =
|
||||
};
|
||||
|
||||
export function resolve(
|
||||
filename: string,
|
||||
text: string,
|
||||
file: ast.Node,
|
||||
reporter: FileReporter,
|
||||
): ResolveMap {
|
||||
let syms = ResolverSyms.root();
|
||||
const resols = new Map<number, Sym>();
|
||||
@ -81,14 +80,8 @@ export function resolve(
|
||||
if (k.tag === "IdentExpr") {
|
||||
const sym = syms.resolveExpr(k.ident);
|
||||
if (sym === null) {
|
||||
printDiagnostics(
|
||||
filename,
|
||||
node.loc,
|
||||
"error",
|
||||
`undefined symbol '${k.ident}'`,
|
||||
text,
|
||||
);
|
||||
Deno.exit(1);
|
||||
reporter.error(node.loc, `undefined symbol '${k.ident}'`);
|
||||
reporter.abort();
|
||||
}
|
||||
resols.set(node.id, sym);
|
||||
}
|
||||
|
||||
11
src/main.ts
11
src/main.ts
@ -1,14 +1,19 @@
|
||||
import * as ast from "./ast.ts";
|
||||
import { Reporter } from "./diagnostics.ts";
|
||||
import * as front from "./front/mod.ts";
|
||||
import * as middle from "./middle.ts";
|
||||
import { FnInterpreter } from "./mir_interpreter.ts";
|
||||
|
||||
const reporter = new Reporter();
|
||||
|
||||
const filename = Deno.args[0];
|
||||
const text = await Deno.readTextFile(filename);
|
||||
|
||||
const fileAst = front.parse(filename, text);
|
||||
const resols = front.resolve(filename, text, fileAst);
|
||||
const checker = new front.Checker(filename, text, fileAst, resols);
|
||||
const fileRep = reporter.ofFile({ filename, text });
|
||||
|
||||
const fileAst = front.parse(text, fileRep);
|
||||
const resols = front.resolve(fileAst, fileRep);
|
||||
const checker = new front.Checker(resols, fileRep);
|
||||
|
||||
let mainFn: ast.NodeWithKind<"FnStmt"> | null = null;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
fn main()
|
||||
{
|
||||
let array: [int; 3] = [1, 2, 3];
|
||||
let array: [int; 3] = [1, 2, false];
|
||||
|
||||
// let a = 4;
|
||||
// let b = a;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user