cranelift-isle: Record all binding names (#5538)
...not just the ones at the outer scope of a rule. Thanks to @avanhatt for pointing out that #5221 didn't capture as much information as I intended it to.
This commit is contained in:
@@ -484,6 +484,9 @@ pub struct BoundVar {
|
|||||||
pub name: Sym,
|
pub name: Sym,
|
||||||
/// The type of the value this variable is bound to.
|
/// The type of the value this variable is bound to.
|
||||||
pub ty: TypeId,
|
pub ty: TypeId,
|
||||||
|
/// A counter used to check whether this variable is still in scope during
|
||||||
|
/// semantic analysis. Not meaningful afterward.
|
||||||
|
scope: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `if-let` clause with a subpattern match on an expr after the
|
/// An `if-let` clause with a subpattern match on an expr after the
|
||||||
@@ -1112,19 +1115,46 @@ impl TypeEnv {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct Bindings {
|
struct Bindings {
|
||||||
|
/// All bindings accumulated so far within the current rule, including let-
|
||||||
|
/// bindings which have gone out of scope.
|
||||||
seen: Vec<BoundVar>,
|
seen: Vec<BoundVar>,
|
||||||
|
/// Counter for unique scope IDs within this set of bindings.
|
||||||
|
next_scope: usize,
|
||||||
|
/// Stack of the scope IDs for bindings which are currently in scope.
|
||||||
|
in_scope: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bindings {
|
impl Bindings {
|
||||||
|
fn enter_scope(&mut self) {
|
||||||
|
self.in_scope.push(self.next_scope);
|
||||||
|
self.next_scope += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_scope(&mut self) {
|
||||||
|
self.in_scope.pop();
|
||||||
|
}
|
||||||
|
|
||||||
fn add_var(&mut self, name: Sym, ty: TypeId) -> VarId {
|
fn add_var(&mut self, name: Sym, ty: TypeId) -> VarId {
|
||||||
let id = VarId(self.seen.len());
|
let id = VarId(self.seen.len());
|
||||||
log!("binding var {:?} as {:?} with type {:?}", name.0, id, ty);
|
let var = BoundVar {
|
||||||
self.seen.push(BoundVar { id, name, ty });
|
id,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
scope: *self
|
||||||
|
.in_scope
|
||||||
|
.last()
|
||||||
|
.expect("enter_scope should be called before add_var"),
|
||||||
|
};
|
||||||
|
log!("binding var {:?}", var);
|
||||||
|
self.seen.push(var);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup(&self, name: Sym) -> Option<&BoundVar> {
|
fn lookup(&self, name: Sym) -> Option<&BoundVar> {
|
||||||
self.seen.iter().rev().find(|binding| binding.name == name)
|
self.seen
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.find(|binding| binding.name == name && self.in_scope.contains(&binding.scope))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1656,6 +1686,7 @@ impl TermEnv {
|
|||||||
&ast::Def::Rule(ref rule) => {
|
&ast::Def::Rule(ref rule) => {
|
||||||
let pos = rule.pos;
|
let pos = rule.pos;
|
||||||
let mut bindings = Bindings::default();
|
let mut bindings = Bindings::default();
|
||||||
|
bindings.enter_scope();
|
||||||
|
|
||||||
let (sym, args) = if let ast::Pattern::Term { sym, args, .. } = &rule.pattern {
|
let (sym, args) = if let ast::Pattern::Term { sym, args, .. } = &rule.pattern {
|
||||||
(sym, args)
|
(sym, args)
|
||||||
@@ -1711,6 +1742,8 @@ impl TermEnv {
|
|||||||
/* on_lhs */ false,
|
/* on_lhs */ false,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
bindings.exit_scope();
|
||||||
|
|
||||||
let rid = RuleId(self.rules.len());
|
let rid = RuleId(self.rules.len());
|
||||||
self.rules.push(Rule {
|
self.rules.push(Rule {
|
||||||
id: rid,
|
id: rid,
|
||||||
@@ -2299,7 +2332,7 @@ impl TermEnv {
|
|||||||
ref body,
|
ref body,
|
||||||
pos,
|
pos,
|
||||||
} => {
|
} => {
|
||||||
let orig_binding_len = bindings.seen.len();
|
bindings.enter_scope();
|
||||||
|
|
||||||
// For each new binding...
|
// For each new binding...
|
||||||
let mut let_defs = vec![];
|
let mut let_defs = vec![];
|
||||||
@@ -2340,7 +2373,7 @@ impl TermEnv {
|
|||||||
let body_ty = body.ty();
|
let body_ty = body.ty();
|
||||||
|
|
||||||
// Pop the bindings.
|
// Pop the bindings.
|
||||||
bindings.seen.truncate(orig_binding_len);
|
bindings.exit_scope();
|
||||||
|
|
||||||
Some(Expr::Let {
|
Some(Expr::Let {
|
||||||
ty: body_ty,
|
ty: body_ty,
|
||||||
|
|||||||
Reference in New Issue
Block a user