Implement lists
This commit is contained in:
parent
e23bf0f887
commit
41483f6b84
139
src/interface.rs
139
src/interface.rs
@ -5,7 +5,7 @@
|
|||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::{Node, Parser, Tree as TSTree};
|
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
||||||
|
|
||||||
use crate::{language, Error, Result, Value, VariableMap};
|
use crate::{language, Error, Result, Value, VariableMap};
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ pub trait EvaluatorTree: Sized {
|
|||||||
///
|
///
|
||||||
/// If necessary, the source code can be accessed directly by getting the
|
/// If necessary, the source code can be accessed directly by getting the
|
||||||
/// node's byte range.
|
/// node's byte range.
|
||||||
fn new(node: Node, source: &str) -> Result<Self>;
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self>;
|
||||||
|
|
||||||
/// Execute dust code by traversing the tree
|
/// Execute dust code by traversing the tree
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value>;
|
fn run(&self, context: &mut VariableMap) -> Result<Value>;
|
||||||
@ -99,17 +99,20 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(self) -> Vec<Result<Value>> {
|
fn run(self) -> Vec<Result<Value>> {
|
||||||
let mut cursor = self.tree.walk();
|
let mut cursor_0 = self.tree.walk();
|
||||||
let node = cursor.node();
|
let mut cursor_1 = self.tree.walk();
|
||||||
|
let node = cursor_0.node();
|
||||||
let item_count = node.child_count();
|
let item_count = node.child_count();
|
||||||
let mut results = Vec::with_capacity(item_count);
|
let mut results = Vec::with_capacity(item_count);
|
||||||
|
|
||||||
println!("{}", node.to_sexp());
|
println!("{}", node.to_sexp());
|
||||||
|
|
||||||
assert_eq!(cursor.node().kind(), "root");
|
assert_eq!(cursor_0.node().kind(), "root");
|
||||||
|
|
||||||
for item_node in node.children(&mut cursor) {
|
cursor_1.goto_first_child();
|
||||||
let item_result = Item::new(item_node, self.source);
|
|
||||||
|
for item_node in node.named_children(&mut cursor_0) {
|
||||||
|
let item_result = Item::new(self.source, &mut cursor_1);
|
||||||
|
|
||||||
match item_result {
|
match item_result {
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
@ -137,10 +140,12 @@ pub enum Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Item {
|
impl EvaluatorTree for Item {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
assert_eq!(node.kind(), "item");
|
let node = cursor.node();
|
||||||
|
cursor.goto_first_child();
|
||||||
|
let child = cursor.node();
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
assert_eq!(node.kind(), "item");
|
||||||
|
|
||||||
if child.kind() == "comment" {
|
if child.kind() == "comment" {
|
||||||
let byte_range = child.byte_range();
|
let byte_range = child.byte_range();
|
||||||
@ -148,7 +153,7 @@ impl EvaluatorTree for Item {
|
|||||||
|
|
||||||
Ok(Item::Comment(comment_text.to_string()))
|
Ok(Item::Comment(comment_text.to_string()))
|
||||||
} else if child.kind() == "statement" {
|
} else if child.kind() == "statement" {
|
||||||
Ok(Item::Statement(Statement::new(child, source)?))
|
Ok(Item::Statement(Statement::new(source, cursor)?))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedSyntax {
|
Err(Error::UnexpectedSyntax {
|
||||||
expected: "comment or statement",
|
expected: "comment or statement",
|
||||||
@ -177,12 +182,15 @@ pub enum Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Statement {
|
impl EvaluatorTree for Statement {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
|
cursor.goto_first_child();
|
||||||
|
let child = cursor.node();
|
||||||
|
|
||||||
assert_eq!(node.kind(), "statement");
|
assert_eq!(node.kind(), "statement");
|
||||||
let child = node.child(0).unwrap();
|
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"expression" => Ok(Self::Expression(Expression::new(child, source)?)),
|
"expression" => Ok(Self::Expression(Expression::new(source, cursor)?)),
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
expected: "expression",
|
expected: "expression",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
@ -209,17 +217,20 @@ pub enum Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Expression {
|
impl EvaluatorTree for Expression {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
|
cursor.goto_first_child();
|
||||||
|
let child = cursor.node();
|
||||||
|
|
||||||
assert_eq!(node.kind(), "expression");
|
assert_eq!(node.kind(), "expression");
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
|
||||||
let expression = match child.kind() {
|
let expression = match child.kind() {
|
||||||
"identifier" => Self::Identifier(Identifier::new(child, source)?),
|
"identifier" => Self::Identifier(Identifier::new(source, cursor)?),
|
||||||
"value" => Expression::Value(Value::new(child, source)?),
|
"value" => Expression::Value(Value::new(source, cursor)?),
|
||||||
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(child, source)?)),
|
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)),
|
||||||
"assignment" => Expression::Assignment(Box::new(Assignment::new(child, source)?)),
|
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)),
|
||||||
"math" => Expression::Math(Box::new(Math::new(child, source)?)),
|
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)),
|
||||||
"function_call" => Expression::FunctionCall(FunctionCall::new(child, source)?),
|
"function_call" => Expression::FunctionCall(FunctionCall::new(source, cursor)?),
|
||||||
_ => return Err(Error::UnexpectedSyntax {
|
_ => return Err(Error::UnexpectedSyntax {
|
||||||
expected:
|
expected:
|
||||||
"identifier, operation, control_flow, assignment, math, function_call or value",
|
"identifier, operation, control_flow, assignment, math, function_call or value",
|
||||||
@ -257,7 +268,9 @@ impl Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Identifier {
|
impl EvaluatorTree for Identifier {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
|
|
||||||
assert_eq!(node.kind(), "identifier");
|
assert_eq!(node.kind(), "identifier");
|
||||||
|
|
||||||
let identifier = &source[node.byte_range()];
|
let identifier = &source[node.byte_range()];
|
||||||
@ -280,23 +293,31 @@ pub struct ControlFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for ControlFlow {
|
impl EvaluatorTree for ControlFlow {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
|
cursor.goto_first_child();
|
||||||
|
let child = cursor.node();
|
||||||
|
|
||||||
assert_eq!(node.kind(), "control_flow");
|
assert_eq!(node.kind(), "control_flow");
|
||||||
|
|
||||||
// Skip the child nodes for the keywords "if", "then" and "else".
|
// Skip the child nodes for the keywords "if", "then" and "else".
|
||||||
let if_expression_node = node.child(1).unwrap();
|
let if_expression_node = child.next_named_sibling().unwrap();
|
||||||
let then_statement_node = node.child(3).unwrap();
|
let if_expression = Expression::new(source, cursor)?;
|
||||||
let else_statement_node = node.child(5);
|
|
||||||
|
let then_statement_node = node.next_named_sibling().unwrap();
|
||||||
|
let then_statement = Statement::new(source, cursor)?;
|
||||||
|
|
||||||
|
let else_statement_node = node.next_named_sibling();
|
||||||
|
|
||||||
let else_statement = if let Some(child) = else_statement_node {
|
let else_statement = if let Some(child) = else_statement_node {
|
||||||
Some(Statement::new(child, source)?)
|
Some(Statement::new(source, cursor)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ControlFlow {
|
Ok(ControlFlow {
|
||||||
if_expression: Expression::new(if_expression_node, source)?,
|
if_expression,
|
||||||
then_statement: Statement::new(then_statement_node, source)?,
|
then_statement,
|
||||||
else_statement,
|
else_statement,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -321,22 +342,30 @@ pub struct Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Assignment {
|
impl EvaluatorTree for Assignment {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
|
cursor.goto_first_child();
|
||||||
assert_eq!(node.kind(), "assignment");
|
assert_eq!(node.kind(), "assignment");
|
||||||
|
|
||||||
let identifier_node = node.child(0).unwrap();
|
cursor.goto_next_sibling();
|
||||||
let statement_node = node.child(2).unwrap();
|
let identifier = Identifier::new(source, cursor)?;
|
||||||
|
|
||||||
|
cursor.goto_next_sibling();
|
||||||
|
let statement = Statement::new(source, cursor)?;
|
||||||
|
|
||||||
|
cursor.goto_next_sibling();
|
||||||
|
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
identifier: Identifier::new(identifier_node, source)?,
|
identifier,
|
||||||
statement: Statement::new(statement_node, source)?,
|
statement,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
||||||
|
let key = self.identifier.clone().take_inner();
|
||||||
let value = self.statement.run(context)?;
|
let value = self.statement.run(context)?;
|
||||||
|
|
||||||
context.set_value(self.identifier.inner(), value)?;
|
context.set_value(key, value)?;
|
||||||
|
|
||||||
Ok(Value::Empty)
|
Ok(Value::Empty)
|
||||||
}
|
}
|
||||||
@ -350,12 +379,15 @@ pub struct Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for Math {
|
impl EvaluatorTree for Math {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
assert_eq!(node.kind(), "math");
|
assert_eq!(node.kind(), "math");
|
||||||
|
|
||||||
let left_node = node.child(0).unwrap();
|
cursor.goto_first_child();
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let left = Expression::new(source, cursor)?;
|
||||||
let right_node = node.child(2).unwrap();
|
|
||||||
|
cursor.goto_next_sibling();
|
||||||
|
let operator_node = cursor.node();
|
||||||
let operator = match operator_node.kind() {
|
let operator = match operator_node.kind() {
|
||||||
"+" => MathOperator::Add,
|
"+" => MathOperator::Add,
|
||||||
"-" => MathOperator::Subtract,
|
"-" => MathOperator::Subtract,
|
||||||
@ -371,10 +403,13 @@ impl EvaluatorTree for Math {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cursor.goto_next_sibling();
|
||||||
|
let right = Expression::new(source, cursor)?;
|
||||||
|
|
||||||
Ok(Math {
|
Ok(Math {
|
||||||
left: Expression::new(left_node, source)?,
|
left,
|
||||||
operator,
|
operator,
|
||||||
right: Expression::new(right_node, source)?,
|
right,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,23 +444,25 @@ pub struct FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvaluatorTree for FunctionCall {
|
impl EvaluatorTree for FunctionCall {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
|
let node = cursor.node();
|
||||||
assert_eq!(node.kind(), "function_call");
|
assert_eq!(node.kind(), "function_call");
|
||||||
|
|
||||||
let identifier_node = node.child(0).unwrap();
|
cursor.goto_first_child();
|
||||||
|
let identifier = Identifier::new(source, cursor)?;
|
||||||
|
|
||||||
let mut expressions = Vec::new();
|
let mut expressions = Vec::new();
|
||||||
|
|
||||||
for index in 2..node.child_count() - 1 {
|
for index in 2..node.child_count() - 1 {
|
||||||
let child = node.child(index).unwrap();
|
cursor.goto_next_sibling();
|
||||||
if child.kind() == "expression" {
|
|
||||||
let expression = Expression::new(node, source)?;
|
let expression = Expression::new(source, cursor)?;
|
||||||
|
|
||||||
expressions.push(expression);
|
expressions.push(expression);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(FunctionCall {
|
Ok(FunctionCall {
|
||||||
identifier: Identifier::new(identifier_node, source)?,
|
identifier,
|
||||||
expressions,
|
expressions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -504,8 +541,8 @@ mod tests {
|
|||||||
fn evaluate_map() {
|
fn evaluate_map() {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
map.set_value("x", Value::Integer(1)).unwrap();
|
map.set_value("x".to_string(), Value::Integer(1)).unwrap();
|
||||||
map.set_value("foo", Value::String("bar".to_string()))
|
map.set_value("foo".to_string(), Value::String("bar".to_string()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(eval("map { x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]);
|
assert_eq!(eval("map { x = 1 foo = 'bar' }"), vec![Ok(Value::Map(map))]);
|
||||||
|
@ -57,7 +57,7 @@ impl Tool for Transform {
|
|||||||
for value in list {
|
for value in list {
|
||||||
let mut context = VariableMap::new();
|
let mut context = VariableMap::new();
|
||||||
|
|
||||||
context.set_value("input", value.clone())?;
|
context.set_value("input".to_string(), value.clone())?;
|
||||||
|
|
||||||
let mapped_value = function.run_with_context(&mut context)?;
|
let mapped_value = function.run_with_context(&mut context)?;
|
||||||
|
|
||||||
@ -321,7 +321,7 @@ impl Tool for Select {
|
|||||||
|
|
||||||
for (key, value) in map.inner() {
|
for (key, value) in map.inner() {
|
||||||
if column_names.contains(key) {
|
if column_names.contains(key) {
|
||||||
selected.set_value(key, value.clone())?;
|
selected.set_value(key.to_string(), value.clone())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ impl Tool for Where {
|
|||||||
for (column_index, cell) in row.iter().enumerate() {
|
for (column_index, cell) in row.iter().enumerate() {
|
||||||
let column_name = table.column_names().get(column_index).unwrap();
|
let column_name = table.column_names().get(column_index).unwrap();
|
||||||
|
|
||||||
context.set_value(column_name, cell.clone())?;
|
context.set_value(column_name.to_string(), cell.clone())?;
|
||||||
}
|
}
|
||||||
let keep_row = function.run_with_context(&mut context)?.as_boolean()?;
|
let keep_row = function.run_with_context(&mut context)?.as_boolean()?;
|
||||||
|
|
||||||
|
163
src/value/mod.rs
163
src/value/mod.rs
@ -10,14 +10,14 @@ use serde::{
|
|||||||
ser::SerializeTuple,
|
ser::SerializeTuple,
|
||||||
Deserialize, Serialize, Serializer,
|
Deserialize, Serialize, Serializer,
|
||||||
};
|
};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::{Node, TreeCursor};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::{Add, Sub},
|
ops::{Add, Range, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod function;
|
pub mod function;
|
||||||
@ -48,129 +48,79 @@ pub enum Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn new(node: Node, source: &str) -> Result<Self> {
|
pub fn new(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> {
|
||||||
assert!(
|
let node = cursor.node();
|
||||||
node.kind() == "value" || node.kind() == "list",
|
cursor.goto_first_child();
|
||||||
"{}",
|
let child = cursor.node();
|
||||||
node.kind()
|
|
||||||
);
|
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
assert_eq!(node.kind(), "value");
|
||||||
let value_snippet = &source[node.byte_range()];
|
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"integer" => {
|
"integer" | "float" | "boolean" | "string" | "empty" => {
|
||||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
Value::from_syntax_node(child, source)
|
||||||
|
|
||||||
Ok(Value::Integer(raw))
|
|
||||||
}
|
|
||||||
"string" => {
|
|
||||||
let quote_str = &value_snippet.chars().nth(0).unwrap();
|
|
||||||
let without_quotes = value_snippet.trim_matches(*quote_str);
|
|
||||||
|
|
||||||
Ok(Value::String(without_quotes.to_string()))
|
|
||||||
}
|
|
||||||
"boolean" => {
|
|
||||||
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
|
||||||
|
|
||||||
Ok(Value::Boolean(raw))
|
|
||||||
}
|
|
||||||
"float" => {
|
|
||||||
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
|
||||||
|
|
||||||
Ok(Value::Float(raw))
|
|
||||||
}
|
}
|
||||||
"list" => {
|
"list" => {
|
||||||
let grandchild_count = child.child_count();
|
let list_length = child.named_child_count();
|
||||||
let mut values = Vec::with_capacity(grandchild_count);
|
let mut values = Vec::with_capacity(list_length);
|
||||||
|
|
||||||
let mut previous_grandchild = child.child(0).unwrap();
|
cursor.goto_first_child();
|
||||||
|
|
||||||
for _ in 0..grandchild_count {
|
for value_node in child.children_by_field_name("item", &mut cursor) {
|
||||||
if let Some(current_node) = previous_grandchild.next_sibling() {
|
let value = Value::from_syntax_node(value_node.child(0).unwrap(), source)?;
|
||||||
if current_node.kind() == "value" {
|
|
||||||
let value = Value::new(current_node, source)?;
|
|
||||||
|
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
previous_grandchild = current_node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::List(values))
|
Ok(Value::List(values))
|
||||||
}
|
}
|
||||||
"table" => {
|
"table" => {
|
||||||
let child_count = node.child_count();
|
|
||||||
let mut column_names = Vec::new();
|
let mut column_names = Vec::new();
|
||||||
let mut rows = Vec::new();
|
|
||||||
|
|
||||||
// Skip the first and last nodes because they are pointy braces.
|
|
||||||
for index in 0..child_count {
|
|
||||||
let child = node.child(index).unwrap();
|
|
||||||
|
|
||||||
if child.kind() == "identifier" {
|
|
||||||
let identifier = Identifier::new(child, source)?;
|
|
||||||
|
|
||||||
column_names.push(identifier.take_inner())
|
|
||||||
}
|
|
||||||
|
|
||||||
if child.kind() == "list" {
|
|
||||||
let child_value = Value::new(node, source)?;
|
|
||||||
|
|
||||||
if let Value::List(row) = child_value {
|
|
||||||
rows.push(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut table = Table::new(column_names);
|
let mut table = Table::new(column_names);
|
||||||
table.reserve(rows.len());
|
|
||||||
|
|
||||||
for row in rows {
|
|
||||||
table.insert(row)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::Table(table))
|
Ok(Value::Table(table))
|
||||||
}
|
}
|
||||||
"map" => {
|
"map" => {
|
||||||
let child_count = node.child_count();
|
let grandchild_count = child.child_count();
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
|
let mut previous_grandchild = child.child(0).unwrap();
|
||||||
let mut key = String::new();
|
let mut key = String::new();
|
||||||
|
|
||||||
for index in 0..child_count {
|
for _ in 0..grandchild_count {
|
||||||
let child = node.child(index).unwrap();
|
if let Some(current_node) = previous_grandchild.next_sibling() {
|
||||||
|
if current_node.kind() == "identifier" {
|
||||||
if child.kind() == "identifier" {
|
key = Identifier::new(source, cursor)?.take_inner();
|
||||||
let identifier = Identifier::new(child, source)?;
|
|
||||||
|
|
||||||
key = identifier.take_inner()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if child.kind() == "value" {
|
if current_node.kind() == "value" {
|
||||||
let value = Value::new(child, source)?;
|
let value = Value::new(source, cursor)?;
|
||||||
|
|
||||||
map.set_value(key.as_str(), value)?;
|
map.set_value(key.clone(), value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_grandchild = current_node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Map(map))
|
||||||
}
|
}
|
||||||
"function" => {
|
"function" => {
|
||||||
let child_count = node.child_count();
|
let child_count = child.child_count();
|
||||||
let mut identifiers = Vec::new();
|
let mut identifiers = Vec::new();
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
for index in 0..child_count {
|
for index in 0..child_count {
|
||||||
let child = node.child(index).unwrap();
|
let child = child.child(index).unwrap();
|
||||||
|
|
||||||
if child.kind() == "identifier" {
|
if child.kind() == "identifier" {
|
||||||
let identifier = Identifier::new(child, source)?;
|
let identifier = Identifier::new(source, cursor)?;
|
||||||
|
|
||||||
identifiers.push(identifier)
|
identifiers.push(identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
if child.kind() == "statement" {
|
if child.kind() == "statement" {
|
||||||
let statement = Statement::new(child, source)?;
|
let statement = Statement::new(source, cursor)?;
|
||||||
|
|
||||||
statements.push(statement)
|
statements.push(statement)
|
||||||
}
|
}
|
||||||
@ -178,15 +128,58 @@ impl Value {
|
|||||||
|
|
||||||
Ok(Value::Function(Function::new(identifiers, statements)))
|
Ok(Value::Function(Function::new(identifiers, statements)))
|
||||||
}
|
}
|
||||||
"empty" => Ok(Value::Empty),
|
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
expected: "integer, string, boolean, float, list, table, function or empty",
|
expected: "integer, float, boolean, string list, table, map, function or empty",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
|
match node.kind() {
|
||||||
|
"integer" => Value::integer_from_source(source, node.byte_range()),
|
||||||
|
"float" => Value::integer_from_source(source, node.byte_range()),
|
||||||
|
"boolean" => Value::integer_from_source(source, node.byte_range()),
|
||||||
|
"string" => Value::integer_from_source(source, node.byte_range()),
|
||||||
|
"empty" => Ok(Value::Empty),
|
||||||
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
|
expected: "integer, float, boolean, string or empty",
|
||||||
|
actual: node.kind(),
|
||||||
|
location: node.start_position(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Value::Integer(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<f64>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Value::Float(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let raw = value_snippet.parse::<bool>().unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(Value::Boolean(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
|
||||||
|
let value_snippet = &source[byte_range];
|
||||||
|
let quote_str = &value_snippet.chars().nth(0).unwrap();
|
||||||
|
let without_quotes = value_snippet.trim_matches(*quote_str);
|
||||||
|
|
||||||
|
Ok(Value::String(without_quotes.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
ValueType::from(self)
|
ValueType::from(self)
|
||||||
}
|
}
|
||||||
@ -612,7 +605,7 @@ impl TryFrom<JsonValue> for Value {
|
|||||||
for (key, node_value) in object.iter() {
|
for (key, node_value) in object.iter() {
|
||||||
let value = Value::try_from(node_value)?;
|
let value = Value::try_from(node_value)?;
|
||||||
|
|
||||||
map.set_value(key, value)?;
|
map.set_value(key.to_string(), value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Map(map))
|
||||||
@ -650,7 +643,7 @@ impl TryFrom<&JsonValue> for Value {
|
|||||||
for (key, node_value) in object.iter() {
|
for (key, node_value) in object.iter() {
|
||||||
let value = Value::try_from(node_value)?;
|
let value = Value::try_from(node_value)?;
|
||||||
|
|
||||||
map.set_value(key, value)?;
|
map.set_value(key.to_string(), value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Map(map))
|
||||||
|
@ -49,7 +49,7 @@ impl VariableMap {
|
|||||||
if let Ok(function) = value.as_function() {
|
if let Ok(function) = value.as_function() {
|
||||||
let mut context = self.clone();
|
let mut context = self.clone();
|
||||||
|
|
||||||
context.set_value("input", argument.clone())?;
|
context.set_value("input".to_string(), argument.clone())?;
|
||||||
|
|
||||||
return function.run_with_context(&mut context);
|
return function.run_with_context(&mut context);
|
||||||
}
|
}
|
||||||
@ -95,8 +95,8 @@ impl VariableMap {
|
|||||||
|
|
||||||
/// Assigns a variable with a Value and the identifier as its key, allowing dot notation to
|
/// Assigns a variable with a Value and the identifier as its key, allowing dot notation to
|
||||||
/// assign nested lists and maps. Returns an error if a List or Map is indexed incorrectly.
|
/// assign nested lists and maps. Returns an error if a List or Map is indexed incorrectly.
|
||||||
pub fn set_value(&mut self, identifier: &str, value: Value) -> Result<()> {
|
pub fn set_value(&mut self, key: String, value: Value) -> Result<()> {
|
||||||
let split = identifier.split_once('.');
|
let split = key.split_once('.');
|
||||||
|
|
||||||
if let Some((identifier, next_identifier)) = split {
|
if let Some((identifier, next_identifier)) = split {
|
||||||
let get_value = self.variables.get_mut(identifier);
|
let get_value = self.variables.get_mut(identifier);
|
||||||
@ -121,7 +121,7 @@ impl VariableMap {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else if let Value::Map(map) = found_value {
|
} else if let Value::Map(map) = found_value {
|
||||||
map.set_value(next_identifier, value)
|
map.set_value(next_identifier.to_string(), value)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ExpectedMap {
|
Err(Error::ExpectedMap {
|
||||||
actual: found_value.clone(),
|
actual: found_value.clone(),
|
||||||
@ -130,7 +130,7 @@ impl VariableMap {
|
|||||||
} else {
|
} else {
|
||||||
let mut new_map = VariableMap::new();
|
let mut new_map = VariableMap::new();
|
||||||
|
|
||||||
new_map.set_value(next_identifier, value)?;
|
new_map.set_value(next_identifier.to_string(), value)?;
|
||||||
|
|
||||||
self.variables
|
self.variables
|
||||||
.insert(identifier.to_string(), Value::Map(new_map));
|
.insert(identifier.to_string(), Value::Map(new_map));
|
||||||
@ -138,7 +138,7 @@ impl VariableMap {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.variables.insert(identifier.to_string(), value);
|
self.variables.insert(key.to_string(), value);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ impl From<&Table> for VariableMap {
|
|||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::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(row.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ mod tests {
|
|||||||
fn get_and_set_simple_value() {
|
fn get_and_set_simple_value() {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
map.set_value("x", Value::Integer(1)).unwrap();
|
map.set_value("x".to_string(), Value::Integer(1)).unwrap();
|
||||||
|
|
||||||
assert_eq!(Value::Integer(1), map.get_value("x").unwrap().unwrap());
|
assert_eq!(Value::Integer(1), map.get_value("x").unwrap().unwrap());
|
||||||
}
|
}
|
||||||
@ -202,12 +202,13 @@ mod tests {
|
|||||||
fn get_and_set_nested_maps() {
|
fn get_and_set_nested_maps() {
|
||||||
let mut map = VariableMap::new();
|
let mut map = VariableMap::new();
|
||||||
|
|
||||||
map.set_value("x", Value::Map(VariableMap::new())).unwrap();
|
map.set_value("x".to_string(), Value::Map(VariableMap::new()))
|
||||||
map.set_value("x.x", Value::Map(VariableMap::new()))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
map.set_value("x.x.x", Value::Map(VariableMap::new()))
|
map.set_value("x.x".to_string(), Value::Map(VariableMap::new()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
map.set_value("x.x.x.x", Value::Map(VariableMap::new()))
|
map.set_value("x.x.x".to_string(), Value::Map(VariableMap::new()))
|
||||||
|
.unwrap();
|
||||||
|
map.set_value("x.x.x.x".to_string(), Value::Map(VariableMap::new()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
Loading…
Reference in New Issue
Block a user