Skip to content

Instantly share code, notes, and snippets.

@teymour-aldridge
Created May 31, 2022 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teymour-aldridge/7a8da73f0cca777924a438017f628e41 to your computer and use it in GitHub Desktop.
Save teymour-aldridge/7a8da73f0cca777924a438017f628e41 to your computer and use it in GitHub Desktop.
/// Unify a set of constraints (i.e. solve them, if that is possible)
fn unify(set: HashSet<Constraint>, mut solved: TyEnv) -> Result<TyEnv, TyCheckError> {
if set.is_empty() {
return Ok(solved);
}
let mut iter = set.into_iter();
let next = if let Some(next) = iter.next() {
next
} else {
return Ok(solved);
};
let u = match next {
Constraint::IdToTy { id, ty } => Some(Substitution::ConcreteForX(ty, id)),
Constraint::IdToId { id, to } => {
if id != to {
Some(Substitution::XforY(id, to))
} else {
None
}
}
Constraint::TyToTy { ty, to } => {
if ty != to {
return Err(TyCheckError::TypeMismatch);
} else {
None
}
}
};
if let Some(u) = u {
// add the substitution to the list of substitutions
solved.feed_substitution(u);
// apply the newly generated substitution to the rest of the set
let new_set: HashSet<Constraint> = iter
.map(|constraint| match (u, constraint) {
// wherever we see y, replace with x
(Substitution::XforY(x, y), Constraint::IdToTy { id, ty }) => Constraint::IdToTy {
id: if id == y { x } else { id },
ty,
},
// wherever we see y, replace with x
(Substitution::XforY(x, y), Constraint::IdToId { id, to }) => Constraint::IdToId {
id: if id == y { x } else { id },
to: if to == y { x } else { to },
},
(Substitution::ConcreteForX(sub_with, x), Constraint::IdToTy { id, ty }) => {
if id == x {
Constraint::TyToTy {
ty: sub_with,
to: ty,
}
} else {
Constraint::IdToTy { id, ty }
}
}
(Substitution::ConcreteForX(sub_with, x), Constraint::IdToId { id, to }) => {
if id == x {
Constraint::IdToTy {
id: to,
ty: sub_with,
}
} else if to == x {
Constraint::IdToTy { id, ty: sub_with }
} else {
Constraint::IdToId { id, to }
}
}
// these substitutions cannot be applied to the constraint set
(Substitution::XforY(_, _), constraint)
| (Substitution::ConcreteForX(_, _), constraint) => constraint,
})
.collect();
unify(new_set, solved)
} else {
unify(iter.collect(), solved)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment