make types
This commit is contained in:
parent
f947c22ffd
commit
d4ced3250b
13
src/ast.ts
13
src/ast.ts
@ -95,11 +95,16 @@ export type NodeWithKind<
|
|||||||
Tag extends NodeKind["tag"],
|
Tag extends NodeKind["tag"],
|
||||||
> = Node & { kind: { tag: Tag } };
|
> = Node & { kind: { tag: Tag } };
|
||||||
|
|
||||||
export function assertNodeWithKind<Tag extends NodeKind["tag"]>(
|
export function assertNodeWithKind<
|
||||||
node: Node,
|
Tag extends NodeKind["tag"],
|
||||||
tag: Tag,
|
>(node: Node, tag: Tag): asserts node is NodeWithKind<Tag> {
|
||||||
): asserts node is NodeWithKind<Tag> {
|
|
||||||
if (node.kind.tag !== tag) {
|
if (node.kind.tag !== tag) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNodeWithKind<
|
||||||
|
Tag extends NodeKind["tag"],
|
||||||
|
>(node: Node, tag: Tag): node is NodeWithKind<Tag> {
|
||||||
|
return node.kind.tag === tag;
|
||||||
|
}
|
||||||
|
|||||||
46
src/front.ts
46
src/front.ts
@ -24,10 +24,52 @@ export class Checker {
|
|||||||
private checkNode(node: ast.Node): Ty {
|
private checkNode(node: ast.Node): Ty {
|
||||||
const k = node.kind;
|
const k = node.kind;
|
||||||
|
|
||||||
if (k.tag === "FnStmt") {
|
if (ast.isNodeWithKind(node, "FnStmt")) {
|
||||||
|
return this.checkFnStmt(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("not checked");
|
if (ast.isNodeWithKind(node, "IdentTy")) {
|
||||||
|
switch (node.kind.ident) {
|
||||||
|
case "int":
|
||||||
|
return Ty.Int;
|
||||||
|
default:
|
||||||
|
this.error(node.line, `unknown type '${node.kind.ident}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`'${k.tag}' not checked`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkFnStmt(stmt: ast.NodeWithKind<"FnStmt">): Ty {
|
||||||
|
const k = stmt.kind;
|
||||||
|
|
||||||
|
const params = k.params.map((param) => this.check(param));
|
||||||
|
const retTy = k.retTy ? this.check(k.retTy) : Ty.Void;
|
||||||
|
|
||||||
|
k.body.visit({
|
||||||
|
visit: (node) => {
|
||||||
|
if (ast.isNodeWithKind(node, "ReturnStmt")) {
|
||||||
|
if (node.kind.expr) {
|
||||||
|
const ty = this.check(node.kind.expr);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const ty = Ty.create("Fn", { params, retTy });
|
||||||
|
return Ty.create("FnStmt", { stmt, ty });
|
||||||
|
}
|
||||||
|
|
||||||
|
private typesCompatible(a: Ty, b: Ty): boolean {
|
||||||
|
const ak = a.kind;
|
||||||
|
const bk = b.kind;
|
||||||
|
if (ak.tag === "Error") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ak.tag === "Void") {
|
||||||
|
return bk.tag === "Void";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private error(line: number, message: string): never {
|
private error(line: number, message: string): never {
|
||||||
|
|||||||
20
src/ty.ts
20
src/ty.ts
@ -33,6 +33,26 @@ export class Ty {
|
|||||||
public id: number,
|
public id: number,
|
||||||
public kind: TyKind,
|
public kind: TyKind,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
isKind<
|
||||||
|
Tag extends TyKind["tag"],
|
||||||
|
>(tag: Tag): this is Ty & { kind: { tag: Tag } } {
|
||||||
|
return this.kind.tag === tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
compatibleWith(other: Ty): boolean {
|
||||||
|
if (this.isKind("Error")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.isKind("Void")) {
|
||||||
|
return other.isKind("Void");
|
||||||
|
}
|
||||||
|
if (this.isKind("Int")) {
|
||||||
|
return other.isKind("Int");
|
||||||
|
}
|
||||||
|
if (this.isKind("Fn")) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TyKind =
|
export type TyKind =
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user