refactor(tvix/eval): encapsulate scope cleanup logic in module
Moves the logic for removing tracked locals from a given scope from the compiler's locals list, and leaves only the actual compiler-related stuff (emitting warnings, cleaning up locals at runtime) in the compiler itself. Change-Id: I9da6eb54967f0a7775f624d602fe11be4c7ed5c4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6466 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
27e69503a7
commit
9da99af860
2 changed files with 55 additions and 37 deletions
|
|
@ -188,11 +188,11 @@ impl Scope {
|
|||
self.poisoned_tokens.contains_key(name)
|
||||
}
|
||||
|
||||
/// "Unpoison" tokens that were poisoned at a given depth. Used
|
||||
/// when scopes are closed.
|
||||
pub fn unpoison(&mut self, depth: usize) {
|
||||
/// "Unpoison" tokens that were poisoned at the current depth.
|
||||
/// Used when scopes are closed.
|
||||
fn unpoison(&mut self) {
|
||||
self.poisoned_tokens
|
||||
.retain(|_, poisoned_at| *poisoned_at != depth);
|
||||
.retain(|_, poisoned_at| *poisoned_at != self.scope_depth);
|
||||
}
|
||||
|
||||
/// Increase the `with`-stack size of this scope.
|
||||
|
|
@ -284,4 +284,45 @@ impl Scope {
|
|||
|
||||
StackIdx(idx.0 - uninitialised_count)
|
||||
}
|
||||
|
||||
/// Decrease the scope depth and remove all locals still tracked
|
||||
/// for the current scope.
|
||||
///
|
||||
/// Returns the count of locals that were dropped while marked as
|
||||
/// initialised (used by the compiler to determine whether to emit
|
||||
/// scope cleanup operations), as well as the spans of the
|
||||
/// definitions of unused locals (used by the compiler to emit
|
||||
/// unused binding warnings).
|
||||
pub fn end_scope(&mut self) -> (usize, Vec<codemap::Span>) {
|
||||
debug_assert!(self.scope_depth != 0, "can not end top scope");
|
||||
|
||||
// If this scope poisoned any builtins or special identifiers,
|
||||
// they need to be reset.
|
||||
self.unpoison();
|
||||
|
||||
let mut pops = 0;
|
||||
let mut unused_spans = vec![];
|
||||
|
||||
// TL;DR - iterate from the back while things belonging to the
|
||||
// ended scope still exist.
|
||||
while self.locals.last().unwrap().depth == self.scope_depth {
|
||||
if let Some(local) = self.locals.pop() {
|
||||
// pop the local from the stack if it was actually
|
||||
// initialised
|
||||
if local.initialised {
|
||||
pops += 1;
|
||||
}
|
||||
|
||||
// analyse whether the local was accessed during its
|
||||
// lifetime, and emit a warning otherwise (unless the
|
||||
// user explicitly chose to ignore it by prefixing the
|
||||
// identifier with `_`)
|
||||
if !local.used && !local.is_ignored() {
|
||||
unused_spans.push(local.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(pops, unused_spans)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue