( exprs_obj: LeanArray<LeanBorrowed<'_>>, )
| 12 | /// This helps diagnose why Lean and Rust make different sharing decisions. |
| 13 | #[unsafe(no_mangle)] |
| 14 | pub extern "C" fn rs_debug_sharing_analysis( |
| 15 | exprs_obj: LeanArray<LeanBorrowed<'_>>, |
| 16 | ) { |
| 17 | let exprs: Vec<Arc<IxonExpr>> = |
| 18 | exprs_obj.map(|x| Arc::new(LeanIxonExpr(x).decode())); |
| 19 | |
| 20 | println!("[Rust] Analyzing {} input expressions", exprs.len()); |
| 21 | |
| 22 | let (info_map, _ptr_to_hash, topo_order) = analyze_block(&exprs, false); |
| 23 | let effective_sizes = |
| 24 | ixon::sharing::compute_effective_sizes(&info_map, &topo_order); |
| 25 | |
| 26 | println!("[Rust] Found {} unique subterms", info_map.len()); |
| 27 | |
| 28 | // Collect subterms with usage >= 2 |
| 29 | let mut candidates: Vec<_> = info_map |
| 30 | .iter() |
| 31 | .filter(|(_, info)| info.usage_count >= 2) |
| 32 | .filter_map(|(hash, info)| { |
| 33 | let eff_size = *effective_sizes.get(hash)?; |
| 34 | Some((hash, info, eff_size)) |
| 35 | }) |
| 36 | .collect(); |
| 37 | |
| 38 | // Sort by usage count descending |
| 39 | candidates.sort_by(|a, b| b.1.usage_count.cmp(&a.1.usage_count)); |
| 40 | |
| 41 | println!("[Rust] Subterms with usage >= 2:"); |
| 42 | for (hash, info, eff_size) in candidates { |
| 43 | let n = info.usage_count; |
| 44 | let n_i = n.cast_signed(); |
| 45 | let eff_size_i = eff_size.cast_signed(); |
| 46 | let potential = (n_i - 1) * eff_size_i - (n_i + eff_size_i); |
| 47 | println!( |
| 48 | " usage={} eff_size={} potential={} hash={:.8}", |
| 49 | n, eff_size, potential, hash |
| 50 | ); |
| 51 | println!(" expr={:?}", info.expr); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /// FFI: Run Rust's sharing analysis on Lean-provided Ixon.Expr array. |
| 56 | /// Returns the number of shared items Rust would produce. |
nothing calls this directly
no test coverage detected