From 4b460c0e68de4a86ad2c278596106e29a24d42f6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 24 Mar 2024 17:34:36 -0400 Subject: [PATCH] Clean up --- dust-lang/src/abstract_tree/map_index.rs | 18 ++++ dust-lang/src/lib.rs | 122 ++++++++++++----------- dust-shell/src/cli.rs | 6 +- dust-shell/src/main.rs | 10 +- 4 files changed, 89 insertions(+), 67 deletions(-) diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index ba31f5a..21ff265 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -69,6 +69,24 @@ impl AbstractNode for MapIndex { }; } + if let ( + Expression::Value(ValueNode::Structure { fields, .. }), + Expression::Identifier(identifier), + ) = (&self.left.node, &self.right.node) + { + return if let Some(type_result) = fields.iter().find_map(|(property, expression)| { + if property == identifier { + Some(expression.node.expected_type(context)) + } else { + None + } + }) { + type_result + } else { + Ok(Type::None) + }; + } + Err(ValidationError::CannotIndexWith { collection_type: self.left.node.expected_type(context)?, collection_position: self.left.position, diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 08e1e3c..aafd428 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -6,7 +6,11 @@ pub mod lexer; pub mod parser; pub mod value; -use std::{cell::RefCell, ops::Range, rc::Rc, vec}; +use std::{ + ops::Range, + sync::{Arc, RwLock}, + vec, +}; use abstract_tree::Type; use ariadne::{Color, Fmt, Label, Report, ReportKind}; @@ -14,42 +18,48 @@ use context::Context; use error::{Error, RuntimeError, TypeConflict, ValidationError}; use lexer::lex; 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()); interpreter.load_std()?; - interpreter.run(Rc::from(source_id), Rc::from(source)) + interpreter.run(Arc::from(source_id), Arc::from(source)) } pub fn interpret_without_std( source_id: &str, source: &str, ) -> Result, InterpreterError> { - let mut interpreter = Interpreter::new(Context::new()); + let interpreter = Interpreter::new(Context::new()); - interpreter.run(Rc::from(source_id.to_string()), Rc::from(source)) + interpreter.run(Arc::from(source_id.to_string()), Arc::from(source)) } pub struct Interpreter { context: Context, - sources: Rc, Rc)>>>, + sources: Arc, Arc)>>>, } impl Interpreter { pub fn new(context: Context) -> Self { Interpreter { context, - sources: Rc::new(RefCell::new(Vec::new())), + sources: Arc::new(RwLock::new(Vec::new())), } } pub fn run( - &mut self, - source_id: Rc, - source: Rc, + &self, + source_id: Arc, + source: Arc, ) -> Result, InterpreterError> { + self.sources + .write() + .unwrap() + .push((source_id.clone(), source.clone())); + let tokens = lex(source.as_ref()).map_err(|errors| InterpreterError { source_id: source_id.clone(), errors, @@ -60,50 +70,42 @@ impl Interpreter { })?; let value_option = abstract_tree .run(&self.context) - .map_err(|errors| InterpreterError { - source_id: source_id.clone(), - errors, - })?; - - self.sources.borrow_mut().push((source_id, source.into())); + .map_err(|errors| InterpreterError { source_id, errors })?; Ok(value_option) } - pub fn run_all, Rc)>>( - &mut self, - sources: T, - ) -> Result, InterpreterError> { - let mut previous_value_option = None; + pub fn load_std(&mut self) -> Result<(), InterpreterError> { + let std_sources = [ + ( + Arc::from("std/io.ds"), + Arc::from(include_str!("../../std/io.ds")), + ), + ( + Arc::from("std/thread.ds"), + Arc::from(include_str!("../../std/thread.ds")), + ), + ]; - for (source_id, source) in sources { - previous_value_option = self.run(source_id.clone(), source)?; + let error = std_sources + .into_par_iter() + .find_map_any(|(source_id, source)| self.run(source_id, source).err()); + + if let Some(error) = error { + Err(error) + } else { + Ok(()) } - - Ok(previous_value_option) } - pub fn load_std(&mut self) -> Result, InterpreterError> { - self.run_all([ - ( - Rc::from("std/io.ds"), - Rc::from(include_str!("../../std/io.ds")), - ), - ( - Rc::from("std/thread.ds"), - Rc::from(include_str!("../../std/thread.ds")), - ), - ]) - } - - pub fn sources(&self) -> vec::IntoIter<(Rc, Rc)> { - self.sources.borrow().clone().into_iter() + pub fn sources(&self) -> vec::IntoIter<(Arc, Arc)> { + self.sources.read().unwrap().clone().into_iter() } } #[derive(Debug, PartialEq)] pub struct InterpreterError { - source_id: Rc, + source_id: Arc, errors: Vec, } @@ -114,7 +116,7 @@ impl InterpreterError { } impl InterpreterError { - pub fn build_reports<'a>(self) -> Vec, Range)>> { + pub fn build_reports<'a>(self) -> Vec, Range)>> { let mut reports = Vec::new(); for error in self.errors { @@ -173,6 +175,17 @@ impl InterpreterError { span.into(), ) } + Error::Validation { error, position } => ( + Report::build( + ReportKind::Custom("Validation Error", Color::Magenta), + self.source_id.clone(), + position.1, + ) + .with_message("The syntax is valid but this code would cause an error.") + .with_note("This error was detected by the interpreter before running the code."), + Some(error), + position, + ), Error::Runtime { error, position } => ( Report::build( ReportKind::Custom("Runtime Error", Color::Red), @@ -185,6 +198,9 @@ impl InterpreterError { ) .with_help( "This is the interpreter's fault. Please submit a bug with this error message.", + ) + .with_label( + Label::new((self.source_id.clone(), position.0..position.1)).with_message("Runtime error occured here.") ), if let RuntimeError::ValidationFailure(validation_error) = error { Some(validation_error) @@ -193,17 +209,6 @@ impl InterpreterError { }, position, ), - Error::Validation { error, position } => ( - Report::build( - ReportKind::Custom("Validation Error", Color::Magenta), - self.source_id.clone(), - position.1, - ) - .with_message("The syntax is valid but this code is not sound.") - .with_note("This error was detected by the interpreter before running the code."), - Some(error), - position, - ), }; let type_color = Color::Green; @@ -235,14 +240,14 @@ impl InterpreterError { ValidationError::TypeCheck { conflict, actual_position, - expected_position: expected_postion, + expected_position, } => { let TypeConflict { actual, expected } = conflict; builder.add_labels([ Label::new(( self.source_id.clone(), - expected_postion.0..expected_postion.1, + expected_position.0..expected_position.1, )) .with_message(format!( "Type {} established here.", @@ -308,11 +313,10 @@ impl InterpreterError { Type::String.fg(type_color) )); - builder.add_labels([Label::new(( - self.source_id.clone(), - position.0..position.1, - )) - .with_message(format!("This has type {}.", actual.fg(type_color),))]) + builder.add_label( + Label::new((self.source_id.clone(), position.0..position.1)) + .with_message(format!("This has type {}.", actual.fg(type_color),)), + ) } } } diff --git a/dust-shell/src/cli.rs b/dust-shell/src/cli.rs index e6b2ba2..c7e8aef 100644 --- a/dust-shell/src/cli.rs +++ b/dust-shell/src/cli.rs @@ -3,7 +3,7 @@ use std::{ io::{self, stderr}, path::PathBuf, process::Command, - rc::Rc, + sync::Arc, }; use ariadne::sources; @@ -19,7 +19,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( @@ -80,7 +80,7 @@ pub fn run_shell(context: Context) -> Result<(), io::Error> { continue; } - let run_result = interpreter.run(Rc::from("input"), Rc::from(buffer.as_str())); + let run_result = interpreter.run(Arc::from("input"), Arc::from(buffer.as_str())); match run_result { Ok(Some(value)) => { diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index e9b4cd5..6ccbd47 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -9,7 +9,7 @@ use colored::Colorize; use std::{ fs::read_to_string, io::{stderr, Write}, - rc::Rc, + sync::Arc, }; use dust_lang::{context::Context, Interpreter}; @@ -46,12 +46,12 @@ fn main() { interpreter.load_std().unwrap(); - let (source_id, source) = if let Some(path) = args.path { + let (source_id, source): (Arc, Arc) = if let Some(path) = args.path { let source = read_to_string(&path).unwrap(); - (Rc::from(path), source) + (Arc::from(path), Arc::from(source.as_str())) } else if let Some(command) = args.command { - (Rc::from("input"), command) + (Arc::from("command"), Arc::from(command.as_str())) } else { match run_shell(context) { Ok(_) => {} @@ -61,7 +61,7 @@ fn main() { return; }; - let run_result = interpreter.run(source_id, Rc::from(source)); + let run_result = interpreter.run(source_id.clone(), source.clone()); match run_result { Ok(value) => {