diff options
author | Aspen Smith <root@gws.fyi> | 2024-07-05T03·39-0400 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-07-05T16·39+0000 |
commit | ac3d717944412b17d7dcd18006c2f9f522b1b3f7 (patch) | |
tree | 79528c039534125e5e3147a088225ed39e451193 /tvix/eval/src/compiler/scope.rs | |
parent | af933c177ad7f3bc9730cc7e51b6bfe6b86fd5ae (diff) |
feat(tvix/eval): Allow passing in an env to evaluation r/8345
Allow passing in a top-level env, a map from name to value, to evaluation. The intent is to support bound identifiers in the REPL just like upstream nix does. Getting this working involves mucking around a bit with internals - most notably, locals now only optionally have a Span (since locals don't have an easy span we can use) - and getting that working requires propagating some minor hacks to places where we currently *need* a span (and which would require too much changing now to make spans optional; my guess is that that would essentially end up making spans optional throughout the codebase). Also, some extra care has to be taken to close out the scope in the case that we do pass in an env, to avoid breaking our assumptions about the size of the stack when we return from the toplevel Change-Id: Ie475b2d3dfc72ccbf298d2a3ea28c63ac877d653 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11953 Tested-by: BuildkiteCI Autosubmit: aspen <root@gws.fyi> Reviewed-by: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/eval/src/compiler/scope.rs')
-rw-r--r-- | tvix/eval/src/compiler/scope.rs | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/tvix/eval/src/compiler/scope.rs b/tvix/eval/src/compiler/scope.rs index 892727c107c9..7b0a66004a7f 100644 --- a/tvix/eval/src/compiler/scope.rs +++ b/tvix/eval/src/compiler/scope.rs @@ -38,7 +38,7 @@ pub struct Local { name: LocalName, /// Source span at which this local was declared. - pub span: codemap::Span, + pub span: Option<codemap::Span>, /// Scope depth of this local. pub depth: usize, @@ -73,6 +73,10 @@ impl Local { LocalName::Phantom => false, } } + + pub fn is_used(&self) -> bool { + self.depth == 0 || self.used || self.is_ignored() + } } /// Represents the current position of an identifier as resolved in a scope. @@ -240,7 +244,7 @@ impl Scope { let idx = self.locals.len(); self.locals.push(Local { initialised, - span, + span: Some(span), name: LocalName::Phantom, depth: self.scope_depth, needs_finaliser: false, @@ -263,7 +267,7 @@ impl Scope { let idx = LocalIdx(self.locals.len()); self.locals.push(Local { name: LocalName::Ident(name.clone()), - span, + span: Some(span), depth: self.scope_depth, initialised: false, needs_finaliser: false, @@ -286,6 +290,23 @@ impl Scope { (idx, shadowed) } + pub fn declare_constant(&mut self, name: String) -> LocalIdx { + let idx = LocalIdx(self.locals.len()); + self.locals.push(Local { + name: LocalName::Ident(name.clone()), + span: None, + depth: 0, + initialised: true, + used: false, + needs_finaliser: false, + must_thunk: false, + }); + // We don't need to worry about shadowing for constants; they're defined at the toplevel + // always + self.by_name.insert(name, ByName::Single(idx)); + idx + } + /// Mark local as initialised after compiling its expression. pub fn mark_initialised(&mut self, idx: LocalIdx) { self.locals[idx.0].initialised = true; @@ -348,8 +369,8 @@ impl Scope { // 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); + if local.is_used() { + unused_spans.extend(local.span); } // remove the by-name index if this was a named local |