1
0

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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