diff --git a/compiler/ast/ast.ts b/compiler/ast/ast.ts index 45a2a11..2f6edfe 100644 --- a/compiler/ast/ast.ts +++ b/compiler/ast/ast.ts @@ -147,7 +147,7 @@ export type ExprKind = | { tag: "for" } & ForExpr | { tag: "c_for" } & CForExpr; -export type PathExpr = { path: Path }; +export type PathExpr = { qty?: Ty; path: Path }; export type IntExpr = { value: number }; export type BoolExpr = { value: boolean }; export type StringExpr = { value: string }; @@ -205,12 +205,11 @@ export type Pat = { export type PatKind = | { tag: "error" } - | { tag: "bind" } & BindPat; + | { tag: "bind" } & BindPat + | { tag: "path" } & PathPat; -export type BindPat = { - ident: Ident; - mut: boolean; -}; +export type BindPat = { ident: Ident; mut: boolean }; +export type PathPat = { qty?: Ty; path: Path }; export type Ty = { kind: TyKind; @@ -230,7 +229,7 @@ export type TyKind = | { tag: "array" } & ArrayTy | { tag: "anon_struct" } & AnonStructTy; -export type PathTy = { path: Path }; +export type PathTy = { qty?: Ty; path: Path }; export type RefTy = { ty: Ty; mut: boolean }; export type PtrTy = { ty: Ty; mut: boolean }; export type SliceTy = { ty: Ty }; diff --git a/compiler/ctx.ts b/compiler/ctx.ts index eabdaac..2f37af3 100644 --- a/compiler/ctx.ts +++ b/compiler/ctx.ts @@ -59,6 +59,8 @@ export class Ctx { .map((key) => keyId(key)); } + // + private identIds = new Ids(); private identStringToId = new Map(); private identIdToString = new Map, string>(); @@ -77,15 +79,78 @@ export class Ctx { return this.identIdToString.get(idKey(ident))!; } - private stmtIds = new Ids(); - private stmts = new Map, hir.Stmt>(); + // - public internStmt(kind: hir.StmtKind, span: Span): hir.StmtId { - const id = this.stmtIds.nextThenStep(); - this.stmts.set(idKey(id), { kind, span }); + private hirIds = new Ids(); + + private stmts = new Map, hir.Stmt>(); + + /// don't intern the same thing twice + public internStmt(kind: hir.StmtKind, span: Span): hir.Stmt { + const id = this.hirIds.nextThenStep(); + const v: hir.Stmt = { id, kind, span }; + this.stmts.set(idKey(id), v); + return v; + } + + private exprs = new Map, hir.Expr>(); + + /// don't intern the same thing twice + public internExpr(kind: hir.ExprKind, span: Span): hir.Expr { + const id = this.hirIds.nextThenStep(); + const v: hir.Expr = { id, kind, span }; + this.exprs.set(idKey(id), v); + return v; + } + + private pats = new Map, hir.Pat>(); + + /// don't intern the same thing twice + public internPat(kind: hir.PatKind, span: Span): hir.Pat { + const id = this.hirIds.nextThenStep(); + const v: hir.Pat = { id, kind, span }; + this.pats.set(idKey(id), v); + return v; + } + + private tys = new Map, hir.Ty>(); + + /// don't intern the same thing twice + public internTy(kind: hir.TyKind, span: Span): hir.Ty { + const id = this.hirIds.nextThenStep(); + const v: hir.Ty = { id, kind, span }; + this.tys.set(idKey(id), v); + return v; + } + + private blocks = new Map, hir.Block>(); + + /// don't intern the same thing twice + public internBlock(block: Omit): hir.Block { + const id = this.hirIds.nextThenStep(); + const v: hir.Block = { id, ...block }; + this.blocks.set(idKey(id), v); + return v; + } + + // + + private defIds = new Ids(); + + private defs = new Map, hir.HirId>(); + + public addHirIdDef(hirId: hir.HirId): hir.DefId { + const id = this.defIds.nextThenStep(); + this.defs.set(idKey(id), hirId); return id; } + public defHirId(id: hir.DefId): hir.HirId { + return this.defs.get(idKey(id))!; + } + + // + public filePosLineText(file: File, pos: Pos): string { const fileTextLines = this.fileInfo(file).text.split("\n"); return fileTextLines[pos.line - 1]; @@ -143,6 +208,7 @@ export type FileInfo = { }; export type IdentId = IdBase & { readonly _: unique symbol }; +export type HirId = IdBase & { readonly _: unique symbol }; export type DefId = IdBase & { readonly _: unique symbol }; export type IdBase = { key: number }; diff --git a/compiler/middle/hir.ts b/compiler/middle/hir.ts index 1127d1e..15e2beb 100644 --- a/compiler/middle/hir.ts +++ b/compiler/middle/hir.ts @@ -1,8 +1,10 @@ +export type { DefId, HirId } from "../ctx.ts"; +import { HirId, IdentId } from "../ctx.ts"; import { Span } from "../diagnostics.ts"; - -export type StmtId = { key: number; readonly unique: unique symbol }; +import { Res } from "./rib.ts"; export type Stmt = { + id: HirId; kind: StmtKind; span: Span; }; @@ -17,28 +19,26 @@ export type StmtKind = | { tag: "assign" } & AssignStmt | { tag: "expr" } & ExprStmt; -export type ItemStmt = { item: ItemId }; +export type ItemStmt = { item: Item }; export type LetStmt = { - pat: PatId; - ty?: TyId; - expr?: ExprId; + pat: Pat; + ty?: Ty; + expr?: Expr; }; -export type ReturnStmt = { expr?: ExprId }; -export type BreakStmt = { expr?: ExprId }; +export type ReturnStmt = { expr?: Expr }; +export type BreakStmt = { expr?: Expr }; export type AssignStmt = { assignType: AssignType; - subject: ExprId; - value: ExprId; + subject: Expr; + value: Expr; }; export type AssignType = "=" | "+=" | "-="; -export type ExprStmt = { expr: ExprId }; - -export type ItemId = { key: number; readonly unique: unique symbol }; +export type ExprStmt = { expr: Expr }; export type Item = { kind: ItemKind; @@ -57,7 +57,7 @@ export type ItemKind = | { tag: "use" } & UseItem | { tag: "type_alias" } & TypeAliasItem; -export type ModBlockItem = { block: BlockId }; +export type ModBlockItem = { block: Block }; export type ModFileItem = { filePath: string }; export type EnumItem = { variants: Variant[] }; export type StructItem = { data: VariantData }; @@ -65,12 +65,12 @@ export type StructItem = { data: VariantData }; export type FnItem = { generics?: Generics; params: Param[]; - returnTy?: TyId; - body: BlockId; + returnTy?: Ty; + body: Block; }; export type UseItem = { _: 0 }; -export type TypeAliasItem = { ty: TyId }; +export type TypeAliasItem = { ty: Ty }; export type Variant = { ident: Ident; @@ -95,14 +95,14 @@ export type StructVariantData = { fields: FieldDef[] }; export type FieldDef = { ident: Ident; - ty: TyId; + ty: Ty; pub: boolean; span: Span; }; export type Param = { - pat: PatId; - ty: TyId; + pat: Pat; + ty: Ty; span: Span; }; @@ -115,9 +115,8 @@ export type GenericParam = { span: Span; }; -export type ExprId = { key: number; readonly unique: unique symbol }; - export type Expr = { + id: HirId; kind: ExprKind; span: Span; }; @@ -148,36 +147,36 @@ export type ExprKind = | { tag: "for" } & ForExpr | { tag: "c_for" } & CForExpr; -export type PathExpr = { path: Path }; +export type PathExpr = { path: QPath }; export type IntExpr = { value: number }; export type BoolExpr = { value: boolean }; export type StringExpr = { value: string }; -export type GroupExpr = { expr: ExprId }; -export type ArrayExpr = { exprs: ExprId[] }; -export type RepeatExpr = { expr: ExprId; length: ExprId }; -export type StructExpr = { path?: Path; fields: ExprField[] }; -export type RefExpr = { expr: ExprId; refType: RefType; mut: boolean }; -export type DerefExpr = { expr: ExprId }; -export type ElemExpr = { expr: ExprId; elem: number }; -export type FieldExpr = { expr: ExprId; ident: Ident }; -export type IndexExpr = { expr: ExprId; index: ExprId }; -export type CallExpr = { expr: ExprId; args: ExprId[] }; -export type UnaryExpr = { unaryType: UnaryType; expr: ExprId }; +export type GroupExpr = { expr: Expr }; +export type ArrayExpr = { exprs: Expr[] }; +export type RepeatExpr = { expr: Expr; length: Expr }; +export type StructExpr = { path?: QPath; fields: ExprField[] }; +export type RefExpr = { expr: Expr; refType: RefType; mut: boolean }; +export type DerefExpr = { expr: Expr }; +export type ElemExpr = { expr: Expr; elem: number }; +export type FieldExpr = { expr: Expr; ident: Ident }; +export type IndexExpr = { expr: Expr; index: Expr }; +export type CallExpr = { expr: Expr; args: Expr[] }; +export type UnaryExpr = { unaryType: UnaryType; expr: Expr }; export type BinaryExpr = { binaryType: BinaryType; - left: ExprId; - right: ExprId; + left: Expr; + right: Expr; }; -export type BlockExpr = { block: BlockId }; -export type IfExpr = { cond: ExprId; truthy: BlockId; falsy?: ExprId }; -export type LoopExpr = { body: BlockId }; -export type WhileExpr = { cond: ExprId; body: BlockId }; -export type ForExpr = { pat: PatId; expr: ExprId; body: BlockId }; +export type BlockExpr = { block: Block }; +export type IfExpr = { cond: Expr; truthy: Block; falsy?: Expr }; +export type LoopExpr = { body: Block }; +export type WhileExpr = { cond: Expr; body: Block }; +export type ForExpr = { pat: Pat; expr: Expr; body: Block }; export type CForExpr = { - decl?: StmtId; - cond?: ExprId; - incr?: StmtId; - body: BlockId; + decl?: Stmt; + cond?: Expr; + incr?: Stmt; + body: Block; }; export type RefType = "ref" | "ptr"; @@ -198,37 +197,26 @@ export type BinaryType = export type ExprField = { ident: Ident; - expr: ExprId; + expr: Expr; span: Span; }; -export type BlockId = { key: number; readonly unique: unique symbol }; - -export type Block = { - stmts: StmtId[]; - expr?: ExprId; - span: Span; -}; - -export type PatId = { key: number; readonly unique: unique symbol }; - export type Pat = { + id: HirId; kind: PatKind; span: Span; }; export type PatKind = | { tag: "error" } - | { tag: "bind" } & BindPat; + | { tag: "bind" } & BindPat + | { tag: "path" } & PathPat; -export type BindPat = { - ident: Ident; - mut: boolean; -}; - -export type TyId = { key: number; readonly unique: unique symbol }; +export type BindPat = { ident: Ident; mut: boolean }; +export type PathPat = { path: QPath }; export type Ty = { + id: HirId; kind: TyKind; span: Span; }; @@ -246,20 +234,31 @@ export type TyKind = | { tag: "array" } & ArrayTy | { tag: "anon_struct" } & AnonStructTy; -export type PathTy = { path: Path }; -export type RefTy = { ty: TyId; mut: boolean }; -export type PtrTy = { ty: TyId; mut: boolean }; -export type SliceTy = { ty: TyId }; -export type ArrayTy = { ty: TyId; length: ExprId }; -export type TupleTy = { elems: TyId[] }; +export type PathTy = { path: QPath }; +export type RefTy = { ty: Ty; mut: boolean }; +export type PtrTy = { ty: Ty; mut: boolean }; +export type SliceTy = { ty: Ty }; +export type ArrayTy = { ty: Ty; length: Expr }; +export type TupleTy = { elems: Ty[] }; export type AnonStructTy = { fields: AnonFieldDef[] }; export type AnonFieldDef = { ident: Ident; - ty: TyId; + ty: Ty; span: Span; }; +export type Block = { + id: HirId; + stmts: Stmt[]; + expr?: Expr; + span: Span; +}; + +export type QPath = + | { tag: "resolved"; path: Path } + | { tag: "type_relative"; ty: Ty; seg: PathSegment }; + export type Path = { segments: PathSegment[]; span: Span; @@ -267,12 +266,13 @@ export type Path = { export type PathSegment = { ident: Ident; - genericArgs?: TyId[]; + res: Res; + genericArgs?: Ty[]; + inferArgs: boolean; span: Span; }; export type Ident = { - internId: number; + id: IdentId; span: Span; }; - diff --git a/compiler/middle/hir_eq.ts b/compiler/middle/hir_eq.ts new file mode 100644 index 0000000..53502fb --- /dev/null +++ b/compiler/middle/hir_eq.ts @@ -0,0 +1,80 @@ +import { arrayEq, exhausted } from "../util.ts"; +import { Ident, Item, Stmt, VariantData } from "./hir.ts"; + +/// Shallow equality +export function stmtEq(a: Stmt, b: Stmt): boolean { + const [ak, bk] = [a.kind, b.kind]; + switch (ak.tag) { + case "error": + return ak.tag === bk.tag; + case "item": + return ak.tag === bk.tag && ak.item === bk.item; + case "let": + return ak.tag === bk.tag && ak.pat === bk.pat && ak.ty === bk.ty && + ak.expr === bk.expr; + case "return": + return ak.tag === bk.tag && ak.expr === bk.expr; + case "break": + return ak.tag === bk.tag && ak.expr === bk.expr; + case "continue": + return ak.tag === bk.tag; + case "assign": + return ak.tag === bk.tag && ak.assignType === bk.assignType && + ak.subject === bk.subject && ak.value === bk.value; + case "expr": + return ak.tag === bk.tag && ak.expr === bk.expr; + } + exhausted(ak); +} + +/// Shallow equality +export function itemEq(a: Item, b: Item): boolean { + const [ak, bk] = [a.kind, b.kind]; + switch (ak.tag) { + case "error": + return ak.tag === bk.tag; + case "mod_block": + return ak.tag === bk.tag && ak.block === bk.block; + case "mod_file": + return ak.tag === bk.tag && ak.filePath === bk.filePath; + case "enum": + return ak.tag === bk.tag && + arrayEq(ak.variants, bk.variants); + case "struct": + return ak.tag === bk.tag && variantDataEq(ak.data, bk.data); + case "fn": + return ak.tag === bk.tag; + case "use": + return ak.tag === bk.tag; + case "type_alias": + return ak.tag === bk.tag; + } + exhausted(ak); +} + +export function variantDataEq(a: VariantData, b: VariantData): boolean { + const [ak, bk] = [a.kind, b.kind]; + switch (ak.tag) { + case "error": + return ak.tag === bk.tag; + case "unit": + return ak.tag === bk.tag; + case "tuple": + return ak.tag === bk.tag && + arrayEq(ak.elems, bk.elems, variantDataEq); + case "struct": + return ak.tag === bk.tag && + arrayEq( + ak.fields, + bk.fields, + (a, b) => + identEq(a.ident, b.ident) && a.ty === b.ty && + a.pub === b.pub && a.span === b.span, + ); + } + exhausted(ak); +} + +export function identEq(a: Ident, b: Ident): boolean { + return a.id === b.id; +} diff --git a/compiler/middle/lower_ast.ts b/compiler/middle/lower_ast.ts index 632cb24..f6f8e48 100644 --- a/compiler/middle/lower_ast.ts +++ b/compiler/middle/lower_ast.ts @@ -1,7 +1,19 @@ import { Ctx, DefId, IdentId } from "../ctx.ts"; import * as ast from "../ast/ast.ts"; -import { ExprId, Ident, ItemId, PatId, StmtId, TyId } from "./hir.ts"; +import { + Block, + Expr, + Ident, + Item, + Pat, + Path, + PathSegment, + QPath, + Stmt, + Ty, +} from "./hir.ts"; import { exhausted, Res as Result, todo } from "../util.ts"; +import { Res, Rib } from "./rib.ts"; export class AstLowerer { private ribs: Rib[] = []; @@ -20,74 +32,367 @@ export class AstLowerer { this.lowerStmts(file.stmts); } - private lowerStmts(stmts: ast.Stmt[]): StmtId[] { + private lowerStmts(stmts: ast.Stmt[]): Stmt[] { return stmts.map((stmt) => this.lowerStmt(stmt)); } - private lowerStmt(stmt: ast.Stmt): StmtId { + private lowerStmt(stmt: ast.Stmt): Stmt { + const span = stmt.span; const kind = stmt.kind; switch (kind.tag) { case "error": - return this.ctx.internStmt(kind, stmt.span); + return this.ctx.internStmt(kind, span); case "item": return this.ctx.internStmt({ tag: "item", item: this.lowerItem(kind.item), - }, stmt.span); + }, span); case "let": return this.lowerLetStmt(stmt, kind); case "return": return this.ctx.internStmt({ tag: "return", expr: kind.expr && this.lowerExpr(kind.expr), - }, stmt.span); + }, span); case "break": return this.ctx.internStmt({ tag: "break", expr: kind.expr && this.lowerExpr(kind.expr), - }, stmt.span); + }, span); case "continue": return this.ctx.internStmt({ tag: "continue", - }, stmt.span); + }, span); case "assign": return this.ctx.internStmt({ tag: "assign", assignType: kind.assignType, subject: this.lowerExpr(kind.subject), value: this.lowerExpr(kind.value), - }, stmt.span); + }, span); case "expr": return this.ctx.internStmt({ tag: "expr", expr: this.lowerExpr(kind.expr), - }, stmt.span); + }, span); } exhausted(kind); } - private lowerLetStmt(stmt: ast.Stmt, kind: ast.LetStmt): StmtId { - return this.ctx.internStmt({ - tag: "let", - pat: this.lowerPat(kind.pat), - ty: kind.ty && this.lowerTy(kind.ty), - expr: kind.expr && this.lowerExpr(kind.expr), - }, stmt.span); + private lowerLetStmt(stmt: ast.Stmt, kind: ast.LetStmt): Stmt { + const expr = kind.expr && this.lowerExpr(kind.expr); + const ty = kind.ty && this.lowerTy(kind.ty); + this.pushRib({ kind: { tag: "normal" }, bindings: new Map() }); + const pat = this.lowerPat(kind.pat); + return this.ctx.internStmt({ tag: "let", pat, ty, expr }, stmt.span); } - private lowerItem(item: ast.Item): ItemId { + private lowerItem(item: ast.Item): Item { return todo(); } - private lowerPat(pat: ast.Pat): PatId { - return todo(); + private lowerExpr(expr: ast.Expr): Expr { + const span = expr.span; + const kind = expr.kind; + switch (kind.tag) { + case "error": + return this.ctx.internExpr(kind, span); + case "path": + return this.ctx.internExpr({ + tag: "path", + path: this.lowerPath(kind.path, kind.qty), + }, span); + case "null": + return this.ctx.internExpr(kind, span); + case "int": + return this.ctx.internExpr(kind, span); + case "bool": + return this.ctx.internExpr(kind, span); + case "str": + return this.ctx.internExpr(kind, span); + case "group": + return this.ctx.internExpr({ + tag: "group", + expr: this.lowerExpr(kind.expr), + }, span); + case "array": + return this.ctx.internExpr({ + tag: "array", + exprs: kind.exprs.map((expr) => this.lowerExpr(expr)), + }, span); + case "repeat": + return this.ctx.internExpr({ + tag: "repeat", + expr: this.lowerExpr(kind.expr), + length: this.lowerExpr(kind.length), + }, span); + case "struct": + return this.ctx.internExpr({ + tag: "struct", + path: kind.path && this.lowerPath(kind.path), + fields: kind.fields.map(({ ident, expr, span }) => ({ + ident, + expr: this.lowerExpr(expr), + span, + })), + }, span); + case "ref": + return this.ctx.internExpr({ + tag: "ref", + expr: this.lowerExpr(kind.expr), + refType: kind.refType, + mut: kind.mut, + }, span); + case "deref": + return this.ctx.internExpr({ + tag: "deref", + expr: this.lowerExpr(kind.expr), + }, span); + case "elem": + return this.ctx.internExpr({ + tag: "elem", + expr: this.lowerExpr(kind.expr), + elem: kind.elem, + }, span); + case "field": + return this.ctx.internExpr({ + tag: "field", + expr: this.lowerExpr(kind.expr), + ident: kind.ident, + }, span); + case "index": + return this.ctx.internExpr({ + tag: "index", + expr: this.lowerExpr(kind.expr), + index: this.lowerExpr(kind.index), + }, span); + case "call": + return this.ctx.internExpr({ + tag: "call", + expr: this.lowerExpr(kind.expr), + args: kind.args.map((arg) => this.lowerExpr(arg)), + }, span); + case "unary": + return this.ctx.internExpr({ + tag: "unary", + expr: this.lowerExpr(kind.expr), + unaryType: kind.unaryType, + }, span); + case "binary": + return this.ctx.internExpr({ + tag: "binary", + left: this.lowerExpr(kind.left), + right: this.lowerExpr(kind.right), + binaryType: kind.binaryType, + }, span); + case "block": + return this.ctx.internExpr({ + tag: "block", + block: this.lowerBlock(kind.block), + }, span); + case "if": + return this.ctx.internExpr({ + tag: "if", + cond: this.lowerExpr(kind.cond), + truthy: this.lowerBlock(kind.truthy), + falsy: kind.falsy && this.lowerExpr(kind.falsy), + }, span); + case "loop": + return this.ctx.internExpr({ + tag: "loop", + body: this.lowerBlock(kind.body), + }, span); + case "while": + throw new Error("not implemented"); + case "for": + throw new Error("not implemented"); + case "c_for": + throw new Error("not implemented"); + } + exhausted(kind); } - private lowerTy(ty: ast.Ty): TyId { - return todo(); + private lowerPat(pat: ast.Pat): Pat { + const span = pat.span; + const kind = pat.kind; + switch (kind.tag) { + case "error": + return this.ctx.internPat(kind, span); + case "bind": { + const v = this.ctx.internPat(kind, span); + this.rib().bindings.set(kind.ident.id, { + tag: "local", + id: v.id, + }); + return v; + } + case "path": + return this.ctx.internPat({ + tag: "path", + path: this.lowerPath(kind.path, kind.qty), + }, span); + } + exhausted(kind); } - private lowerExpr(expr: ast.Expr): ExprId { - return todo(); + private lowerTy(ty: ast.Ty): Ty { + const span = ty.span; + const kind = ty.kind; + switch (kind.tag) { + case "error": + return this.ctx.internTy(kind, span); + case "null": + return this.ctx.internTy(kind, span); + case "int": + return this.ctx.internTy(kind, span); + case "bool": + return this.ctx.internTy(kind, span); + case "str": + return this.ctx.internTy(kind, span); + case "path": + return this.ctx.internTy({ + tag: "path", + path: this.lowerPath(kind.path, kind.qty), + }, span); + case "ref": + return this.ctx.internTy({ + tag: "ref", + ty: this.lowerTy(kind.ty), + mut: kind.mut, + }, span); + case "ptr": + return this.ctx.internTy({ + tag: "ptr", + ty: this.lowerTy(kind.ty), + mut: kind.mut, + }, span); + case "slice": + return this.ctx.internTy({ + tag: "slice", + ty: this.lowerTy(kind.ty), + }, span); + case "array": + return this.ctx.internTy({ + tag: "array", + ty: this.lowerTy(kind.ty), + length: this.lowerExpr(kind.length), + }, span); + case "anon_struct": + return this.ctx.internTy({ + tag: "anon_struct", + fields: kind.fields.map(({ ident, ty, span }) => ({ + ident, + ty: this.lowerTy(ty), + span, + })), + }, span); + } + exhausted(kind); + } + + private lowerBlock(block: ast.Block): Block { + const point = this.ribPoint(); + const stmts = block.stmts.map((stmt) => this.lowerStmt(stmt)); + const expr = block.expr && this.lowerExpr(block.expr); + this.returnToRibPoint(point); + return this.ctx.internBlock({ stmts, expr, span: block.span }); + } + + private lowerPath(path: ast.Path, qty?: ast.Ty): QPath { + if (qty) { + const ty = this.lowerTy(qty); + if (path.segments.length !== 1) { + throw new Error(); + } + const seg = path.segments[0]; + return { + tag: "type_relative", + ty, + seg: { + ident: seg.ident, + res: todo(), + genericArgs: seg.genericArgs && + seg.genericArgs.map((ty) => this.lowerTy(ty)), + inferArgs: false, + span: path.span, + }, + }; + } + const res = this.resolvePathSegs(path.segments); + return { + path: { + segments + } + }; + } + + private resolvePathSegs(segs: ast.PathSegment[]): [Res, PathSegment[]] { + if (segs.length <= 1) { + const seg = segs[0]; + const res = this.resolveTyIdent(seg.ident); + return [res, [{ident: seg.ident, res, genericArgs:seg.genericArgs && + seg.genericArgs.map((ty) => this.lowerTy(ty)), inferArgs: }]] + } + const innerRes = this.resolvePathSegs(segs.slice(1)); + switch (innerRes.tag) { + case "error": + return innerRes; + case "def": { + const irk = innerRes.kind; + switch (irk.tag) { + case "mod": + return todo(); + case "struct": + return todo(); + case "enum": + return todo(); + case "variant": + return todo(); + case "ty_alias": + return todo(); + case "ty_param": + return todo(); + case "fn": + return todo(); + case "ctor": + return todo(); + case "use": + return todo(); + case "field": + return todo(); + } + exhausted(irk); + return todo(); + } + case "local": + throw new Error("should not be possible"); + } + exhausted(innerRes); + } + + private resolveTyIdent(ident: Ident): Res { + } + + private resolveValIdent(ident: Ident): Res { + } + + private rib(): Rib { + return this.ribs.at(-1)!; + } + + private pushRib(rib: Rib) { + this.ribs.push(rib); + } + + private popRib() { + this.ribs.pop(); + } + + private ribPoint(): number { + return this.ribs.length; + } + + private returnToRibPoint(point: number) { + this.ribs = this.ribs.slice(0, point); } } diff --git a/compiler/middle/rib.ts b/compiler/middle/rib.ts index 937e70a..99fe2dd 100644 --- a/compiler/middle/rib.ts +++ b/compiler/middle/rib.ts @@ -1,4 +1,5 @@ -import { DefId, IdentId } from "../ctx.ts"; +import { DefId, HirId, IdentId } from "../ctx.ts"; +import { Mod } from "../main.ts"; // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.Rib.html export type Rib = { @@ -11,23 +12,23 @@ export type RibKind = | { tag: "normal" } | { tag: "fn" } | { tag: "item"; defKind: DefKind } - | { tag: "mod" }; + | { tag: "mod"; mod: Mod }; // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/enum.RibKind.html export type Res = | { tag: "error" } | { tag: "def"; kind: DefKind; id: DefId } - | { tag: "local"; id: DefId }; + | { tag: "local"; id: HirId }; // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.DefKind.html export type DefKind = - | { type: "mod" } - | { type: "struct" } - | { type: "enum" } - | { type: "variant" } - | { type: "ty_alias" } - | { type: "ty_param" } - | { type: "fn" } - | { type: "ctor" } - | { type: "use" } - | { type: "field" }; + | { tag: "mod" } + | { tag: "struct" } + | { tag: "enum" } + | { tag: "variant" } + | { tag: "ty_alias" } + | { tag: "ty_param" } + | { tag: "fn" } + | { tag: "ctor" } + | { tag: "use" } + | { tag: "field" }; diff --git a/compiler/util.ts b/compiler/util.ts index bd4d661..1472973 100644 --- a/compiler/util.ts +++ b/compiler/util.ts @@ -31,3 +31,21 @@ export const ControlFlow = { } as const; export const range = (length: number) => (new Array(length).fill(0)); + +export const strictEq = (a: T, b: T): boolean => a === b; + +export function arrayEq( + a: T[], + b: T[], + elemCmp: (a: T, b: T) => boolean = strictEq, +): boolean { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; ++i) { + if (!elemCmp(a[i], b[i])) { + return false; + } + } + return true; +}