diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 852a535..d4a7a82 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -112,7 +112,7 @@ impl AbstractTree { pub fn run( self, - context: &mut Context, + context: &Context, manage_memory: bool, ) -> Result, Vec> { let mut errors = Vec::new(); diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 597c0a6..b324c2f 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -296,13 +296,6 @@ impl AbstractNode for ValueNode { body, } => { let function_context = context.create_child(); - let mut value_parameters = Vec::with_capacity(constructors.len()); - - for (identifier, constructor) in constructors { - let r#type = constructor.construct(&function_context)?; - - value_parameters.push((identifier, r#type)); - } if let Some(identifiers) = &type_parameters { for identifier in identifiers { @@ -316,6 +309,14 @@ impl AbstractNode for ValueNode { } } + let mut value_parameters = Vec::with_capacity(constructors.len()); + + for (identifier, constructor) in constructors { + let r#type = constructor.construct(&function_context)?; + + value_parameters.push((identifier, r#type)); + } + let return_type = if let Some(constructor) = return_type { Some(constructor.construct(&function_context)?) } else { diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 23761c0..75e8226 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -14,16 +14,15 @@ use std::{ use abstract_tree::{AbstractTree, Type}; use ariadne::{Color, Config, Fmt, Label, Report, ReportKind}; -use chumsky::prelude::*; use context::Context; use error::{DustError, RuntimeError, TypeConflict, ValidationError}; use lexer::{lex, Token}; -use parser::{parse, parser}; +use parser::parse; use rayon::prelude::*; pub use value::Value; pub fn interpret<'src>(source_id: &str, source: &str) -> Result, InterpreterError> { - let mut interpreter = Interpreter::new(Context::new(None)); + let interpreter = Interpreter::new(Context::new(None)); interpreter.load_std()?; interpreter.run(Arc::from(source_id), Arc::from(source)) @@ -33,7 +32,7 @@ pub fn interpret_without_std( source_id: &str, source: &str, ) -> Result, InterpreterError> { - let mut interpreter = Interpreter::new(Context::new(None)); + let interpreter = Interpreter::new(Context::new(None)); interpreter.run(Arc::from(source_id.to_string()), Arc::from(source)) } @@ -51,11 +50,11 @@ impl Interpreter { } } - pub fn lex<'source>( - &mut self, + pub fn lex<'src>( + &self, source_id: Arc, - source: &'source str, - ) -> Result>, InterpreterError> { + source: &'src str, + ) -> Result>, InterpreterError> { let mut sources = self.sources.write().unwrap(); sources.clear(); @@ -66,10 +65,10 @@ impl Interpreter { .map_err(|errors| InterpreterError { source_id, errors }) } - pub fn parse<'source>( - &mut self, + pub fn parse<'src>( + &self, source_id: Arc, - source: &'source str, + source: &'src str, ) -> Result { let mut sources = self.sources.write().unwrap(); @@ -84,7 +83,7 @@ impl Interpreter { } pub fn run( - &mut self, + &self, source_id: Arc, source: Arc, ) -> Result, InterpreterError> { @@ -102,18 +101,20 @@ impl Interpreter { errors, })?; let value_option = abstract_tree - .run(&mut self.context, true) + .run(&self.context, true) .map_err(|errors| InterpreterError { source_id, errors })?; Ok(value_option) } - pub fn load_std(&mut self) -> Result<(), InterpreterError> { - let std_sources: [(Arc, Arc); 5] = [ + pub fn load_std(&self) -> Result<(), InterpreterError> { + let std_core_source: (Arc, Arc) = { ( Arc::from("std/core.ds"), Arc::from(include_str!("../../std/core.ds")), - ), + ) + }; + let std_sources: [(Arc, Arc); 4] = [ ( Arc::from("std/fs.ds"), Arc::from(include_str!("../../std/fs.ds")), @@ -134,39 +135,21 @@ impl Interpreter { log::info!("Start loading standard library..."); - let error = std_sources - .into_par_iter() - .find_map_any(|(source_id, source)| { - self.sources - .write() - .unwrap() - .push((source_id.clone(), source.clone())); + // Always load the core library first because other parts of the standard library may depend + // on it. + self.run(std_core_source.0, std_core_source.1)?; - let lex_result = lex(source.as_ref()).map_err(|errors| InterpreterError { - source_id: source_id.clone(), - errors, - }); - let tokens = match lex_result { - Ok(tokens) => tokens, - Err(error) => return Some(error), - }; - let parse_result = parser(true) - .parse(tokens.spanned((tokens.len()..tokens.len()).into())) - .into_result() - .map_err(|errors| InterpreterError { - source_id: source_id.clone(), - errors: errors.into_iter().map(DustError::from).collect(), - }); - let abstract_tree = match parse_result { - Ok(statements) => AbstractTree::new(statements), - Err(error) => return Some(error), - }; - - abstract_tree - .run(&mut self.context.clone(), false) - .map_err(|errors| InterpreterError { source_id, errors }) - .err() - }); + let error = if cfg!(test) { + // In debug mode, load the standard library sequentially to get consistent errors. + std_sources + .into_iter() + .find_map(|(source_id, source)| self.run(source_id, source).err()) + } else { + // In release mode, load the standard library asynchronously. + std_sources + .into_par_iter() + .find_map_any(|(source_id, source)| self.run(source_id, source).err()) + }; log::info!("Finish loading standard library."); diff --git a/dust-shell/src/cli.rs b/dust-shell/src/cli.rs index 2650c50..5745340 100644 --- a/dust-shell/src/cli.rs +++ b/dust-shell/src/cli.rs @@ -16,7 +16,7 @@ use reedline::{ }; pub fn run_shell(context: Context) -> Result<(), io::Error> { - let mut interpreter = Interpreter::new(context.clone()); + let interpreter = Interpreter::new(context.clone()); let mut keybindings = default_emacs_keybindings(); keybindings.add_binding( diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index bc249da..9b75da6 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -57,7 +57,7 @@ fn main() { let args = Args::parse(); let context = Context::new(None); - let mut interpreter = Interpreter::new(context.clone()); + let interpreter = Interpreter::new(context.clone()); if !args.no_std { let load_std_result = interpreter.load_std();