90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import { CheckedExpr, CheckedType } from "./checked.ts";
|
|
import { ParsedExpr } from "./parsed.ts";
|
|
import { CompileError, Position } from "./token.ts";
|
|
|
|
export type SymbolValue = {
|
|
id: number;
|
|
subject: string;
|
|
valueType: CheckedType;
|
|
};
|
|
|
|
export class SymbolTable {
|
|
private idCounter = 0;
|
|
private symbols: { [key: string]: SymbolValue } = {};
|
|
|
|
public define(subject: string, valueType: CheckedType) {
|
|
if (subject in this.symbols) {
|
|
throw new Error("redefinition not implemented");
|
|
}
|
|
const id = this.idCounter;
|
|
this.idCounter++;
|
|
this.symbols[subject] = { id, subject, valueType };
|
|
}
|
|
}
|
|
|
|
export class Checker {
|
|
private symbolTable = new SymbolTable();
|
|
public errors: CompileError[] = [];
|
|
|
|
public check(statements: ParsedExpr[]): CheckedExpr[] {
|
|
return statements as CheckedExpr[];
|
|
}
|
|
|
|
private searchTopLevelStatements(statements: ParsedExpr[]) {
|
|
for (const statement of statements) {
|
|
switch (statement.exprType) {
|
|
case "fn":
|
|
this.searchTopLevelFn(statement);
|
|
break;
|
|
case "let":
|
|
break;
|
|
default:
|
|
this.errors.push({
|
|
pos: statement.pos,
|
|
message:
|
|
`statement '${statement.exprType}' not supported in top level`,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private searchTopLevelFn(statement: ParsedExpr & { exprType: "fn" }) {
|
|
}
|
|
|
|
private checkExpr(expr: ParsedExpr): CheckedExpr {
|
|
switch (expr.exprType) {
|
|
case "error":
|
|
return this.errorExpr(expr.message, expr.pos);
|
|
case "unit":
|
|
return { pos: expr.pos, exprType: "unit" };
|
|
case "id":
|
|
throw new Error("not implemented");
|
|
case "int":
|
|
case "if":
|
|
case "block":
|
|
case "call":
|
|
case "index":
|
|
case "increment":
|
|
case "decrement":
|
|
case "unary":
|
|
case "binary":
|
|
case "assign":
|
|
default:
|
|
return this.errorExpr(
|
|
`expected expression, got '${expr.exprType}' statement`,
|
|
expr.pos,
|
|
);
|
|
}
|
|
}
|
|
|
|
private errorExpr(message: string, pos: Position): CheckedExpr {
|
|
this.errors.push({ message, pos });
|
|
return {
|
|
pos,
|
|
exprType: "error",
|
|
message,
|
|
};
|
|
}
|
|
}
|