57 lines
1.4 KiB
TypeScript
57 lines
1.4 KiB
TypeScript
import { isTypeInContext } from "./contexts";
|
|
import { ContextEntry, Term, Type } from "./data";
|
|
|
|
function check(
|
|
ctx: ContextEntry[],
|
|
term: Term,
|
|
type: Type
|
|
): [boolean, ContextEntry[]] {
|
|
switch (term.kind) {
|
|
case "var":
|
|
break;
|
|
case "unit":
|
|
return [type.kind === "unit", ctx];
|
|
case "lambda": {
|
|
// Get A and B first
|
|
if (type.kind !== "arrow") return [false, ctx];
|
|
const { input: A, output: B } = type;
|
|
}
|
|
case "app":
|
|
break;
|
|
case "annot":
|
|
break;
|
|
}
|
|
}
|
|
|
|
function synthesize(ctx: ContextEntry[], term: Term): [Type, ContextEntry[]] {
|
|
switch (term.kind) {
|
|
case "var": {
|
|
const res = lookupTypeVariable(ctx, term.name);
|
|
if (!res) throw new Error("wtf?");
|
|
return [res, ctx];
|
|
}
|
|
case "unit":
|
|
return [{ kind: "unit" }, ctx];
|
|
case "lambda": {
|
|
}
|
|
case "app":
|
|
break;
|
|
case "annot": {
|
|
// Require that the type exists
|
|
if (!isTypeInContext(term.type, ctx))
|
|
throw new Error("type doesn't exist");
|
|
|
|
// Require that the term checks against the type
|
|
const [result, outputCtx] = check(ctx, term.term, term.type);
|
|
if (!result) throw new Error("invalid annotation: term doesn't check");
|
|
|
|
return [term.type, outputCtx];
|
|
}
|
|
}
|
|
}
|
|
|
|
function synthesizeApp(
|
|
ctx: ContextEntry[],
|
|
funcType: Type,
|
|
term: Term
|
|
): [Type, ContextEntry[]] {}
|