import { CheckedExpr, CheckedType } from "./checked.ts"; import { ParsedExpr as AnyParsedExpr } from "./parsed.ts"; import { CompileError, Position } from "./token.ts"; type ParsedExpr< Type extends AnyParsedExpr["exprType"] = AnyParsedExpr["exprType"], > = & AnyParsedExpr & { exprType: Type; }; 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<"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": return this.checkInt(expr); 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 checkInt(expr: ParsedExpr<"int">): CheckedExpr { return { pos: expr.pos, exprType: "int", value: expr.value, valueType: { pos: expr.pos, typeType: "i16" }, }; } private errorExpr(message: string, pos: Position): CheckedExpr { this.errors.push({ message, pos }); return { pos, exprType: "error", message, }; } }