( pat: Pat, expr: Expression, x: Expression, env: Env, k: () => boolean )
| 103 | env.delete(name); |
| 104 | return false; |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Is `expr` an occurrence of the bound variable `x`? |
| 109 | * |
| 110 | * Name AND binding, the ordinary equality question — NOT the "patterns are |
| 111 | * syntax" carve-out (`m`'s `case 'const'` and `match-dispatch`'s template |
| 112 | * comparisons are that; this one compares a SUBJECT sub-expression against the |
| 113 | * driver's own integration variable). |
| 114 | * |
| 115 | * `RubiDriver.int` takes the variable as a STRING and re-boxes it with |
| 116 | * `ce.symbol`, so historically it carried the CALLER's binding while parsing |
| 117 | * `\int … dx` minted the integral's own — the reason this used to compare by |
| 118 | * name alone (366 misses, all on `x`, all from this site). The integrand now |
| 119 | * arrives LIFTED into the caller's scope (`liftIntegrand`, |
| 120 | * `boxed-expression/utils.ts`) so both sides denote one binding, and the |
| 121 | * comparison can ask the real |
| 122 | * question. `sameBindingDef` also treats a call frame's parameter definition as |
| 123 | * its static binding, and two raw occurrences still agree — the parse route |
| 124 | * leaves a binding-site symbol undefined. |
| 125 | */ |
| 126 | function sameBoundName(expr: Expression, x: Expression): boolean { |
| 127 | if (!isSymbol(expr)) return expr.isSame(x); |
| 128 | if (!isSymbol(x) || expr.symbol !== x.symbol) return false; |
| 129 | return sameBindingDef(expr.valueDefinition, x.valueDefinition); |
| 130 | } |
| 131 | |
| 132 | function m( |
| 133 | pat: Pat, |
| 134 | expr: Expression, |
| 135 | x: Expression, |
| 136 | env: Env, |
| 137 | k: () => boolean |
no test coverage detected