slige/compiler/ast.ts
2024-12-13 12:12:16 +01:00

152 lines
3.5 KiB
TypeScript

import { Pos } from "./token.ts";
import { VType } from "./vtype.ts";
export type Ast = File[];
export type File = {
path: string;
stmts: Stmt[];
};
export type Stmt = {
kind: StmtKind;
pos: Pos;
id: number;
};
export type StmtKind =
| { type: "error" }
| { type: "import"; path: Expr }
| { type: "break"; expr?: Expr }
| { type: "return"; expr?: Expr }
| {
type: "fn";
ident: string;
params: Param[];
returnType?: EType;
body: Expr;
anno?: Anno;
vtype?: VType;
}
| { type: "let"; param: Param; value: Expr }
| { type: "assign"; subject: Expr; value: Expr }
| { type: "expr"; expr: Expr };
export type Expr = {
kind: ExprKind;
pos: Pos;
vtype?: VType;
id: number;
};
export type ExprKind =
| { type: "error" }
| { type: "int"; value: number }
| { type: "string"; value: string }
| { type: "ident"; value: string }
| { type: "group"; expr: Expr }
| { type: "field"; subject: Expr; value: string }
| { type: "index"; subject: Expr; value: Expr }
| { type: "call"; subject: Expr; args: Expr[] }
| { type: "unary"; unaryType: UnaryType; subject: Expr }
| { type: "binary"; binaryType: BinaryType; left: Expr; right: Expr }
| { type: "if"; cond: Expr; truthy: Expr; falsy?: Expr }
| { type: "bool"; value: boolean }
| { type: "null" }
| { type: "loop"; body: Expr }
| { type: "block"; stmts: Stmt[]; expr?: Expr }
| {
type: "sym";
ident: string;
sym: Sym;
};
export type UnaryType = "not";
export type BinaryType =
| "+"
| "*"
| "=="
| "-"
| "/"
| "!="
| "<"
| ">"
| "<="
| ">="
| "or"
| "and";
export type Param = {
ident: string;
etype?: EType;
pos: Pos;
vtype?: VType;
};
export type Sym = {
ident: string;
pos?: Pos;
} & SymKind;
export type SymKind =
| { type: "let"; stmt: Stmt; param: Param }
| { type: "let_static"; stmt: Stmt; param: Param }
| { type: "fn"; stmt: Stmt }
| { type: "fn_param"; param: Param }
| { type: "closure"; inner: Sym }
| { type: "builtin"; builtinId: number };
export type EType = {
kind: ETypeKind;
pos: Pos;
id: number;
};
export type ETypeKind =
| { type: "error" }
| { type: "ident"; value: string }
| { type: "array"; inner: EType }
| { type: "struct"; fields: Param[] };
export type ETypeParam = {
ident: string;
pos: Pos;
vtype?: VType;
};
export type Anno = {
ident: string;
values: Expr[];
pos: Pos;
};
export function stmtToString(stmt: Stmt): string {
const body = (() => {
switch (stmt.kind.type) {
case "assign":
return `{ subject: ${exprToString(stmt.kind.subject)}, value: ${
exprToString(stmt.kind.value)
} }`;
}
return "(<not implemented>)";
})();
const { line } = stmt.pos;
return `${stmt.kind.type}:${line}${body}`;
}
export function exprToString(expr: Expr): string {
const body = (() => {
switch (expr.kind.type) {
case "binary":
return `(${
exprToString(expr.kind.left)
} ${expr.kind.binaryType} ${exprToString(expr.kind.right)})`;
case "sym":
return `(${expr.kind.ident})`;
}
return "(<not implemented>)";
})();
const { line } = expr.pos;
return `${expr.kind.type}:${line}${body}`;
}