diff --git a/dust-lang/examples/interpreter_async.rs b/dust-lang/examples/interpreter_async.rs index 7e2432a..1b3a985 100644 --- a/dust-lang/examples/interpreter_async.rs +++ b/dust-lang/examples/interpreter_async.rs @@ -4,7 +4,6 @@ use std::{ time::Duration, }; -use context::Context; use dust_lang::*; fn run_fibnacci(interpreter: &Interpreter, i: u8) -> Value { @@ -30,13 +29,15 @@ fn run_fibnacci(interpreter: &Interpreter, i: u8) -> Value { } fn main() { - let interpreter = Interpreter::new(Context::new()); + let interpreter = Interpreter::new(); let (tx, rx) = channel(); for i in 1..10 { let interpreter = interpreter.clone(); let tx = tx.clone(); + println!("Spawning thread for fib({})", i); + thread::spawn(move || { let value = run_fibnacci(&interpreter, i); diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index cb0f8c7..7ecbd8b 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -23,6 +23,7 @@ use std::{ }; pub use abstract_tree::Type; +use standard_library::core_context; pub use value::Value; use abstract_tree::AbstractTree; @@ -33,7 +34,7 @@ use lexer::{lex, Token}; use parser::{parse, parser}; pub fn interpret(source_id: &str, source: &str) -> Result, InterpreterError> { - let interpreter = Interpreter::new(Context::new()); + let interpreter = Interpreter::new(); interpreter.run(Arc::from(source_id), Arc::from(source)) } @@ -44,14 +45,14 @@ pub fn interpret(source_id: &str, source: &str) -> Result, Interpr /// used to identify the source of errors and to provide more detailed error messages. #[derive(Clone, Debug)] pub struct Interpreter { - context: Context, + contexts: Arc, Context>>>, sources: Arc, Arc>>>, } impl Interpreter { - pub fn new(context: Context) -> Self { + pub fn new() -> Self { Interpreter { - context, + contexts: Arc::new(RwLock::new(HashMap::new())), sources: Arc::new(RwLock::new(HashMap::new())), } } @@ -111,8 +112,9 @@ impl Interpreter { source_id: source_id.clone(), errors, })?; + let context = self.get_or_create_context(&source_id); let value_option = abstract_tree - .run(&self.context, true) + .run(&context, true) .map_err(|errors| InterpreterError { source_id, errors })?; Ok(value_option) @@ -121,6 +123,20 @@ impl Interpreter { pub fn sources(&self) -> hash_map::IntoIter, Arc> { self.sources.read().unwrap().clone().into_iter() } + + fn get_or_create_context(&self, source_id: &Arc) -> Context { + let mut contexts = self.contexts.write().unwrap(); + + if let Some(context) = contexts.get(source_id) { + context.clone() + } else { + let context = core_context().clone(); + + contexts.insert(source_id.clone(), context.clone()); + + context + } + } } #[derive(Debug, PartialEq)] diff --git a/dust-shell/src/cli.rs b/dust-shell/src/cli.rs index 4a10698..aa9b8ef 100644 --- a/dust-shell/src/cli.rs +++ b/dust-shell/src/cli.rs @@ -7,7 +7,7 @@ use std::{ }; use ariadne::sources; -use dust_lang::{context::Context, *}; +use dust_lang::*; use nu_ansi_term::{Color, Style}; use reedline::{ default_emacs_keybindings, ColumnarMenu, DefaultHinter, EditCommand, Emacs, KeyCode, @@ -15,8 +15,8 @@ use reedline::{ SqliteBackedHistory, }; -pub fn run_shell(context: Context) -> Result<(), io::Error> { - let interpreter = Interpreter::new(context.clone()); +pub fn run_shell() -> Result<(), io::Error> { + let interpreter = Interpreter::new(); let mut keybindings = default_emacs_keybindings(); keybindings.add_binding( diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index 63f793e..648e850 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -14,7 +14,7 @@ use std::{ sync::Arc, }; -use dust_lang::{context::Context, Interpreter}; +use dust_lang::Interpreter; /// Command-line arguments to be parsed. #[derive(Parser, Debug)] @@ -56,8 +56,7 @@ fn main() { .init(); let args = Args::parse(); - let context = Context::new_with_std_core().unwrap(); - let interpreter = Interpreter::new(context.clone()); + let interpreter = Interpreter::new(); let (source_id, source): (Arc, Arc) = if let Some(path) = args.path { let source = read_to_string(&path).unwrap(); @@ -66,7 +65,7 @@ fn main() { } else if let Some(command) = args.command { (Arc::from("command"), Arc::from(command)) } else { - match run_shell(context) { + match run_shell() { Ok(_) => {} Err(error) => eprintln!("{error}"), }