about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-27T14·06+0300
committertazjin <tazjin@tvl.su>2022-09-04T17·40+0000
commit00aeb6dfaf97c515b155387fc7de27429cf86f74 (patch)
tree790b098be59f3b1694a6209ede916f6bd7dd66e2
parent33cde1422e473770ab0ca30759ece618cb4c3680 (diff)
refactor(tvix/eval): introduce Depth enum to track variable status r/4636
This does not yet change anything semantically, but will be useful for
resolving simple cases of self-recursion etc.

Change-Id: I139ecb7e4a8a81193774392a96e73e0ea6b9f85d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6300
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
-rw-r--r--tvix/eval/src/compiler/mod.rs30
1 files changed, 26 insertions, 4 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index f8b9ccc460..38eaddddc1 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -36,6 +36,26 @@ pub struct CompilationOutput {
     pub errors: Vec<Error>,
 }
 
+/// Represents the initialisation status of a variable, tracking
+/// whether it is only known or also already defined.
+enum Depth {
+    /// Variable is defined and located at the given depth.
+    At(usize),
+
+    /// Variable is known but not yet defined.
+    Unitialised,
+}
+
+impl Depth {
+    /// Does this variable live above the other given depth?
+    fn above(&self, theirs: usize) -> bool {
+        match self {
+            Depth::Unitialised => false,
+            Depth::At(ours) => *ours > theirs,
+        }
+    }
+}
+
 /// Represents a single local already known to the compiler.
 struct Local {
     // Definition name, which can be different kinds of tokens (plain
@@ -47,7 +67,7 @@ struct Local {
     node: Option<rnix::SyntaxNode>,
 
     // Scope depth of this local.
-    depth: usize,
+    depth: Depth,
 
     // Phantom locals are not actually accessible by users (e.g.
     // intermediate values used for `with`).
@@ -948,7 +968,9 @@ impl Compiler {
         // TL;DR - iterate from the back while things belonging to the
         // ended scope still exist.
         while !self.scope().locals.is_empty()
-            && self.scope().locals[self.scope().locals.len() - 1].depth > self.scope().scope_depth
+            && self.scope().locals[self.scope().locals.len() - 1]
+                .depth
+                .above(self.scope().scope_depth)
         {
             pops += 1;
 
@@ -992,8 +1014,8 @@ impl Compiler {
         }
 
         self.scope_mut().locals.push(Local {
-            depth,
             name,
+            depth: Depth::At(depth),
             node: Some(node),
             phantom: false,
             used: false,
@@ -1003,7 +1025,7 @@ impl Compiler {
     fn declare_phantom(&mut self) {
         let depth = self.scope().scope_depth;
         self.scope_mut().locals.push(Local {
-            depth,
+            depth: Depth::At(depth),
             name: "".into(),
             node: None,
             phantom: true,