mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 00:34:06 +02:00
compiler: investigate pattern lower
This commit is contained in:
parent
f9e14e5056
commit
a5502810cd
@ -224,31 +224,36 @@ export function visitItem<
|
|||||||
item: Item,
|
item: Item,
|
||||||
...p: P
|
...p: P
|
||||||
) {
|
) {
|
||||||
visitIdent(v, item.ident, ...p);
|
|
||||||
const kind = item.kind;
|
const kind = item.kind;
|
||||||
switch (kind.tag) {
|
switch (kind.tag) {
|
||||||
case "error":
|
case "error":
|
||||||
if (v.visitErrorItem?.(item, ...p) === "stop") return;
|
if (v.visitErrorItem?.(item, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
return;
|
return;
|
||||||
case "mod_block":
|
case "mod_block":
|
||||||
if (v.visitModBlockItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitModBlockItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
visitBlock(v, kind.block, ...p);
|
visitBlock(v, kind.block, ...p);
|
||||||
return;
|
return;
|
||||||
case "mod_file":
|
case "mod_file":
|
||||||
if (v.visitModFileItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitModFileItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
return;
|
return;
|
||||||
case "enum":
|
case "enum":
|
||||||
if (v.visitEnumItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitEnumItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
for (const variant of kind.variants) {
|
for (const variant of kind.variants) {
|
||||||
visitVariant(v, variant, ...p);
|
visitVariant(v, variant, ...p);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case "struct":
|
case "struct":
|
||||||
if (v.visitStructItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitStructItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
visitVariantData(v, kind.data, ...p);
|
visitVariantData(v, kind.data, ...p);
|
||||||
return;
|
return;
|
||||||
case "fn":
|
case "fn":
|
||||||
if (v.visitFnItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitFnItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
for (const param of kind.params) {
|
for (const param of kind.params) {
|
||||||
visitParam(v, param, ...p);
|
visitParam(v, param, ...p);
|
||||||
}
|
}
|
||||||
@ -256,9 +261,11 @@ export function visitItem<
|
|||||||
return;
|
return;
|
||||||
case "use":
|
case "use":
|
||||||
if (v.visitUseItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitUseItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
return;
|
return;
|
||||||
case "type_alias":
|
case "type_alias":
|
||||||
if (v.visitTypeAliasItem?.(item, kind, ...p) === "stop") return;
|
if (v.visitTypeAliasItem?.(item, kind, ...p) === "stop") return;
|
||||||
|
visitIdent(v, item.ident, ...p);
|
||||||
visitTy(v, kind.ty, ...p);
|
visitTy(v, kind.ty, ...p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ export class Checker {
|
|||||||
return resu.val;
|
return resu.val;
|
||||||
}
|
}
|
||||||
case "local": {
|
case "local": {
|
||||||
const ty = this.exprTy(expr);
|
const patResu = this.resols.patRes();
|
||||||
const resu = this.resolveTys(ty, expected);
|
const resu = this.resolveTys(ty, expected);
|
||||||
if (!resu.ok) {
|
if (!resu.ok) {
|
||||||
this.report(resu.val, expr.span);
|
this.report(resu.val, expr.span);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"workspace": ["./ast", "./check", "./middle", "./parse", "./resolve", "./ty", "./common"],
|
"workspace": ["./ast", "./check", "./middle", "./parse", "./resolve", "./ty", "./common"],
|
||||||
"lint": {
|
"lint": {
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"tags": ["recommended"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"verbatim-module-syntax",
|
"verbatim-module-syntax",
|
||||||
"no-unused-vars"
|
"no-unused-vars"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as ast from "@slige/ast";
|
import * as ast from "@slige/ast";
|
||||||
import { IdBase, IdentId, IdMap, Res } from "@slige/common";
|
import { AstId, IdBase, IdentId, IdMap, Res } from "@slige/common";
|
||||||
|
|
||||||
export interface Syms {
|
export interface Syms {
|
||||||
getVal(ident: ast.Ident): Resolve;
|
getVal(ident: ast.Ident): Resolve;
|
||||||
@ -14,13 +14,21 @@ export type Resolve = {
|
|||||||
kind: ResolveKind;
|
kind: ResolveKind;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LocalId = IdBase & { readonly _: unique symbol };
|
|
||||||
|
|
||||||
export type ResolveKind =
|
export type ResolveKind =
|
||||||
| { tag: "error" }
|
| { tag: "error" }
|
||||||
| { tag: "fn"; item: ast.Item; kind: ast.FnItem }
|
| { tag: "fn"; item: ast.Item; kind: ast.FnItem }
|
||||||
| { tag: "local"; id: LocalId };
|
| { tag: "local"; id: LocalId };
|
||||||
|
|
||||||
|
export type PatResolve =
|
||||||
|
| { tag: "param"; paramIdx: number }
|
||||||
|
| { tag: "let"; stmt: ast.Stmt; kind: ast.LetStmt };
|
||||||
|
|
||||||
|
export type LocalId = IdBase & { readonly _: unique symbol };
|
||||||
|
|
||||||
|
export type Local =
|
||||||
|
| { tag: "param"; paramIdx: number }
|
||||||
|
| { tag: "let"; stmt: ast.Stmt; kind: ast.LetStmt };
|
||||||
|
|
||||||
export const ResolveError = (ident: ast.Ident): Resolve => ({
|
export const ResolveError = (ident: ast.Ident): Resolve => ({
|
||||||
ident,
|
ident,
|
||||||
kind: { tag: "error" },
|
kind: { tag: "error" },
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
FnSyms,
|
FnSyms,
|
||||||
LocalId,
|
LocalId,
|
||||||
LocalSyms,
|
LocalSyms,
|
||||||
|
PatResolve,
|
||||||
Resolve,
|
Resolve,
|
||||||
ResolveError,
|
ResolveError,
|
||||||
RootSyms,
|
RootSyms,
|
||||||
@ -14,6 +15,7 @@ export { type LocalId } from "./cx.ts";
|
|||||||
export class Resols {
|
export class Resols {
|
||||||
public constructor(
|
public constructor(
|
||||||
private exprResols: IdMap<AstId, Resolve>,
|
private exprResols: IdMap<AstId, Resolve>,
|
||||||
|
private patResols: IdMap<AstId, PatResolve>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public exprRes(id: AstId): Resolve {
|
public exprRes(id: AstId): Resolve {
|
||||||
@ -22,6 +24,13 @@ export class Resols {
|
|||||||
}
|
}
|
||||||
return this.exprResols.get(id)!;
|
return this.exprResols.get(id)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public patRes(id: AstId): PatResolve {
|
||||||
|
if (!this.patResols.has(id)) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
return this.patResols.get(id)!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Resolver implements ast.Visitor {
|
export class Resolver implements ast.Visitor {
|
||||||
@ -30,6 +39,9 @@ export class Resolver implements ast.Visitor {
|
|||||||
private syms: Syms = this.rootSyms;
|
private syms: Syms = this.rootSyms;
|
||||||
|
|
||||||
private exprResols = new IdMap<AstId, Resolve>();
|
private exprResols = new IdMap<AstId, Resolve>();
|
||||||
|
private patResols = new IdMap<AstId, PatResolve>();
|
||||||
|
|
||||||
|
private patResolveStack: PatResolve[] = [];
|
||||||
|
|
||||||
private localIds = new Ids<LocalId>();
|
private localIds = new Ids<LocalId>();
|
||||||
|
|
||||||
@ -42,13 +54,23 @@ export class Resolver implements ast.Visitor {
|
|||||||
ast.visitFile(this, this.entryFileAst);
|
ast.visitFile(this, this.entryFileAst);
|
||||||
return new Resols(
|
return new Resols(
|
||||||
this.exprResols,
|
this.exprResols,
|
||||||
|
this.patResols,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitFile(file: ast.File): ast.VisitRes {
|
visitFile(file: ast.File): ast.VisitRes {
|
||||||
this.currentFile = file.file;
|
this.currentFile = file.file;
|
||||||
|
this.fnBodiesToCheck.push([]);
|
||||||
ast.visitStmts(this, file.stmts);
|
ast.visitStmts(this, file.stmts);
|
||||||
this.visitFnBodies();
|
this.popAndVisitFnBodies();
|
||||||
|
return "stop";
|
||||||
|
}
|
||||||
|
|
||||||
|
visitBlock(block: ast.Block): ast.VisitRes {
|
||||||
|
this.fnBodiesToCheck.push([]);
|
||||||
|
ast.visitStmts(this, block.stmts);
|
||||||
|
this.popAndVisitFnBodies();
|
||||||
|
block.expr && ast.visitExpr(this, block.expr);
|
||||||
return "stop";
|
return "stop";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +78,9 @@ export class Resolver implements ast.Visitor {
|
|||||||
kind.ty && ast.visitTy(this, kind.ty);
|
kind.ty && ast.visitTy(this, kind.ty);
|
||||||
kind.expr && ast.visitExpr(this, kind.expr);
|
kind.expr && ast.visitExpr(this, kind.expr);
|
||||||
this.syms = new LocalSyms(this.syms);
|
this.syms = new LocalSyms(this.syms);
|
||||||
|
this.patResolveStack.push({ tag: "let", stmt, kind });
|
||||||
ast.visitPat(this, kind.pat);
|
ast.visitPat(this, kind.pat);
|
||||||
|
this.patResolveStack.pop();
|
||||||
return "stop";
|
return "stop";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,25 +101,28 @@ export class Resolver implements ast.Visitor {
|
|||||||
todo();
|
todo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private fnBodiesToCheck: [ast.Item, ast.FnItem][] = [];
|
private fnBodiesToCheck: [ast.Item, ast.FnItem][][] = [];
|
||||||
|
|
||||||
visitFnItem(item: ast.Item, kind: ast.FnItem): ast.VisitRes {
|
visitFnItem(item: ast.Item, kind: ast.FnItem): ast.VisitRes {
|
||||||
this.syms.defVal(item.ident, { tag: "fn", item, kind });
|
this.syms.defVal(item.ident, { tag: "fn", item, kind });
|
||||||
this.fnBodiesToCheck.push([item, kind]);
|
this.fnBodiesToCheck.at(-1)!.push([item, kind]);
|
||||||
return "stop";
|
return "stop";
|
||||||
}
|
}
|
||||||
|
|
||||||
private visitFnBodies() {
|
private popAndVisitFnBodies() {
|
||||||
for (const [_item, kind] of this.fnBodiesToCheck) {
|
for (const [_item, kind] of this.fnBodiesToCheck.at(-1)!) {
|
||||||
const outerSyms = this.syms;
|
const outerSyms = this.syms;
|
||||||
this.syms = new FnSyms(this.syms);
|
this.syms = new FnSyms(this.syms);
|
||||||
this.syms = new LocalSyms(this.syms);
|
this.syms = new LocalSyms(this.syms);
|
||||||
for (const param of kind.params) {
|
for (const [paramIdx, param] of kind.params.entries()) {
|
||||||
|
this.patResolveStack.push({ tag: "param", paramIdx });
|
||||||
ast.visitParam(this, param);
|
ast.visitParam(this, param);
|
||||||
|
this.patResolveStack.pop();
|
||||||
}
|
}
|
||||||
|
ast.visitBlock(this, kind.body!);
|
||||||
this.syms = outerSyms;
|
this.syms = outerSyms;
|
||||||
}
|
}
|
||||||
this.fnBodiesToCheck = [];
|
this.fnBodiesToCheck.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
visitPathExpr(expr: ast.Expr, kind: ast.PathExpr): ast.VisitRes {
|
visitPathExpr(expr: ast.Expr, kind: ast.PathExpr): ast.VisitRes {
|
||||||
@ -137,6 +164,7 @@ export class Resolver implements ast.Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
visitBindPat(pat: ast.Pat, kind: ast.BindPat): ast.VisitRes {
|
visitBindPat(pat: ast.Pat, kind: ast.BindPat): ast.VisitRes {
|
||||||
|
this.patResols.set(pat.id, this.patResolveStack.at(-1)!);
|
||||||
const res = this.syms.defVal(kind.ident, {
|
const res = this.syms.defVal(kind.ident, {
|
||||||
tag: "local",
|
tag: "local",
|
||||||
id: this.localIds.nextThenStep(),
|
id: this.localIds.nextThenStep(),
|
||||||
@ -157,13 +185,6 @@ export class Resolver implements ast.Visitor {
|
|||||||
todo(pat, kind);
|
todo(pat, kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitBlock(block: ast.Block): ast.VisitRes {
|
|
||||||
ast.visitStmts(this, block.stmts);
|
|
||||||
this.visitFnBodies();
|
|
||||||
block.expr && ast.visitExpr(this, block.expr);
|
|
||||||
return "stop";
|
|
||||||
}
|
|
||||||
|
|
||||||
visitPath(_path: ast.Path): ast.VisitRes {
|
visitPath(_path: ast.Path): ast.VisitRes {
|
||||||
throw new Error("should not be reached");
|
throw new Error("should not be reached");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user