(
&mut self,
width: &KExpr<M>,
lhs: &KExpr<M>,
rhs: &KExpr<M>,
)
| 2492 | if self.env.nat_succ_stuck.contains(&entry_key) { |
| 2493 | return Ok(None); |
| 2494 | } |
| 2495 | let mut visited: Vec<(super::env::Addr, super::env::CtxAddr)> = |
| 2496 | vec![entry_key]; |
| 2497 | let mut offset = num_bigint::BigUint::from(1u64); |
| 2498 | let mut cur = arg.clone(); |
| 2499 | |
| 2500 | loop { |
| 2501 | if let Some(result) = |
| 2502 | self.try_reduce_nat_succ_linear_rec(&cur, &offset)? |
| 2503 | { |
| 2504 | return Ok(Some(result)); |
| 2505 | } |
| 2506 | |
| 2507 | let w = self.whnf_with_nat_succ_mode(&cur, NatSuccMode::Stuck)?; |
| 2508 | if let Some(n) = extract_nat_lit(&w, &self.prims) { |
| 2509 | let result = Nat(&n.0 + &offset); |
| 2510 | let blob_addr = Address::hash(&result.to_le_bytes()); |
| 2511 | return Ok(Some(KExpr::nat(result, blob_addr))); |
| 2512 | } |
| 2513 | |
| 2514 | let (head, args) = collect_app_spine(&w); |
| 2515 | if let ExprData::Const(id, _, _) = head.data() |
| 2516 | && id.addr == self.prims.nat_succ.addr |
| 2517 | && args.len() == 1 |
| 2518 | { |
| 2519 | crate::perf::record_nat_succ_peel(); |
| 2520 | offset += 1u64; |
| 2521 | cur = args[0].clone(); |
| 2522 | let cur_key = self.whnf_key(&cur); |
| 2523 | if self.env.nat_succ_stuck.contains(&cur_key) { |
| 2524 | // Known-stuck suffix: the whole chain above it is stuck too. |
| 2525 | self.env.nat_succ_stuck.extend(visited); |
| 2526 | return Ok(None); |
| 2527 | } |
| 2528 | visited.push(cur_key); |
| 2529 | // The whnf'd form `succ(cur)` can also surface later as a |
| 2530 | // succ-iter argument; record it alongside the raw chain. |
| 2531 | let w_key = self.whnf_key(&w); |
| 2532 | visited.push(w_key); |
| 2533 | continue; |
| 2534 | } |
| 2535 | |
| 2536 | self.env.nat_succ_stuck.extend(visited); |
| 2537 | return Ok(None); |
| 2538 | } |
no test coverage detected