2023-10-29 23:31:06 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use tree_sitter::Node;
|
|
|
|
|
2023-12-05 22:08:22 +00:00
|
|
|
use crate::{AbstractTree, Error, Expression, List, Map, Result, Type, Value};
|
2023-10-29 23:31:06 +00:00
|
|
|
|
2023-12-06 19:13:22 +00:00
|
|
|
/// Abstract representation of an index expression.
|
|
|
|
///
|
|
|
|
/// An index is a means of accessing values stored in list, maps and strings.
|
2023-10-29 23:31:06 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
|
|
pub struct Index {
|
2023-11-15 01:41:57 +00:00
|
|
|
pub collection: Expression,
|
|
|
|
pub index: Expression,
|
|
|
|
pub index_end: Option<Expression>,
|
2023-10-29 23:31:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AbstractTree for Index {
|
2023-11-30 03:54:46 +00:00
|
|
|
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
|
2023-10-29 23:31:06 +00:00
|
|
|
let collection_node = node.child(0).unwrap();
|
2023-11-30 03:54:46 +00:00
|
|
|
let collection = Expression::from_syntax_node(source, collection_node, context)?;
|
2023-10-29 23:31:06 +00:00
|
|
|
|
2023-10-30 21:11:06 +00:00
|
|
|
let index_node = node.child(2).unwrap();
|
2023-11-30 03:54:46 +00:00
|
|
|
let index = Expression::from_syntax_node(source, index_node, context)?;
|
2023-10-29 23:31:06 +00:00
|
|
|
|
2023-10-30 21:11:06 +00:00
|
|
|
let index_end_node = node.child(4);
|
2023-10-29 23:31:06 +00:00
|
|
|
let index_end = if let Some(index_end_node) = index_end_node {
|
2023-11-30 03:54:46 +00:00
|
|
|
Some(Expression::from_syntax_node(
|
|
|
|
source,
|
|
|
|
index_end_node,
|
|
|
|
context,
|
|
|
|
)?)
|
2023-10-29 23:31:06 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Index {
|
|
|
|
collection,
|
|
|
|
index,
|
|
|
|
index_end,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-11-30 00:23:42 +00:00
|
|
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
2023-11-15 01:00:57 +00:00
|
|
|
let collection = self.collection.run(source, context)?;
|
2023-10-29 23:31:06 +00:00
|
|
|
|
2023-11-15 01:00:57 +00:00
|
|
|
match collection {
|
2023-10-29 23:31:06 +00:00
|
|
|
Value::List(list) => {
|
|
|
|
let index = self.index.run(source, context)?.as_integer()? as usize;
|
|
|
|
|
|
|
|
let item = if let Some(index_end) = &self.index_end {
|
|
|
|
let index_end = index_end.run(source, context)?.as_integer()? as usize;
|
|
|
|
let sublist = list.items()[index..=index_end].to_vec();
|
|
|
|
|
|
|
|
Value::List(List::with_items(sublist))
|
|
|
|
} else {
|
|
|
|
list.items().get(index).cloned().unwrap_or_default()
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(item)
|
|
|
|
}
|
2023-11-15 01:41:57 +00:00
|
|
|
Value::Map(map) => {
|
2023-11-10 21:24:19 +00:00
|
|
|
let value = if let Expression::Identifier(identifier) = &self.index {
|
|
|
|
let key = identifier.inner();
|
|
|
|
|
2023-12-09 22:15:41 +00:00
|
|
|
map.variables()?
|
|
|
|
.get(key)
|
|
|
|
.map(|(value, _)| value.clone())
|
|
|
|
.unwrap_or_default()
|
2023-11-10 21:24:19 +00:00
|
|
|
} else {
|
2023-11-15 01:00:57 +00:00
|
|
|
let value = self.index.run(source, context)?;
|
2023-11-10 21:24:19 +00:00
|
|
|
let key = value.as_string()?;
|
|
|
|
|
2023-12-09 22:15:41 +00:00
|
|
|
map.variables()?
|
|
|
|
.get(key)
|
|
|
|
.map(|(value, _)| value.clone())
|
|
|
|
.unwrap_or_default()
|
2023-11-10 21:24:19 +00:00
|
|
|
};
|
2023-10-29 23:31:06 +00:00
|
|
|
|
2023-10-30 21:11:06 +00:00
|
|
|
Ok(value)
|
2023-10-29 23:31:06 +00:00
|
|
|
}
|
|
|
|
Value::String(string) => {
|
|
|
|
let index = self.index.run(source, context)?.as_integer()? as usize;
|
|
|
|
let item = string.chars().nth(index).unwrap_or_default();
|
|
|
|
|
|
|
|
Ok(Value::String(item.to_string()))
|
|
|
|
}
|
2023-11-15 01:00:57 +00:00
|
|
|
_ => Err(Error::ExpectedCollection { actual: collection }),
|
2023-10-29 23:31:06 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
|
2023-12-05 22:08:22 +00:00
|
|
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
2023-12-13 20:47:41 +00:00
|
|
|
match self.collection.expected_type(context)? {
|
|
|
|
Type::List(item_type) => Ok(*item_type.clone()),
|
|
|
|
Type::Map => Ok(Type::Any),
|
2023-12-26 22:19:12 +00:00
|
|
|
Type::None => Ok(Type::None),
|
2023-12-13 20:47:41 +00:00
|
|
|
_ => todo!(),
|
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
}
|
2023-10-29 23:31:06 +00:00
|
|
|
}
|
2023-11-10 21:24:19 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use crate::evaluate;
|
|
|
|
|
|
|
|
#[test]
|
2023-11-30 14:30:25 +00:00
|
|
|
fn list_index() {
|
2023-11-10 21:24:19 +00:00
|
|
|
let test = evaluate("x = [1 [2] 3] x:1:0").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(Value::Integer(2), test);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-11-30 14:30:25 +00:00
|
|
|
fn map_index() {
|
2023-11-28 16:01:38 +00:00
|
|
|
let test = evaluate("x = {y = {z = 2}} x:y:z").unwrap();
|
2023-11-10 21:24:19 +00:00
|
|
|
|
|
|
|
assert_eq!(Value::Integer(2), test);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-11-30 14:30:25 +00:00
|
|
|
fn complex_index() {
|
|
|
|
let test = evaluate(
|
|
|
|
"
|
|
|
|
x = [1 2 3]
|
2023-12-12 23:21:16 +00:00
|
|
|
y = (fn) <int> { 0 }
|
2023-11-30 16:05:09 +00:00
|
|
|
x:(y)
|
2023-11-30 14:30:25 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-11-10 21:24:19 +00:00
|
|
|
|
|
|
|
assert_eq!(Value::Integer(1), test);
|
|
|
|
}
|
|
|
|
}
|