Implement new control flow syntax

This commit is contained in:
Jeff 2023-10-10 13:29:11 -04:00
parent 574cff5cc6
commit 9450e6dc96
16 changed files with 229 additions and 277 deletions

View File

@ -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 => {

View File

@ -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),
} }
} }
} }

View File

@ -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)
} }
} }

View File

@ -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)

View File

@ -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)
} }

View File

@ -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

View File

@ -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()) {

View File

@ -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!()
} }
} }

View File

@ -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,

View File

@ -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>;
} }

View File

@ -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),
} }
} }
} }

View File

@ -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)?;
} }
} }

View File

@ -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,

View File

@ -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();

View File

@ -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)) impl AbstractTree for ValueNode {
} fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
"float" => { let value_type = match node.kind() {
let bytes = &source[child.byte_range()]; "integer" => ValueType::Integer,
let raw_value = bytes.parse::<f64>().unwrap(); "float" => ValueType::Float,
"string" => ValueType::String,
Ok(Value::Float(raw_value)) "boolean" => ValueType::Boolean,
} "empty" => ValueType::Empty,
"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),
"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();
} }
Ok(Value::List(values)) ValueType::ListExact(child_nodes)
}
"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(),
end_byte: node.end_byte(),
})
}
if child.kind() == "identifier" { fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
let identifier = Identifier::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());
identifiers.push(identifier) for node in nodes {
} let value = node.run(source, context)?;
if child.kind() == "item" { values.push(value);
item = Some(Item::from_syntax_node(child, source)?);
}
} }
Ok(Value::Function(Function::new(identifiers, item.unwrap()))) Value::List(values)
} }
_ => Err(Error::UnexpectedSyntax { ValueType::Empty => Value::Empty,
expected: "string, integer, float, boolean, list, table, map, function or empty", ValueType::Map(nodes) => {
actual: child.kind(), let mut values = VariableMap::new();
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
}),
}
}
pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> { for (key, node) in nodes {
let item_count = node.named_child_count(); let value = node.run(source, context)?;
let mut values = Vec::with_capacity(item_count);
let mut current_node = node.child(1).unwrap();
while values.len() < item_count { values.set_value(key.clone(), value)?;
if current_node.is_named() { }
let value = Value::from_syntax_node(current_node, source)?;
values.push(value); Value::Map(values)
} }
ValueType::Table => todo!(),
ValueType::Function => todo!(),
};
current_node = current_node.next_sibling().unwrap(); Ok(value)
}
Ok(Value::List(values))
} }
}
impl Value {
pub fn value_type(&self) -> ValueType { pub fn value_type(&self) -> ValueType {
ValueType::from(self) ValueType::from(self)
} }

View File

@ -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,
} }