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