import { strictEqual, ok } from "node:assert"; import { describe, it } from "node:test"; import { apply, isLeaf, isStem, isFork } from "../src/tree.js"; import { reduce } from "../src/cli.js"; describe("tree — basic types", () => { it("Leaf is empty array", () => { ok(isLeaf([])); ok(!isStem([])); ok(!isFork([])); }); it("Stem is single-element array", () => { ok(isStem([[]])); ok(!isLeaf([[]])); }); it("Fork is two-element array", () => { ok(isFork([[], []])); ok(!isLeaf([[], []])); }); }); describe("tree — apply rules", () => { // Leaf = [], Stem = [child], Fork = [right, left] it("apply(Leaf, b) = Stem(b)", () => { const b = []; // Leaf const result = apply([], b); ok(isStem(result), "Stem(b) should be a Stem"); strictEqual(result[0], b); }); it("apply(Stem(a), b) = Fork(a, b)", () => { const a = []; // Leaf const b = []; // Leaf const result = apply([a], b); ok(isFork(result), "Fork(a, b) should be a Fork"); // Fork = [right, left] = [b, a] strictEqual(result[0], b); strictEqual(result[1], a); }); it("apply(Fork(Leaf, a), _) = a", () => { // Fork(Leaf, a) = [a, Leaf] const a = []; // Leaf const result = apply([a, []], []); strictEqual(result, a); ok(isLeaf(result)); }); }); describe("tree — reduction", () => { it("reduces Leaf to Leaf", () => { const result = reduce([], 100); ok(isLeaf(result)); }); it("reduces Stem Leaf to Stem Leaf", () => { const result = reduce([[]], 100); ok(isStem(result)); ok(isLeaf(result[0])); }); it("reduces Fork Leaf Leaf to Fork Leaf Leaf", () => { const result = reduce([[], []], 100); ok(isFork(result)); ok(isLeaf(result[0])); ok(isLeaf(result[1])); }); it("S combinator applied to Leaf reduces", () => { // S = t (t (t t)) t = Fork (Fork (Fork Leaf Leaf) Leaf) Leaf // In array form: [[[], []], [], []] const s = [[], [[[], []], []]]; const leaf = []; const result = reduce([s, leaf], 100); ok(Array.isArray(result), "S Leaf should reduce to an array"); }); });