Compute a binary nat operation. Returns `None` if the operation can't be computed (e.g., exponent too large) — caller leaves the expression unreduced.
( addr: &Address, p: &Primitives<M>, a: &Nat, b: &Nat, )
| 2903 | Some(v) => v, |
| 2904 | None => return Ok(None), |
| 2905 | }; |
| 2906 | let b_val = match extract_nat_value(&wb, &self.prims) { |
| 2907 | Some(v) => v, |
| 2908 | None => return Ok(None), |
| 2909 | }; |
| 2910 | |
| 2911 | // S5: Eq.refl is universe-polymorphic: @Eq.refl.{u}. |
| 2912 | // For Bool : Type = Sort 1, we need u = 1 = Succ(Zero). |
| 2913 | let u1 = KUniv::succ(KUniv::zero()); |
| 2914 | |
| 2915 | // decLt n m → decLe (n+1) m |
| 2916 | if is_dec_lt { |
| 2917 | let succ_a = Nat(&a_val.0 + 1u64); |
| 2918 | let succ_a_addr = Address::hash(&succ_a.to_le_bytes()); |
| 2919 | let succ_a_expr = self.intern(KExpr::nat(succ_a, succ_a_addr)); |
| 2920 | // Build: Nat.decLe (n+1) m |
| 2921 | let dec_le_const = |
| 2922 | self.intern(KExpr::cnst(self.prims.nat_dec_le.clone(), Box::new([]))); |
| 2923 | let mut result = self.intern(KExpr::app(dec_le_const, succ_a_expr)); |
| 2924 | result = self.intern(KExpr::app(result, args[1].clone())); |
| 2925 | for arg in args.iter().skip(2) { |
| 2926 | result = self.intern(KExpr::app(result, arg.clone())); |
| 2927 | } |
| 2928 | // Recursively reduce the decLe |
| 2929 | return Ok(Some(result)); |
| 2930 | } |
| 2931 | |
| 2932 | // Extract the proposition from the type of `e`. |
| 2933 | // `e : Decidable prop` → we need `prop` as the first constructor argument. |
| 2934 | // Use infer_only to avoid def-eq checks (safe within WHNF). |
| 2935 | let prop = match self.with_infer_only(|tc| tc.infer(e)) { |
| 2936 | Ok(e_ty) => { |
| 2937 | let e_ty_whnf = self.whnf(&e_ty)?; |
| 2938 | let (_, type_args) = collect_app_spine(&e_ty_whnf); |
| 2939 | match type_args.into_iter().next() { |
| 2940 | Some(p) => p, |
| 2941 | None => return Ok(None), // not `Decidable prop` — bail |
| 2942 | } |
| 2943 | }, |
| 2944 | Err(_) => return Ok(None), // inference failed — bail to delta |
| 2945 | }; |
| 2946 | |
| 2947 | let (b_result, proof_true_fn, proof_false_fn) = if is_dec_le { |
| 2948 | ( |
| 2949 | a_val <= b_val, |
| 2950 | &self.prims.nat_le_of_ble_eq_true, |
| 2951 | &self.prims.nat_not_le_of_not_ble_eq_true, |
| 2952 | ) |
| 2953 | } else { |
| 2954 | // is_dec_eq |
| 2955 | ( |
| 2956 | a_val == b_val, |
| 2957 | &self.prims.nat_eq_of_beq_eq_true, |
| 2958 | &self.prims.nat_ne_of_beq_eq_false, |
| 2959 | ) |
| 2960 | }; |
| 2961 | let proof_true_fn = proof_true_fn.clone(); |
| 2962 | let proof_false_fn = proof_false_fn.clone(); |
no test coverage detected