1
0

Add reference counting for list values

This commit is contained in:
Jeff 2023-10-26 18:03:59 -04:00
parent a5390c5150
commit 25778cc480
15 changed files with 167 additions and 83 deletions

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Filter { pub struct Filter {
@ -30,21 +30,23 @@ impl AbstractTree for Filter {
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let value = self.expression.run(source, context)?;
let list = value.as_list()?; let values = value.as_list()?.items();
let key = self.identifier.inner(); let key = self.identifier.inner();
let mut context = context.clone(); 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())?; context.set_value(key.clone(), value.clone())?;
let should_include = self.item.run(source, &mut context)?.as_boolean()?; let should_include = self.item.run(source, &mut context)?.as_boolean()?;
if should_include { 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))
} }
} }

View File

@ -30,11 +30,11 @@ impl AbstractTree for Find {
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let value = self.expression.run(source, context)?;
let list = value.as_list()?; let values = value.as_list()?.items();
let key = self.identifier.inner(); let key = self.identifier.inner();
let mut context = context.clone(); let mut context = context.clone();
for value in list { for value in values.iter() {
context.set_value(key.clone(), value.clone())?; context.set_value(key.clone(), value.clone())?;
let should_return = self.item.run(source, &mut context)?.as_boolean()?; let should_return = self.item.run(source, &mut context)?.as_boolean()?;

View File

@ -29,13 +29,13 @@ impl AbstractTree for For {
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let expression_run = self.expression.run(source, context)?;
let list = value.as_list()?; let values = expression_run.as_list()?.items();
let key = self.identifier.inner(); let key = self.identifier.inner();
let original_value = context.get_value(key)?; let original_value = context.get_value(key)?;
for value in list { for value in values.iter() {
context.set_value(key.clone(), value.clone())?; context.set_value(key.clone(), value.clone())?;
self.item.run(source, context)?; self.item.run(source, context)?;

View File

@ -26,13 +26,13 @@ impl AbstractTree for Insert {
let table_name = self.identifier.inner().clone(); let table_name = self.identifier.inner().clone();
let mut table = self.identifier.run(source, context)?.as_table()?.clone(); let mut table = self.identifier.run(source, context)?.as_table()?.clone();
let new_rows = self.expression.run(source, context)?.into_inner_list()?; 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 values.iter() {
let row_values = row.clone().into_inner_list()?;
for row in new_rows { table.insert(row_values.items().clone())?;
table.insert(row.into_inner_list()?)?;
} }
context.set_value(table_name, Value::Table(table))?; context.set_value(table_name, Value::Table(table))?;

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Remove { pub struct Remove {
@ -29,30 +29,34 @@ impl AbstractTree for Remove {
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let expression_run = self.expression.run(source, context)?;
let mut list = value.into_inner_list()?; let values = expression_run.into_inner_list()?;
let key = self.identifier.inner(); let key = self.identifier.inner();
let mut sub_context = context.clone(); 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())?; sub_context.set_value(key.clone(), value.clone())?;
let should_remove = self.item.run(source, &mut sub_context)?.as_boolean()?; let should_remove = self.item.run(source, &mut sub_context)?.as_boolean()?;
if should_remove { if should_remove {
list.remove(index); should_remove_index = Some(index);
match &self.expression { match &self.expression {
Expression::Identifier(identifier) => { 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());
} }
} }
if let Some(index) = should_remove_index {
Ok(values.items_mut().remove(index))
} else {
Ok(Value::Empty) Ok(Value::Empty)
} }
}
} }

View File

@ -11,7 +11,7 @@ use reqwest::blocking::get;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Tool { pub enum Tool {
@ -287,7 +287,7 @@ impl AbstractTree for Tool {
Ok(Value::String(data)) Ok(Value::String(data))
} }
Tool::Length(expression) => { 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)) Ok(Value::Integer(length as i64))
} }
@ -399,7 +399,7 @@ impl AbstractTree for Tool {
contents.push(Value::String(file_path)); contents.push(Value::String(file_path));
} }
Value::List(contents) Value::List(List::with_items(contents))
} else { } else {
Value::String(read_to_string(path)?) Value::String(read_to_string(path)?)
}; };
@ -517,7 +517,7 @@ impl AbstractTree for Tool {
Tool::Random(expressions) => { Tool::Random(expressions) => {
if expressions.len() == 1 { if expressions.len() == 1 {
let value = expressions[0].run(source, context)?; let value = expressions[0].run(source, context)?;
let list = value.as_list()?; let list = value.as_list()?.items();
if list.len() < 2 { if list.len() < 2 {
return Err(Error::ExpectedMinLengthList { return Err(Error::ExpectedMinLengthList {
@ -555,7 +555,7 @@ impl AbstractTree for Tool {
.map(|column_name| Value::String(column_name)) .map(|column_name| Value::String(column_name))
.collect(); .collect();
Ok(Value::List(column_names)) Ok(Value::List(List::with_items(column_names)))
} }
Tool::Rows(expression) => { Tool::Rows(expression) => {
let rows = expression let rows = expression
@ -564,10 +564,10 @@ impl AbstractTree for Tool {
.rows() .rows()
.iter() .iter()
.cloned() .cloned()
.map(|row| Value::List(row)) .map(|row| Value::List(List::with_items(row)))
.collect(); .collect();
Ok(Value::List(rows)) Ok(Value::List(List::with_items(rows)))
} }
} }
} }

View File

@ -1,7 +1,8 @@
use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; 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)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Transform { pub struct Transform {
@ -29,19 +30,29 @@ impl AbstractTree for Transform {
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let expression_run = self.expression.run(source, context)?;
let list = value.as_list()?; let values = expression_run.as_list()?.items();
let key = self.identifier.inner(); let key = self.identifier.inner();
let mut context = context.clone(); let context = context.clone();
let mut new_list = Vec::with_capacity(list.len()); let new_list = List::with_capacity(values.len());
for value in list { values.par_iter().try_for_each_with(
context.set_value(key.clone(), value.clone())?; (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)) Ok(Value::List(new_list))
} }

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Error, Expression, Function, Identifier, Item, Map, Result, Table, Value, AbstractTree, Error, Expression, Function, Identifier, Item, List, Map, Result, Table, Value,
ValueType, ValueType,
}; };
@ -157,7 +157,7 @@ impl AbstractTree for ValueNode {
values.push(value); values.push(value);
} }
Value::List(values) Value::List(List::with_items(values))
} }
ValueType::Empty => Value::Empty, ValueType::Empty => Value::Empty,
ValueType::Map(nodes) => { ValueType::Map(nodes) => {
@ -185,10 +185,10 @@ impl AbstractTree for ValueNode {
} }
let _row_values = row_expression.run(source, context)?; 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 { for value in row_values.iter() {
let row = value.as_list()?.clone(); let row = value.as_list()?.items().clone();
rows.push(row) rows.push(row)
} }

View File

@ -31,7 +31,7 @@ pub fn evaluate(source: &str) -> Result<Value> {
/// ///
/// ```rust /// ```rust
/// # use dust_lang::*; /// # use dust_lang::*;
/// let mut context = VariableMap::new(); /// let mut context = Map::new();
/// ///
/// context.set_value("one".into(), 1.into()); /// context.set_value("one".into(), 1.into());
/// context.set_value("two".into(), 2.into()); /// context.set_value("two".into(), 2.into());
@ -96,7 +96,7 @@ impl<'context, 'code> Evaluator<'context, 'code> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::Table; use crate::{List, Table};
use super::*; use super::*;
@ -137,11 +137,11 @@ mod tests {
fn evaluate_list() { fn evaluate_list() {
assert_eq!( assert_eq!(
evaluate("[1, 2, 'foobar']"), evaluate("[1, 2, 'foobar']"),
Ok(Value::List(vec![ Ok(Value::List(List::with_items(vec![
Value::Integer(1), Value::Integer(1),
Value::Integer(2), Value::Integer(2),
Value::String("foobar".to_string()), Value::String("foobar".to_string()),
])) ])))
); );
} }

View File

@ -8,7 +8,7 @@ pub use crate::{
abstract_tree::*, abstract_tree::*,
error::*, error::*,
evaluator::*, 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; mod abstract_tree;

60
src/value/list.rs Normal file
View File

@ -0,0 +1,60 @@
use std::{
cmp::Ordering,
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use crate::Value;
#[derive(Debug, Clone)]
pub struct List(Arc<RwLock<Vec<Value>>>);
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<Value>) -> Self {
List(Arc::new(RwLock::new(items)))
}
pub fn items(&self) -> RwLockReadGuard<'_, Vec<Value>> {
self.0.read().unwrap()
}
pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec<Value>> {
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<Ordering> {
let left = self.0.read().unwrap().clone().into_iter();
let right = other.0.read().unwrap().clone().into_iter();
left.partial_cmp(right)
}
}

View File

@ -9,7 +9,7 @@ use std::{
sync::{Arc, RwLock, RwLockReadGuard}, 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. /// 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 { } else if let Value::Map(map) = value {
map.get_value(next_identifier) map.get_value(next_identifier)
} else { } 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 { while missing_elements > 0 {
list.push(value.clone()); items.push(value.clone());
missing_elements -= 1; missing_elements -= 1;
} }
@ -197,7 +198,10 @@ impl From<&Table> for Map {
let mut map = Map::new(); let mut map = Map::new();
for (row_index, row) in value.rows().iter().enumerate() { for (row_index, row) in value.rows().iter().enumerate() {
map.set_value(row_index.to_string(), Value::List(row.clone())) map.set_value(
row_index.to_string(),
Value::List(List::with_items(row.clone())),
)
.unwrap(); .unwrap();
} }

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values. //! Types that represent runtime values.
use crate::{ use crate::{
error::{Error, Result}, error::{Error, Result},
Function, Map, Table, ValueType, Function, List, Map, Table, ValueType,
}; };
use json::JsonValue; use json::JsonValue;
@ -20,6 +20,7 @@ use std::{
}; };
pub mod function; pub mod function;
pub mod list;
pub mod map; pub mod map;
pub mod table; pub mod table;
pub mod value_type; pub mod value_type;
@ -31,7 +32,7 @@ pub mod value_type;
/// value that can be treated as any other. /// value that can be treated as any other.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub enum Value { pub enum Value {
List(Vec<Value>), List(List),
Map(Map), Map(Map),
Table(Table), Table(Table),
Function(Function), Function(Function),
@ -141,7 +142,7 @@ impl Value {
} }
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`. /// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`.
pub fn as_list(&self) -> Result<&Vec<Value>> { pub fn as_list(&self) -> Result<&List> {
match self { match self {
Value::List(list) => Ok(list), Value::List(list) => Ok(list),
value => Err(Error::ExpectedList { value => Err(Error::ExpectedList {
@ -151,7 +152,7 @@ impl Value {
} }
/// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`. /// Borrows the value stored in `self` as `Vec<Value>`, or returns `Err` if `self` is not a `Value::List`.
pub fn into_inner_list(self) -> Result<Vec<Value>> { pub fn into_inner_list(self) -> Result<List> {
match self { match self {
Value::List(list) => Ok(list), Value::List(list) => Ok(list),
value => Err(Error::ExpectedList { value => Err(Error::ExpectedList {
@ -321,7 +322,7 @@ impl AddAssign for Value {
(Value::Float(left), Value::Float(right)) => *left += right, (Value::Float(left), Value::Float(right)) => *left += right,
(Value::Float(left), Value::Integer(right)) => *left += right as f64, (Value::Float(left), Value::Integer(right)) => *left += right as f64,
(Value::String(left), Value::String(right)) => *left += &right, (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::Integer(inner) => serializer.serialize_i64(*inner),
Value::Boolean(inner) => serializer.serialize_bool(*inner), Value::Boolean(inner) => serializer.serialize_bool(*inner),
Value::List(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)?; list.serialize_element(value)?;
} }
@ -425,7 +427,7 @@ impl Display for Value {
Value::Empty => write!(f, "empty"), Value::Empty => write!(f, "empty"),
Value::List(list) => { Value::List(list) => {
write!(f, "[")?; write!(f, "[")?;
for value in list { for value in list.items().iter() {
write!(f, " {value} ")?; write!(f, " {value} ")?;
} }
write!(f, "]") write!(f, "]")
@ -469,7 +471,7 @@ impl From<bool> for Value {
impl From<Vec<Value>> for Value { impl From<Vec<Value>> for Value {
fn from(vec: Vec<Value>) -> Self { fn from(vec: Vec<Value>) -> Self {
Value::List(vec) Value::List(List::with_items(vec))
} }
} }
@ -509,15 +511,15 @@ impl TryFrom<JsonValue> for Value {
Ok(Value::Map(map)) Ok(Value::Map(map))
} }
Array(array) => { Array(array) => {
let mut list = Vec::new(); let mut values = Vec::new();
for json_value in array { for json_value in array {
let value = Value::try_from(json_value)?; 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)) Ok(Value::Map(map))
} }
Array(array) => { Array(array) => {
let mut list = Vec::new(); let mut values = Vec::new();
for json_value in array { for json_value in array {
let value = Value::try_from(json_value)?; 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); list.push(value);
} }
Ok(Value::List(list)) Ok(Value::List(List::with_items(list)))
} }
fn visit_map<M>(self, mut access: M) -> std::result::Result<Value, M::Error> fn visit_map<M>(self, mut access: M) -> std::result::Result<Value, M::Error>

View File

@ -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 comfy_table::{Cell, Color, ContentArrangement, Table as ComfyTable};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
@ -146,7 +146,7 @@ impl Display for Table {
Value::List(list) => { Value::List(list) => {
let mut string = "(".to_string(); let mut string = "(".to_string();
for (index, value) in list.into_iter().enumerate() { for (index, value) in list.items().iter().enumerate() {
if index > 0 { if index > 0 {
string.push_str(", "); string.push_str(", ");
} }
@ -248,11 +248,11 @@ impl From<&Value> for Table {
} }
} }
impl From<&Vec<Value>> for Table { impl From<&List> for Table {
fn from(list: &Vec<Value>) -> Self { fn from(list: &List) -> Self {
let mut table = Table::new(vec!["index".to_string(), "item".to_string()]); 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 table
.insert(vec![Value::Integer(i as i64), value.clone()]) .insert(vec![Value::Integer(i as i64), value.clone()])
.unwrap(); .unwrap();
@ -262,13 +262,13 @@ impl From<&Vec<Value>> for Table {
} }
} }
impl From<&mut Vec<Value>> for Table { impl From<&mut List> for Table {
fn from(list: &mut Vec<Value>) -> Self { fn from(list: &mut List) -> Self {
let mut table = Table::new(vec!["index".to_string(), "item".to_string()]); 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() { if let Ok(list) = value.as_list() {
table.insert(list.clone()).unwrap(); table.insert(list.items().clone()).unwrap();
} else { } else {
table table
.insert(vec![Value::Integer(i as i64), value.clone()]) .insert(vec![Value::Integer(i as i64), value.clone()])

View File

@ -104,6 +104,7 @@ impl From<&Value> for ValueType {
Value::Empty => ValueType::Empty, Value::Empty => ValueType::Empty,
Value::List(list) => { Value::List(list) => {
let value_nodes = list let value_nodes = list
.items()
.iter() .iter()
.map(|value| Expression::Value(ValueNode::new(value.value_type(), 0, 0))) .map(|value| Expression::Value(ValueNode::new(value.value_type(), 0, 0)))
.collect(); .collect();