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 15241x 15241x 15241x 15241x 60872x 846160x 846160x 846160x 60872x 15241x 15241x 15241x 15241x 15241x 15241x 612021x 612021x 612021x 612021x 612021x 612021x 612021x 418603x 418603x 418603x 418603x 418603x 1130155x 1130155x 711845x 711845x 711845x 711845x 711845x 711845x 711845x 711845x 329458x 329458x 329458x 711845x 711845x 1130155x 382094x 382094x 1130155x 418603x 418603x 418603x 612021x 612021x 612021x 612021x 15241x 15241x 15241x | /** @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;
}
|