* Store a `NotElement(x, setExpr)` exclusion fact in the assumptions DB. * If `x` has a value, the exclusion is decided by evaluation instead.
( ce: ComputeEngine, x: Expression, setExpr: Expression )
| 261 | ]); |
| 262 | |
| 263 | /** |
| 264 | * Assume a conjunction: each conjunct is assumed independently |
| 265 | * (design §3.2, "shallow saturation"). |
| 266 | * |
| 267 | * Result: `'contradiction'` if any conjunct contradicts, |
| 268 | * `'not-a-predicate'` if any conjunct is unsupported, `'tautology'` if |
| 269 | * every conjunct was already known, `'ok'` otherwise. |
| 270 | */ |
| 271 | function assumeConjunction(proposition: Expression): AssumeResult { |
| 272 | console.assert(proposition.operator === 'And'); |
| 273 | if (!isFunction(proposition)) return 'not-a-predicate'; |
| 274 | |
| 275 | const ce = proposition.engine; |
| 276 | |
| 277 | // Atomicity (SYM P2-9): a conjunction must apply all-or-nothing when it |
| 278 | // contradicts. The historical loop applied each conjunct in turn, so a |
| 279 | // later contradictory conjunct left the earlier ones installed (e.g. |
| 280 | // `And(p > 0, p < −5)` reported `'contradiction'` yet left `p > 0`). |
| 281 | // |
| 282 | // Validate the whole conjunction in an isolated child scope first: the |
| 283 | // child inherits the caller's assumptions (copied) and symbol bindings (via |
no test coverage detected