| 1316 | e: Entry, |
| 1317 | guards: ReadonlyArray<GuardSpec>, |
| 1318 | closures: ReadonlyArray<(sub: Sub) => boolean>, |
| 1319 | seedTypes: Record<string, string> |
| 1320 | ): Record<string, MathJSON> | null { |
| 1321 | const vars = e.variables; |
| 1322 | const sub: Sub = {}; |
| 1323 | |
| 1324 | // Guards are checked at the depth where their last referenced variable is |
| 1325 | // assigned (massive pruning for multi-variable entries). |
| 1326 | const wcIndex = new Map<string, number>(vars.map((v, i) => ['_' + v, i])); |
| 1327 | const guardDepth = guards.map((g) => { |
| 1328 | let depth = -1; |
| 1329 | for (const w of guardWildcards(g)) depth = Math.max(depth, wcIndex.get(w) ?? vars.length - 1); |
| 1330 | return depth; |
| 1331 | }); |
| 1332 | |
| 1333 | // Variable-free guards must hold outright |
| 1334 | for (let i = 0; i < guards.length; i++) |
| 1335 | if (guardDepth[i] === -1 && !closures[i](sub)) return null; |
| 1336 | if (vars.length === 0) return {}; |
| 1337 | |
| 1338 | // A variable the entry APPLIES (`chi` in `chi(m)`) is typed `function` by |
| 1339 | // `variableTypes` in `load.ts`. Every candidate below is a number literal, |