Commit ebe5242
committed
feat(check): not / and / or narrowing predicates
Wires `not <cond>`, `<cond> and <cond>`, `<cond> or <cond>` into
interpretCondition. The Refinement.Negate method (previously dead
code) becomes the implementation of `not`; the binary cases follow
standard short-circuit narrowing semantics.
`not c`: flip truthy and falsy.
`a and b`:
- WhenTrue: both truthy. Apply a's WhenTrue, then merge b's
WhenTrue on top. b is computed against the a-truthy frame, so
its refinement reflects what's known at that point in the
short-circuit evaluation. Example:
`if x != null and y != null:` narrows both x and y.
- WhenFalse: at least one falsy. This is a disjunction we can't
express as a single refinement map without losing info, so we
leave it empty. Matches Pyright/mypy.
`a or b`: mirror image of and.
- WhenFalse: both falsy. Sequential apply.
- WhenTrue: at least one truthy, conservatively empty.
Right-operand frame matters. For `if x != null and x.field > 5:`,
the right hand x.field needs x narrowed to non-null - otherwise the
field-access narrowing logic would be working from the original
nullable type. interpretAnd / interpretOr build the right-side
frame by layering the appropriate left-side refinement before
interpreting the right.
mergeRefinementMaps overlays the right's narrowings on top of the
left's. When both refine the same symbol, the right wins because
it was computed in the tighter frame. Concretely:
`if x != null and type_of(x) == "int":` - left says x is int (non-
null), right (under that frame) further says x is int. Right wins
since they agree; if right had refined further (e.g. x is the int
arm of a union), that tighter narrowing would survive.
Combined with the Negate-based not, this unlocks the De Morgan
patterns too: `if not (x == null or y == null):` correctly
narrows both x and y to non-null, by flipping or's WhenFalse
(both non-null) into the outer WhenTrue.
Five new snapshot cases cover: bare not, simple and-chain, the
short-circuit "right sees left" property, or's symmetric falsy
narrowing in the else branch, and the De Morgan composition.1 parent 35d6990 commit ebe5242
1 file changed
Lines changed: 139 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
0 commit comments