diff options
author | Vincent Ambo <mail@tazj.in> | 2022-09-23T16·04+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-28T00·09+0000 |
commit | 14147e9b5f1f16b2a713e2aee58ea201db0e0308 (patch) | |
tree | 02eb36a638ee2407b6deb5a7ccac7c8ee9fa4e46 /tvix/eval | |
parent | 6d60c22b2a3d514ee6f3adfe36f94146d9a7bc1c (diff) |
refactor(tvix/eval): introduce type to track kind of bindings r/4976
As part of the unification of binding logic between different carriers of bindings, we need to track which kind of bindings we are dealing with (attribute set? recursive scope? ...) to correctly emit keys and declare identifiers in the locals stack. Right now this changes no functionality as `BindingsKind::Attrs` is not yet used (only RecAttrs and LetIn, which was previously represented by the `rec_attrs` boolean). Change-Id: Id2ac27894079ab584521cb568d75c124f7bf2403 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6771 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval')
-rw-r--r-- | tvix/eval/src/compiler/bindings.rs | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs index b09989bc00e2..7ee8ef8a84f0 100644 --- a/tvix/eval/src/compiler/bindings.rs +++ b/tvix/eval/src/compiler/bindings.rs @@ -32,6 +32,25 @@ struct TrackedBinding { binding: Binding, } +/// What kind of bindings scope is being compiled? +#[derive(Clone, Copy, PartialEq)] +enum BindingsKind { + /// Standard `let ... in ...`-expression. + LetIn, + + /// Non-recursive attribute set. + Attrs, + + /// Recursive attribute set. + RecAttrs, +} + +impl BindingsKind { + fn is_attrs(&self) -> bool { + matches!(self, BindingsKind::Attrs | BindingsKind::RecAttrs) + } +} + /// AST-traversing functions related to bindings. impl Compiler<'_> { fn compile_inherits<N>( @@ -39,7 +58,7 @@ impl Compiler<'_> { slot: LocalIdx, count: &mut usize, bindings: &mut Vec<TrackedBinding>, - rec_attrs: bool, + kind: BindingsKind, node: &N, ) where N: ToSpan + ast::HasEntry, @@ -57,7 +76,7 @@ impl Compiler<'_> { // Within a `let` binding, inheriting from the outer // scope is a no-op *if* the identifier can be // statically resolved. - None if !rec_attrs && !self.scope().has_with() => { + None if !kind.is_attrs() && !self.scope().has_with() => { self.emit_warning(&inherit, WarningKind::UselessInherit); continue; } @@ -77,7 +96,7 @@ impl Compiler<'_> { // If the identifier resolves statically in a // `let`, it has precedence over dynamic // bindings, and the inherit is useless. - if !rec_attrs + if kind == BindingsKind::LetIn && matches!( self.scope_mut().resolve_local(&name), LocalPosition::Known(_) @@ -87,7 +106,7 @@ impl Compiler<'_> { continue; } - if rec_attrs { + if kind == BindingsKind::RecAttrs { self.emit_constant(Value::String(SmolStr::new(&name).into()), &attr); let span = self.span_for(&attr); self.scope_mut().declare_phantom(span, true); @@ -118,7 +137,7 @@ impl Compiler<'_> { // Begin with the inherit (from)s since they all become a thunk anyway for (from, name, span) in inherit_froms { - let key_slot = if rec_attrs { + let key_slot = if kind.is_attrs() { Some(KeySlot { slot: self.scope_mut().declare_phantom(span, false), name: SmolStr::new(&name), @@ -358,7 +377,7 @@ impl Compiler<'_> { self.scope_mut().begin_scope(); if node.rec_token().is_some() { - let count = self.compile_recursive_scope(slot, true, &node); + let count = self.compile_recursive_scope(slot, BindingsKind::RecAttrs, &node); self.push_op(OpCode::OpAttrs(Count(count)), &node); } else { let mut count = self.compile_inherit_attrs(slot, node.inherits()); @@ -376,7 +395,7 @@ impl Compiler<'_> { self.scope_mut().end_scope(); } - fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, rec_attrs: bool, node: &N) -> usize + fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, kind: BindingsKind, node: &N) -> usize where N: ToSpan + ast::HasEntry, { @@ -386,7 +405,7 @@ impl Compiler<'_> { // Vector to track these observed bindings. let mut bindings: Vec<TrackedBinding> = vec![]; - self.compile_inherits(slot, &mut count, &mut bindings, rec_attrs, node); + self.compile_inherits(slot, &mut count, &mut bindings, kind, node); // Declare all regular bindings for entry in node.attrpath_values() { @@ -408,7 +427,7 @@ impl Compiler<'_> { continue; } - let key_slot = if rec_attrs { + let key_slot = if kind.is_attrs() { let span = self.span_for(&entry.attrpath().unwrap()); Some(KeySlot { slot: self.scope_mut().declare_phantom(span, false), @@ -486,7 +505,7 @@ impl Compiler<'_> { /// simply pushed on the stack and their indices noted in the /// entries vector. pub(super) fn compile_let_in(&mut self, slot: LocalIdx, node: ast::LetIn) { - self.compile_recursive_scope(slot, false, &node); + self.compile_recursive_scope(slot, BindingsKind::LetIn, &node); // Deal with the body, then clean up the locals afterwards. self.compile(slot, node.body().unwrap()); @@ -496,7 +515,7 @@ impl Compiler<'_> { pub(super) fn compile_legacy_let(&mut self, slot: LocalIdx, node: ast::LegacyLet) { self.emit_warning(&node, WarningKind::DeprecatedLegacyLet); self.scope_mut().begin_scope(); - self.compile_recursive_scope(slot, true, &node); + self.compile_recursive_scope(slot, BindingsKind::RecAttrs, &node); self.push_op(OpCode::OpAttrs(Count(node.entries().count())), &node); self.emit_constant(Value::String(SmolStr::new_inline("body").into()), &node); self.push_op(OpCode::OpAttrsSelect, &node); |