Repository: HigherOrderCO/Bend
File: src/term/transform/encode_pattern_matching.rs (Rust)

Code before:
  def_id: DefId,
  crnt_name: &Name,
  crnt_rules: Vec<usize>,
  match_path: Vec<Pattern>,
) {
  let def = &book.defs[&def_id];
  // This is safe since we check exhaustiveness earlier.
  let fst_rule_idx = crnt_rules[0];
  let fst_rule = &def.rules[fst_rule_idx];
  let crnt_arg_idx = match_path.len();

  // Check if we've reached the end for this subfunction.
  // We did if all the (possibly zero) remaining patterns are variables and not matches.
  let all_args_done = crnt_arg_idx >= fst_rule.arity();
  let is_fst_rule_irrefutable =
    all_args_done || fst_rule.pats[crnt_arg_idx ..].iter().all(|p| matches!(p, Pattern::Var(_)));

  if is_fst_rule_irrefutable {
    // First rule will always be selected, generate leaf case.
    make_leaf_pattern_matching_case(book, def_id, crnt_name, fst_rule_idx, match_path);
  } else {
    let is_matching_case =
      crnt_rules.iter().any(|rule_idx| matches!(def.rules[*rule_idx].pats[crnt_arg_idx], Pattern::Ctr(..)));
    if is_matching_case {
      // Current arg is pattern matching, encode the pattern matching call
      make_branch_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    } else if crnt_rules
      .iter()
      .any(|rule_idx| matches!(def.rules[*rule_idx].pats[crnt_arg_idx], Pattern::Num(..)))
    {
      make_num_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    } else {
      // Current arg is not pattern matching, call next subfunction passing this arg.
      make_non_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    }
  }
}

/// Builds the function calling one of the original rule bodies.
fn make_leaf_pattern_matching_case(
  book: &mut Book,
  def_id: DefId,
  crnt_name: &Name,
  rule_idx: usize,
  match_path: Vec<Pattern>,
) {
  let def_name = book.def_names.name(&def_id).unwrap();
  let rule_def_name = make_rule_name(def_name, rule_idx);
  let rule_def_id = book.def_names.def_id(&rule_def_name).unwrap();
  let rule = &book.defs[&def_id].rules[rule_idx];


Review comment (suggestion):
And change the name of these functions to `make_adt_matching_case` and `make_num_matching_case` or similar.

Code after:
  def_id: DefId,
  crnt_name: &Name,
  crnt_rules: Vec<usize>,
  match_path: Vec<Pattern>,
) {
  let def = &book.defs[&def_id];
  // This is safe since we check exhaustiveness earlier.
  let fst_rule_idx = crnt_rules[0];
  let fst_rule = &def.rules[fst_rule_idx];
  let crnt_arg_idx = match_path.len();

  // Check if we've reached the end for this subfunction.
  // We did if all the (possibly zero) remaining patterns are variables and not matches.
  let all_args_done = crnt_arg_idx >= fst_rule.arity();
  let is_fst_rule_irrefutable =
    all_args_done || fst_rule.pats[crnt_arg_idx ..].iter().all(|p| matches!(p, Pattern::Var(_)));

  if is_fst_rule_irrefutable {
    // First rule will always be selected, generate leaf case.
    make_leaf_pattern_matching_case(book, def_id, crnt_name, fst_rule_idx, match_path);
  } else {
    let is_adt_case =
      crnt_rules.iter().any(|rule_idx| matches!(def.rules[*rule_idx].pats[crnt_arg_idx], Pattern::Ctr(..)));
    let is_num_case =
      crnt_rules.iter().any(|rule_idx| matches!(def.rules[*rule_idx].pats[crnt_arg_idx], Pattern::Num(..)));
    if is_adt_case {
      // Current arg is pattern matching, encode the pattern matching call
      make_adt_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    } else if is_num_case {
      make_num_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    } else {
      // Current arg is not pattern matching, call next subfunction passing this arg.
      make_non_pattern_matching_case(book, def_type, def_id, crnt_name, crnt_rules, match_path);
    }
  }
}

/// Builds the function calling one of the original rule bodies.
fn make_leaf_pattern_matching_case(
  book: &mut Book,
  def_id: DefId,
  crnt_name: &Name,
  rule_idx: usize,
  match_path: Vec<Pattern>,
) {
  let def_name = book.def_names.name(&def_id).unwrap();
  let rule_def_name = make_rule_name(def_name, rule_idx);
  let rule_def_id = book.def_names.def_id(&rule_def_name).unwrap();
  let rule = &book.defs[&def_id].rules[rule_idx];

  // The term we're building