From 269788086ec7cfabe70734b9be840efa87bd3f28 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Wed, 24 Aug 2022 01:54:34 +0300 Subject: feat(tvix/eval): compile lambda definitions Compiles lambda definitions of the simple form (i.e. without formals arguments) and emits them as constants like any other value. This does not yet implement actually invoking these functions in the VM. Change-Id: Ie1e0a13220b68c1728be229b875f0992e685c5ef Reviewed-on: https://cl.tvl.fyi/c/depot/+/6247 Tested-by: BuildkiteCI Reviewed-by: grfn --- tvix/eval/src/compiler.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) 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. -- cgit 1.4.1