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 15270x 15270x 15270x 15270x 60986x 847788x 847788x 847788x 60986x 15270x 15270x 15270x 15270x 15270x 15270x 613206x 613206x 613206x 613206x 613206x 613206x 613206x 419895x 419895x 419895x 419895x 419895x 1133557x 1133557x 713955x 713955x 713955x 713955x 713955x 713955x 713955x 713955x 330509x 330509x 330509x 713955x 713955x 1133557x 383153x 383153x 1133557x 419895x 419895x 419895x 613206x 613206x 613206x 613206x 15270x 15270x 15270x | /** @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; } |