// Original Starshine generator; licensing scope: ../../LICENSE.
// Copyright 2026 Joshua Tenner. No upstream counterpart is claimed.

///|
fn gen_valid_msf_record_copy_config() -> GenValidConfig {
  let base = GenValidConfig::binaryen_oracle_coverage_forced_default()
  GenValidConfig::{
    ..base,
    max_type_defs: 7,
    max_imports: 1,
    max_defined_funcs: 38,
    max_tables: 0,
    max_mems: 0,
    max_globals: 1,
    max_tags: 0,
    max_elems: 0,
    max_datas: 0,
    max_params: 2,
    max_results: 1,
    max_locals: 2,
    max_body_statements: 3000,
    max_body_depth: 40,
    max_module_byte_size_budget: Some(200013),
    features: GenValidFeatureToggles::{
      ..base.features,
      allow_imports: true,
      allow_tables: false,
      allow_mems: false,
      allow_globals: true,
      allow_tags: false,
      allow_start: false,
      allow_elems: false,
      allow_datas: false,
      allow_ref_types: true,
      allow_calls: true,
      allow_call_indirect: false,
      allow_tail_calls: false,
      allow_typed_body_generator: true,
    },
  }
}

///|
// Every generated input contains 8..12 matching copies of a 12..32-field
// immutable record. Ordinary i32 exports execute the copies in generic runtime
// comparison; typed exports independently expose null traps and old/new aliases.
fn gen_valid_msf_record_copy_module(seed : UInt64) -> Module {
  let fields = 12 + (seed % 21UL).to_int()
  let arms = 8 + (seed % 5UL).to_int()
  let initial = 100 + ((seed >> 8) % 1000UL).to_int()
  let replacement = 41 + ((seed >> 20) % 1000UL).to_int()
  let i32 = ValType::i32()
  let record = TypeIdx::new(0U)
  let ref_ = ValType::ref_type(RefType::new(true, HeapType::new(record)))
  let nonnull = ValType::ref_type(RefType::new(false, HeapType::new(record)))
  let types = [
    RecType::new(
      SubType::comp_type(
        CompType::struct_(
          Array::make(
            fields,
            FieldType::new(StorageType::val_type(i32), Mut::const_()),
          ),
        ),
      ),
    ),
    RecType::new(SubType::comp_type(CompType::func([i32], []))),
    RecType::new(SubType::comp_type(CompType::func([], [nonnull]))),
    RecType::new(SubType::comp_type(CompType::func([ref_, i32], [ref_]))),
    RecType::new(SubType::comp_type(CompType::func([ref_], [i32]))),
    RecType::new(SubType::comp_type(CompType::func([i32], [i32]))),
    RecType::new(SubType::comp_type(CompType::func([ref_, ref_], [i32]))),
  ]
  let make_body : Array[Instruction] = []
  for field in 0..= 0; selected = selected - 1 {
    let arm : Array[Instruction] = []
    for field in 0..