mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-31 05:00:52 +00:00
63 lines
1.4 KiB
TypeScript
63 lines
1.4 KiB
TypeScript
|
import { exhausted } from "../util.ts";
|
||
|
import { File, ModBlockStmt, ModFileStmt, Stmt } from "./ast.ts";
|
||
|
|
||
|
export type VisitRes = "stop" | void;
|
||
|
|
||
|
type R = VisitRes;
|
||
|
type PM = unknown[];
|
||
|
|
||
|
export interface Visitor<
|
||
|
P extends PM = [],
|
||
|
> {
|
||
|
visitFile?(file: File, ...p: P): R;
|
||
|
visitStmt?(stmt: Stmt, ...p: P): R;
|
||
|
visitErrorStmt?(stmt: Stmt, ...p: P): R;
|
||
|
visitModBlockStmt?(stmt: Stmt, kind: ModBlockStmt, ...p: P): R;
|
||
|
visitModFileStmt?(stmt: Stmt, kind: ModFileStmt, ...p: P): R;
|
||
|
}
|
||
|
|
||
|
export function visitFile<
|
||
|
P extends PM = [],
|
||
|
>(
|
||
|
v: Visitor<P>,
|
||
|
file: File,
|
||
|
...p: P
|
||
|
) {
|
||
|
if (v.visitFile?.(file, ...p) === "stop") return;
|
||
|
visitStmts(v, file.stmts, ...p);
|
||
|
}
|
||
|
|
||
|
export function visitStmts<
|
||
|
P extends PM = [],
|
||
|
>(
|
||
|
v: Visitor<P>,
|
||
|
stmts: Stmt[],
|
||
|
...p: P
|
||
|
) {
|
||
|
for (const stmt of stmts) {
|
||
|
visitStmt(v, stmt, ...p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function visitStmt<
|
||
|
P extends PM = [],
|
||
|
>(
|
||
|
v: Visitor<P>,
|
||
|
stmt: Stmt,
|
||
|
...p: P
|
||
|
) {
|
||
|
switch (stmt.kind.tag) {
|
||
|
case "error":
|
||
|
if (v.visitErrorStmt?.(stmt, ...p) === "stop") return;
|
||
|
return;
|
||
|
case "mod_block":
|
||
|
if (v.visitModBlockStmt?.(stmt, stmt.kind, ...p) === "stop") return;
|
||
|
visitStmts(v, stmt.kind.stmts, ...p);
|
||
|
return;
|
||
|
case "mod_file":
|
||
|
if (v.visitModFileStmt?.(stmt, stmt.kind, ...p) === "stop") return;
|
||
|
return;
|
||
|
}
|
||
|
exhausted(stmt.kind);
|
||
|
}
|