refactor(tvix/eval): introduce Closure struct in Value type
This struct will carry the upvalue machinery in addition to the lambda itself. For now, all lambdas are wrapped in closures (though technically analysis of the environment can later remove innermost Closure wrapper, but this optimisation may not be worth it). Change-Id: If2b68549ec1ea4ab838fdc47a2181c694ac937f2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6269 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
af9dca3663
commit
6ce2c666c3
5 changed files with 17 additions and 10 deletions
|
@ -44,7 +44,7 @@ fn pure_builtins() -> Vec<Builtin> {
|
||||||
}),
|
}),
|
||||||
Builtin::new("isFunction", 1, |args| {
|
Builtin::new("isFunction", 1, |args| {
|
||||||
Ok(Value::Bool(match args[0] {
|
Ok(Value::Bool(match args[0] {
|
||||||
Value::Lambda(_) => true,
|
Value::Closure(_) => true,
|
||||||
Value::Builtin(_) => true,
|
Value::Builtin(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -23,7 +23,7 @@ use std::rc::Rc;
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::errors::{Error, ErrorKind, EvalResult};
|
use crate::errors::{Error, ErrorKind, EvalResult};
|
||||||
use crate::opcode::{CodeIdx, OpCode};
|
use crate::opcode::{CodeIdx, OpCode};
|
||||||
use crate::value::{Lambda, Value};
|
use crate::value::{Closure, Lambda, Value};
|
||||||
use crate::warnings::{EvalWarning, WarningKind};
|
use crate::warnings::{EvalWarning, WarningKind};
|
||||||
|
|
||||||
/// Represents the result of compiling a piece of Nix code. If
|
/// Represents the result of compiling a piece of Nix code. If
|
||||||
|
@ -822,7 +822,9 @@ impl Compiler {
|
||||||
crate::disassembler::disassemble_chunk(&compiled.lambda.chunk);
|
crate::disassembler::disassemble_chunk(&compiled.lambda.chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit_constant(Value::Lambda(compiled.lambda));
|
self.emit_constant(Value::Closure(Closure {
|
||||||
|
lambda: compiled.lambda,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_apply(&mut self, node: ast::Apply) {
|
fn compile_apply(&mut self, node: ast::Apply) {
|
||||||
|
|
|
@ -21,3 +21,8 @@ impl Lambda {
|
||||||
&mut self.chunk
|
&mut self.chunk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Closure {
|
||||||
|
pub lambda: Lambda,
|
||||||
|
}
|
|
@ -5,14 +5,14 @@ use std::{fmt::Display, path::PathBuf};
|
||||||
|
|
||||||
mod attrs;
|
mod attrs;
|
||||||
mod builtin;
|
mod builtin;
|
||||||
mod lambda;
|
mod function;
|
||||||
mod list;
|
mod list;
|
||||||
mod string;
|
mod string;
|
||||||
|
|
||||||
use crate::errors::{ErrorKind, EvalResult};
|
use crate::errors::{ErrorKind, EvalResult};
|
||||||
pub use attrs::NixAttrs;
|
pub use attrs::NixAttrs;
|
||||||
pub use builtin::Builtin;
|
pub use builtin::Builtin;
|
||||||
pub use lambda::Lambda;
|
pub use function::{Closure, Lambda};
|
||||||
pub use list::NixList;
|
pub use list::NixList;
|
||||||
pub use string::NixString;
|
pub use string::NixString;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ pub enum Value {
|
||||||
Path(PathBuf),
|
Path(PathBuf),
|
||||||
Attrs(Rc<NixAttrs>),
|
Attrs(Rc<NixAttrs>),
|
||||||
List(NixList),
|
List(NixList),
|
||||||
Lambda(Lambda),
|
Closure(Closure),
|
||||||
Builtin(Builtin),
|
Builtin(Builtin),
|
||||||
|
|
||||||
// Internal values that, while they technically exist at runtime,
|
// Internal values that, while they technically exist at runtime,
|
||||||
|
@ -52,7 +52,7 @@ impl Value {
|
||||||
Value::Path(_) => "path",
|
Value::Path(_) => "path",
|
||||||
Value::Attrs(_) => "set",
|
Value::Attrs(_) => "set",
|
||||||
Value::List(_) => "list",
|
Value::List(_) => "list",
|
||||||
Value::Lambda(_) | Value::Builtin(_) => "lambda",
|
Value::Closure(_) | Value::Builtin(_) => "lambda",
|
||||||
|
|
||||||
// Internal types
|
// Internal types
|
||||||
Value::AttrPath(_) | Value::Blackhole | Value::NotFound => "internal",
|
Value::AttrPath(_) | Value::Blackhole | Value::NotFound => "internal",
|
||||||
|
@ -130,7 +130,7 @@ impl Display for Value {
|
||||||
Value::Path(p) => p.display().fmt(f),
|
Value::Path(p) => p.display().fmt(f),
|
||||||
Value::Attrs(attrs) => attrs.fmt(f),
|
Value::Attrs(attrs) => attrs.fmt(f),
|
||||||
Value::List(list) => list.fmt(f),
|
Value::List(list) => list.fmt(f),
|
||||||
Value::Lambda(_) => f.write_str("lambda"), // TODO: print position
|
Value::Closure(_) => f.write_str("lambda"), // TODO: print position
|
||||||
Value::Builtin(builtin) => builtin.fmt(f),
|
Value::Builtin(builtin) => builtin.fmt(f),
|
||||||
|
|
||||||
// Nix prints floats with a maximum precision of 5 digits
|
// Nix prints floats with a maximum precision of 5 digits
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
chunk::Chunk,
|
chunk::Chunk,
|
||||||
errors::{ErrorKind, EvalResult},
|
errors::{ErrorKind, EvalResult},
|
||||||
opcode::OpCode,
|
opcode::OpCode,
|
||||||
value::{Lambda, NixAttrs, NixList, Value},
|
value::{Closure, Lambda, NixAttrs, NixList, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "disassembler")]
|
#[cfg(feature = "disassembler")]
|
||||||
|
@ -357,7 +357,7 @@ impl VM {
|
||||||
OpCode::OpCall => {
|
OpCode::OpCall => {
|
||||||
let callable = self.pop();
|
let callable = self.pop();
|
||||||
match callable {
|
match callable {
|
||||||
Value::Lambda(lambda) => self.call(lambda, 1),
|
Value::Closure(Closure { lambda }) => self.call(lambda, 1),
|
||||||
Value::Builtin(builtin) => {
|
Value::Builtin(builtin) => {
|
||||||
let arg = self.pop();
|
let arg = self.pop();
|
||||||
let result = builtin.apply(arg)?;
|
let result = builtin.apply(arg)?;
|
||||||
|
|
Loading…
Add table
Reference in a new issue