Implement new control flow syntax
This commit is contained in:
parent
574cff5cc6
commit
9450e6dc96
@ -20,9 +20,9 @@ pub enum AssignmentOperator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Assignment {
|
impl AbstractTree for Assignment {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let identifier_node = node.child(0).unwrap();
|
let identifier_node = node.child(0).unwrap();
|
||||||
let identifier = Identifier::from_syntax_node(identifier_node, source)?;
|
let identifier = Identifier::from_syntax_node(source, identifier_node)?;
|
||||||
|
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
||||||
let operator = match operator_node.kind() {
|
let operator = match operator_node.kind() {
|
||||||
@ -30,17 +30,17 @@ impl AbstractTree for Assignment {
|
|||||||
"+=" => AssignmentOperator::PlusEqual,
|
"+=" => AssignmentOperator::PlusEqual,
|
||||||
"-=" => AssignmentOperator::MinusEqual,
|
"-=" => AssignmentOperator::MinusEqual,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "=, += or -=",
|
expected: "=, += or -=",
|
||||||
actual: operator_node.kind(),
|
actual: operator_node.kind(),
|
||||||
location: operator_node.start_position(),
|
location: operator_node.start_position(),
|
||||||
relevant_source: source[node.byte_range()].to_string(),
|
relevant_source: source[operator_node.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let statement_node = node.child(2).unwrap();
|
let statement_node = node.child(2).unwrap();
|
||||||
let statement = Statement::from_syntax_node(statement_node, source)?;
|
let statement = Statement::from_syntax_node(source, statement_node)?;
|
||||||
|
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
identifier,
|
identifier,
|
||||||
@ -49,9 +49,9 @@ impl AbstractTree for Assignment {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let key = self.identifier.clone().take_inner();
|
let key = self.identifier.run(source, context)?.to_string();
|
||||||
let mut value = self.statement.run(context)?;
|
let mut value = self.statement.run(source, context)?;
|
||||||
|
|
||||||
match self.operator {
|
match self.operator {
|
||||||
AssignmentOperator::PlusEqual => {
|
AssignmentOperator::PlusEqual => {
|
||||||
|
@ -1,39 +1,39 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Identifier, Result, Value, VariableMap};
|
use crate::{value::ValueNode, AbstractTree, Error, Identifier, Result, Value, VariableMap};
|
||||||
|
|
||||||
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
|
Value(ValueNode),
|
||||||
Identifier(Identifier),
|
Identifier(Identifier),
|
||||||
Value(Value),
|
|
||||||
Math(Box<Math>),
|
Math(Box<Math>),
|
||||||
Logic(Box<Logic>),
|
Logic(Box<Logic>),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Expression {
|
impl AbstractTree for Expression {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("expression", node.kind());
|
debug_assert_eq!("expression", node.kind());
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
let expression = match child.kind() {
|
let expression = match child.kind() {
|
||||||
"value" => Expression::Value(Value::from_syntax_node(child, source)?),
|
"value" => Expression::Value(ValueNode::from_syntax_node(source, child)?),
|
||||||
"identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?),
|
"identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?),
|
||||||
"math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)),
|
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)),
|
||||||
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(child, source)?)),
|
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)),
|
||||||
"function_call" => {
|
"function_call" => {
|
||||||
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
|
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "value, identifier, math or function_call",
|
expected: "value, identifier, math or function_call",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
relevant_source: source[node.byte_range()].to_string(),
|
relevant_source: source[child.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -41,13 +41,13 @@ impl AbstractTree for Expression {
|
|||||||
Ok(expression)
|
Ok(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Value(value) => Ok(value.clone()),
|
Expression::Value(value_node) => value_node.run(source, context),
|
||||||
Expression::Identifier(identifier) => identifier.run(context),
|
Expression::Identifier(identifier) => identifier.run(source, context),
|
||||||
Expression::Math(math) => math.run(context),
|
Expression::Math(math) => math.run(source, context),
|
||||||
Expression::Logic(logic) => logic.run(context),
|
Expression::Logic(logic) => logic.run(source, context),
|
||||||
Expression::FunctionCall(function_call) => function_call.run(context),
|
Expression::FunctionCall(function_call) => function_call.run(source, context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,14 @@ pub enum FunctionName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for FunctionCall {
|
impl AbstractTree for FunctionCall {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("function_call", node.kind());
|
debug_assert_eq!("function_call", node.kind());
|
||||||
|
|
||||||
let name_node = node.child(1).unwrap();
|
let name_node = node.child(1).unwrap();
|
||||||
|
|
||||||
let name = match name_node.kind() {
|
let name = match name_node.kind() {
|
||||||
"identifier" => {
|
"identifier" => {
|
||||||
FunctionName::Identifier(Identifier::from_syntax_node(name_node, source)?)
|
FunctionName::Identifier(Identifier::from_syntax_node(source, name_node)?)
|
||||||
}
|
}
|
||||||
"tool" => {
|
"tool" => {
|
||||||
let tool_node = name_node.child(0).unwrap();
|
let tool_node = name_node.child(0).unwrap();
|
||||||
@ -45,7 +45,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
let mut current_index = 2;
|
let mut current_index = 2;
|
||||||
while current_index < node.child_count() - 1 {
|
while current_index < node.child_count() - 1 {
|
||||||
let expression_node = node.child(current_index).unwrap();
|
let expression_node = node.child(current_index).unwrap();
|
||||||
let expression = Expression::from_syntax_node(expression_node, source)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
arguments.push(expression);
|
arguments.push(expression);
|
||||||
|
|
||||||
@ -55,20 +55,21 @@ impl AbstractTree for FunctionCall {
|
|||||||
Ok(FunctionCall { name, arguments })
|
Ok(FunctionCall { name, arguments })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let identifier = match &self.name {
|
let identifier = match &self.name {
|
||||||
FunctionName::Identifier(identifier) => identifier,
|
FunctionName::Identifier(identifier) => identifier,
|
||||||
FunctionName::Tool(tool) => {
|
FunctionName::Tool(tool) => {
|
||||||
let value = self
|
let value = self
|
||||||
.arguments
|
.arguments
|
||||||
.first()
|
.first()
|
||||||
.map(|expression| expression.run(context))
|
.map(|expression| expression.run(source, context))
|
||||||
.unwrap_or(Ok(Value::Empty))?;
|
.unwrap_or(Ok(Value::Empty))?;
|
||||||
|
|
||||||
return tool.run(&value);
|
return tool.run(&value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let definition = if let Some(value) = context.get_value(identifier.inner())? {
|
let key = identifier.inner();
|
||||||
|
let definition = if let Some(value) = context.get_value(key)? {
|
||||||
value.as_function().cloned()?
|
value.as_function().cloned()?
|
||||||
} else {
|
} else {
|
||||||
return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone()));
|
return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone()));
|
||||||
@ -78,12 +79,12 @@ impl AbstractTree for FunctionCall {
|
|||||||
let mut function_context = context.clone();
|
let mut function_context = context.clone();
|
||||||
|
|
||||||
for (identifier, expression) in id_expr_pairs {
|
for (identifier, expression) in id_expr_pairs {
|
||||||
let key = identifier.clone().take_inner();
|
let key = identifier.run(source, context)?.to_string();
|
||||||
let value = expression.run(&mut function_context)?;
|
let value = expression.run(source, &mut function_context)?;
|
||||||
|
|
||||||
function_context.set_value(key, value)?;
|
function_context.set_value(key, value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
definition.body().run(&mut function_context)
|
definition.body().run(source, &mut function_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@ impl Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Identifier {
|
impl AbstractTree for Identifier {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let identifier = &source[node.byte_range()];
|
let identifier = &source[node.byte_range()];
|
||||||
|
|
||||||
Ok(Identifier(identifier.to_string()))
|
Ok(Identifier(identifier.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let value = context.get_value(&self.0)?.unwrap_or_default();
|
let value = context.get_value(&self.0)?.unwrap_or_default();
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
@ -13,12 +13,12 @@ pub struct IfElse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for IfElse {
|
impl AbstractTree for IfElse {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let if_node = node.child(0).unwrap().child(1).unwrap();
|
let if_node = node.child(0).unwrap().child(1).unwrap();
|
||||||
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
let if_expression = Expression::from_syntax_node(source, if_node)?;
|
||||||
|
|
||||||
let then_node = node.child(0).unwrap().child(3).unwrap();
|
let then_node = node.child(0).unwrap().child(3).unwrap();
|
||||||
let then_statement = Statement::from_syntax_node(then_node, source)?;
|
let then_statement = Statement::from_syntax_node(source, then_node)?;
|
||||||
|
|
||||||
let child_count = node.child_count();
|
let child_count = node.child_count();
|
||||||
let mut else_if_expressions = Vec::new();
|
let mut else_if_expressions = Vec::new();
|
||||||
@ -31,19 +31,19 @@ impl AbstractTree for IfElse {
|
|||||||
if let Some(node) = child {
|
if let Some(node) = child {
|
||||||
if node.kind() == "else_if" {
|
if node.kind() == "else_if" {
|
||||||
let expression_node = node.child(1).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(expression_node, source)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
else_if_expressions.push(expression);
|
else_if_expressions.push(expression);
|
||||||
|
|
||||||
let statement_node = node.child(3).unwrap();
|
let statement_node = node.child(3).unwrap();
|
||||||
let statement = Statement::from_syntax_node(statement_node, source)?;
|
let statement = Statement::from_syntax_node(source, statement_node)?;
|
||||||
|
|
||||||
else_if_statements.push(statement);
|
else_if_statements.push(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.kind() == "else" {
|
if node.kind() == "else" {
|
||||||
let else_node = node.child(2).unwrap();
|
let else_node = node.child(2).unwrap();
|
||||||
else_statement = Some(Statement::from_syntax_node(else_node, source)?);
|
else_statement = Some(Statement::from_syntax_node(source, else_node)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,26 +57,26 @@ impl AbstractTree for IfElse {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let if_boolean = self.if_expression.run(context)?.as_boolean()?;
|
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
|
||||||
|
|
||||||
if if_boolean {
|
if if_boolean {
|
||||||
self.then_statement.run(context)
|
self.then_statement.run(source, context)
|
||||||
} else {
|
} else {
|
||||||
let expressions = &self.else_if_expressions;
|
let expressions = &self.else_if_expressions;
|
||||||
|
|
||||||
for (index, expression) in expressions.into_iter().enumerate() {
|
for (index, expression) in expressions.into_iter().enumerate() {
|
||||||
let if_boolean = expression.run(context)?.as_boolean()?;
|
let if_boolean = expression.run(source, context)?.as_boolean()?;
|
||||||
|
|
||||||
if if_boolean {
|
if if_boolean {
|
||||||
let statement = self.else_if_statements.get(index).unwrap();
|
let statement = self.else_if_statements.get(index).unwrap();
|
||||||
|
|
||||||
return statement.run(context);
|
return statement.run(source, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(statement) = &self.else_statement {
|
if let Some(statement) = &self.else_statement {
|
||||||
statement.run(context)
|
statement.run(source, context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Empty)
|
Ok(Value::Empty)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ impl Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Item {
|
impl AbstractTree for Item {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("item", node.kind());
|
debug_assert_eq!("item", node.kind());
|
||||||
|
|
||||||
let child_count = node.child_count();
|
let child_count = node.child_count();
|
||||||
@ -32,13 +32,13 @@ impl AbstractTree for Item {
|
|||||||
let child = node.child(index).unwrap();
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
let statement = match child.kind() {
|
let statement = match child.kind() {
|
||||||
"statement" => Statement::from_syntax_node(child, source)?,
|
"statement" => Statement::from_syntax_node(source, child)?,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "comment or statement",
|
expected: "comment or statement",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
relevant_source: source[node.byte_range()].to_string(),
|
relevant_source: source[child.byte_range()].to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -49,12 +49,12 @@ impl AbstractTree for Item {
|
|||||||
Ok(Item { statements })
|
Ok(Item { statements })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let mut prev_result = Ok(Value::Empty);
|
let mut prev_result = Ok(Value::Empty);
|
||||||
|
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
prev_result?;
|
prev_result?;
|
||||||
prev_result = statement.run(context);
|
prev_result = statement.run(source, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_result
|
prev_result
|
||||||
|
@ -11,9 +11,9 @@ pub struct Logic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Logic {
|
impl AbstractTree for Logic {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let left_node = node.child(0).unwrap();
|
let left_node = node.child(0).unwrap();
|
||||||
let left = Expression::from_syntax_node(left_node, source)?;
|
let left = Expression::from_syntax_node(source, left_node)?;
|
||||||
|
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
||||||
let operator = match operator_node.kind() {
|
let operator = match operator_node.kind() {
|
||||||
@ -25,7 +25,7 @@ impl AbstractTree for Logic {
|
|||||||
">=" => LogicOperator::GreaterOrEqual,
|
">=" => LogicOperator::GreaterOrEqual,
|
||||||
"<=" => LogicOperator::LessOrEqaul,
|
"<=" => LogicOperator::LessOrEqaul,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "==, && or ||",
|
expected: "==, && or ||",
|
||||||
actual: operator_node.kind(),
|
actual: operator_node.kind(),
|
||||||
location: operator_node.start_position(),
|
location: operator_node.start_position(),
|
||||||
@ -35,7 +35,7 @@ impl AbstractTree for Logic {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let right_node = node.child(2).unwrap();
|
let right_node = node.child(2).unwrap();
|
||||||
let right = Expression::from_syntax_node(right_node, source)?;
|
let right = Expression::from_syntax_node(source, right_node)?;
|
||||||
|
|
||||||
Ok(Logic {
|
Ok(Logic {
|
||||||
left,
|
left,
|
||||||
@ -44,9 +44,9 @@ impl AbstractTree for Logic {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
let left = self.left.run(context)?;
|
let left = self.left.run(source, context)?;
|
||||||
let right = self.right.run(context)?;
|
let right = self.right.run(source, context)?;
|
||||||
let result = match self.operator {
|
let result = match self.operator {
|
||||||
LogicOperator::Equal => {
|
LogicOperator::Equal => {
|
||||||
if let (Ok(left_num), Ok(right_num)) = (left.as_number(), right.as_number()) {
|
if let (Ok(left_num), Ok(right_num)) = (left.as_number(), right.as_number()) {
|
||||||
|
@ -12,11 +12,11 @@ use crate::{AbstractTree, Result, Value, VariableMap};
|
|||||||
pub struct Match {}
|
pub struct Match {}
|
||||||
|
|
||||||
impl AbstractTree for Match {
|
impl AbstractTree for Match {
|
||||||
fn from_syntax_node(_node: Node, _source: &str) -> Result<Self> {
|
fn from_syntax_node(_source: &str, _node: Node) -> Result<Self> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, _context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, _source: &str, _context: &mut VariableMap) -> Result<Value> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ pub struct Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Math {
|
impl AbstractTree for Math {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let left_node = node.child(0).unwrap();
|
let left_node = node.child(0).unwrap();
|
||||||
let left = Expression::from_syntax_node(left_node, source)?;
|
let left = Expression::from_syntax_node(source, left_node)?;
|
||||||
|
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
||||||
let operator = match operator_node.kind() {
|
let operator = match operator_node.kind() {
|
||||||
@ -23,7 +23,7 @@ impl AbstractTree for Math {
|
|||||||
"/" => MathOperator::Divide,
|
"/" => MathOperator::Divide,
|
||||||
"%" => MathOperator::Modulo,
|
"%" => MathOperator::Modulo,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "+, -, *, / or %",
|
expected: "+, -, *, / or %",
|
||||||
actual: operator_node.kind(),
|
actual: operator_node.kind(),
|
||||||
location: operator_node.start_position(),
|
location: operator_node.start_position(),
|
||||||
@ -33,7 +33,7 @@ impl AbstractTree for Math {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let right_node = node.child(2).unwrap();
|
let right_node = node.child(2).unwrap();
|
||||||
let right = Expression::from_syntax_node(right_node, source)?;
|
let right = Expression::from_syntax_node(source, right_node)?;
|
||||||
|
|
||||||
Ok(Math {
|
Ok(Math {
|
||||||
left,
|
left,
|
||||||
@ -42,11 +42,11 @@ impl AbstractTree for Math {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self.operator {
|
match self.operator {
|
||||||
MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => {
|
MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => {
|
||||||
let left_value = self.left.run(context)?.as_int()?;
|
let left_value = self.left.run(source, context)?.as_int()?;
|
||||||
let right_value = self.right.run(context)?.as_int()?;
|
let right_value = self.right.run(source, context)?.as_int()?;
|
||||||
let outcome = match &self.operator {
|
let outcome = match &self.operator {
|
||||||
MathOperator::Add => left_value + right_value,
|
MathOperator::Add => left_value + right_value,
|
||||||
MathOperator::Subtract => left_value - right_value,
|
MathOperator::Subtract => left_value - right_value,
|
||||||
@ -57,8 +57,8 @@ impl AbstractTree for Math {
|
|||||||
Ok(Value::Integer(outcome))
|
Ok(Value::Integer(outcome))
|
||||||
}
|
}
|
||||||
MathOperator::Divide | MathOperator::Modulo => {
|
MathOperator::Divide | MathOperator::Modulo => {
|
||||||
let left_value = self.left.run(context)?.as_number()?;
|
let left_value = self.left.run(source, context)?.as_number()?;
|
||||||
let right_value = self.right.run(context)?.as_number()?;
|
let right_value = self.right.run(source, context)?.as_number()?;
|
||||||
let outcome = match self.operator {
|
let outcome = match self.operator {
|
||||||
MathOperator::Divide => left_value / right_value,
|
MathOperator::Divide => left_value / right_value,
|
||||||
MathOperator::Modulo => left_value % right_value,
|
MathOperator::Modulo => left_value % right_value,
|
||||||
|
@ -40,8 +40,8 @@ pub trait AbstractTree: 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 from_syntax_node(node: Node, source: &str) -> Result<Self>;
|
fn from_syntax_node(source: &str, node: Node) -> 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, source: &str, context: &mut VariableMap) -> Result<Value>;
|
||||||
}
|
}
|
||||||
|
@ -20,43 +20,43 @@ pub enum Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Statement {
|
impl AbstractTree for Statement {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
debug_assert_eq!("statement", node.kind());
|
debug_assert_eq!("statement", node.kind());
|
||||||
|
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
"assignment" => Ok(Statement::Assignment(Box::new(
|
"assignment" => Ok(Statement::Assignment(Box::new(
|
||||||
Assignment::from_syntax_node(child, source)?,
|
Assignment::from_syntax_node(source, child)?,
|
||||||
))),
|
))),
|
||||||
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
||||||
child, source,
|
source, child,
|
||||||
)?)),
|
)?)),
|
||||||
"if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node(
|
"if_else" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node(
|
||||||
child, source,
|
source, child,
|
||||||
)?))),
|
)?))),
|
||||||
"tool" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node(
|
"tool" => Ok(Statement::IfElse(Box::new(IfElse::from_syntax_node(
|
||||||
child, source,
|
source, child,
|
||||||
)?))),
|
)?))),
|
||||||
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
|
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
|
||||||
child, source,
|
source, child,
|
||||||
)?))),
|
)?))),
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "assignment, expression, if...else or tool",
|
expected: "assignment, expression, if...else or tool",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
relevant_source: source[node.byte_range()].to_string(),
|
relevant_source: source[child.byte_range()].to_string(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.run(context),
|
Statement::Assignment(assignment) => assignment.run(source, context),
|
||||||
Statement::Expression(expression) => expression.run(context),
|
Statement::Expression(expression) => expression.run(source, context),
|
||||||
Statement::IfElse(if_else) => if_else.run(context),
|
Statement::IfElse(if_else) => if_else.run(source, context),
|
||||||
Statement::Match(r#match) => r#match.run(context),
|
Statement::Match(r#match) => r#match.run(source, context),
|
||||||
Statement::While(r#while) => r#while.run(context),
|
Statement::While(r#while) => r#while.run(source, context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Expression, Item, Result, Value, VariableMap};
|
use crate::{AbstractTree, Expression, Item, Result, Value, VariableMap};
|
||||||
|
|
||||||
@ -9,18 +10,18 @@ pub struct While {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for While {
|
impl AbstractTree for While {
|
||||||
fn from_syntax_node(node: tree_sitter::Node, source: &str) -> crate::Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> crate::Result<Self> {
|
||||||
debug_assert_eq!("while", node.kind());
|
debug_assert_eq!("while", node.kind());
|
||||||
|
|
||||||
let expression_node = node.child(1).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(expression_node, source)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let child_count = node.child_count();
|
let child_count = node.child_count();
|
||||||
let mut items = Vec::with_capacity(child_count);
|
let mut items = Vec::with_capacity(child_count);
|
||||||
|
|
||||||
for index in 3..child_count - 1 {
|
for index in 3..child_count - 1 {
|
||||||
let item_node = node.child(index).unwrap();
|
let item_node = node.child(index).unwrap();
|
||||||
let item = Item::from_syntax_node(item_node, source)?;
|
let item = Item::from_syntax_node(source, item_node)?;
|
||||||
|
|
||||||
items.push(item);
|
items.push(item);
|
||||||
}
|
}
|
||||||
@ -28,10 +29,10 @@ impl AbstractTree for While {
|
|||||||
Ok(While { expression, items })
|
Ok(While { expression, items })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
while self.expression.run(context)?.as_boolean()? {
|
while self.expression.run(source, context)?.as_boolean()? {
|
||||||
for item in &self.items {
|
for item in &self.items {
|
||||||
item.run(context)?;
|
item.run(source, context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
UnexpectedSyntax {
|
UnexpectedSyntaxNode {
|
||||||
expected: &'static str,
|
expected: &'static str,
|
||||||
actual: &'static str,
|
actual: &'static str,
|
||||||
location: tree_sitter::Point,
|
location: tree_sitter::Point,
|
||||||
@ -533,15 +533,14 @@ impl fmt::Display for Error {
|
|||||||
f,
|
f,
|
||||||
"Wrong number of columns for this table. Expected {expected}, found {actual}."
|
"Wrong number of columns for this table. Expected {expected}, found {actual}."
|
||||||
),
|
),
|
||||||
UnexpectedSyntax {
|
UnexpectedSyntaxNode {
|
||||||
expected,
|
expected,
|
||||||
actual,
|
actual,
|
||||||
location,
|
location,
|
||||||
relevant_source: surrounding_text,
|
relevant_source
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Unexpected syntax at {location}. Expected {expected}, but found {actual}.
|
"Unexpected syntax at {location}. Expected {expected}, but found {actual}. {relevant_source}"
|
||||||
>> {surrounding_text} <<"
|
|
||||||
),
|
),
|
||||||
ExpectedFieldName => write!(
|
ExpectedFieldName => write!(
|
||||||
f,
|
f,
|
||||||
|
@ -88,8 +88,8 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
println!("{}", root_node.to_sexp());
|
println!("{}", root_node.to_sexp());
|
||||||
|
|
||||||
for item_node in root_node.children(&mut cursor) {
|
for item_node in root_node.children(&mut cursor) {
|
||||||
let item = Item::from_syntax_node(item_node, self.source)?;
|
let item = Item::from_syntax_node(self.source, item_node)?;
|
||||||
prev_result = item.run(self.context);
|
prev_result = item.run(self.source, self.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_result
|
prev_result
|
||||||
@ -98,10 +98,7 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::Table;
|
||||||
abstract_tree::{expression::Expression, identifier::Identifier, statement::Statement},
|
|
||||||
Function, Table,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -246,21 +243,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn evaluate_function() {
|
|
||||||
let function = Function::new(
|
|
||||||
vec![Identifier::new("message".to_string())],
|
|
||||||
Item::new(vec![Statement::Expression(Expression::Identifier(
|
|
||||||
Identifier::new("message".to_string()),
|
|
||||||
))]),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
evaluate("function <message> { message }"),
|
|
||||||
Ok(Value::Function(function))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_function_call() {
|
fn evaluate_function_call() {
|
||||||
let mut context = VariableMap::new();
|
let mut context = VariableMap::new();
|
||||||
|
219
src/value/mod.rs
219
src/value/mod.rs
@ -1,7 +1,7 @@
|
|||||||
//! Types that represent runtime values.
|
//! Types that represent runtime values.
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
AbstractTree, Function, Identifier, Item, Table, ValueType, VariableMap,
|
AbstractTree, Function, Identifier, Table, ValueType, VariableMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
@ -14,10 +14,11 @@ use tree_sitter::Node;
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
collections::BTreeMap,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ops::{Add, AddAssign, Sub, SubAssign},
|
ops::{Add, AddAssign, Range, Sub, SubAssign},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod function;
|
pub mod function;
|
||||||
@ -30,7 +31,7 @@ pub mod variable_map;
|
|||||||
/// Every whale variable has a key and a Value. Variables are represented by
|
/// Every whale variable has a key and a Value. Variables are represented by
|
||||||
/// storing them in a VariableMap. This means the map of variables is itself a
|
/// storing them in a VariableMap. This means the map of variables is itself a
|
||||||
/// value that can be treated as any other.
|
/// value that can be treated as any other.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
Map(VariableMap),
|
Map(VariableMap),
|
||||||
@ -44,163 +45,121 @@ pub enum Value {
|
|||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
pub struct ValueNode {
|
||||||
let child = node.child(0).unwrap();
|
value_type: ValueType,
|
||||||
|
start_byte: usize,
|
||||||
|
end_byte: usize,
|
||||||
|
}
|
||||||
|
|
||||||
match child.kind() {
|
impl ValueNode {
|
||||||
"integer" => {
|
pub fn byte_range(&self) -> Range<usize> {
|
||||||
let bytes = &source[child.byte_range()];
|
self.start_byte..self.end_byte
|
||||||
let raw_value = bytes.parse::<i64>().unwrap();
|
|
||||||
|
|
||||||
Ok(Value::Integer(raw_value))
|
|
||||||
}
|
}
|
||||||
"float" => {
|
}
|
||||||
let bytes = &source[child.byte_range()];
|
|
||||||
let raw_value = bytes.parse::<f64>().unwrap();
|
|
||||||
|
|
||||||
Ok(Value::Float(raw_value))
|
impl AbstractTree for ValueNode {
|
||||||
}
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
"string" => {
|
let value_type = match node.kind() {
|
||||||
let byte_range_without_quotes = child.start_byte() + 1..child.end_byte() - 1;
|
"integer" => ValueType::Integer,
|
||||||
let text = &source[byte_range_without_quotes];
|
"float" => ValueType::Float,
|
||||||
|
"string" => ValueType::String,
|
||||||
Ok(Value::String(text.to_string()))
|
"boolean" => ValueType::Boolean,
|
||||||
}
|
"empty" => ValueType::Empty,
|
||||||
"boolean" => {
|
|
||||||
let bytes = &source[child.byte_range()];
|
|
||||||
let raw_value = bytes.parse::<bool>().unwrap();
|
|
||||||
|
|
||||||
Ok(Value::Boolean(raw_value))
|
|
||||||
}
|
|
||||||
"empty" => Ok(Value::Empty),
|
|
||||||
"list" => {
|
"list" => {
|
||||||
let item_count = child.named_child_count();
|
let mut child_nodes = Vec::new();
|
||||||
let mut values = Vec::with_capacity(item_count);
|
|
||||||
let mut current_node = child.child(1).unwrap();
|
|
||||||
|
|
||||||
while values.len() < item_count {
|
for index in 0..node.child_count() - 1 {
|
||||||
if current_node.is_named() {
|
let child_syntax_node = node.child(index).unwrap();
|
||||||
let value = Value::from_syntax_node(current_node, source)?;
|
let child_value = ValueNode::from_syntax_node(source, child_syntax_node)?;
|
||||||
|
|
||||||
values.push(value);
|
child_nodes.push(child_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_node = current_node.next_sibling().unwrap();
|
ValueType::ListExact(child_nodes)
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::List(values))
|
|
||||||
}
|
|
||||||
"table" => {
|
|
||||||
let mut current_node = child.child(0).unwrap();
|
|
||||||
let header_and_row_count = child.named_child_count();
|
|
||||||
|
|
||||||
let mut headers = Vec::new();
|
|
||||||
let mut rows = Vec::new();
|
|
||||||
|
|
||||||
while headers.len() + rows.len() < header_and_row_count {
|
|
||||||
println!("{current_node:?}");
|
|
||||||
|
|
||||||
if current_node.kind() == "identifier" {
|
|
||||||
let identifier = Identifier::from_syntax_node(current_node, source)?;
|
|
||||||
let identifier_text = identifier.take_inner();
|
|
||||||
|
|
||||||
headers.push(identifier_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if current_node.kind() == "list" {
|
|
||||||
let value = Value::list_from_syntax_node(current_node, source)?;
|
|
||||||
let row = value.into_inner_list()?;
|
|
||||||
|
|
||||||
rows.push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(node) = current_node.next_sibling() {
|
|
||||||
current_node = node;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let table = Table::from_raw_parts(headers, rows);
|
|
||||||
|
|
||||||
Ok(Value::Table(table))
|
|
||||||
}
|
}
|
||||||
|
"table" => ValueType::Table,
|
||||||
"map" => {
|
"map" => {
|
||||||
let mut map = VariableMap::new();
|
let mut child_nodes = BTreeMap::new();
|
||||||
let pair_count = child.named_child_count();
|
let mut current_key = "".to_string();
|
||||||
let mut current_key = String::new();
|
|
||||||
let mut current_node = child.child(0).unwrap();
|
|
||||||
|
|
||||||
while map.len() < pair_count {
|
for index in 0..node.child_count() - 1 {
|
||||||
if current_node.kind() == "identifier" {
|
let child_syntax_node = node.child(index).unwrap();
|
||||||
let identifier_text = &source[current_node.byte_range()];
|
|
||||||
current_key = identifier_text.to_string();
|
if child_syntax_node.kind() == "identifier" {
|
||||||
|
current_key =
|
||||||
|
Identifier::from_syntax_node(source, child_syntax_node)?.take_inner();
|
||||||
}
|
}
|
||||||
|
|
||||||
if current_node.kind() == "value" {
|
if child_syntax_node.kind() == "value" {
|
||||||
let value = Value::from_syntax_node(current_node, source)?;
|
let child_value = ValueNode::from_syntax_node(source, child_syntax_node)?;
|
||||||
|
let key = current_key.clone();
|
||||||
|
|
||||||
map.set_value(current_key.to_string(), value)?;
|
child_nodes.insert(key, child_value);
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(node) = current_node.next_sibling() {
|
|
||||||
current_node = node;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
ValueType::Map(child_nodes)
|
||||||
}
|
}
|
||||||
"function" => {
|
"function" => ValueType::Function,
|
||||||
let child_count = child.child_count();
|
_ => {
|
||||||
let mut identifiers = Vec::new();
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
let mut item = None;
|
expected:
|
||||||
|
"string, integer, float, boolean, list, table, map, function or empty",
|
||||||
|
actual: node.kind(),
|
||||||
|
location: node.start_position(),
|
||||||
|
relevant_source: source[node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for index in 0..child_count {
|
Ok(ValueNode {
|
||||||
let child = child.child(index).unwrap();
|
value_type,
|
||||||
|
start_byte: node.start_byte(),
|
||||||
if child.kind() == "identifier" {
|
end_byte: node.end_byte(),
|
||||||
let identifier = Identifier::from_syntax_node(child, source)?;
|
})
|
||||||
|
|
||||||
identifiers.push(identifier)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if child.kind() == "item" {
|
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||||
item = Some(Item::from_syntax_node(child, source)?);
|
let value_source = &source[self.byte_range()];
|
||||||
}
|
let value = match &self.value_type {
|
||||||
}
|
ValueType::Any => todo!(),
|
||||||
|
ValueType::String => Value::String(value_source.to_owned()),
|
||||||
|
ValueType::Float => Value::Float(value_source.parse().unwrap()),
|
||||||
|
ValueType::Integer => Value::Integer(value_source.parse().unwrap()),
|
||||||
|
ValueType::Boolean => Value::Boolean(value_source.parse().unwrap()),
|
||||||
|
ValueType::ListExact(nodes) => {
|
||||||
|
let mut values = Vec::with_capacity(nodes.len());
|
||||||
|
|
||||||
Ok(Value::Function(Function::new(identifiers, item.unwrap())))
|
for node in nodes {
|
||||||
}
|
let value = node.run(source, context)?;
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
|
||||||
expected: "string, integer, float, boolean, list, table, map, function or empty",
|
|
||||||
actual: child.kind(),
|
|
||||||
location: child.start_position(),
|
|
||||||
relevant_source: source[child.byte_range()].to_string(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
|
||||||
let item_count = node.named_child_count();
|
|
||||||
let mut values = Vec::with_capacity(item_count);
|
|
||||||
let mut current_node = node.child(1).unwrap();
|
|
||||||
|
|
||||||
while values.len() < item_count {
|
|
||||||
if current_node.is_named() {
|
|
||||||
let value = Value::from_syntax_node(current_node, source)?;
|
|
||||||
|
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_node = current_node.next_sibling().unwrap();
|
Value::List(values)
|
||||||
|
}
|
||||||
|
ValueType::Empty => Value::Empty,
|
||||||
|
ValueType::Map(nodes) => {
|
||||||
|
let mut values = VariableMap::new();
|
||||||
|
|
||||||
|
for (key, node) in nodes {
|
||||||
|
let value = node.run(source, context)?;
|
||||||
|
|
||||||
|
values.set_value(key.clone(), value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::List(values))
|
Value::Map(values)
|
||||||
}
|
}
|
||||||
|
ValueType::Table => todo!(),
|
||||||
|
ValueType::Function => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
ValueType::from(self)
|
ValueType::from(self)
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,27 @@
|
|||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt::{self, Debug, Display, Formatter},
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Value;
|
use crate::Value;
|
||||||
|
|
||||||
|
use super::ValueNode;
|
||||||
|
|
||||||
/// The type of a `Value`.
|
/// The type of a `Value`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
|
||||||
pub enum ValueType {
|
pub enum ValueType {
|
||||||
Any,
|
Any,
|
||||||
String,
|
String,
|
||||||
Float,
|
Float,
|
||||||
Integer,
|
Integer,
|
||||||
Boolean,
|
Boolean,
|
||||||
List,
|
ListExact(Vec<ValueNode>),
|
||||||
ListOf(Box<ValueType>),
|
|
||||||
ListExact(Vec<ValueType>),
|
|
||||||
Empty,
|
Empty,
|
||||||
Map,
|
Map(BTreeMap<String, ValueNode>),
|
||||||
Table,
|
Table,
|
||||||
Function,
|
Function,
|
||||||
Time,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for ValueType {}
|
impl Eq for ValueType {}
|
||||||
@ -32,21 +36,10 @@ impl PartialEq for ValueType {
|
|||||||
(ValueType::Integer, ValueType::Integer) => true,
|
(ValueType::Integer, ValueType::Integer) => true,
|
||||||
(ValueType::Boolean, ValueType::Boolean) => true,
|
(ValueType::Boolean, ValueType::Boolean) => true,
|
||||||
(ValueType::ListExact(left), ValueType::ListExact(right)) => left == right,
|
(ValueType::ListExact(left), ValueType::ListExact(right)) => left == right,
|
||||||
(ValueType::ListExact(_), ValueType::List) => true,
|
|
||||||
(ValueType::List, ValueType::ListExact(_)) => true,
|
|
||||||
(ValueType::ListOf(left), ValueType::ListOf(right)) => left == right,
|
|
||||||
(ValueType::ListOf(_), ValueType::List) => true,
|
|
||||||
(ValueType::List, ValueType::ListOf(_)) => true,
|
|
||||||
(ValueType::ListOf(value_type), ValueType::ListExact(exact_list))
|
|
||||||
| (ValueType::ListExact(exact_list), ValueType::ListOf(value_type)) => exact_list
|
|
||||||
.iter()
|
|
||||||
.all(|exact_type| exact_type == value_type.as_ref()),
|
|
||||||
(ValueType::List, ValueType::List) => true,
|
|
||||||
(ValueType::Empty, ValueType::Empty) => true,
|
(ValueType::Empty, ValueType::Empty) => true,
|
||||||
(ValueType::Map, ValueType::Map) => true,
|
(ValueType::Map(left), ValueType::Map(right)) => left == right,
|
||||||
(ValueType::Table, ValueType::Table) => true,
|
(ValueType::Table, ValueType::Table) => true,
|
||||||
(ValueType::Function, ValueType::Function) => true,
|
(ValueType::Function, ValueType::Function) => true,
|
||||||
(ValueType::Time, ValueType::Time) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,10 +53,6 @@ impl Display for ValueType {
|
|||||||
ValueType::Float => write!(f, "float"),
|
ValueType::Float => write!(f, "float"),
|
||||||
ValueType::Integer => write!(f, "integer"),
|
ValueType::Integer => write!(f, "integer"),
|
||||||
ValueType::Boolean => write!(f, "boolean"),
|
ValueType::Boolean => write!(f, "boolean"),
|
||||||
ValueType::List => write!(f, "list"),
|
|
||||||
ValueType::ListOf(value_type) => {
|
|
||||||
write!(f, "({value_type}s)")
|
|
||||||
}
|
|
||||||
ValueType::ListExact(list) => {
|
ValueType::ListExact(list) => {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
for (index, item) in list.into_iter().enumerate() {
|
for (index, item) in list.into_iter().enumerate() {
|
||||||
@ -71,16 +60,15 @@ impl Display for ValueType {
|
|||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{item}")?;
|
write!(f, "{item:?}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
ValueType::Empty => write!(f, "empty"),
|
ValueType::Empty => write!(f, "empty"),
|
||||||
ValueType::Map => write!(f, "map"),
|
ValueType::Map(map) => write!(f, "map"),
|
||||||
ValueType::Table => write!(f, "table"),
|
ValueType::Table => write!(f, "table"),
|
||||||
ValueType::Function => write!(f, "function"),
|
ValueType::Function => write!(f, "function"),
|
||||||
ValueType::Time => write!(f, "time"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,11 +88,33 @@ impl From<&Value> for ValueType {
|
|||||||
Value::Boolean(_) => ValueType::Boolean,
|
Value::Boolean(_) => ValueType::Boolean,
|
||||||
Value::Empty => ValueType::Empty,
|
Value::Empty => ValueType::Empty,
|
||||||
Value::List(list) => {
|
Value::List(list) => {
|
||||||
let values = list.iter().map(|value| value.value_type()).collect();
|
let value_nodes = list
|
||||||
|
.iter()
|
||||||
|
.map(|value| ValueNode {
|
||||||
|
value_type: value.value_type(),
|
||||||
|
start_byte: 0,
|
||||||
|
end_byte: 0,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
ValueType::ListExact(values)
|
ValueType::ListExact(value_nodes)
|
||||||
|
}
|
||||||
|
Value::Map(map) => {
|
||||||
|
let mut value_nodes = BTreeMap::new();
|
||||||
|
|
||||||
|
for (key, value) in map.inner() {
|
||||||
|
let value_type = ValueType::from(value);
|
||||||
|
let value_node = ValueNode {
|
||||||
|
value_type,
|
||||||
|
start_byte: 0,
|
||||||
|
end_byte: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
value_nodes.insert(key.to_string(), value_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType::Map(value_nodes)
|
||||||
}
|
}
|
||||||
Value::Map(_) => ValueType::Map,
|
|
||||||
Value::Table { .. } => ValueType::Table,
|
Value::Table { .. } => ValueType::Table,
|
||||||
Value::Function(_) => ValueType::Function,
|
Value::Function(_) => ValueType::Function,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user