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

Code before:
  book.check_exhaustive_patterns(&def_types)?;
  book.encode_pattern_matching_functions(&def_types);
  Ok(())
}

pub fn run_book(
  mut book: Book,
  mem_size: usize,
  parallel: bool,
  debug: bool,
  linear: bool,
  errors: bool,
  mut warning_opts: WarningOpts,
  opts: Opts,
) -> Result<(Term, DefNames, RunInfo), String> {
  let CompileResult { core_book, hvmc_names, labels, warnings } = compile_book(&mut book, opts)?;
  let warnings = warning_opts.filter(warnings);

  // if both enabled, ignore the all option
  if warning_opts.all && errors {
    warning_opts.all = false;
  }
  if !warning_opts.all {
    if !warnings.is_empty() {
      let warnings = warnings.iter().join("\n");
      if errors {
        return Err(format!("{warnings}\nCould not run the code because of the previous warnings"));
      } else {
        eprintln!("{warnings}");
      }
    }
  }

  fn debug_hook(net: &Net, book: &Book, hvmc_names: &HvmcNames, labels: &Labels, linear: bool) {
    let net = hvmc_to_net(net, &|id| hvmc_names.hvmc_name_to_id[&id]);
    let (res_term, errors) = net_to_term(&net, book, labels, linear);
    println!(
      "{}{}\n---------------------------------------",
      errors.display(&book.def_names),
      res_term.display(&book.def_names)
    );
  }
  let debug_hook =
    if debug { Some(|net: &_| debug_hook(net, &book, &hvmc_names, &labels, linear)) } else { None };

  let (res_lnet, stats) = run_compiled(&core_book, mem_size, parallel, debug_hook);
  let net = hvmc_to_net(&res_lnet, &|id| hvmc_names.hvmc_name_to_id[&id]);
  let (res_term, readback_errors) = net_to_term(&net, &book, &labels, linear);
  let info = RunInfo { stats, readback_errors, net: res_lnet };
  Ok((res_term, book.def_names, info))
}

Review comment (suggestion):
We should deny on individual warnings. Just as suggested below a `is_warning_enabled` function, we could have a `is_warning_denied` and filter those that are true.

I also suggest having `-D<warning>` and `-Dno-<warning>` just like for warnings and optimizations.

Code after:
  book.check_exhaustive_patterns(&def_types)?;
  book.encode_pattern_matching_functions(&def_types);
  Ok(())
}

pub fn run_book(
  mut book: Book,
  mem_size: usize,
  parallel: bool,
  debug: bool,
  linear: bool,
  warning_opts: WarningOpts,
  opts: Opts,
) -> Result<(Term, DefNames, RunInfo), String> {
  let CompileResult { core_book, hvmc_names, labels, warnings } = compile_book(&mut book, opts)?;

  let warns = warning_opts.filter(&warnings, WarnState::Warn);
  if !warns.is_empty() {
    let warns = warns.iter().join("\n");
    eprintln!("Warnings:\n{warns}");
  }

  let denies = warning_opts.filter(&warnings, WarnState::Deny);
  if !denies.is_empty() {
    let denies = denies.iter().join("\n");
    return Err(format!("{denies}\nCould not run the code because of the previous warnings"));
  }

  fn debug_hook(net: &Net, book: &Book, hvmc_names: &HvmcNames, labels: &Labels, linear: bool) {
    let net = hvmc_to_net(net, &|id| hvmc_names.hvmc_name_to_id[&id]);
    let (res_term, errors) = net_to_term(&net, book, labels, linear);
    println!(
      "{}{}\n---------------------------------------",
      errors.display(&book.def_names),
      res_term.display(&book.def_names)
    );
  }
  let debug_hook =
    if debug { Some(|net: &_| debug_hook(net, &book, &hvmc_names, &labels, linear)) } else { None };

  let (res_lnet, stats) = run_compiled(&core_book, mem_size, parallel, debug_hook);
  let net = hvmc_to_net(&res_lnet, &|id| hvmc_names.hvmc_name_to_id[&id]);
  let (res_term, readback_errors) = net_to_term(&net, &book, &labels, linear);
  let info = RunInfo { stats, readback_errors, net: res_lnet };
  Ok((res_term, book.def_names, info))
}

pub fn run_compiled(
  book: &hvmc::ast::Book,
  mem_size: usize,
  parallel: bool,