about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-28T12·41+0300
committertazjin <tazjin@tvl.su>2022-09-06T07·45+0000
commit900a92935d458fff6c4117ba29558ac8aeb529f9 (patch)
treebee489898d2abd4f117228e0990ec38775bab1b3
parent47b356286751bff8f41930761a402564d54d1898 (diff)
refactor(tvix/eval): declare all locals before compiling them r/4662
This actually makes things full-circle, as this tree already had this
implementation once before all the other required components were in
place.

With this commit, the compiler can resolve recursive upvalues within
the same scope (though they will not yet work at runtime).

Change-Id: I6267e477d08f367257c3a6dde054b880d7b47211
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6326
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
-rw-r--r--tvix/eval/src/compiler/mod.rs13
1 files changed, 12 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index ca1098af64..fb08662da8 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -654,6 +654,9 @@ impl Compiler {
 
         self.compile_let_inherit(node.inherits());
 
+        // First pass to ensure that all identifiers are known;
+        // required for resolving recursion.
+        let mut entries: Vec<(String, rnix::ast::Expr)> = vec![];
         for entry in node.attrpath_values() {
             let mut path = match normalise_ident_path(entry.attrpath().unwrap().attrs()) {
                 Ok(p) => p,
@@ -669,7 +672,15 @@ impl Compiler {
 
             let name = path.pop().unwrap();
             self.declare_local(entry.attrpath().unwrap().syntax().clone(), &name);
-            self.compile(entry.value().unwrap());
+            entries.push((name, entry.value().unwrap()));
+        }
+
+        // Second pass to place the values in the correct stack slots.
+        for (name, value) in entries.into_iter() {
+            self.compile(value);
+
+            // Any code after this point will observe the value in the
+            // right stack slot, so mark it as initialised.
             self.mark_initialised(&name);
         }