bend/fun/transform/
desugar_open.rs

1use crate::{
2  diagnostics::Diagnostics,
3  fun::{Adts, Ctx, Term},
4  maybe_grow,
5};
6
7impl Ctx<'_> {
8  pub fn desugar_open(&mut self) -> Result<(), Diagnostics> {
9    for def in self.book.defs.values_mut() {
10      for rule in def.rules.iter_mut() {
11        if let Err(err) = rule.body.desugar_open(&self.book.adts) {
12          self.info.add_function_error(err, def.name.clone(), def.source.clone());
13        }
14      }
15    }
16
17    self.info.fatal(())
18  }
19}
20
21impl Term {
22  fn desugar_open(&mut self, adts: &Adts) -> Result<(), String> {
23    maybe_grow(|| {
24      match self {
25        Term::Open { typ, var, bod } => {
26          bod.desugar_open(adts)?;
27          if let Some(adt) = adts.get(&*typ) {
28            if adt.ctrs.len() == 1 {
29              let ctr = adt.ctrs.keys().next().unwrap();
30              *self = Term::Mat {
31                arg: Box::new(Term::Var { nam: var.clone() }),
32                bnd: Some(std::mem::take(var)),
33                with_bnd: vec![],
34                with_arg: vec![],
35                arms: vec![(Some(ctr.clone()), vec![], std::mem::take(bod))],
36              }
37            } else {
38              return Err(format!("Type '{typ}' of an 'open' has more than one constructor"));
39            }
40          } else {
41            return Err(format!("Type '{typ}' of an 'open' is not defined"));
42          }
43        }
44        Term::Def { def, nxt } => {
45          for rule in def.rules.iter_mut() {
46            rule.body.desugar_open(adts)?;
47          }
48          nxt.desugar_open(adts)?;
49        }
50        _ => {
51          for child in self.children_mut() {
52            child.desugar_open(adts)?;
53          }
54        }
55      }
56      Ok(())
57    })
58  }
59}