( ce: IComputeEngine, symbol: undefined | MathJsonSymbol | MathJsonSymbol[] )
| 420 | console.error(e instanceof Error ? e.message : String(e)); |
| 421 | throw e; |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | export function forget( |
| 426 | ce: IComputeEngine, |
| 427 | symbol: undefined | MathJsonSymbol | MathJsonSymbol[] |
| 428 | ): void { |
| 429 | // |
| 430 | // ## THEORY OF OPERATIONS |
| 431 | // |
| 432 | // When forgeting we need to preserve existing definitions for symbols, |
| 433 | // as some expressions may be pointing to them. Instead, we |
| 434 | // reset the value of those definitions, but don't change the domain. |
| 435 | // |
| 436 | |
| 437 | if (symbol === undefined) { |
| 438 | ce.context.assumptions?.clear(); |
| 439 | |
| 440 | // Also undo value bindings installed by `assume(x = …)` (SYM P2-10): the |
| 441 | // docstring promises no-arg forget() removes *all* assumptions, but a |
| 442 | // value assigned via `assume` used to survive (so `x` still evaluated to |
| 443 | // its assumed value). Only assumption-installed values are cleared — user |
| 444 | // `declare()`/`assign()` values (never recorded in `assumptionBindings`) |
| 445 | // are left intact. |
| 446 | const installed = ce.context.assumptionBindings; |
| 447 | if (installed) { |
| 448 | for (const s of installed) { |
| 449 | const binding = ce.context.lexicalScope.bindings.get(s); |
| 450 | if (binding && isValueDef(binding) && !binding.value.isConstant) |
| 451 | binding.value.value = undefined; |
| 452 | } |
| 453 | installed.clear(); |
| 454 | } |
| 455 | |
| 456 | // The removed assumptions could affect existing expressions |
| 457 | ce._noteStateEvent({ kind: 'assumption' }); |
| 458 | if (ce.context) ce.context._assumptionsDirty = true; |
| 459 | |
| 460 | return; |
| 461 | } |
| 462 | |
| 463 | if (Array.isArray(symbol)) { |
| 464 | for (const x of symbol) forget(ce, x); |
| 465 | return; |
| 466 | } |
| 467 | |
| 468 | if (typeof symbol === 'string') { |
| 469 | // Remove any assumptions that make a reference to this symbol |
| 470 | // (note that when a scope is created, any assumptions from the |
| 471 | // parent scope are copied over, so this effectively removes any |
| 472 | // reference to this symbol, even if there are assumptions about |
| 473 | // it in a parent scope. However, when the current scope exits, |
| 474 | // any previous assumptions about the symbol will be restored). |
| 475 | for (const [assumption, _val] of ce.context.assumptions) { |
| 476 | if (assumption.has(symbol)) ce.context.assumptions.delete(assumption); |
| 477 | } |
| 478 | |
| 479 | // Also reset the symbol's value in the current scope's bindings. |
nothing calls this directly
no test coverage detected