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