diff options
author | Vincent Ambo <mail@tazj.in> | 2022-10-04T15·20+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-10-06T15·22+0000 |
commit | 44acffc688aa61c363d050e28424041dc9cd0e33 (patch) | |
tree | 92ad69057b93304830d020cc8fadf16c439c4230 /tvix/eval/src/value/builtin.rs | |
parent | c1884919fcfd5f83c54f7729a3b5c347c22fdd31 (diff) |
refactor(tvix/eval): builtins now contain closures r/5040
For some upcoming builtins (notably, import) we need to capture arguments in the builtin's implementation. To allow this, we can no longer use function pointers for builtins, but must use a reference-counted closure object instead. Unfortunately this adds an extra pointer operation to every builtin call. We should benchmark this later against having a split builtin representation. Change-Id: I109d98d0e25998870542f47573eb1ec2e546f2a2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6856 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
Diffstat (limited to 'tvix/eval/src/value/builtin.rs')
-rw-r--r-- | tvix/eval/src/value/builtin.rs | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/tvix/eval/src/value/builtin.rs b/tvix/eval/src/value/builtin.rs index ca9924c5d5aa..fc8043176211 100644 --- a/tvix/eval/src/value/builtin.rs +++ b/tvix/eval/src/value/builtin.rs @@ -7,10 +7,13 @@ use crate::{errors::ErrorKind, vm::VM}; use super::Value; -use std::fmt::{Debug, Display}; +use std::{ + fmt::{Debug, Display}, + rc::Rc, +}; -/// Function pointer type for builtins implemented directly by backing -/// Rust code. +/// Trait for closure types of builtins implemented directly by +/// backing Rust code. /// /// Builtins declare their arity and are passed a vector with the /// right number of arguments. Additionally, as they might have to @@ -19,7 +22,8 @@ use std::fmt::{Debug, Display}; /// /// Errors returned from a builtin will be annotated with the location /// of the call to the builtin. -pub type BuiltinFn = fn(arg: Vec<Value>, vm: &mut VM) -> Result<Value, ErrorKind>; +pub trait BuiltinFn: Fn(Vec<Value>, &mut VM) -> Result<Value, ErrorKind> {} +impl<F: Fn(Vec<Value>, &mut VM) -> Result<Value, ErrorKind>> BuiltinFn for F {} /// Represents a single built-in function which directly executes Rust /// code that operates on a Nix value. @@ -40,18 +44,22 @@ pub struct Builtin { /// or 2) and whether they need to be forced. `true` causes the /// corresponding argument to be forced before `func` is called. strict_args: &'static [bool], - func: BuiltinFn, + func: Rc<dyn BuiltinFn>, /// Partially applied function arguments. partials: Vec<Value>, } impl Builtin { - pub fn new(name: &'static str, strict_args: &'static [bool], func: BuiltinFn) -> Self { + pub fn new<F: BuiltinFn + 'static>( + name: &'static str, + strict_args: &'static [bool], + func: F, + ) -> Self { Builtin { name, strict_args, - func, + func: Rc::new(func), partials: vec![], } } |