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

Code before:
      }
      (Pattern::Num(..), Pattern::Num(..)) => new_pats.push(other_arg.clone()),
      (Pattern::Num(..), _) => unreachable!(),
      (Pattern::Tup(_, _), Pattern::Tup(fst, snd)) => {
        new_pats.push(*fst.clone());
        new_pats.push(*snd.clone());
      }
      (Pattern::Tup(..), Pattern::Var(Some(other_arg))) => {
        let fst_nam = make_var_name(&mut var_count);
        let snd_nam = make_var_name(&mut var_count);
        let fst_arg = Term::Var { nam: fst_nam.clone() };
        let snd_arg = Term::Var { nam: snd_nam.clone() };
        new_pats.push(Pattern::Var(Some(fst_nam)));
        new_pats.push(Pattern::Var(Some(snd_nam)));
        let new_ctr = Term::Tup { fst: Box::new(fst_arg), snd: Box::new(snd_arg) };
        new_body.subst(other_arg, &new_ctr);
      }
      (Pattern::Var(..), _) => new_pats.push(other_arg.clone()),
      // Unreachable cases, we only call this function if we know the two patterns match together
      (
        Pattern::Ctr(..) | Pattern::Tup(..),
        Pattern::Ctr(..) | Pattern::Num(..) | Pattern::Tup(..),
      ) => {
        unreachable!()
      }
      (Pattern::Ctr(..), Pattern::Var(None)) => new_pats.push(Pattern::Var(None)),
      (Pattern::Tup(..), Pattern::Var(None)) => {
        new_pats.push(Pattern::Var(None));
        new_pats.push(Pattern::Var(None));
      },
    }
  }
  Rule { pats: new_pats, body: new_body }
}

fn make_var_name(var_count: &mut usize) -> Name {
  let nam = Name(format!("x${var_count}"));
  *var_count += 1;
  nam
}


Review comment (refactor):
Shouldn't you push one * pattern for each field that is being extracted from the nested pattern?
Try testing this:
```
data Tuple = (Pair a b)
(Foo (Pair (Pair a b) c)) = ...
(Foo *) = ...
```

Code after:
      }
      // Since numbers don't have subpatterns this should be unreachable.
      (Pattern::Num(..), _) => unreachable!(),
      (Pattern::Tup(_, _), Pattern::Tup(fst, snd)) => {
        new_pats.push(*fst.clone());
        new_pats.push(*snd.clone());
      }
      (Pattern::Tup(..), Pattern::Var(Some(other_arg))) => {
        let fst_nam = make_var_name(&mut var_count);
        let snd_nam = make_var_name(&mut var_count);
        let fst_arg = Term::Var { nam: fst_nam.clone() };
        let snd_arg = Term::Var { nam: snd_nam.clone() };
        new_pats.push(Pattern::Var(Some(fst_nam)));
        new_pats.push(Pattern::Var(Some(snd_nam)));
        let new_ctr = Term::Tup { fst: Box::new(fst_arg), snd: Box::new(snd_arg) };
        new_body.subst(other_arg, &new_ctr);
      }
      (Pattern::Var(..), _) => new_pats.push(other_arg.clone()),
      // Unreachable cases, we only call this function if we know the two patterns match together
      (
        Pattern::Ctr(..) | Pattern::Tup(..),
        Pattern::Ctr(..) | Pattern::Num(..) | Pattern::Tup(..),
      ) => {
        unreachable!()
      }
      (Pattern::Ctr(_, ctr_fields), Pattern::Var(None)) => {
        for _ in ctr_fields {
          new_pats.push(Pattern::Var(None));
        }
      },
      (Pattern::Tup(..), Pattern::Var(None)) => {
        new_pats.push(Pattern::Var(None));
        new_pats.push(Pattern::Var(None));
      },
    }
  }
  Rule { pats: new_pats, body: new_body }
}

fn make_var_name(var_count: &mut usize) -> Name {
  let nam = Name(format!("x${var_count}"));
  *var_count += 1;
  nam
}