rust/typeck: just store the closure for lambdas
This commit is contained in:
parent
b99ff62ea2
commit
8e5c8f697f
|
@ -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)?;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue