Skip to content

Commit

Permalink
[sc-489] Simplify passes by using iterators over the AST
Browse files Browse the repository at this point in the history
  • Loading branch information
developedby committed Mar 5, 2024
1 parent 319b246 commit 483a681
Show file tree
Hide file tree
Showing 24 changed files with 785 additions and 890 deletions.
44 changes: 6 additions & 38 deletions src/term/check/ctrs_arities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,44 +71,12 @@ impl Pattern {

impl Term {
pub fn check_ctrs_arities(&self, arities: &HashMap<Name, usize>) -> Result<(), MatchErr> {
stacker::maybe_grow(1024 * 32, 1024 * 1024, move || {
match self {
Term::Mat { args, rules } => {
for arg in args {
arg.check_ctrs_arities(arities)?;
}
for rule in rules {
for pat in &rule.pats {
pat.check_ctrs_arities(arities)?;
}
rule.body.check_ctrs_arities(arities)?;
}
}
Term::Let { pat, val, nxt } => {
pat.check_ctrs_arities(arities)?;
val.check_ctrs_arities(arities)?;
nxt.check_ctrs_arities(arities)?;
}

Term::Lst { els } | Term::Sup { els, .. } | Term::Tup { els } => {
for el in els {
el.check_ctrs_arities(arities)?;
}
}
Term::App { fun: fst, arg: snd, .. }
| Term::Dup { val: fst, nxt: snd, .. }
| Term::Opx { fst, snd, .. } => {
fst.check_ctrs_arities(arities)?;
snd.check_ctrs_arities(arities)?;
}
Term::Lam { bod, .. } | Term::Chn { bod, .. } => bod.check_ctrs_arities(arities)?,
Term::Var { .. }
| Term::Lnk { .. }
| Term::Num { .. }
| Term::Str { .. }
| Term::Ref { .. }
| Term::Era
| Term::Err => {}
Term::recursive_call(move || {
for pat in self.patterns() {
pat.check_ctrs_arities(arities)?;
}
for child in self.children() {
child.check_ctrs_arities(arities)?;
}
Ok(())
})
Expand Down
40 changes: 10 additions & 30 deletions src/term/check/match_arity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,39 +33,19 @@ impl Definition {

impl Term {
pub fn check_match_arity(&self) -> Result<(), MatchErr> {
stacker::maybe_grow(1024 * 32, 1024 * 1024, move || {
match self {
Term::Mat { args, rules } => {
let expected = args.len();
for rule in rules {
let found = rule.pats.len();
if found != expected {
return Err(MatchErr::ArityMismatch(found, expected));
}
rule.body.check_match_arity()?;
Term::recursive_call(move || {
if let Term::Mat { args, rules } = self {
let expected = args.len();
for rule in rules {
let found = rule.pats.len();
if found != expected {
return Err(MatchErr::ArityMismatch(found, expected));
}
}
}

Term::Lst { els } | Term::Sup { els, .. } | Term::Tup { els } => {
for el in els {
el.check_match_arity()?;
}
}
Term::App { fun: fst, arg: snd, .. }
| Term::Dup { val: fst, nxt: snd, .. }
| Term::Opx { fst, snd, .. }
| Term::Let { val: fst, nxt: snd, .. } => {
fst.check_match_arity()?;
snd.check_match_arity()?;
}
Term::Lam { bod, .. } | Term::Chn { bod, .. } => bod.check_match_arity()?,
Term::Var { .. }
| Term::Lnk { .. }
| Term::Num { .. }
| Term::Str { .. }
| Term::Ref { .. }
| Term::Era
| Term::Err => {}
for child in self.children() {
child.check_match_arity()?;
}
Ok(())
})
Expand Down
43 changes: 6 additions & 37 deletions src/term/check/unbound_pats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,43 +63,12 @@ impl Pattern {

impl Term {
pub fn check_unbound_pats(&self, is_ctr: &impl Fn(&Name) -> bool) -> Result<(), UnboundCtrErr> {
stacker::maybe_grow(1024 * 32, 1024 * 1024, move || {
match self {
Term::Let { pat, val, nxt } => {
pat.check_unbounds(is_ctr)?;
val.check_unbound_pats(is_ctr)?;
nxt.check_unbound_pats(is_ctr)?;
}
Term::Mat { args, rules } => {
for arg in args {
arg.check_unbound_pats(is_ctr)?;
}
for rule in rules {
for pat in &rule.pats {
pat.check_unbounds(is_ctr)?;
}
rule.body.check_unbound_pats(is_ctr)?;
}
}
Term::Lst { els } | Term::Sup { els, .. } | Term::Tup { els } => {
for el in els {
el.check_unbound_pats(is_ctr)?;
}
}
Term::App { fun: fst, arg: snd, .. }
| Term::Dup { val: fst, nxt: snd, .. }
| Term::Opx { fst, snd, .. } => {
fst.check_unbound_pats(is_ctr)?;
snd.check_unbound_pats(is_ctr)?;
}
Term::Lam { bod, .. } | Term::Chn { bod, .. } => bod.check_unbound_pats(is_ctr)?,
Term::Var { .. }
| Term::Lnk { .. }
| Term::Ref { .. }
| Term::Num { .. }
| Term::Str { .. }
| Term::Era
| Term::Err => (),
Term::recursive_call(move || {
for pat in self.patterns() {
pat.check_unbounds(is_ctr)?;
}
for child in self.children() {
child.check_unbound_pats(is_ctr)?;
}
Ok(())
})
Expand Down
94 changes: 28 additions & 66 deletions src/term/check/unbound_vars.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
diagnostics::Info,
term::{Ctx, Name, Pattern, Term},
term::{Ctx, Name, Term},
};
use std::{
collections::{hash_map::Entry, HashMap},
Expand Down Expand Up @@ -40,7 +40,7 @@ impl Ctx<'_> {
for rule in &mut def.rules {
let mut scope = HashMap::new();
for pat in &rule.pats {
pat.binds().for_each(|nam| push_scope(Some(nam), &mut scope));
pat.named_binds().for_each(|nam| push_scope(Some(nam), &mut scope));
}

rule.body.check_unbound_vars(&mut scope, &mut errs);
Expand Down Expand Up @@ -82,76 +82,38 @@ pub fn check_uses<'a>(
globals: &mut HashMap<&'a Name, (usize, usize)>,
errs: &mut Vec<UnboundVarErr>,
) {
match term {
Term::Lam { nam, bod, .. } => {
push_scope(nam.as_ref(), scope);
check_uses(bod, scope, globals, errs);
pop_scope(nam.as_ref(), scope);
}
Term::Var { nam } => {
if !scope.contains_key(nam) {
errs.push(UnboundVarErr::Local(nam.clone()));
*term = Term::Err;
}
}
Term::Chn { nam, bod, .. } => {
if let Some(nam) = nam {
globals.entry(nam).or_default().0 += 1;
}
check_uses(bod, scope, globals, errs);
}
Term::Lnk { nam } => {
globals.entry(nam).or_default().1 += 1;
}
Term::Let { pat: Pattern::Var(nam), val, nxt } => {
check_uses(val, scope, globals, errs);
push_scope(nam.as_ref(), scope);
check_uses(nxt, scope, globals, errs);
pop_scope(nam.as_ref(), scope);
}
Term::Dup { bnd, val, nxt, .. } => {
check_uses(val, scope, globals, errs);
for bnd in bnd.iter() {
push_scope(bnd.as_ref(), scope);
}
check_uses(nxt, scope, globals, errs);
for bnd in bnd.iter() {
pop_scope(bnd.as_ref(), scope);
}
}
Term::Let { pat, val, nxt } => {
check_uses(val, scope, globals, errs);
for bnd in pat.bind_or_eras() {
push_scope(bnd.as_ref(), scope);
Term::recursive_call(move || {
match term {
Term::Var { nam } => {
if !scope.contains_key(nam) {
errs.push(UnboundVarErr::Local(nam.clone()));
*term = Term::Err;
}
}
check_uses(nxt, scope, globals, errs);
for bnd in pat.bind_or_eras() {
pop_scope(bnd.as_ref(), scope);
Term::Chn { nam, bod, .. } => {
if let Some(nam) = nam {
globals.entry(nam).or_default().0 += 1;
}
check_uses(bod, scope, globals, errs);
}
}
Term::App { fun: fst, arg: snd, .. } | Term::Opx { fst, snd, .. } => {
check_uses(fst, scope, globals, errs);
check_uses(snd, scope, globals, errs);
}
Term::Mat { args, rules } => {
for arg in args {
check_uses(arg, scope, globals, errs);
Term::Lnk { nam } => {
globals.entry(nam).or_default().1 += 1;
}
for rule in rules {
rule.pats.iter().flat_map(|p| p.binds()).for_each(|nam| push_scope(Some(nam), scope));

check_uses(&mut rule.body, scope, globals, errs);

rule.pats.iter().flat_map(|p| p.binds()).rev().for_each(|nam| pop_scope(Some(nam), scope));
}
}
Term::Lst { els } | Term::Sup { els, .. } | Term::Tup { els } => {
for el in els {
check_uses(el, scope, globals, errs);
_ => {
for (child, binds) in term.children_mut_with_binds() {
// TODO: how to avoid creating this vec for the binds?
for bind in binds.iter() {
push_scope(bind.as_ref(), scope);
}
check_uses(child, scope, globals, errs);
for bind in binds.iter().rev() {
pop_scope(bind.as_ref(), scope);
}
}
}
}
Term::Ref { .. } | Term::Num { .. } | Term::Str { .. } | Term::Era | Term::Err => (),
}
})
}

fn push_scope<'a>(nam: Option<&'a Name>, scope: &mut HashMap<&'a Name, u64>) {
Expand Down
4 changes: 2 additions & 2 deletions src/term/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ macro_rules! display {

impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Term::recursive_call(move || match self {
Term::Lam { tag, nam, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), var_as_str(nam), bod)
}
Expand Down Expand Up @@ -83,7 +83,7 @@ impl fmt::Display for Term {
Term::Tup { els } => write!(f, "({})", DisplayJoin(|| els.iter(), ", "),),
Term::Lst { els } => write!(f, "[{}]", DisplayJoin(|| els.iter(), ", "),),
Term::Err => write!(f, "<Invalid>"),
}
})
}
}

Expand Down
Loading

0 comments on commit 483a681

Please sign in to comment.