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

Code before:
          (Term::Var { nam: namegen.var_name(next) }, true)
        }
        _ => unreachable!(),
      },
    }
  }
  // A hashmap linking ports to binder names. Those ports have names:
  // Port 1 of a con node (λ), ports 1 and 2 of a fan node (let).
  let mut namegen = NameGen::default();

  let mut dup_scope = HashMap::new();
  let mut tup_scope = Scope::default();

  // Reads the main term from the net
  let (mut main, mut valid) =
    reader(net, net.enter_port(ROOT), &mut namegen, &mut dup_scope, &mut tup_scope, book);

  // Read all the let bodies.
  while let Some(tup) = tup_scope.vec.pop() {
    let val = net.enter_port(Port(tup, 0));
    let (val, val_valid) = reader(net, val, &mut namegen, &mut dup_scope, &mut tup_scope, book);
    let fst = namegen.decl_name(net, Port(tup, 1));
    let snd = namegen.decl_name(net, Port(tup, 2));

    let mut vars = HashSet::new();
    val.get_needed_vars(&mut vars);

    let let_ctx = LetBody::Ctx(fst, snd, val);

    match let_ctx.search_and_insert(&mut main, &mut vars) {
      Err(LetBody::Ctx(fst, snd, val)) => {
        main = Term::Let { pat: LetPat::Tup(fst, snd), val: Box::new(val), nxt: Box::new(main) }
      }
      Err(_) => unreachable!(),
      Ok(_) => {}
    }

    valid = valid && val_valid;
  }

  (main, valid)
}

enum LetBody {
  Used,
  Ctx(Option<Name>, Option<Name>, Term),
}

type LetResult = Result<(LetBody, bool), LetBody>;

impl LetBody {

Review comment (suggestion):
I would suggest changing this variable (and it's uses within the other functions) from `vars` to `free_vars` as well as changing `Term::get_needed_vars` to `Term::free_vars`

Code after:
          (Term::Var { nam: namegen.var_name(next) }, true)
        }
        _ => unreachable!(),
      },
    }
  }
  // A hashmap linking ports to binder names. Those ports have names:
  // Port 1 of a con node (λ), ports 1 and 2 of a fan node (let).
  let mut namegen = NameGen::default();

  let mut dup_scope = HashMap::new();
  let mut tup_scope = Scope::default();

  // Reads the main term from the net
  let (mut main, mut valid) =
    reader(net, net.enter_port(ROOT), &mut namegen, &mut dup_scope, &mut tup_scope, book);

  // Read all the let bodies.
  while let Some(tup) = tup_scope.vec.pop() {
    let val = net.enter_port(Port(tup, 0));
    let (val, val_valid) = reader(net, val, &mut namegen, &mut dup_scope, &mut tup_scope, book);
    let fst = namegen.decl_name(net, Port(tup, 1));
    let snd = namegen.decl_name(net, Port(tup, 2));

    let mut free_vars = HashSet::new();
    val.free_vars(&mut free_vars);

    let let_ctx = LetInsertion::Todo(fst, snd, val);

    match let_ctx.search_and_insert(&mut main, &mut free_vars).0 {
      LetInsertion::Err(fst, snd, val) => {
        main = Term::Let { pat: LetPat::Tup(fst, snd), val: Box::new(val), nxt: Box::new(main) }
      }
      LetInsertion::Ok => {}
      _ => unreachable!(),
    }

    valid = valid && val_valid;
  }

  (main, valid)
}

enum LetInsertion {
  Ok,
  Err(Option<Name>, Option<Name>, Term),
  Todo(Option<Name>, Option<Name>, Term),
}

impl LetInsertion {
  /// Searchers the term and inserts the let body in the position bettewn where the vars it depends are defined,