diff options
Diffstat (limited to 'tvix/eval/src/builtins/impure.rs')
-rw-r--r-- | tvix/eval/src/builtins/impure.rs | 111 |
1 files changed, 11 insertions, 100 deletions
diff --git a/tvix/eval/src/builtins/impure.rs b/tvix/eval/src/builtins/impure.rs index d371d877977d..e8c032cc77e6 100644 --- a/tvix/eval/src/builtins/impure.rs +++ b/tvix/eval/src/builtins/impure.rs @@ -2,20 +2,17 @@ use builtin_macros::builtins; use smol_str::SmolStr; use std::{ - collections::BTreeMap, env, - rc::{Rc, Weak}, + rc::Rc, time::{SystemTime, UNIX_EPOCH}, }; use crate::{ - compiler::GlobalsMap, errors::ErrorKind, io::FileType, - observer::NoOpObserver, - value::{Builtin, BuiltinArgument, NixAttrs, Thunk}, + value::{NixAttrs, Thunk}, vm::VM, - SourceCode, Value, + Value, }; #[builtins] @@ -67,13 +64,13 @@ mod impure_builtins { /// Return all impure builtins, that is all builtins which may perform I/O /// outside of the VM and so cannot be used in all contexts (e.g. WASM). -pub(super) fn builtins() -> BTreeMap<&'static str, Value> { - let mut map: BTreeMap<&'static str, Value> = impure_builtins::builtins() +pub fn impure_builtins() -> Vec<(&'static str, Value)> { + let mut result = impure_builtins::builtins() .into_iter() - .map(|b| (b.name(), Value::Builtin(b))) - .collect(); + .map(super::builtin_tuple) + .collect::<Vec<_>>(); - map.insert( + result.push(( "storeDir", Value::Thunk(Thunk::new_suspended_native(Rc::new(Box::new( |vm: &mut VM| match vm.io().store_dir() { @@ -81,7 +78,7 @@ pub(super) fn builtins() -> BTreeMap<&'static str, Value> { Some(dir) => Ok(Value::String(dir.into())), }, )))), - ); + )); // currentTime pins the time at which evaluation was started { @@ -92,94 +89,8 @@ pub(super) fn builtins() -> BTreeMap<&'static str, Value> { Err(err) => -(err.duration().as_secs() as i64), }; - map.insert("currentTime", Value::Integer(seconds)); + result.push(("currentTime", Value::Integer(seconds))); } - map -} - -/// Constructs and inserts the `import` builtin. This builtin is special in that -/// it needs to capture the [crate::SourceCode] structure to correctly track -/// source code locations while invoking a compiler. -// TODO: need to be able to pass through a CompilationObserver, too. -pub fn builtins_import(globals: &Weak<GlobalsMap>, source: SourceCode) -> Builtin { - // This (very cheap, once-per-compiler-startup) clone exists - // solely in order to keep the borrow checker happy. It - // resolves the tension between the requirements of - // Rc::new_cyclic() and Builtin::new() - let globals = globals.clone(); - - Builtin::new( - "import", - &[BuiltinArgument { - strict: true, - name: "path", - }], - None, - move |mut args: Vec<Value>, vm: &mut VM| { - let mut path = super::coerce_value_to_path(&args.pop().unwrap(), vm)?; - if path.is_dir() { - path.push("default.nix"); - } - - let current_span = vm.current_light_span(); - - if let Some(cached) = vm.import_cache.get(&path) { - return Ok(cached.clone()); - } - - let contents = vm.io().read_to_string(path.clone())?; - - let parsed = rnix::ast::Root::parse(&contents); - let errors = parsed.errors(); - - let file = source.add_file(path.to_string_lossy().to_string(), contents); - - if !errors.is_empty() { - return Err(ErrorKind::ImportParseError { - path, - file, - errors: errors.to_vec(), - }); - } - - let result = crate::compiler::compile( - &parsed.tree().expr().unwrap(), - Some(path.clone()), - file, - // The VM must ensure that a strong reference to the - // globals outlives any self-references (which are - // weak) embedded within the globals. If the - // expect() below panics, it means that did not - // happen. - globals - .upgrade() - .expect("globals dropped while still in use"), - &mut NoOpObserver::default(), - ) - .map_err(|err| ErrorKind::ImportCompilerError { - path: path.clone(), - errors: vec![err], - })?; - - if !result.errors.is_empty() { - return Err(ErrorKind::ImportCompilerError { - path, - errors: result.errors, - }); - } - - // Compilation succeeded, we can construct a thunk from whatever it spat - // out and return that. - let res = Value::Thunk(Thunk::new_suspended(result.lambda, current_span)); - - vm.import_cache.insert(path, res.clone()); - - for warning in result.warnings { - vm.push_warning(warning); - } - - Ok(res) - }, - ) + result } |