diff options
author | Marvin Borner | 2025-02-08 18:47:05 +0100 |
---|---|---|
committer | Marvin Borner | 2025-02-08 18:47:05 +0100 |
commit | 0e6ed67467aab98734b713e761d6fc80a1f9a500 (patch) | |
tree | 1f7d880c6b7953506c2214378748b23276c26f4a | |
parent | ee09aea3ef59b189917bad851bb15e6ed8d01cd9 (diff) |
Extend to tree arity to all perfect squares
-rw-r--r-- | main.js | 97 |
1 files changed, 45 insertions, 52 deletions
@@ -43,30 +43,6 @@ const drawScreen = (worker, ctxs, colors) => { worker.postMessage({ drawScreen: [colors, ctxs] }); }; -const ctxTopLeft = (ctx) => { - const x = [ctx.x[0], ctx.x[0] + (ctx.x[1] - ctx.x[0]) / 2]; - const y = [ctx.y[0], ctx.y[0] + (ctx.y[1] - ctx.y[0]) / 2]; - return { x, y }; -}; - -const ctxTopRight = (ctx) => { - const x = [ctx.x[0] + (ctx.x[1] - ctx.x[0]) / 2, ctx.x[1]]; - const y = [ctx.y[0], ctx.y[0] + (ctx.y[1] - ctx.y[0]) / 2]; - return { x, y }; -}; - -const ctxBottomLeft = (ctx) => { - const x = [ctx.x[0], ctx.x[0] + (ctx.x[1] - ctx.x[0]) / 2]; - const y = [ctx.y[0] + (ctx.y[1] - ctx.y[0]) / 2, ctx.y[1]]; - return { x, y }; -}; - -const ctxBottomRight = (ctx) => { - const x = [ctx.x[0] + (ctx.x[1] - ctx.x[0]) / 2, ctx.x[1]]; - const y = [ctx.y[0] + (ctx.y[1] - ctx.y[0]) / 2, ctx.y[1]]; - return { x, y }; -}; - /* lambda calculus */ // --- @@ -349,15 +325,25 @@ const toColor = (t) => { return UNKNOWN; }; -// [((((0 tl) tr) bl) br)] -const seemsScreeny = (t) => - t.type === "abs" && - t.body.type === "app" && - t.body.left.type === "app" && - t.body.left.left.type === "app" && - t.body.left.left.left.type === "app" && - t.body.left.left.left.left.type === "idx" && - t.body.left.left.left.left.idx === 0; +// [((((0 tl) tr) bl) br) ...] +// (or more, as long as n is perfect square) +const seemsScreeny = (t) => { + if (t.type !== "abs") return false; + t = t.body; + let d = 0; + while ((d++, t.type === "app")) t = t.left; + return d > 4 && Math.sqrt(d - 1) % 1 === 0 && t.type === "idx" && t.idx === 0 + ? d - 1 + : false; +}; + +const getSubScreens = (t) => { + if (t.type !== "abs") return false; + t = t.body; + let ts = []; + while (t.type === "app" && ts.unshift(t)) t = t.left; + return ts; +}; const clearScreen = (worker) => { worker.postMessage({ clear: true }); @@ -501,7 +487,7 @@ const whnf = (t) => { }; // screen normal form -// one of [((((0 tl) tr) bl) br)], [[0]], [[1]] +// one of [((((0 tl) tr) bl) br) ...], [[0]], [[1]] // TODO: Is this form of caching fundamentally wrong? (incongruences after subst or idx shifts!?) // Does this only work accidentally because of WHNF, deliberate symmetry and closed terms or sth? const snfCache = {}; @@ -575,28 +561,35 @@ const reduceLoop = (conf, _t) => { // smaller resolutions apparently crash the browser tab lol if (ctx.x[1] - ctx.x[0] < MAXRES) continue; - if (seemsScreeny(t)) { - const tl = t.body.left.left.left.right; - const tlCtx = ctxTopLeft(ctx); - stack.push({ ctx: tlCtx, t: tl }); + let n; + if ((n = seemsScreeny(t))) { + const subScreens = getSubScreens(t); + console.assert(n == subScreens.length); - const tr = t.body.left.left.right; - const trCtx = ctxTopRight(ctx); - stack.push({ ctx: trCtx, t: tr }); + const splitSize = Math.sqrt(n); + const ctxWidth = (ctx.x[1] - ctx.x[0]) / splitSize; + const ctxHeight = (ctx.y[1] - ctx.y[0]) / splitSize; - const bl = t.body.left.right; - const blCtx = ctxBottomLeft(ctx); - stack.push({ ctx: blCtx, t: bl }); + const ctxs = []; + const colors = []; - const br = t.body.right; - const brCtx = ctxBottomRight(ctx); - stack.push({ ctx: brCtx, t: br }); + let x0 = ctx.x[0]; + let y0 = ctx.y[0]; + + for (let i = 0; i < n; i++) { + const current = subScreens[i]; + const subCtx = { x: [x0, x0 + ctxWidth], y: [y0, y0 + ctxHeight] }; + ctxs.push(subCtx); + stack.push({ ctx: subCtx, t: current.right }); + colors.push(toColor(current.right)); + + if ((i + 1) % splitSize == 0) { + x0 = ctx.x[0]; + y0 += ctxHeight; + } else x0 += ctxWidth; + } - drawScreen( - worker, - [tlCtx, trCtx, blCtx, brCtx], - [toColor(tl), toColor(tr), toColor(bl), toColor(br)], - ); + drawScreen(worker, ctxs, colors); } else { // TODO: could we risk gnfing here? drawAt(worker, ctx.x, ctx.y, toColor(t)); |