diff --git a/src/abstract_tree/filter.rs b/src/abstract_tree/filter.rs index 4fa41d5..ebac2ff 100644 --- a/src/abstract_tree/filter.rs +++ b/src/abstract_tree/filter.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Expression, Identifier, Item, Map, Result, Value}; +use crate::{AbstractTree, Expression, Identifier, Item, List, Map, Result, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Filter { @@ -30,21 +30,23 @@ impl AbstractTree for Filter { fn run(&self, source: &str, context: &mut Map) -> Result { let value = self.expression.run(source, context)?; - let list = value.as_list()?; + let values = value.as_list()?.items(); let key = self.identifier.inner(); let mut context = context.clone(); - let mut new_list = Vec::with_capacity(list.len()); + let mut new_values = Vec::with_capacity(values.len()); - for value in list { + for value in values.iter() { context.set_value(key.clone(), value.clone())?; let should_include = self.item.run(source, &mut context)?.as_boolean()?; if should_include { - new_list.push(value.clone()); + new_values.push(value.clone()); } } - Ok(Value::List(new_list)) + let list = List::with_items(new_values); + + Ok(Value::List(list)) } } diff --git a/src/abstract_tree/find.rs b/src/abstract_tree/find.rs index a5d30c3..a6dd8c2 100644 --- a/src/abstract_tree/find.rs +++ b/src/abstract_tree/find.rs @@ -30,11 +30,11 @@ impl AbstractTree for Find { fn run(&self, source: &str, context: &mut Map) -> Result { let value = self.expression.run(source, context)?; - let list = value.as_list()?; + let values = value.as_list()?.items(); let key = self.identifier.inner(); let mut context = context.clone(); - for value in list { + for value in values.iter() { context.set_value(key.clone(), value.clone())?; let should_return = self.item.run(source, &mut context)?.as_boolean()?; diff --git a/src/abstract_tree/for.rs b/src/abstract_tree/for.rs index 2321740..830b480 100644 --- a/src/abstract_tree/for.rs +++ b/src/abstract_tree/for.rs @@ -29,13 +29,13 @@ impl AbstractTree for For { } fn run(&self, source: &str, context: &mut Map) -> Result { - let value = self.expression.run(source, context)?; - let list = value.as_list()?; + let expression_run = self.expression.run(source, context)?; + let values = expression_run.as_list()?.items(); let key = self.identifier.inner(); let original_value = context.get_value(key)?; - for value in list { + for value in values.iter() { context.set_value(key.clone(), value.clone())?; self.item.run(source, context)?; diff --git a/src/abstract_tree/insert.rs b/src/abstract_tree/insert.rs index a4affbe..a4586c5 100644 --- a/src/abstract_tree/insert.rs +++ b/src/abstract_tree/insert.rs @@ -26,13 +26,13 @@ impl AbstractTree for Insert { let table_name = self.identifier.inner().clone(); let mut table = self.identifier.run(source, context)?.as_table()?.clone(); let new_rows = self.expression.run(source, context)?.into_inner_list()?; + let values = new_rows.items(); - table.reserve(new_rows.len()); + table.reserve(values.len()); - println!("{new_rows:?}"); - - for row in new_rows { - table.insert(row.into_inner_list()?)?; + for row in values.iter() { + let row_values = row.clone().into_inner_list()?; + table.insert(row_values.items().clone())?; } context.set_value(table_name, Value::Table(table))?; diff --git a/src/abstract_tree/remove.rs b/src/abstract_tree/remove.rs index 0e92175..ca06dcb 100644 --- a/src/abstract_tree/remove.rs +++ b/src/abstract_tree/remove.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Expression, Identifier, Item, Map, Result, Value}; +use crate::{AbstractTree, Expression, Identifier, Item, List, Map, Result, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Remove { @@ -29,30 +29,34 @@ impl AbstractTree for Remove { } fn run(&self, source: &str, context: &mut Map) -> Result { - let value = self.expression.run(source, context)?; - let mut list = value.into_inner_list()?; + let expression_run = self.expression.run(source, context)?; + let values = expression_run.into_inner_list()?; let key = self.identifier.inner(); let mut sub_context = context.clone(); + let mut should_remove_index = None; - for (index, value) in list.clone().iter().enumerate() { + for (index, value) in values.items().iter().enumerate() { sub_context.set_value(key.clone(), value.clone())?; let should_remove = self.item.run(source, &mut sub_context)?.as_boolean()?; if should_remove { - list.remove(index); + should_remove_index = Some(index); match &self.expression { Expression::Identifier(identifier) => { - context.set_value(identifier.inner().clone(), Value::List(list))?; + context + .set_value(identifier.inner().clone(), Value::List(values.clone()))?; } _ => {} } - - return Ok(value.clone()); } } - Ok(Value::Empty) + if let Some(index) = should_remove_index { + Ok(values.items_mut().remove(index)) + } else { + Ok(Value::Empty) + } } } diff --git a/src/abstract_tree/tool.rs b/src/abstract_tree/tool.rs index 091e2f3..9032a91 100644 --- a/src/abstract_tree/tool.rs +++ b/src/abstract_tree/tool.rs @@ -11,7 +11,7 @@ use reqwest::blocking::get; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Error, Expression, Map, Result, Table, Value, ValueType}; +use crate::{AbstractTree, Error, Expression, List, Map, Result, Table, Value, ValueType}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub enum Tool { @@ -287,7 +287,7 @@ impl AbstractTree for Tool { Ok(Value::String(data)) } Tool::Length(expression) => { - let length = expression.run(source, context)?.as_list()?.len(); + let length = expression.run(source, context)?.as_list()?.items().len(); Ok(Value::Integer(length as i64)) } @@ -399,7 +399,7 @@ impl AbstractTree for Tool { contents.push(Value::String(file_path)); } - Value::List(contents) + Value::List(List::with_items(contents)) } else { Value::String(read_to_string(path)?) }; @@ -517,7 +517,7 @@ impl AbstractTree for Tool { Tool::Random(expressions) => { if expressions.len() == 1 { let value = expressions[0].run(source, context)?; - let list = value.as_list()?; + let list = value.as_list()?.items(); if list.len() < 2 { return Err(Error::ExpectedMinLengthList { @@ -555,7 +555,7 @@ impl AbstractTree for Tool { .map(|column_name| Value::String(column_name)) .collect(); - Ok(Value::List(column_names)) + Ok(Value::List(List::with_items(column_names))) } Tool::Rows(expression) => { let rows = expression @@ -564,10 +564,10 @@ impl AbstractTree for Tool { .rows() .iter() .cloned() - .map(|row| Value::List(row)) + .map(|row| Value::List(List::with_items(row))) .collect(); - Ok(Value::List(rows)) + Ok(Value::List(List::with_items(rows))) } } } diff --git a/src/abstract_tree/transform.rs b/src/abstract_tree/transform.rs index 94db846..8374263 100644 --- a/src/abstract_tree/transform.rs +++ b/src/abstract_tree/transform.rs @@ -1,7 +1,8 @@ +use rayon::prelude::*; use serde::{Deserialize, Serialize}; use tree_sitter::Node; -use crate::{AbstractTree, Expression, Identifier, Item, Map, Result, Value}; +use crate::{AbstractTree, Expression, Identifier, Item, List, Map, Result, Value}; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] pub struct Transform { @@ -29,19 +30,29 @@ impl AbstractTree for Transform { } fn run(&self, source: &str, context: &mut Map) -> Result { - let value = self.expression.run(source, context)?; - let list = value.as_list()?; + let expression_run = self.expression.run(source, context)?; + let values = expression_run.as_list()?.items(); let key = self.identifier.inner(); - let mut context = context.clone(); - let mut new_list = Vec::with_capacity(list.len()); + let context = context.clone(); + let new_list = List::with_capacity(values.len()); - for value in list { - context.set_value(key.clone(), value.clone())?; + values.par_iter().try_for_each_with( + (context, new_list.clone()), + |(context, new_list), value| { + context.set_value(key.clone(), value.clone()).unwrap(); - let value = self.item.run(source, &mut context)?; + let item_run = self.item.run(source, context); - new_list.push(value); - } + match item_run { + Ok(value) => { + new_list.items_mut().push(value); + + Ok(()) + } + Err(error) => Err(error), + } + }, + )?; Ok(Value::List(new_list)) } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index f92d691..b74028e 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use tree_sitter::Node; use crate::{ - AbstractTree, Error, Expression, Function, Identifier, Item, Map, Result, Table, Value, + AbstractTree, Error, Expression, Function, Identifier, Item, List, Map, Result, Table, Value, ValueType, }; @@ -157,7 +157,7 @@ impl AbstractTree for ValueNode { values.push(value); } - Value::List(values) + Value::List(List::with_items(values)) } ValueType::Empty => Value::Empty, ValueType::Map(nodes) => { @@ -185,10 +185,10 @@ impl AbstractTree for ValueNode { } let _row_values = row_expression.run(source, context)?; - let row_values = _row_values.as_list()?; + let row_values = _row_values.as_list()?.items(); - for value in row_values { - let row = value.as_list()?.clone(); + for value in row_values.iter() { + let row = value.as_list()?.items().clone(); rows.push(row) } diff --git a/src/evaluator.rs b/src/evaluator.rs index b709249..75f38f9 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -31,7 +31,7 @@ pub fn evaluate(source: &str) -> Result { /// /// ```rust /// # use dust_lang::*; -/// let mut context = VariableMap::new(); +/// let mut context = Map::new(); /// /// context.set_value("one".into(), 1.into()); /// context.set_value("two".into(), 2.into()); @@ -96,7 +96,7 @@ impl<'context, 'code> Evaluator<'context, 'code> { #[cfg(test)] mod tests { - use crate::Table; + use crate::{List, Table}; use super::*; @@ -137,11 +137,11 @@ mod tests { fn evaluate_list() { assert_eq!( evaluate("[1, 2, 'foobar']"), - Ok(Value::List(vec![ + Ok(Value::List(List::with_items(vec![ Value::Integer(1), Value::Integer(2), Value::String("foobar".to_string()), - ])) + ]))) ); } diff --git a/src/lib.rs b/src/lib.rs index 4df445e..66b60c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub use crate::{ abstract_tree::*, error::*, evaluator::*, - value::{function::Function, map::Map, table::Table, value_type::ValueType, Value}, + value::{function::Function, list::List, map::Map, table::Table, value_type::ValueType, Value}, }; mod abstract_tree; diff --git a/src/value/list.rs b/src/value/list.rs new file mode 100644 index 0000000..f0b32a4 --- /dev/null +++ b/src/value/list.rs @@ -0,0 +1,60 @@ +use std::{ + cmp::Ordering, + sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, +}; + +use crate::Value; + +#[derive(Debug, Clone)] +pub struct List(Arc>>); + +impl List { + pub fn new() -> Self { + List(Arc::new(RwLock::new(Vec::new()))) + } + + pub fn with_capacity(capacity: usize) -> Self { + List(Arc::new(RwLock::new(Vec::with_capacity(capacity)))) + } + + pub fn with_items(items: Vec) -> Self { + List(Arc::new(RwLock::new(items))) + } + + pub fn items(&self) -> RwLockReadGuard<'_, Vec> { + self.0.read().unwrap() + } + + pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec> { + self.0.write().unwrap() + } +} + +impl Eq for List {} + +impl PartialEq for List { + fn eq(&self, other: &Self) -> bool { + let left = self.0.read().unwrap().clone().into_iter(); + let right = other.0.read().unwrap().clone().into_iter(); + + left.eq(right) + } +} + +impl Ord for List { + fn cmp(&self, other: &Self) -> Ordering { + let left = self.0.read().unwrap().clone().into_iter(); + let right = other.0.read().unwrap().clone().into_iter(); + + left.cmp(right) + } +} + +impl PartialOrd for List { + fn partial_cmp(&self, other: &Self) -> Option { + let left = self.0.read().unwrap().clone().into_iter(); + let right = other.0.read().unwrap().clone().into_iter(); + + left.partial_cmp(right) + } +} diff --git a/src/value/map.rs b/src/value/map.rs index 168e786..00bcfdd 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -9,7 +9,7 @@ use std::{ sync::{Arc, RwLock, RwLockReadGuard}, }; -use crate::{value::Value, Error, Result, Table}; +use crate::{value::Value, Error, List, Result, Table}; /// A collection dust variables comprised of key-value pairs. /// @@ -53,7 +53,7 @@ impl Map { }); }; - Ok(list.get(index).cloned()) + Ok(list.items().get(index).cloned()) } else if let Value::Map(map) = value { map.get_value(next_identifier) } else { @@ -83,10 +83,11 @@ impl Map { }); }; - let mut missing_elements = index.saturating_sub(list.len()) + 1; + let mut missing_elements = index.saturating_sub(list.items().len()) + 1; + let mut items = list.items_mut(); while missing_elements > 0 { - list.push(value.clone()); + items.push(value.clone()); missing_elements -= 1; } @@ -197,8 +198,11 @@ impl From<&Table> for Map { let mut map = Map::new(); for (row_index, row) in value.rows().iter().enumerate() { - map.set_value(row_index.to_string(), Value::List(row.clone())) - .unwrap(); + map.set_value( + row_index.to_string(), + Value::List(List::with_items(row.clone())), + ) + .unwrap(); } map diff --git a/src/value/mod.rs b/src/value/mod.rs index fe867c1..6d48850 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -1,7 +1,7 @@ //! Types that represent runtime values. use crate::{ error::{Error, Result}, - Function, Map, Table, ValueType, + Function, List, Map, Table, ValueType, }; use json::JsonValue; @@ -20,6 +20,7 @@ use std::{ }; pub mod function; +pub mod list; pub mod map; pub mod table; pub mod value_type; @@ -31,7 +32,7 @@ pub mod value_type; /// value that can be treated as any other. #[derive(Debug, Clone, Default)] pub enum Value { - List(Vec), + List(List), Map(Map), Table(Table), Function(Function), @@ -141,7 +142,7 @@ impl Value { } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::List`. - pub fn as_list(&self) -> Result<&Vec> { + pub fn as_list(&self) -> Result<&List> { match self { Value::List(list) => Ok(list), value => Err(Error::ExpectedList { @@ -151,7 +152,7 @@ impl Value { } /// Borrows the value stored in `self` as `Vec`, or returns `Err` if `self` is not a `Value::List`. - pub fn into_inner_list(self) -> Result> { + pub fn into_inner_list(self) -> Result { match self { Value::List(list) => Ok(list), value => Err(Error::ExpectedList { @@ -321,7 +322,7 @@ impl AddAssign for Value { (Value::Float(left), Value::Float(right)) => *left += right, (Value::Float(left), Value::Integer(right)) => *left += right as f64, (Value::String(left), Value::String(right)) => *left += &right, - (Value::List(list), value) => list.push(value), + (Value::List(list), value) => list.items_mut().push(value), _ => {} } } @@ -399,9 +400,10 @@ impl Serialize for Value { Value::Integer(inner) => serializer.serialize_i64(*inner), Value::Boolean(inner) => serializer.serialize_bool(*inner), Value::List(inner) => { - let mut list = serializer.serialize_tuple(inner.len())?; + let items = inner.items(); + let mut list = serializer.serialize_tuple(items.len())?; - for value in inner { + for value in items.iter() { list.serialize_element(value)?; } @@ -425,7 +427,7 @@ impl Display for Value { Value::Empty => write!(f, "empty"), Value::List(list) => { write!(f, "[")?; - for value in list { + for value in list.items().iter() { write!(f, " {value} ")?; } write!(f, "]") @@ -469,7 +471,7 @@ impl From for Value { impl From> for Value { fn from(vec: Vec) -> Self { - Value::List(vec) + Value::List(List::with_items(vec)) } } @@ -509,15 +511,15 @@ impl TryFrom for Value { Ok(Value::Map(map)) } Array(array) => { - let mut list = Vec::new(); + let mut values = Vec::new(); for json_value in array { let value = Value::try_from(json_value)?; - list.push(value); + values.push(value); } - Ok(Value::List(list)) + Ok(Value::List(List::with_items(values))) } } } @@ -547,15 +549,15 @@ impl TryFrom<&JsonValue> for Value { Ok(Value::Map(map)) } Array(array) => { - let mut list = Vec::new(); + let mut values = Vec::new(); for json_value in array { let value = Value::try_from(json_value)?; - list.push(value); + values.push(value); } - Ok(Value::List(list)) + Ok(Value::List(List::with_items(values))) } } } @@ -822,7 +824,7 @@ impl<'de> Visitor<'de> for ValueVisitor { list.push(value); } - Ok(Value::List(list)) + Ok(Value::List(List::with_items(list))) } fn visit_map(self, mut access: M) -> std::result::Result diff --git a/src/value/table.rs b/src/value/table.rs index 917c6cd..196b4f2 100644 --- a/src/value/table.rs +++ b/src/value/table.rs @@ -1,4 +1,4 @@ -use crate::{Error, Map, Result, Value}; +use crate::{Error, List, Map, Result, Value}; use comfy_table::{Cell, Color, ContentArrangement, Table as ComfyTable}; use serde::{Deserialize, Serialize}; use std::{ @@ -146,7 +146,7 @@ impl Display for Table { Value::List(list) => { let mut string = "(".to_string(); - for (index, value) in list.into_iter().enumerate() { + for (index, value) in list.items().iter().enumerate() { if index > 0 { string.push_str(", "); } @@ -248,11 +248,11 @@ impl From<&Value> for Table { } } -impl From<&Vec> for Table { - fn from(list: &Vec) -> Self { +impl From<&List> for Table { + fn from(list: &List) -> Self { let mut table = Table::new(vec!["index".to_string(), "item".to_string()]); - for (i, value) in list.iter().enumerate() { + for (i, value) in list.items().iter().enumerate() { table .insert(vec![Value::Integer(i as i64), value.clone()]) .unwrap(); @@ -262,13 +262,13 @@ impl From<&Vec> for Table { } } -impl From<&mut Vec> for Table { - fn from(list: &mut Vec) -> Self { +impl From<&mut List> for Table { + fn from(list: &mut List) -> Self { let mut table = Table::new(vec!["index".to_string(), "item".to_string()]); - for (i, value) in list.iter().enumerate() { + for (i, value) in list.items().iter().enumerate() { if let Ok(list) = value.as_list() { - table.insert(list.clone()).unwrap(); + table.insert(list.items().clone()).unwrap(); } else { table .insert(vec![Value::Integer(i as i64), value.clone()]) diff --git a/src/value/value_type.rs b/src/value/value_type.rs index 4b88631..57428cb 100644 --- a/src/value/value_type.rs +++ b/src/value/value_type.rs @@ -104,6 +104,7 @@ impl From<&Value> for ValueType { Value::Empty => ValueType::Empty, Value::List(list) => { let value_nodes = list + .items() .iter() .map(|value| Expression::Value(ValueNode::new(value.value_type(), 0, 0))) .collect();