slige/compiler/ast.ts

225 lines
5.2 KiB
TypeScript
Raw Normal View History

2024-12-29 04:39:22 +00:00
import type { Syms } from "./resolver_syms.ts";
2024-12-10 20:42:15 +00:00
import { Pos } from "./token.ts";
2024-12-26 02:56:59 +00:00
import { GenericArgsMap, VType } from "./vtype.ts";
2024-11-15 14:20:49 +00:00
2024-12-29 04:39:22 +00:00
export type Mod = {
filePath: string;
ast: Stmt[];
2024-12-29 04:39:22 +00:00
};
2024-11-15 14:20:49 +00:00
export type Stmt = {
2024-12-06 13:17:52 +00:00
kind: StmtKind;
pos: Pos;
2024-12-30 23:12:34 +00:00
details?: StmtDetails;
2024-12-06 13:17:52 +00:00
id: number;
2024-11-15 14:20:49 +00:00
};
export type StmtKind =
| { type: "error" }
| { type: "mod_block"; ident: string; stmts: Stmt[] }
2024-12-29 04:39:22 +00:00
| { type: "mod_file"; ident: string; filePath: string }
| { type: "mod"; ident: string; mod: Mod }
2024-12-06 13:17:52 +00:00
| { type: "break"; expr?: Expr }
| { type: "return"; expr?: Expr }
| {
type: "fn";
ident: string;
genericParams?: GenericParam[];
2024-12-06 13:17:52 +00:00
params: Param[];
returnType?: EType;
body: Expr;
2024-12-09 12:33:33 +00:00
vtype?: VType;
2024-12-06 13:17:52 +00:00
}
| { type: "let"; param: Param; value: Expr }
2024-12-31 04:32:41 +00:00
| { type: "type_alias"; param: Param }
| { type: "assign"; assignType: AssignType; subject: Expr; value: Expr }
2024-12-06 13:17:52 +00:00
| { type: "expr"; expr: Expr };
2024-11-15 14:20:49 +00:00
export type AssignType = "=" | "+=" | "-=";
2024-12-30 23:12:34 +00:00
export type StmtDetails = {
pub: boolean;
annos: Anno[];
};
2024-11-15 14:20:49 +00:00
export type Expr = {
2024-12-06 13:17:52 +00:00
kind: ExprKind;
pos: Pos;
vtype?: VType;
id: number;
2024-11-15 14:20:49 +00:00
};
export type ExprKind =
| { type: "error" }
2024-12-06 13:17:52 +00:00
| { type: "int"; value: number }
| { type: "string"; value: string }
| { type: "ident"; ident: string }
| {
type: "sym";
ident: string;
sym: Sym;
}
2024-12-06 13:17:52 +00:00
| { type: "group"; expr: Expr }
2024-12-31 02:38:38 +00:00
| { type: "array"; exprs: Expr[] }
| { type: "struct"; fields: Field[] }
| { type: "field"; subject: Expr; ident: string }
2024-12-06 13:17:52 +00:00
| { type: "index"; subject: Expr; value: Expr }
2024-12-26 02:56:59 +00:00
| {
type: "call";
subject: Expr;
args: Expr[];
genericArgs?: GenericArgsMap;
}
| { type: "path"; subject: Expr; ident: string }
| { type: "etype_args"; subject: Expr; etypeArgs: EType[] }
2024-12-06 13:17:52 +00:00
| { type: "unary"; unaryType: UnaryType; subject: Expr }
| { type: "binary"; binaryType: BinaryType; left: Expr; right: Expr }
2024-12-17 09:24:18 +00:00
| { type: "if"; cond: Expr; truthy: Expr; falsy?: Expr; elsePos?: Pos }
2024-12-06 13:17:52 +00:00
| { type: "bool"; value: boolean }
| { type: "null" }
| { type: "loop"; body: Expr }
| { type: "block"; stmts: Stmt[]; expr?: Expr }
| { type: "while"; cond: Expr; body: Expr }
| { type: "for_in"; param: Param; value: Expr; body: Expr }
| {
type: "for";
decl?: Stmt;
cond?: Expr;
incr?: Stmt;
body: Expr;
2024-12-06 13:17:52 +00:00
};
2024-11-22 13:06:28 +00:00
export type UnaryType = "not" | "-";
2024-12-13 09:26:34 +00:00
export type BinaryType =
| "+"
| "*"
| "=="
| "-"
| "/"
| "!="
| "<"
| ">"
| "<="
| ">="
| "or"
| "and";
2024-12-31 02:38:38 +00:00
export type Field = {
ident: string;
expr: Expr;
pos: Pos;
};
2024-12-13 09:26:34 +00:00
export type Param = {
2025-01-02 03:40:09 +00:00
id: number;
index?: number;
2024-12-13 09:26:34 +00:00
ident: string;
etype?: EType;
pos: Pos;
vtype?: VType;
};
2024-11-22 13:06:28 +00:00
export type Sym = {
2024-12-06 13:17:52 +00:00
ident: string;
pos?: Pos;
2024-12-10 13:36:41 +00:00
} & SymKind;
export type SymKind =
| { type: "let"; stmt: Stmt; param: Param }
| { type: "let_static"; stmt: Stmt; param: Param }
2024-12-31 04:32:41 +00:00
| { type: "type_alias"; stmt: Stmt; param: Param }
2024-12-10 13:36:41 +00:00
| { type: "fn"; stmt: Stmt }
| { type: "fn_param"; param: Param }
| { type: "closure"; inner: Sym }
2024-12-29 04:39:22 +00:00
| { type: "generic"; stmt: Stmt; genericParam: GenericParam }
| { type: "mod"; syms: Syms };
2024-12-06 13:17:52 +00:00
export type EType = {
kind: ETypeKind;
pos: Pos;
id: number;
};
2024-11-22 13:06:28 +00:00
2024-12-06 13:17:52 +00:00
export type ETypeKind =
| { type: "error" }
| { type: "null" }
| { type: "int" }
| { type: "bool" }
| { type: "string" }
| { type: "ident"; ident: string }
| {
type: "sym";
ident: string;
sym: Sym;
}
2024-12-06 13:17:52 +00:00
| { type: "array"; inner: EType }
2024-12-31 02:38:38 +00:00
| { type: "struct"; fields: Param[] }
| { type: "type_of"; expr: Expr };
2024-12-11 11:36:19 +00:00
export type GenericParam = {
2024-12-26 00:51:05 +00:00
id: number;
2025-01-02 03:40:09 +00:00
index: number;
2024-12-13 09:26:34 +00:00
ident: string;
pos: Pos;
vtype?: VType;
};
2024-12-11 11:36:19 +00:00
export type Anno = {
ident: string;
2024-12-30 23:12:34 +00:00
args: Expr[];
2024-12-11 11:36:19 +00:00
pos: Pos;
};
export class AstCreator {
private nextNodeId = 0;
2024-12-30 23:12:34 +00:00
public stmt(kind: StmtKind, pos: Pos, details?: StmtDetails): Stmt {
2025-01-02 03:40:09 +00:00
const id = this.genId();
2024-12-30 23:12:34 +00:00
return { kind, pos, details, id };
}
public expr(kind: ExprKind, pos: Pos): Expr {
2025-01-02 03:40:09 +00:00
const id = this.genId();
return { kind, pos, id };
}
public etype(kind: ETypeKind, pos: Pos): EType {
2025-01-02 03:40:09 +00:00
const id = this.genId();
return { kind, pos, id };
}
public param(val: Omit<Param, "id">): Param {
const id = this.genId();
return { ...val, id };
}
public genericParam(val: Omit<GenericParam, "id">): GenericParam {
const id = this.genId();
return { ...val, id };
}
private genId(): number {
const id = this.nextNodeId;
this.nextNodeId += 1;
2025-01-02 03:40:09 +00:00
return id;
}
}
2024-12-30 23:12:34 +00:00
export class AnnoView {
public constructor(private details?: StmtDetails) {}
public has(...idents: string[]): boolean {
return this.details?.annos.some((anno) =>
idents.some((ident) => anno.ident === ident)
) ?? false;
}
public get(ident: string): Anno {
const anno = this.details?.annos.find((anno) => anno.ident === ident);
if (!anno) {
throw new Error();
}
return anno;
}
}