about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/builtins/mod.rs67
-rw-r--r--tvix/eval/src/value/attrs.rs8
2 files changed, 60 insertions, 15 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index b5e8bb289b..39e29580b4 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -3,29 +3,66 @@
 //! See //tvix/eval/docs/builtins.md for a some context on the
 //! available builtins in Nix.
 
-use std::collections::HashMap;
+use std::{
+    collections::{BTreeMap, HashMap},
+    rc::Rc,
+};
 
-use crate::value::{Builtin, Value};
+use crate::value::{Builtin, NixAttrs, NixString, Value};
 
-macro_rules! builtin {
-    ( $map:ident, $name:literal, $arity:literal, $body:expr ) => {
-        $map.insert($name, Value::Builtin(Builtin::new($name, $arity, $body)));
-    };
+fn pure_builtins() -> Vec<Builtin> {
+    vec![
+        Builtin::new("isNull", 1, |args| {
+            Ok(Value::Bool(matches!(args[0], Value::Null)))
+        }),
+        Builtin::new("toString", 1, |args| {
+            // TODO: toString is actually not the same as Display
+            Ok(Value::String(format!("{}", args[0]).into()))
+        }),
+    ]
+}
+
+fn builtins_set() -> NixAttrs {
+    let mut map: BTreeMap<NixString, Value> = BTreeMap::new();
+
+    for builtin in pure_builtins() {
+        map.insert(builtin.name().into(), Value::Builtin(builtin));
+    }
+
+    NixAttrs::from_map(map)
 }
 
 /// Set of Nix builtins that are globally available.
 pub fn global_builtins() -> HashMap<&'static str, Value> {
-    let mut globals = HashMap::new();
+    let builtins = builtins_set();
+    let mut globals: HashMap<&'static str, Value> = HashMap::new();
 
-    builtin!(globals, "isNull", 1, |args| Ok(Value::Bool(matches!(
-        args[0],
-        Value::Null
-    ))));
+    // known global builtins from the builtins set.
+    for global in &[
+        "abort",
+        "baseNameOf",
+        "derivation",
+        "derivationStrict",
+        "dirOf",
+        "fetchGit",
+        "fetchMercurial",
+        "fetchTarball",
+        "fromTOML",
+        "import",
+        "isNull",
+        "map",
+        "placeholder",
+        "removeAttrs",
+        "scopedImport",
+        "throw",
+        "toString",
+    ] {
+        if let Some(builtin) = builtins.select(global) {
+            globals.insert(global, builtin.clone());
+        }
+    }
 
-    builtin!(globals, "toString", 1, |args| {
-        // TODO: toString is actually not the same as Display
-        Ok(Value::String(format!("{}", args[0]).into()))
-    });
+    globals.insert("builtins", Value::Attrs(Rc::new(builtins)));
 
     globals
 }
diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs
index 319f6bdfa9..4109691992 100644
--- a/tvix/eval/src/value/attrs.rs
+++ b/tvix/eval/src/value/attrs.rs
@@ -259,6 +259,14 @@ impl NixAttrs {
 
         Ok(attrs)
     }
+
+    /// Construct an attribute set directly from a BTreeMap
+    /// representation. This is only visible inside of the crate, as
+    /// it is intended exclusively for use with the construction of
+    /// global sets for the compiler.
+    pub(crate) fn from_map(map: BTreeMap<NixString, Value>) -> Self {
+        NixAttrs(AttrsRep::Map(map))
+    }
 }
 
 // In Nix, name/value attribute pairs are frequently constructed from