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 15152x 15152x 15152x 15152x 60518x 840836x 840836x 840836x 60518x 15152x 15152x 15152x 15152x 15152x 15152x 608154x 608154x 608154x 608154x 608154x 608154x 608154x 414778x 414778x 414778x 414778x 414778x 1119854x 1119854x 705366x 705366x 705366x 705366x 705366x 705366x 705366x 705366x 326409x 326409x 326409x 705366x 705366x 1119854x 378667x 378667x 1119854x 414778x 414778x 414778x 608154x 608154x 608154x 608154x 15152x 15152x 15152x | /** @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; } |