about summary refs log tree commit diff
path: root/tvix/eval/src/compiler.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/compiler.rs')
-rw-r--r--tvix/eval/src/compiler.rs41
1 files changed, 40 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs
index bbf97ccaed..bb751e4f92 100644
--- a/tvix/eval/src/compiler.rs
+++ b/tvix/eval/src/compiler.rs
@@ -160,13 +160,13 @@ impl Compiler {
             ast::Expr::LetIn(let_in) => self.compile_let_in(let_in),
             ast::Expr::Ident(ident) => self.compile_ident(ident),
             ast::Expr::With(with) => self.compile_with(with),
+            ast::Expr::Lambda(lambda) => self.compile_lambda(lambda),
 
             // Parenthesized expressions are simply unwrapped, leaving
             // their value on the stack.
             ast::Expr::Paren(paren) => self.compile(paren.expr().unwrap()),
 
             ast::Expr::LegacyLet(_) => todo!("legacy let"),
-            ast::Expr::Lambda(_) => todo!("function definition"),
             ast::Expr::Apply(_) => todo!("function application"),
 
             ast::Expr::Root(_) => unreachable!("there cannot be more than one root"),
@@ -735,6 +735,45 @@ impl Compiler {
         self.compile(node.body().unwrap());
     }
 
+    fn compile_lambda(&mut self, node: ast::Lambda) {
+        // Open new lambda context in compiler, which has its own
+        // scope etc.
+        self.contexts.push(LambdaCtx::new());
+        self.begin_scope();
+
+        // Compile the function itself
+        match node.param().unwrap() {
+            ast::Param::Pattern(_) => todo!("formals function definitions"),
+            ast::Param::IdentParam(param) => {
+                let name = param
+                    .ident()
+                    .unwrap()
+                    .ident_token()
+                    .unwrap()
+                    .text()
+                    .to_string();
+
+                self.declare_local(param.syntax().clone(), name);
+            }
+        }
+
+        self.compile(node.body().unwrap());
+        self.end_scope();
+
+        // TODO: determine and insert enclosing name, if available.
+
+        // Pop the lambda context back off, and emit the finished
+        // lambda as a constant.
+        let compiled = self.contexts.pop().unwrap();
+
+        #[cfg(feature = "disassembler")]
+        {
+            crate::disassembler::disassemble_chunk(&compiled.lambda.chunk);
+        }
+
+        self.emit_constant(Value::Lambda(compiled.lambda));
+    }
+
     /// Emit the literal string value of an identifier. Required for
     /// several operations related to attribute sets, where
     /// identifiers are used as string keys.