Enumerate the anon-mode kernel work set from `env.consts`. Returns one `AnonWorkItem` per kernel-checkable group of constants. The total number of checked target addresses is `work.iter().map(|w| w.targets().len()).sum()`. Errors only on a corrupted env (missing const at an enumerated address, or a Tag4 head byte that doesn't correspond to a known `ConstantInfo` variant).
(env: &IxonEnv)
| 113 | /// address, or a Tag4 head byte that doesn't correspond to a known |
| 114 | /// `ConstantInfo` variant). |
| 115 | pub fn build_anon_work(env: &IxonEnv) -> Result<Vec<AnonWorkItem>, String> { |
| 116 | use ConstVariantTag as Tag; |
| 117 | use ixon::constant::ConstantInfo as CI; |
| 118 | use ixon::constant::MutConst as MC; |
| 119 | |
| 120 | let mut work: Vec<AnonWorkItem> = Vec::new(); |
| 121 | |
| 122 | // Sort keys for deterministic ordering across runs. |
| 123 | let mut keys: Vec<Address> = |
| 124 | env.consts.iter().map(|e| e.key().clone()).collect(); |
| 125 | keys.sort_unstable(); |
| 126 | |
| 127 | for addr in keys { |
| 128 | let lc = env.consts.get(&addr).ok_or_else(|| { |
| 129 | format!("build_anon_work: missing const at {}", addr.hex()) |
| 130 | })?; |
| 131 | let tag = lc.value().peek_variant().map_err(|e| { |
| 132 | format!("build_anon_work: peek_variant {}: {e}", addr.hex()) |
| 133 | })?; |
| 134 | match tag { |
| 135 | Tag::IPrj | Tag::CPrj | Tag::RPrj | Tag::DPrj => { |
| 136 | // Skip — covered by parent block. |
| 137 | }, |
| 138 | Tag::Defn | Tag::Recr | Tag::Axio | Tag::Quot => { |
| 139 | work.push(AnonWorkItem::Standalone { addr: addr.clone() }); |
| 140 | }, |
| 141 | Tag::Muts => { |
| 142 | // Materialize once to enumerate members; the `Arc<Constant>` |
| 143 | // drops at the end of this arm — no cache retention. |
| 144 | let constant = lc.value().get().map_err(|e| { |
| 145 | format!("build_anon_work: materialize Muts {}: {e}", addr.hex()) |
| 146 | })?; |
| 147 | let CI::Muts(members) = &constant.info else { |
| 148 | return Err(format!( |
| 149 | "build_anon_work: Tag::Muts but ConstantInfo is {:?} at {}", |
| 150 | constant.info.variant(), |
| 151 | addr.hex() |
| 152 | )); |
| 153 | }; |
| 154 | let mut targets: Vec<Address> = Vec::new(); |
| 155 | for (i, member) in members.iter().enumerate() { |
| 156 | let i = i as u64; |
| 157 | let member_addr = match member { |
| 158 | MC::Defn(_) => anon_defn_proj_addr(&addr, i), |
| 159 | MC::Indc(_) => anon_indc_proj_addr(&addr, i), |
| 160 | MC::Recr(_) => anon_recr_proj_addr(&addr, i), |
| 161 | }; |
| 162 | targets.push(member_addr); |
| 163 | if let MC::Indc(ind) = member { |
| 164 | for cidx in 0..ind.ctors.len() as u64 { |
| 165 | targets.push(anon_ctor_proj_addr(&addr, i, cidx)); |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | if targets.is_empty() { |
| 170 | continue; |
| 171 | } |
| 172 | let primary = targets[0].clone(); |