Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 14883x 14883x 14883x 14883x 59444x 804238x 804238x 804238x 59444x 14883x 14883x 14883x 14883x 14883x 14883x 590781x 590781x 590781x 590781x 590781x 590781x 590781x 409284x 409284x 409284x 409284x 409284x 1104665x 1104665x 695667x 695667x 695667x 695667x 695667x 695667x 695667x 695667x 321911x 321911x 321911x 695667x 695667x 1104665x 373470x 373470x 1104665x 409284x 409284x 409284x 590781x 590781x 590781x 590781x 14883x 14883x 14883x | /** @import { Visitors, Context } from 'zimmerframe' */ const overrides = { visit() { throw new Error('Cannot call visit() during analysis'); }, stop() { throw new Error('Cannot call stop() during analysis'); } }; /** * @template {{ type: string }} T * @template U * @param {...Visitors<T, U>} tasks * @returns */ export function merge(...tasks) { /** @type {Record<string, any[]>} */ const visitors = {}; for (const task of tasks) { for (const key in task) { if (!visitors[key]) visitors[key] = []; visitors[key].push(task[key]); } } /** @type {Visitors<T, U>} */ // @ts-expect-error const combined = {}; for (const key in visitors) { const fns = visitors[key]; /** * @param {T} node * @param {Context<T, U>} context */ function visitor(node, context) { /** * @param {number} i * @param {U} state */ function go(i, state) { const fn = fns[i]; if (!fn) return context.next(state); let called_next = false; fn(node, { ...context, ...overrides, state, next(next_state = state) { called_next = true; go(i + 1, next_state); } }); if (!called_next) { go(i + 1, state); } } go(0, context.state); } // @ts-expect-error combined[key] = visitor; } return combined; } |