rust/typeck: just store the closure for lambdas

This commit is contained in:
Alain Zscheile 2023-11-06 21:18:20 +01:00
parent b99ff62ea2
commit 8e5c8f697f
2 changed files with 60 additions and 88 deletions

View file

@ -22,16 +22,6 @@ pub struct Var {}
#[derive(Clone, Debug)]
pub struct Expr(pub Rc<RefCell<ExprKind>>);
#[derive(Clone, Debug)]
pub struct TyLambda {
pub argty: Expr,
pub arg: Rc<Var>,
// NOTE: the binds can't reference the `arg`.
pub binds_direct: Vec<Rc<Var>>,
pub binds_indirect: Vec<Expr>,
pub exp: Expr,
}
/// expression graph without pattern matching
/// NOTE: don't insert loops into this or it'll result in memory leaks
#[derive(Clone, Debug)]
@ -74,8 +64,16 @@ pub enum ExprKind {
Lambda(Rc<Var>, Expr),
LinTyLambda(TyLambda),
TyLambda(TyLambda),
TyLambda {
argty: Expr,
arg: Rc<Var>,
// NOTE: the binds can't reference the `arg`.
// if only a single variable is bound, it gets put into the binds directly
// otherwise stuff is wrapped into a record
// this is mostly important for linearity concerns and references
binds: Expr,
exp: Expr,
},
// LetBind intentionally missing
Apply(Expr, Expr),
@ -128,68 +126,6 @@ fn subst_prune_csr<'a>(hsvars: &'a HashMap<Expr>, csr: &Rc<Var>) -> Cow<'a, Hash
}
}
impl TyLambda {
fn deep_clone_intern(
&self,
hmexpr: &mut HashMap<Rc<RefCell<ExprKind>>>,
hsvars: &HashMap<Expr>,
) -> Self {
Self {
// we don't need to prune the CSR from the argty and binds because they don't bind it
argty: self.argty.deep_clone_intern(hmexpr, hsvars),
arg: Rc::clone(&self.arg),
binds_direct: self.binds_direct.iter().map(Rc::clone).collect(),
binds_indirect: self
.binds_indirect
.iter()
.map(|i| i.deep_clone_intern(hmexpr, hsvars))
.collect(),
exp: self
.exp
.deep_clone_intern(hmexpr, &subst_prune_csr(hsvars, &self.arg)),
}
}
fn deep_eq_intern(&self, oth: &Self, hsv: &mut DeepEqExprs, hscsrs: &mut DeepEqVars) -> bool {
if !self.argty.deep_eq_intern(&oth.argty, hsv, hscsrs) {
return false;
}
// NOTE: for now we assume that the order of references matches exactly...
if self.binds_direct.len() != oth.binds_direct.len()
|| self.binds_indirect.len() != oth.binds_indirect.len()
{
return false;
}
if !self
.binds_direct
.iter()
.zip(oth.binds_direct.iter())
.all(
|(lhs, rhs)| match hscsrs.entry((Rc::as_ptr(lhs), Rc::as_ptr(rhs))) {
Entry::Occupied(occ) => *occ.get(),
Entry::Vacant(vac) => {
vac.insert(false);
false
}
},
)
{
return false;
}
if !self
.binds_indirect
.iter()
.zip(oth.binds_indirect.iter())
.all(|(i, j)| i.deep_eq_intern(j, hsv, hscsrs))
{
return false;
}
// important: the argument type and binds can't reference the argument variable
deep_eq_mark_var(hscsrs, &self.arg, &oth.arg);
self.exp.deep_eq_intern(&oth.exp, hsv, hscsrs)
}
}
impl Expr {
fn deep_clone_intern(
&self,
@ -255,8 +191,18 @@ impl Expr {
inner.deep_clone_intern(hmexpr, &subst_prune_csr(hsvars, csr)),
),
Ek::TyLambda(tl) => Ek::TyLambda(tl.deep_clone_intern(hmexpr, hsvars)),
Ek::LinTyLambda(tl) => Ek::LinTyLambda(tl.deep_clone_intern(hmexpr, hsvars)),
Ek::TyLambda {
argty,
arg,
binds,
exp,
} => Ek::TyLambda {
// we don't need to prune the CSR from the argty and binds because they don't bind it
argty: argty.deep_clone_intern(hmexpr, hsvars),
arg: Rc::clone(arg),
binds: binds.deep_clone_intern(hmexpr, hsvars),
exp: exp.deep_clone_intern(hmexpr, &subst_prune_csr(hsvars, arg)),
},
Ek::Apply(lhs, rhs) => Ek::Apply(
lhs.deep_clone_intern(hmexpr, hsvars),
@ -366,8 +312,31 @@ impl Expr {
deep_eq_mark_var(hscsrs, cslhs, csrhs);
exlhs.deep_eq_intern(exrhs, hsv, hscsrs)
}
(Ek::TyLambda(lhs), Ek::TyLambda(rhs)) => lhs.deep_eq_intern(rhs, hsv, hscsrs),
(Ek::LinTyLambda(lhs), Ek::LinTyLambda(rhs)) => lhs.deep_eq_intern(rhs, hsv, hscsrs),
(
Ek::TyLambda {
argty: lhs_argty,
binds: lhs_binds,
arg: lhs_arg,
exp: lhs_exp,
},
Ek::TyLambda {
argty: rhs_argty,
binds: rhs_binds,
arg: rhs_arg,
exp: rhs_exp,
},
) => {
// NOTE: we assume that the binds match exactly
// important: the argument type and binds can't reference the argument variable
if !(lhs_argty.deep_eq_intern(rhs_argty, hsv, hscsrs)
&& lhs_binds.deep_eq_intern(rhs_binds, hsv, hscsrs))
{
false
} else {
deep_eq_mark_var(hscsrs, lhs_arg, rhs_arg);
lhs_exp.deep_eq_intern(rhs_exp, hsv, hscsrs)
}
}
// this case should be rarely encountered, but it might happen
(Ek::Apply(ll, lr), Ek::Apply(rl, rr)) => {
@ -566,12 +535,15 @@ impl Expr {
}
}
Ek::Lambda(_, inner) => inner.force_intern(hsx)?,
Ek::TyLambda(tl) | Ek::LinTyLambda(tl) => {
tl.argty.force_intern(hsx)?;
tl.binds_indirect
.iter()
.try_for_each(|i| i.force_intern(hsx))?;
tl.exp.force_intern(hsx)?;
Ek::TyLambda {
argty,
binds,
arg: _,
exp,
} => {
argty.force_intern(hsx)?;
binds.force_intern(hsx)?;
exp.force_intern(hsx)?;
}
Ek::Apply(lhs, rhs) => {
lhs.force_intern(hsx)?;

View file

@ -1,10 +1,10 @@
pub mod egraph;
pub use egraph::Expr as Type;
pub use egraph::Expr;
use Expr as Type;
#[derive(Clone, Debug, thiserror::Error]
pub enum Error {
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum Error {}
#[derive(Clone, Debug)]
pub enum BinderState {