Def-eq for nat-like values: handles mixed literal/constructor comparison. Fast-path: two Nat literals are compared directly by value (O(1) instead of O(n) recursion depth that would blow the def_eq_depth limit).
(
&mut self,
a: &KExpr<M>,
b: &KExpr<M>,
)
| 947 | } |
| 948 | } |
| 949 | |
| 950 | /// Check if expression is nat zero (literal 0 or Nat.zero constructor). |
| 951 | fn is_nat_zero(&self, e: &KExpr<M>) -> bool { |
| 952 | match e.data() { |
| 953 | ExprData::Nat(v, _, _) => v.0 == num_bigint::BigUint::ZERO, |
| 954 | ExprData::Const(id, _, _) => id.addr == self.prims.nat_zero.addr, |
| 955 | _ => false, |
| 956 | } |
| 957 | } |
| 958 | |
| 959 | /// Allocation-free check that `e` could decompose to `base + offset`: |
| 960 | /// a Nat literal, `Nat.zero`/`Nat.succ`, or an app whose head constant is |
| 961 | /// `Nat.succ`/`Nat.add`. Walks the app chain by reference — no spine Vec. |
| 962 | fn nat_offset_candidate(&self, e: &KExpr<M>) -> bool { |
| 963 | let mut cur = e; |
| 964 | loop { |
| 965 | match cur.data() { |
| 966 | ExprData::Nat(..) => return true, |
| 967 | ExprData::Const(id, _, _) => { |
| 968 | let p = &self.prims; |
| 969 | return id.addr == p.nat_zero.addr |
| 970 | || id.addr == p.nat_succ.addr |
no test coverage detected