refactor(tvix/eval): return a lambda from the compiler

Changes the internal compiler plumbing to not just return a chunk of
code, but the same chunk wrapped inside of a lambda value.

This is one more step towards compiling runtime lambdas.

Change-Id: If0035f8e65a2970c5ae123fc068a2396e1d8fd72
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6240
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2022-08-23 22:54:25 +03:00 committed by tazjin
parent 4715f9a3a0
commit 6f31c895ff
5 changed files with 28 additions and 16 deletions

View file

@ -1,7 +1,7 @@
use crate::opcode::{CodeIdx, ConstantIdx, OpCode};
use crate::value::Value;
#[derive(Debug, Default)]
#[derive(Clone, Debug, Default)]
pub struct Chunk {
pub code: Vec<OpCode>,
pub constants: Vec<Value>,

View file

@ -21,14 +21,14 @@ use std::path::{Path, PathBuf};
use crate::chunk::Chunk;
use crate::errors::{Error, ErrorKind, EvalResult};
use crate::opcode::{CodeIdx, OpCode};
use crate::value::Value;
use crate::value::{Lambda, Value};
use crate::warnings::{EvalWarning, WarningKind};
/// Represents the result of compiling a piece of Nix code. If
/// compilation was successful, the resulting bytecode can be passed
/// to the VM.
pub struct CompilationResult {
pub chunk: Chunk,
pub lambda: Lambda,
pub warnings: Vec<EvalWarning>,
pub errors: Vec<Error>,
}
@ -90,7 +90,7 @@ struct Scope {
}
struct Compiler {
chunk: Chunk,
lambda: Lambda,
scope: Scope,
warnings: Vec<EvalWarning>,
@ -102,7 +102,8 @@ struct Compiler {
// structures of the compiler.
impl Compiler {
fn chunk(&mut self) -> &mut Chunk {
&mut self.chunk
std::rc::Rc::<Chunk>::get_mut(self.lambda.chunk())
.expect("compiler flaw: long-lived chunk reference")
}
fn emit_constant(&mut self, value: Value) {
@ -910,7 +911,7 @@ pub fn compile(expr: ast::Expr, location: Option<PathBuf>) -> EvalResult<Compila
let mut c = Compiler {
root_dir,
chunk: Chunk::default(),
lambda: Lambda::new_anonymous(),
warnings: vec![],
errors: vec![],
scope: Default::default(),
@ -919,7 +920,7 @@ pub fn compile(expr: ast::Expr, location: Option<PathBuf>) -> EvalResult<Compila
c.compile(expr);
Ok(CompilationResult {
chunk: c.chunk,
lambda: c.lambda,
warnings: c.warnings,
errors: c.errors,
})

View file

@ -31,7 +31,7 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> {
let result = crate::compiler::compile(root_expr, location)?;
#[cfg(feature = "disassembler")]
crate::disassembler::disassemble_chunk(&result.chunk);
crate::disassembler::disassemble_chunk(&result.lambda.chunk);
for warning in result.warnings {
eprintln!(
@ -49,5 +49,5 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> {
return Err(err.clone());
}
crate::vm::run_chunk(result.chunk)
crate::vm::run_lambda(result.lambda)
}

View file

@ -3,10 +3,21 @@ use std::rc::Rc;
use crate::chunk::Chunk;
use super::NixString;
#[derive(Clone, Debug)]
pub struct Lambda {
name: Option<NixString>,
chunk: Rc<Chunk>,
// name: Option<NixString>,
pub(crate) chunk: Rc<Chunk>,
}
impl Lambda {
pub fn new_anonymous() -> Self {
Lambda {
// name: None,
chunk: Default::default(),
}
}
pub fn chunk(&mut self) -> &mut Rc<Chunk> {
&mut self.chunk
}
}

View file

@ -7,7 +7,7 @@ use crate::{
chunk::Chunk,
errors::{ErrorKind, EvalResult},
opcode::OpCode,
value::{NixAttrs, NixList, Value},
value::{Lambda, NixAttrs, NixList, Value},
};
#[cfg(feature = "disassembler")]
@ -365,9 +365,9 @@ impl VM {
}
}
pub fn run_chunk(chunk: Chunk) -> EvalResult<Value> {
pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> {
let mut vm = VM {
chunk,
chunk: Rc::<Chunk>::try_unwrap(lambda.chunk).unwrap(),
ip: 0,
stack: vec![],
with_stack: vec![],