diff options
-rw-r--r-- | corp/tvixbolt/src/main.rs | 4 | ||||
-rw-r--r-- | tvix/eval/src/builtins/impure.rs | 8 | ||||
-rw-r--r-- | tvix/eval/src/compiler/mod.rs | 14 | ||||
-rw-r--r-- | tvix/eval/src/eval.rs | 20 |
4 files changed, 32 insertions, 14 deletions
diff --git a/corp/tvixbolt/src/main.rs b/corp/tvixbolt/src/main.rs index a389a33f04ed..f81ae070a2ce 100644 --- a/corp/tvixbolt/src/main.rs +++ b/corp/tvixbolt/src/main.rs @@ -1,4 +1,6 @@ +use std::cell::RefCell; use std::fmt::Write; +use std::rc::Rc; use serde::{Deserialize, Serialize}; use tvix_eval::observer::TracingObserver; @@ -256,7 +258,7 @@ fn eval(trace: bool, code: &str) -> Output { &root_expr, Some("/nixbolt".into()), file.clone(), - tvix_eval::global_builtins(), + Rc::new(RefCell::new(tvix_eval::global_builtins())), &mut compilation_observer, ) .unwrap(); diff --git a/tvix/eval/src/builtins/impure.rs b/tvix/eval/src/builtins/impure.rs index 675bdd50950e..7c98fcb4e192 100644 --- a/tvix/eval/src/builtins/impure.rs +++ b/tvix/eval/src/builtins/impure.rs @@ -1,4 +1,5 @@ use std::{ + cell::RefCell, collections::{BTreeMap, HashMap}, rc::Rc, time::{SystemTime, UNIX_EPOCH}, @@ -43,7 +44,10 @@ pub(super) fn builtins() -> BTreeMap<NixString, Value> { /// 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(source: SourceCode) -> Builtin { +pub fn builtins_import( + globals: Rc<RefCell<HashMap<&'static str, Value>>>, + source: SourceCode, +) -> Builtin { Builtin::new( "import", &[true], @@ -83,7 +87,7 @@ pub fn builtins_import(source: SourceCode) -> Builtin { &parsed.tree().expr().unwrap(), Some(path.clone()), file, - HashMap::new(), // TODO: pass through globals + globals.clone(), &mut NoOpObserver::default(), ) .map_err(|err| ErrorKind::ImportCompilerError { diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index eb617b227351..472f4aaf363d 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -21,6 +21,7 @@ use codemap::Span; use path_clean::PathClean; use rnix::ast::{self, AstToken}; use smol_str::SmolStr; +use std::cell::RefCell; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -103,7 +104,7 @@ impl<'observer> Compiler<'observer> { pub(crate) fn new( location: Option<PathBuf>, file: Arc<codemap::File>, - globals: HashMap<&'static str, Value>, + globals: Rc<RefCell<HashMap<&'static str, Value>>>, observer: &'observer mut dyn CompilerObserver, ) -> EvalResult<Self> { let mut root_dir = match location { @@ -124,11 +125,13 @@ impl<'observer> Compiler<'observer> { root_dir.pop(); } + let globals = globals.borrow(); + Ok(Self { root_dir, file, observer, - globals: prepare_globals(globals), + globals: prepare_globals(&globals), contexts: vec![LambdaCtx::new()], warnings: vec![], errors: vec![], @@ -1103,7 +1106,7 @@ fn optimise_tail_call(chunk: &mut Chunk) { /// Note that all builtin functions are *not* considered part of the /// language in this sense and MUST be supplied as additional global /// values, including the `builtins` set itself. -fn prepare_globals(additional: HashMap<&'static str, Value>) -> GlobalsMap { +fn prepare_globals(additional: &HashMap<&'static str, Value>) -> GlobalsMap { let mut globals: GlobalsMap = HashMap::new(); globals.insert( @@ -1127,7 +1130,8 @@ fn prepare_globals(additional: HashMap<&'static str, Value>) -> GlobalsMap { }), ); - for (ident, value) in additional.into_iter() { + for (ident, value) in additional.iter() { + let value: Value = value.clone(); globals.insert( ident, Rc::new(move |compiler, span| compiler.emit_constant(value.clone(), &span)), @@ -1141,7 +1145,7 @@ pub fn compile( expr: &ast::Expr, location: Option<PathBuf>, file: Arc<codemap::File>, - globals: HashMap<&'static str, Value>, + globals: Rc<RefCell<HashMap<&'static str, Value>>>, observer: &mut dyn CompilerObserver, ) -> EvalResult<CompilationOutput> { let mut c = Compiler::new(location, file, globals, observer)?; diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs index aed4292282b9..4e50b7279c38 100644 --- a/tvix/eval/src/eval.rs +++ b/tvix/eval/src/eval.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{cell::RefCell, path::PathBuf, rc::Rc}; use crate::{ builtins::global_builtins, @@ -59,13 +59,21 @@ pub fn interpret(code: &str, location: Option<PathBuf>, options: Options) -> Eva } // TODO: encapsulate this import weirdness in builtins - let mut builtins = global_builtins(); + + let builtins = Rc::new(RefCell::new(global_builtins())); #[cfg(feature = "impure")] - builtins.insert( - "import", - Value::Builtin(crate::builtins::impure::builtins_import(source.clone())), - ); + { + // We need to insert import into the builtins, but the + // builtins passed to import must have import *in it*. + let import = Value::Builtin(crate::builtins::impure::builtins_import( + builtins.clone(), + source.clone(), + )); + + builtins.borrow_mut().insert("import", import); + // TODO: also add it into the inner builtins set + }; let result = if options.dump_bytecode { crate::compiler::compile( |