plsandbox/stlc-bidir/simple.test.ts
2024-11-25 21:12:03 -06:00

108 lines
2.5 KiB
TypeScript

import { test, expect, describe } from "bun:test";
import {
abs1,
abs2,
app1,
app2,
arr,
convertToDebruijn,
evaluate,
infer,
parseExpr,
parseTy,
unitTy,
var1,
var2,
} from ".";
const kCombinator = `lam (x : ()) . lam (y : ()) . x`;
const kCombinatorTy = `() -> (() -> ())`;
const sCombinator = `lam (x : () -> (() -> ())) . lam (y : () -> ()) . lam (z : ()) . (x z) (y z)`;
describe("parser", () => {
test("K combinator", () => {
const parsed = parseExpr(kCombinator);
const expr = abs1("x", unitTy(), abs1("y", unitTy(), var1("x")));
expect(parsed).toEqual(expr);
});
test("S combinator", () => {
const parsed = parseExpr(sCombinator);
const expr = abs1(
"x",
arr(unitTy(), arr(unitTy(), unitTy())),
abs1(
"y",
arr(unitTy(), unitTy()),
abs1(
"z",
unitTy(),
app1(app1(var1("x"), var1("z")), app1(var1("y"), var1("z"))),
),
),
);
expect(parsed).toEqual(expr);
});
});
describe("convertToDeBruijn", () => {
test("K combinator", () => {
const expr = parseExpr(kCombinator);
const expr2 = abs2(unitTy(), abs2(unitTy(), var2(1)));
expect(convertToDebruijn(expr)).toEqual(expr2);
});
test("S combinator", () => {
const expr = abs1(
"x",
arr(unitTy(), arr(unitTy(), unitTy())),
abs1(
"y",
arr(unitTy(), unitTy()),
abs1(
"z",
unitTy(),
app1(app1(var1("x"), var1("z")), app1(var1("y"), var1("z"))),
),
),
);
const expr2 = abs2(
arr(unitTy(), arr(unitTy(), unitTy())),
abs2(
arr(unitTy(), unitTy()),
abs2(unitTy(), app2(app2(var2(2), var2(0)), app2(var2(1), var2(0)))),
),
);
expect(convertToDebruijn(expr)).toEqual(expr2);
});
});
describe("infer", () => {
test("K combinator", () => {
const expr = parseExpr(kCombinator);
const expr2 = convertToDebruijn(expr);
const ty = parseTy(kCombinatorTy);
expect(infer(expr2)).toEqual(ty);
});
test("K combinator negative", () => {
const expr = parseExpr(kCombinator);
const expr2 = convertToDebruijn(expr);
const ty = parseTy(`() -> (() -> (() -> ()))`);
expect(infer(expr2)).not.toEqual(ty);
});
});
describe("evaluate", () => {
test("simple", () => {
const expr = parseExpr(`(lam (x : ()) . x) ()`);
const expr2 = parseExpr(`()`);
expect(evaluate(convertToDebruijn(expr))).toEqual(convertToDebruijn(expr2));
});
});