about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-23T21·01+0300
committertazjin <tazjin@tvl.su>2022-09-01T21·56+0000
commitfc865eb157380fa5d2c779bd0cc207b73a514572 (patch)
tree42d5462ce13bffa4ede04dba69aa642586e09026 /tvix/eval
parent9d1451773b543b076d33c8eadcd65d1ef6483f9f (diff)
refactor(tvix/eval): introduce LambdaCtx structure to compiler r/4580
This structure carries context about the lambda currently being
compiled (which may well be the top-level lambda of an input AST).

Using the indirection helpers in the compiler, things like the scope,
code and constants of the function being compiled are now taken from
the current lambda context instead.

Change-Id: If5f864d826c2e72855cee4b728ea1830e9b5ac06
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6246
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/compiler.rs35
1 files changed, 28 insertions, 7 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs
index 2167dce77d53..bbf97ccaedf0 100644
--- a/tvix/eval/src/compiler.rs
+++ b/tvix/eval/src/compiler.rs
@@ -89,10 +89,23 @@ struct Scope {
     poisoned_null: usize,
 }
 
-struct Compiler {
+/// Represents the lambda currently being compiled.
+struct LambdaCtx {
     lambda: Lambda,
     scope: Scope,
+}
+
+impl LambdaCtx {
+    fn new() -> Self {
+        LambdaCtx {
+            lambda: Lambda::new_anonymous(),
+            scope: Default::default(),
+        }
+    }
+}
 
+struct Compiler {
+    contexts: Vec<LambdaCtx>,
     warnings: Vec<EvalWarning>,
     errors: Vec<Error>,
     root_dir: PathBuf,
@@ -101,17 +114,26 @@ struct Compiler {
 // Helper functions for emitting code and metadata to the internal
 // structures of the compiler.
 impl Compiler {
+    fn context(&self) -> &LambdaCtx {
+        &self.contexts[self.contexts.len() - 1]
+    }
+
+    fn context_mut(&mut self) -> &mut LambdaCtx {
+        let idx = self.contexts.len() - 1;
+        &mut self.contexts[idx]
+    }
+
     fn chunk(&mut self) -> &mut Chunk {
-        std::rc::Rc::<Chunk>::get_mut(self.lambda.chunk())
+        std::rc::Rc::<Chunk>::get_mut(self.context_mut().lambda.chunk())
             .expect("compiler flaw: long-lived chunk reference")
     }
 
     fn scope(&self) -> &Scope {
-        &self.scope
+        &self.context().scope
     }
 
     fn scope_mut(&mut self) -> &mut Scope {
-        &mut self.scope
+        &mut self.context_mut().scope
     }
 
     fn emit_constant(&mut self, value: Value) {
@@ -915,16 +937,15 @@ pub fn compile(expr: ast::Expr, location: Option<PathBuf>) -> EvalResult<Compila
 
     let mut c = Compiler {
         root_dir,
-        lambda: Lambda::new_anonymous(),
+        contexts: vec![LambdaCtx::new()],
         warnings: vec![],
         errors: vec![],
-        scope: Default::default(),
     };
 
     c.compile(expr);
 
     Ok(CompilationResult {
-        lambda: c.lambda,
+        lambda: c.contexts.pop().unwrap().lambda,
         warnings: c.warnings,
         errors: c.errors,
     })