nandgame-compiler/checker.ts

108 lines
3.0 KiB
TypeScript
Raw Normal View History

2023-04-27 01:32:06 +01:00
import { CheckedExpr, CheckedType } from "./checked.ts";
2023-05-01 12:36:06 +01:00
import { ParsedExpr as AnyParsedExpr } from "./parsed.ts";
2023-04-27 13:48:08 +01:00
import { CompileError, Position } from "./token.ts";
2023-04-27 01:32:06 +01:00
2023-05-01 12:36:06 +01:00
type ParsedExpr<
Type extends AnyParsedExpr["exprType"] = AnyParsedExpr["exprType"],
> =
& AnyParsedExpr
& {
exprType: Type;
};
2023-04-27 01:32:06 +01:00
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;
}
}
}
2023-05-01 12:36:06 +01:00
private searchTopLevelFn(statement: ParsedExpr<"fn">) {
2023-04-27 01:32:06 +01:00
}
2023-04-27 13:48:08 +01:00
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":
2023-05-01 12:36:06 +01:00
return this.checkInt(expr);
2023-04-27 13:48:08 +01:00
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,
);
}
}
2023-05-01 12:36:06 +01:00
private checkInt(expr: ParsedExpr<"int">): CheckedExpr {
return {
pos: expr.pos,
exprType: "int",
value: expr.value,
valueType: { pos: expr.pos, typeType: "i16" },
};
}
2023-04-27 13:48:08 +01:00
private errorExpr(message: string, pos: Position): CheckedExpr {
this.errors.push({ message, pos });
return {
pos,
exprType: "error",
message,
};
}
}