Add reference counting for list values
This commit is contained in:
parent
a5390c5150
commit
25778cc480
@ -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<Value> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ impl AbstractTree for Find {
|
||||
|
||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||
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()?;
|
||||
|
@ -29,13 +29,13 @@ impl AbstractTree for For {
|
||||
}
|
||||
|
||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||
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)?;
|
||||
|
@ -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))?;
|
||||
|
@ -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<Value> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Value> {
|
||||
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))
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ pub fn evaluate(source: &str) -> Result<Value> {
|
||||
///
|
||||
/// ```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()),
|
||||
]))
|
||||
])))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
60
src/value/list.rs
Normal file
60
src/value/list.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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<Value>),
|
||||
List(List),
|
||||
Map(Map),
|
||||
Table(Table),
|
||||
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`.
|
||||
pub fn as_list(&self) -> Result<&Vec<Value>> {
|
||||
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<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 {
|
||||
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<bool> for Value {
|
||||
|
||||
impl From<Vec<Value>> for Value {
|
||||
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))
|
||||
}
|
||||
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<M>(self, mut access: M) -> std::result::Result<Value, M::Error>
|
||||
|
@ -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<Value>> for Table {
|
||||
fn from(list: &Vec<Value>) -> 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<Value>> for Table {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&mut Vec<Value>> for Table {
|
||||
fn from(list: &mut Vec<Value>) -> 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()])
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user