1
0

Begin changes for new type definitions

This commit is contained in:
Jeff 2023-11-29 19:23:42 -05:00
parent 5ffb797b5f
commit bc2615a1ed
46 changed files with 11666 additions and 11898 deletions

407
grammar.js Normal file
View File

@ -0,0 +1,407 @@
module.exports = grammar({
name: "dust",
word: $ => $.identifier,
extras: $ => [/\s/, $._comment],
rules: {
root: $ =>
prec(1, repeat1($.statement)),
_comment: $ => /[#][^#\n]*[#|\n]/,
block: $ =>
seq(
optional("async"),
"{",
repeat1($.statement),
"}",
),
statement: $ =>
prec.left(
seq(
choice(
$.assignment,
$.block,
$.expression,
$.for,
$.if_else,
$.index_assignment,
$.match,
$.return,
$.use,
$.while,
),
optional(";"),
),
),
expression: $ =>
prec.right(
choice(
$._expression_kind,
seq(
"(",
$._expression_kind,
")",
),
),
),
_expression_kind: $ =>
prec.right(
choice(
$.function_call,
$.identifier,
$.index,
$.logic,
$.math,
$.value,
$.yield,
),
),
_expression_list: $ =>
repeat1(
prec.right(
seq(
$.expression,
optional(","),
),
),
),
identifier: $ =>
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
value: $ =>
choice(
$.integer,
$.float,
$.string,
$.boolean,
$.list,
$.function,
$.table,
$.map,
),
integer: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
float: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
".",
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
string: $ =>
/("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
boolean: $ =>
choice("true", "false"),
list: $ =>
seq(
"[",
repeat(
prec.left(
seq(
$.expression,
optional(","),
),
),
),
"]",
),
map: $ =>
seq(
"{",
repeat(
seq(
$.identifier,
"=",
$.statement,
optional(","),
),
),
"}",
),
index: $ =>
prec.left(
1,
seq(
$.expression,
":",
$.expression,
optional(
seq("..", $.expression),
),
),
),
math: $ =>
prec.left(
seq(
$.expression,
$.math_operator,
$.expression,
),
),
math_operator: $ =>
choice("+", "-", "*", "/", "%"),
logic: $ =>
prec.right(
seq(
$.expression,
$.logic_operator,
$.expression,
),
),
logic_operator: $ =>
choice(
"==",
"!=",
"&&",
"||",
">",
"<",
">=",
"<=",
),
assignment: $ =>
seq(
field(
"identifier",
$.identifier,
),
optional(
field(
"type",
$.type_definition,
),
),
field(
"assignment_operator",
$.assignment_operator,
),
field("statement", $.statement),
),
index_assignment: $ =>
seq(
$.index,
$.assignment_operator,
$.statement,
),
assignment_operator: $ =>
prec.right(
choice("=", "+=", "-="),
),
if_else: $ =>
prec.right(
seq(
$.if,
repeat($.else_if),
optional($.else),
),
),
if: $ =>
seq("if", $.expression, $.block),
else_if: $ =>
seq(
"else if",
$.expression,
$.block,
),
else: $ => seq("else", $.block),
match: $ =>
prec.right(
seq(
"match",
$.expression,
repeat1(
seq(
$.expression,
"=>",
$.block,
),
),
),
),
while: $ =>
seq(
"while",
$.expression,
$.block,
),
for: $ =>
seq(
choice("for", "async for"),
$.identifier,
"in",
$.expression,
$.block,
),
identifier_list: $ =>
prec.right(
choice(
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
),
),
),
table: $ =>
prec.right(
seq(
"table",
$.identifier_list,
$.expression,
),
),
return: $ =>
seq("return", $.expression),
use: $ => seq("use", $.string),
type_definition: $ =>
seq("<", $.type, ">"),
type: $ =>
prec.right(
choice(
"any",
"bool",
seq(
"fn",
repeat(
seq(
$.type,
optional(","),
),
),
optional(seq("->", $.type)),
),
"int",
seq("list", $.type),
"map",
"num",
"str",
),
),
function: $ =>
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
$.block,
),
function_call: $ =>
prec.right(
1,
seq(
"(",
$.expression,
optional($._expression_list),
")",
),
),
yield: $ =>
prec.left(
seq(
$.expression,
"->",
"(",
$.expression,
optional($._expression_list),
")",
),
),
},
});

View File

@ -1,12 +1,12 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, Type, Value}; use crate::{AbstractTree, Error, Identifier, Map, Result, Statement, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment { pub struct Assignment {
identifier: Identifier, identifier: Identifier,
r#type: Option<Type>, r#type: Option<TypeDefinition>,
operator: AssignmentOperator, operator: AssignmentOperator,
statement: Statement, statement: Statement,
} }
@ -27,7 +27,7 @@ impl AbstractTree for Assignment {
let type_node = node.child_by_field_name("type"); let type_node = node.child_by_field_name("type");
let r#type = if let Some(type_node) = type_node { let r#type = if let Some(type_node) = type_node {
Some(Type::from_syntax_node(source, type_node)?) Some(TypeDefinition::from_syntax_node(source, type_node)?)
} else { } else {
None None
}; };
@ -62,7 +62,7 @@ impl AbstractTree for Assignment {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let key = self.identifier.inner(); let key = self.identifier.inner();
let value = self.statement.run(source, context)?; let value = self.statement.run(source, context)?;
@ -86,12 +86,12 @@ impl AbstractTree for Assignment {
AssignmentOperator::Equal => value, AssignmentOperator::Equal => value,
}; };
if let Some(r#type) = &self.r#type {
r#type.check(&new_value)?;
}
context.variables_mut()?.insert(key.clone(), new_value); context.variables_mut()?.insert(key.clone(), new_value);
Ok(Value::Empty) Ok(Value::Empty)
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Empty)
}
} }

View File

@ -4,7 +4,7 @@ use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Statement, Value}; use crate::{AbstractTree, Error, Map, Result, Statement, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block { pub struct Block {
@ -41,7 +41,7 @@ impl AbstractTree for Block {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
if self.is_async { if self.is_async {
let statements = &self.statements; let statements = &self.statements;
let final_result = RwLock::new(Ok(Value::Empty)); let final_result = RwLock::new(Ok(Value::Empty));
@ -81,4 +81,8 @@ impl AbstractTree for Block {
prev_result.unwrap_or(Ok(Value::Empty)) prev_result.unwrap_or(Ok(Value::Empty))
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.statements.last().unwrap().expected_type(context)
}
} }

View File

@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Value, Yield, value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, TypeDefinition,
Value, Yield,
}; };
use super::{function_call::FunctionCall, logic::Logic, math::Math}; use super::{function_call::FunctionCall, logic::Logic, math::Math};
@ -51,7 +52,7 @@ impl AbstractTree for Expression {
Ok(expression) Ok(expression)
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
match self { match self {
Expression::Value(value_node) => value_node.run(source, context), Expression::Value(value_node) => value_node.run(source, context),
Expression::Identifier(identifier) => identifier.run(source, context), Expression::Identifier(identifier) => identifier.run(source, context),
@ -62,4 +63,16 @@ impl AbstractTree for Expression {
Expression::Yield(r#yield) => r#yield.run(source, context), Expression::Yield(r#yield) => r#yield.run(source, context),
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
match self {
Expression::Value(value_node) => value_node.expected_type(context),
Expression::Identifier(identifier) => identifier.expected_type(context),
Expression::Math(math) => math.expected_type(context),
Expression::Logic(logic) => logic.expected_type(context),
Expression::FunctionCall(function_call) => function_call.expected_type(context),
Expression::Index(index) => index.expected_type(context),
Expression::Yield(r#yield) => r#yield.expected_type(context),
}
}
} }

View File

@ -1,77 +0,0 @@
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Expression, Identifier, List, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Filter {
count: Option<Expression>,
item_id: Identifier,
collection: Expression,
predicate: Block,
}
impl AbstractTree for Filter {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
let count = match node.child_by_field_name("count") {
Some(node) => Some(Expression::from_syntax_node(source, node)?),
None => None,
};
let item_id_node = node.child_by_field_name("item_id").unwrap();
let item_id = Identifier::from_syntax_node(source, item_id_node)?;
let collection_node = node.child_by_field_name("collection").unwrap();
let collection = Expression::from_syntax_node(source, collection_node)?;
let predicate_node = node.child_by_field_name("predicate").unwrap();
let predicate = Block::from_syntax_node(source, predicate_node)?;
Ok(Filter {
count,
item_id,
collection,
predicate,
})
}
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.collection.run(source, context)?;
let values = value.as_list()?.items();
let key = self.item_id.inner();
let new_values = List::new();
let count = match &self.count {
Some(expression) => Some(expression.run(source, context)?.as_integer()? as usize),
None => None,
};
let loop_context = Map::clone_from(context)?;
values.par_iter().try_for_each(|value| {
if let Some(max) = count {
if new_values.items().len() == max {
return Ok(());
}
}
let mut iter_context = loop_context.clone();
iter_context
.variables_mut()?
.insert(key.clone(), value.clone());
let should_include = self
.predicate
.run(source, &mut iter_context)?
.as_boolean()?;
if should_include {
new_values.items_mut().push(value.clone());
}
Ok::<(), Error>(())
})?;
Ok(Value::List(new_values))
}
}

View File

@ -2,7 +2,9 @@ use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Value}; use crate::{
AbstractTree, Block, Error, Expression, Identifier, Map, Result, TypeDefinition, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct For { pub struct For {
@ -47,7 +49,7 @@ impl AbstractTree for For {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let expression_run = self.collection.run(source, context)?; let expression_run = self.collection.run(source, context)?;
let values = expression_run.as_list()?.items(); let values = expression_run.as_list()?.items();
let key = self.item_id.inner(); let key = self.item_id.inner();
@ -76,4 +78,8 @@ impl AbstractTree for For {
Ok(Value::Empty) Ok(Value::Empty)
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Empty)
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Value, BUILT_IN_FUNCTIONS}; use crate::{AbstractTree, Error, Map, Result, TypeDefinition, Value, BUILT_IN_FUNCTIONS};
use super::expression::Expression; use super::expression::Expression;
@ -45,7 +45,7 @@ impl AbstractTree for FunctionCall {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let function = if let Expression::Identifier(identifier) = &self.function { let function = if let Expression::Identifier(identifier) = &self.function {
let key = identifier.inner(); let key = identifier.inner();
@ -77,15 +77,17 @@ impl AbstractTree for FunctionCall {
let mut function_context = Map::clone_from(context)?; let mut function_context = Map::clone_from(context)?;
let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter()); let parameter_expression_pairs = function.parameters().iter().zip(self.arguments.iter());
for ((identifier, r#type), expression) in parameter_expression_pairs { for (identifier, expression) in parameter_expression_pairs {
let key = identifier.clone().take_inner(); let key = identifier.clone().take_inner();
let value = expression.run(source, context)?; let value = expression.run(source, context)?;
r#type.check(&value)?;
function_context.variables_mut()?.insert(key, value); function_context.variables_mut()?.insert(key, value);
} }
function.run(source, &mut function_context) function.run(source, &mut function_context)
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.function.expected_type(context)
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Value}; use crate::{AbstractTree, Error, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(String); pub struct Identifier(String);
@ -29,11 +29,19 @@ impl AbstractTree for Identifier {
Ok(Identifier(identifier.to_string())) Ok(Identifier(identifier.to_string()))
} }
fn run(&self, _source: &str, context: &mut Map) -> Result<Value> { fn run(&self, _source: &str, context: &Map) -> Result<Value> {
if let Some(value) = context.variables()?.get(&self.0) { if let Some(value) = context.variables()?.get(&self.0) {
Ok(value.clone()) Ok(value.clone())
} else { } else {
Err(Error::VariableIdentifierNotFound(self.inner().clone())) Err(Error::VariableIdentifierNotFound(self.inner().clone()))
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
if let Some(value) = context.variables()?.get(&self.0) {
Ok(value.r#type(context)?)
} else {
Ok(TypeDefinition::Empty)
}
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Block, Expression, Map, Result, Value}; use crate::{AbstractTree, Block, Expression, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse { pub struct IfElse {
@ -55,7 +55,7 @@ impl AbstractTree for IfElse {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let if_boolean = self.if_expression.run(source, context)?.as_boolean()?; let if_boolean = self.if_expression.run(source, context)?.as_boolean()?;
if if_boolean { if if_boolean {
@ -80,4 +80,8 @@ impl AbstractTree for IfElse {
} }
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.if_block.expected_type(context)
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, List, Map, Result, Value}; use crate::{AbstractTree, Error, Expression, List, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Index { pub struct Index {
@ -32,7 +32,7 @@ impl AbstractTree for Index {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let collection = self.collection.run(source, context)?; let collection = self.collection.run(source, context)?;
match collection { match collection {
@ -73,6 +73,10 @@ impl AbstractTree for Index {
_ => Err(Error::ExpectedCollection { actual: collection }), _ => Err(Error::ExpectedCollection { actual: collection }),
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.collection.expected_type(context)
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Index, Map, Result, Statement, Value}; use crate::{AbstractTree, Error, Index, Map, Result, Statement, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct IndexAssignment { pub struct IndexAssignment {
@ -49,7 +49,7 @@ impl AbstractTree for IndexAssignment {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let index_collection = self.index.collection.run(source, context)?; let index_collection = self.index.collection.run(source, context)?;
let index_context = index_collection.as_map().unwrap_or(&context); let index_context = index_collection.as_map().unwrap_or(&context);
let index_key = if let crate::Expression::Identifier(identifier) = &self.index.index { let index_key = if let crate::Expression::Identifier(identifier) = &self.index.index {
@ -90,4 +90,8 @@ impl AbstractTree for IndexAssignment {
Ok(Value::Empty) Ok(Value::Empty)
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Empty)
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Map, Result, Value}; use crate::{AbstractTree, Error, Expression, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Logic { pub struct Logic {
@ -45,7 +45,7 @@ impl AbstractTree for Logic {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let left = self.left.run(source, context)?; let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?; let right = self.right.run(source, context)?;
let result = match self.operator { let result = match self.operator {
@ -73,6 +73,10 @@ impl AbstractTree for Logic {
Ok(Value::Boolean(result)) Ok(Value::Boolean(result))
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Boolean)
}
} }
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]

View File

@ -6,7 +6,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Map, Result, Value}; use crate::{AbstractTree, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Match {} pub struct Match {}
@ -16,7 +16,11 @@ impl AbstractTree for Match {
todo!() todo!()
} }
fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> { fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
todo!()
}
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
todo!() todo!()
} }
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Map, Result, Value}; use crate::{AbstractTree, Error, Expression, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Math { pub struct Math {
@ -42,7 +42,7 @@ impl AbstractTree for Math {
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let left = self.left.run(source, context)?; let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?; let right = self.right.run(source, context)?;
let value = match self.operator { let value = match self.operator {
@ -55,6 +55,10 @@ impl AbstractTree for Math {
Ok(value) Ok(value)
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Number)
}
} }
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]

View File

@ -9,38 +9,67 @@
pub mod assignment; pub mod assignment;
pub mod block; pub mod block;
pub mod expression; pub mod expression;
pub mod filter;
pub mod find;
pub mod r#for; pub mod r#for;
pub mod function_call; pub mod function_call;
pub mod identifier; pub mod identifier;
pub mod if_else; pub mod if_else;
pub mod index; pub mod index;
pub mod index_assignment; pub mod index_assignment;
pub mod insert;
pub mod logic; pub mod logic;
pub mod r#match; pub mod r#match;
pub mod math; pub mod math;
pub mod remove;
pub mod select;
pub mod statement; pub mod statement;
pub mod transform; pub mod type_defintion;
pub mod r#type;
pub mod r#use; pub mod r#use;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
pub mod r#yield; pub mod r#yield;
pub use { pub use {
assignment::*, block::*, expression::*, filter::*, find::*, function_call::*, identifier::*, assignment::*, block::*, expression::*, function_call::*, identifier::*, if_else::*, index::*,
if_else::*, index::*, index_assignment::IndexAssignment, insert::*, logic::*, math::*, index_assignment::IndexAssignment, logic::*, math::*, r#for::*, r#match::*, r#use::*,
r#for::*, r#match::*, r#type::*, r#use::*, r#while::*, r#yield::*, remove::*, select::*, r#while::*, r#yield::*, statement::*, type_defintion::*, value_node::*,
statement::*, transform::*, value_node::*,
}; };
use tree_sitter::Node; use tree_sitter::Node;
use crate::{Map, Result, Value}; use crate::{Error, Map, Result, Value};
pub struct Root {
statements: Vec<Statement>,
}
impl AbstractTree for Root {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
Error::expect_syntax_node(source, "root", node)?;
let statement_count = node.child_count();
let mut statements = Vec::with_capacity(statement_count);
for index in 0..statement_count {
let statement_node = node.child(index).unwrap();
let statement = Statement::from_syntax_node(source, statement_node)?;
statements.push(statement);
}
Ok(Root { statements })
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
let mut value = Value::Empty;
for statement in &self.statements {
value = statement.run(source, context)?;
}
Ok(value)
}
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.statements.last().unwrap().expected_type(context)
}
}
/// This trait is implemented by the Evaluator's internal types to form an /// This trait is implemented by the Evaluator's internal types to form an
/// executable tree that resolves to a single value. /// executable tree that resolves to a single value.
@ -57,5 +86,7 @@ pub trait AbstractTree: Sized {
fn from_syntax_node(source: &str, node: Node) -> 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, source: &str, context: &mut Map) -> Result<Value>; fn run(&self, source: &str, context: &Map) -> Result<Value>;
fn expected_type(&self, context: &Map) -> Result<TypeDefinition>;
} }

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, IndexAssignment, AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match,
Insert, Map, Match, Remove, Result, Select, Transform, Use, Value, While, Result, TypeDefinition, Use, Value, While,
}; };
/// Abstract representation of a statement. /// Abstract representation of a statement.
@ -17,13 +17,7 @@ pub enum Statement {
While(Box<While>), While(Box<While>),
Block(Box<Block>), Block(Box<Block>),
For(Box<For>), For(Box<For>),
Transform(Box<Transform>),
Filter(Box<Filter>),
Find(Box<Find>),
Remove(Box<Remove>),
Use(Use), Use(Use),
Select(Box<Select>),
Insert(Box<Insert>),
IndexAssignment(Box<IndexAssignment>), IndexAssignment(Box<IndexAssignment>),
} }
@ -60,25 +54,7 @@ impl AbstractTree for Statement {
"for" => Ok(Statement::For(Box::new(For::from_syntax_node( "for" => Ok(Statement::For(Box::new(For::from_syntax_node(
source, child, source, child,
)?))), )?))),
"transform" => Ok(Statement::Transform(Box::new(Transform::from_syntax_node(
source, child,
)?))),
"filter" => Ok(Statement::Filter(Box::new(Filter::from_syntax_node(
source, child,
)?))),
"find" => Ok(Statement::Find(Box::new(Find::from_syntax_node(
source, child,
)?))),
"remove" => Ok(Statement::Remove(Box::new(Remove::from_syntax_node(
source, child,
)?))),
"select" => Ok(Statement::Select(Box::new(Select::from_syntax_node(
source, child,
)?))),
"use" => Ok(Statement::Use(Use::from_syntax_node(source, child)?)), "use" => Ok(Statement::Use(Use::from_syntax_node(source, child)?)),
"insert" => Ok(Statement::Insert(Box::new(Insert::from_syntax_node(
source, child,
)?))),
"index_assignment" => Ok(Statement::IndexAssignment(Box::new(IndexAssignment::from_syntax_node( "index_assignment" => Ok(Statement::IndexAssignment(Box::new(IndexAssignment::from_syntax_node(
source, child, source, child,
)?))), )?))),
@ -91,7 +67,7 @@ impl AbstractTree for Statement {
} }
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
match self { match self {
Statement::Assignment(assignment) => assignment.run(source, context), Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Return(expression) => expression.run(source, context), Statement::Return(expression) => expression.run(source, context),
@ -101,14 +77,23 @@ impl AbstractTree for Statement {
Statement::While(r#while) => r#while.run(source, context), Statement::While(r#while) => r#while.run(source, context),
Statement::Block(block) => block.run(source, context), Statement::Block(block) => block.run(source, context),
Statement::For(r#for) => r#for.run(source, context), Statement::For(r#for) => r#for.run(source, context),
Statement::Transform(transform) => transform.run(source, context),
Statement::Filter(filter) => filter.run(source, context),
Statement::Find(find) => find.run(source, context),
Statement::Remove(remove) => remove.run(source, context),
Statement::Use(run) => run.run(source, context), Statement::Use(run) => run.run(source, context),
Statement::Select(select) => select.run(source, context),
Statement::Insert(insert) => insert.run(source, context),
Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context), Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context),
} }
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
match self {
Statement::Assignment(assignment) => assignment.expected_type(context),
Statement::Return(expression) => expression.expected_type(context),
Statement::Expression(expression) => expression.expected_type(context),
Statement::IfElse(if_else) => if_else.expected_type(context),
Statement::Match(r#match) => r#match.expected_type(context),
Statement::While(r#while) => r#while.expected_type(context),
Statement::Block(block) => block.expected_type(context),
Statement::For(r#for) => r#for.expected_type(context),
Statement::Use(r#use) => r#use.expected_type(context),
Statement::IndexAssignment(index_assignment) => index_assignment.expected_type(context),
}
}
} }

View File

@ -1,117 +0,0 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Type {
Any,
Boolean,
Float,
Function,
Integer,
List,
Map,
String,
Table,
}
impl Type {
pub fn check(&self, value: &Value) -> Result<()> {
match (self, value.r#type()) {
(Type::Any, _)
| (Type::Boolean, Type::Boolean)
| (Type::Float, Type::Float)
| (Type::Function, Type::Function)
| (Type::Integer, Type::Integer)
| (Type::List, Type::List)
| (Type::Map, Type::Map)
| (Type::String, Type::String)
| (Type::Table, Type::Table) => Ok(()),
(Type::Boolean, _) => Err(Error::TypeCheck {
expected: Type::Boolean,
actual: value.clone(),
}),
(Type::Float, _) => Err(Error::TypeCheck {
expected: Type::Float,
actual: value.clone(),
}),
(Type::Function, _) => Err(Error::TypeCheck {
expected: Type::Function,
actual: value.clone(),
}),
(Type::Integer, _) => Err(Error::TypeCheck {
expected: Type::Integer,
actual: value.clone(),
}),
(Type::List, _) => Err(Error::TypeCheck {
expected: Type::List,
actual: value.clone(),
}),
(Type::Map, _) => Err(Error::TypeCheck {
expected: Type::Map,
actual: value.clone(),
}),
(Type::String, _) => Err(Error::TypeCheck {
expected: Type::String,
actual: value.clone(),
}),
(Type::Table, _) => Err(Error::TypeCheck {
expected: Type::Table,
actual: value.clone(),
}),
}
}
}
impl AbstractTree for Type {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
Error::expect_syntax_node(source, "type", node)?;
let range_without_punctuation = node.start_byte() + 1..node.end_byte() - 1;
let r#type = match &source[range_without_punctuation] {
"any" => Type::Any,
"bool" => Type::Boolean,
"float" => Type::Float,
"fn" => Type::Function,
"int" => Type::Integer,
"list" => Type::List,
"map" => Type::Map,
"str" => Type::String,
"table" => Type::Table,
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected: "any, bool, float, fn, int, list, map, str or table",
actual: node.kind(),
location: node.start_position(),
relevant_source: source[node.byte_range()].to_string(),
})
}
};
Ok(r#type)
}
fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
Ok(Value::Empty)
}
}
impl Display for Type {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"),
Type::Float => write!(f, "float"),
Type::Function => write!(f, "function"),
Type::Integer => write!(f, "integer"),
Type::List => write!(f, "list"),
Type::Map => write!(f, "map"),
Type::String => write!(f, "string"),
Type::Table => write!(f, "table"),
}
}
}

View File

@ -0,0 +1,170 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{AbstractTree, Error, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum TypeDefinition {
Any,
Boolean,
Empty,
Float,
Function {
parameter_types: Vec<TypeDefinition>,
return_type: Box<TypeDefinition>,
},
Integer,
List(Box<TypeDefinition>),
Map,
Number,
String,
Table,
}
impl TypeDefinition {
// pub fn check(&self, value: &Value) -> Result<()> {
// match (self, value.r#type()?) {
// (Type::Any, _)
// | (Type::Boolean, Type::Boolean)
// | (Type::Empty, Type::Empty)
// | (Type::Float, Type::Float)
// | (Type::Integer, Type::Integer)
// | (Type::Map, Type::Map)
// | (Type::Number, Type::Number)
// | (Type::Number, Type::Integer)
// | (Type::Number, Type::Float)
// | (Type::Integer, Type::Number)
// | (Type::Float, Type::Number)
// | (Type::String, Type::String)
// | (Type::Table, Type::Table) => Ok(()),
// (Type::List(expected), Type::List(actual)) => {
// if expected != &actual {
// Err(Error::TypeCheck {
// expected: Type::List(expected.clone()),
// actual: value.clone(),
// })
// } else {
// Ok(())
// }
// }
// (
// Type::Function {
// parameter_types: left_parameters,
// return_type: left_return,
// },
// Type::Function {
// parameter_types: right_parameters,
// return_type: right_return,
// },
// ) => {
// if left_parameters != &right_parameters || left_return != &right_return {
// Err(Error::TypeCheck {
// expected: Type::Function {
// parameter_types: left_parameters.clone(),
// return_type: left_return.clone(),
// },
// actual: value.clone(),
// })
// } else {
// Ok(())
// }
// }
// (Type::Boolean, _) => Err(Error::TypeCheck {
// expected: Type::Boolean,
// actual: value.clone(),
// }),
// (Type::Empty, _) => Err(Error::TypeCheck {
// expected: Type::Empty,
// actual: value.clone(),
// }),
// (Type::Float, _) => Err(Error::TypeCheck {
// expected: Type::Float,
// actual: value.clone(),
// }),
// (expected, _) => Err(Error::TypeCheck {
// expected: expected.clone(),
// actual: value.clone(),
// }),
// (Type::Integer, _) => Err(Error::TypeCheck {
// expected: Type::Integer,
// actual: value.clone(),
// }),
// (expected, _) => Err(Error::TypeCheck {
// expected: expected.clone(),
// actual: value.clone(),
// }),
// (Type::Map, _) => Err(Error::TypeCheck {
// expected: Type::Map,
// actual: value.clone(),
// }),
// (Type::String, _) => Err(Error::TypeCheck {
// expected: Type::String,
// actual: value.clone(),
// }),
// (Type::Table, _) => Err(Error::TypeCheck {
// expected: Type::Table,
// actual: value.clone(),
// }),
// }
// }
}
impl AbstractTree for TypeDefinition {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
Error::expect_syntax_node(source, "type_definition", node)?;
let type_node = node.child(1).unwrap();
let type_symbol = &source[type_node.byte_range()];
let r#type = match type_symbol {
"any" => TypeDefinition::Any,
"bool" => TypeDefinition::Boolean,
"float" => TypeDefinition::Float,
"fn" => {
todo!()
}
"int" => TypeDefinition::Integer,
"map" => TypeDefinition::Map,
"str" => TypeDefinition::String,
"table" => TypeDefinition::Table,
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected: "any, bool, float, fn, int, list, map, str or table",
actual: type_node.kind(),
location: type_node.start_position(),
relevant_source: source[type_node.byte_range()].to_string(),
})
}
};
Ok(r#type)
}
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
Ok(Value::Empty)
}
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Empty)
}
}
impl Display for TypeDefinition {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
TypeDefinition::Any => write!(f, "any"),
TypeDefinition::Boolean => write!(f, "bool"),
TypeDefinition::Empty => write!(f, "empty"),
TypeDefinition::Float => write!(f, "float"),
TypeDefinition::Function { .. } => write!(f, "function"),
TypeDefinition::Integer => write!(f, "integer"),
TypeDefinition::List(_) => write!(f, "list"),
TypeDefinition::Map => write!(f, "map"),
TypeDefinition::Number => write!(f, "number"),
TypeDefinition::String => write!(f, "string"),
TypeDefinition::Table => write!(f, "table"),
}
}
}

View File

@ -2,7 +2,7 @@ use std::fs::read_to_string;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{evaluate_with_context, AbstractTree, Error, Map, Result, Value}; use crate::{evaluate_with_context, AbstractTree, Error, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Use { pub struct Use {
@ -21,7 +21,7 @@ impl AbstractTree for Use {
Ok(Use { path }) Ok(Use { path })
} }
fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> { fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
let file_contents = read_to_string(&self.path)?; let file_contents = read_to_string(&self.path)?;
let mut file_context = Map::new(); let mut file_context = Map::new();
@ -29,4 +29,8 @@ impl AbstractTree for Use {
Ok(Value::Map(file_context)) Ok(Value::Map(file_context))
} }
fn expected_type(&self, _context: &Map) -> Result<TypeDefinition> {
Ok(TypeDefinition::Map)
}
} }

View File

@ -5,7 +5,7 @@ use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table, AbstractTree, Error, Expression, Function, Identifier, List, Map, Result, Statement, Table,
Value, TypeDefinition, Value,
}; };
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
@ -112,7 +112,7 @@ impl AbstractTree for ValueNode {
Ok(value_node) Ok(value_node)
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let value = match self { let value = match self {
ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()), ValueNode::Boolean(value_source) => Value::Boolean(value_source.parse().unwrap()),
ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()), ValueNode::Float(value_source) => Value::Float(value_source.parse().unwrap()),
@ -176,4 +176,31 @@ impl AbstractTree for ValueNode {
Ok(value) Ok(value)
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
let r#type = match self {
ValueNode::Boolean(_) => TypeDefinition::Boolean,
ValueNode::Float(_) => TypeDefinition::Float,
ValueNode::Integer(_) => TypeDefinition::Integer,
ValueNode::String(_) => TypeDefinition::String,
ValueNode::List(expressions) => {
let first_expression_type = if let Some(first) = expressions.first() {
first.expected_type(context)?
} else {
TypeDefinition::Empty
};
TypeDefinition::List(Box::new(first_expression_type))
}
ValueNode::Empty => TypeDefinition::Any,
ValueNode::Map(_) => TypeDefinition::Map,
ValueNode::Table {
column_names: _,
rows: _,
} => TypeDefinition::Table,
ValueNode::Function(function) => function.expected_type(context)?,
};
Ok(r#type)
}
} }

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Block, Expression, Map, Result, Value}; use crate::{AbstractTree, Block, Expression, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct While { pub struct While {
@ -22,13 +22,17 @@ impl AbstractTree for While {
Ok(While { expression, block }) Ok(While { expression, block })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
while self.expression.run(source, context)?.as_boolean()? { while self.expression.run(source, context)?.as_boolean()? {
self.block.run(source, context)?; self.block.run(source, context)?;
} }
Ok(Value::Empty) Ok(Value::Empty)
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.block.expected_type(context)
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Expression, FunctionCall, Result, Value}; use crate::{AbstractTree, Expression, FunctionCall, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Yield { pub struct Yield {
@ -35,7 +35,11 @@ impl AbstractTree for Yield {
Ok(Yield { call }) Ok(Yield { call })
} }
fn run(&self, source: &str, context: &mut crate::Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
self.call.run(source, context) self.call.run(source, context)
} }
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.call.expected_type(context)
}
} }

View File

@ -5,7 +5,7 @@
use tree_sitter::{Node, Point}; use tree_sitter::{Node, Point};
use crate::{value::Value, Identifier, Type}; use crate::{value::Value, Identifier, TypeDefinition};
use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time}; use std::{fmt, io, num::ParseFloatError, string::FromUtf8Error, sync::PoisonError, time};
@ -21,7 +21,7 @@ pub enum Error {
}, },
TypeCheck { TypeCheck {
expected: Type, expected: TypeDefinition,
actual: Value, actual: Value,
}, },

View File

@ -4,7 +4,7 @@
//! functions or by constructing your own Evaluator. //! functions or by constructing your own Evaluator.
use tree_sitter::{Parser, Tree as TSTree}; use tree_sitter::{Parser, Tree as TSTree};
use crate::{language, AbstractTree, Map, Result, Statement, Value}; use crate::{language, AbstractTree, Map, Result, Root, Value};
/// Evaluate the given source code. /// Evaluate the given source code.
/// ///
@ -50,41 +50,34 @@ pub fn evaluate_with_context(source: &str, context: &mut Map) -> Result<Value> {
let mut parser = Parser::new(); let mut parser = Parser::new();
parser.set_language(language()).unwrap(); parser.set_language(language()).unwrap();
Evaluator::new(parser, context, source).run() Interpreter::parse(parser, context, source)?.run()
} }
/// A source code interpreter for the Dust language. /// A source code interpreter for the Dust language.
pub struct Evaluator<'c, 's> { pub struct Interpreter<'c, 's> {
_parser: Parser, _parser: Parser,
context: &'c mut Map, context: &'c mut Map,
source: &'s str, source: &'s str,
syntax_tree: TSTree, syntax_tree: TSTree,
abstract_tree: Root,
} }
impl<'c, 's> Evaluator<'c, 's> { impl<'c, 's> Interpreter<'c, 's> {
pub fn new(mut parser: Parser, context: &'c mut Map, source: &'s str) -> Self { pub fn parse(mut parser: Parser, context: &'c mut Map, source: &'s str) -> Result<Self> {
let syntax_tree = parser.parse(source, None).unwrap(); let syntax_tree = parser.parse(source, None).unwrap();
let abstract_tree = Root::from_syntax_node(source, syntax_tree.root_node())?;
Evaluator { Ok(Interpreter {
_parser: parser, _parser: parser,
context, context,
source, source,
syntax_tree, syntax_tree,
} abstract_tree,
})
} }
pub fn run(self) -> Result<Value> { pub fn run(&mut self) -> Result<Value> {
let root_node = self.syntax_tree.root_node(); self.abstract_tree.run(self.source, self.context)
let mut value = Value::Empty;
for index in 0..root_node.child_count() {
let statement_node = root_node.child(index).unwrap();
let statement = Statement::from_syntax_node(self.source, statement_node)?;
value = statement.run(self.source, self.context)?;
}
Ok(value)
} }
pub fn syntax_tree(&self) -> String { pub fn syntax_tree(&self) -> String {
@ -247,7 +240,7 @@ mod tests {
assert_eq!( assert_eq!(
evaluate( evaluate(
" "
foobar = |message <str>| <str> { message } foobar <fn str -> str> = |message| { message }
(foobar 'Hiya') (foobar 'Hiya')
", ",
), ),

View File

@ -8,14 +8,14 @@ pub use crate::{
abstract_tree::*, abstract_tree::*,
built_in_functions::{BuiltInFunction, BUILT_IN_FUNCTIONS}, built_in_functions::{BuiltInFunction, BUILT_IN_FUNCTIONS},
error::*, error::*,
evaluator::*, evaluate::*,
value::{function::Function, list::List, map::Map, table::Table, Value}, value::{function::Function, list::List, map::Map, table::Table, Value},
}; };
mod abstract_tree; mod abstract_tree;
pub mod built_in_functions; pub mod built_in_functions;
mod error; mod error;
mod evaluator; mod evaluate;
mod value; mod value;
use tree_sitter::Language; use tree_sitter::Language;

View File

@ -12,7 +12,7 @@ use tree_sitter::Parser as TSParser;
use std::{borrow::Cow, fs::read_to_string}; use std::{borrow::Cow, fs::read_to_string};
use dust_lang::{evaluate_with_context, language, Evaluator, Map, Value}; use dust_lang::{evaluate_with_context, language, Interpreter, Map, Value};
/// Command-line arguments to be parsed. /// Command-line arguments to be parsed.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -30,10 +30,14 @@ struct Args {
#[arg(short = 'p', long)] #[arg(short = 'p', long)]
input_path: Option<String>, input_path: Option<String>,
/// A path to file whose contents will be assigned to the "input" variable. /// Show the syntax tree.
#[arg(short = 't', long = "tree")] #[arg(short = 't', long = "tree")]
show_syntax_tree: bool, show_syntax_tree: bool,
/// Launch in interactive mode.
#[arg(short, long)]
interactive: bool,
/// Location of the file to run. /// Location of the file to run.
path: Option<String>, path: Option<String>,
} }
@ -74,13 +78,21 @@ fn main() {
let mut parser = TSParser::new(); let mut parser = TSParser::new();
parser.set_language(language()).unwrap(); parser.set_language(language()).unwrap();
let evaluator = Evaluator::new(parser, &mut context, &source); let mut interpreter = Interpreter::parse(parser, &mut context, &source).unwrap();
if args.show_syntax_tree { if args.interactive {
println!("{}", evaluator.syntax_tree()); loop {
let result = interpreter.run();
println!("{result:?}")
}
} }
let eval_result = evaluator.run(); if args.show_syntax_tree {
println!("{}", interpreter.syntax_tree());
}
let eval_result = interpreter.run();
match eval_result { match eval_result {
Ok(value) => { Ok(value) => {

View File

@ -3,19 +3,22 @@ use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, Block, Error, Identifier, Map, Result, Type, Value}; use crate::{AbstractTree, Block, Error, Identifier, Map, Result, TypeDefinition, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Function { pub struct Function {
parameters: Vec<(Identifier, Type)>, parameters: Vec<Identifier>,
return_type: Option<Type>,
body: Block, body: Block,
} }
impl Function { impl Function {
pub fn parameters(&self) -> &Vec<(Identifier, Type)> { pub fn parameters(&self) -> &Vec<Identifier> {
&self.parameters &self.parameters
} }
pub fn body(&self) -> &Block {
&self.body
}
} }
impl AbstractTree for Function { impl AbstractTree for Function {
@ -25,57 +28,29 @@ impl AbstractTree for Function {
let child_count = node.child_count(); let child_count = node.child_count();
let mut parameters = Vec::new(); let mut parameters = Vec::new();
for index in 1..child_count - 2 { for index in 0..child_count {
let parameter_node = {
let child = node.child(index).unwrap(); let child = node.child(index).unwrap();
if child.is_named() { if child.is_named() {
child let identifier = Identifier::from_syntax_node(source, child)?;
} else { parameters.push(identifier);
continue;
} }
};
Error::expect_syntax_node(source, "parameter", parameter_node)?;
let identifier_node = parameter_node.child(0).unwrap();
let identifier = Identifier::from_syntax_node(source, identifier_node)?;
let type_node = parameter_node.child(1).unwrap();
let r#type = Type::from_syntax_node(source, type_node)?;
parameters.push((identifier, r#type))
} }
let return_type_node = node.child(child_count - 2).unwrap();
let return_type = if return_type_node.is_named() {
Some(Type::from_syntax_node(source, return_type_node)?)
} else {
None
};
let body_node = node.child(child_count - 1).unwrap(); let body_node = node.child(child_count - 1).unwrap();
let body = Block::from_syntax_node(source, body_node)?; let body = Block::from_syntax_node(source, body_node)?;
Ok(Function { Ok(Function { parameters, body })
parameters,
return_type,
body,
})
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &Map) -> Result<Value> {
let return_value = self.body.run(source, context)?; let return_value = self.body.run(source, context)?;
if let Some(r#type) = &self.return_type { Ok(return_value)
r#type.check(&return_value)?;
} else if !return_value.is_empty() {
return Err(Error::ExpectedEmpty {
actual: return_value.clone(),
});
} }
Ok(return_value) fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
self.body.expected_type(context)
} }
} }
@ -83,8 +58,8 @@ impl Display for Function {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"Function {{ parameters: {:?}, return_type: {:?}, body: {:?} }}", "Function {{ parameters: {:?}, body: {:?} }}",
self.parameters, self.return_type, self.body self.parameters, self.body
) )
} }
} }

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},
Function, List, Map, Table, Type, AbstractTree, Function, List, Map, Table, TypeDefinition,
}; };
use serde::{ use serde::{
@ -43,18 +43,41 @@ pub enum Value {
} }
impl Value { impl Value {
pub fn r#type(&self) -> Type { pub fn r#type(&self, context: &Map) -> Result<TypeDefinition> {
match self { let r#type = match self {
Value::List(_) => Type::List, Value::List(list) => {
Value::Map(_) => Type::Map, let first_item_type = if let Some(first) = list.items().first() {
Value::Table(_) => Type::Table, first.r#type(context)?
Value::Function(_) => Type::Function, } else {
Value::String(_) => Type::String, TypeDefinition::Empty
Value::Float(_) => Type::Float, };
Value::Integer(_) => Type::Integer,
Value::Boolean(_) => Type::Boolean, TypeDefinition::List(Box::new(first_item_type))
Value::Empty => Type::Any,
} }
Value::Map(_) => TypeDefinition::Map,
Value::Table(_) => TypeDefinition::Table,
Value::Function(function) => {
let parameter_types = Vec::new();
for identifier in function.parameters() {
let _type = identifier.expected_type(context)?;
}
let return_type = function.body().expected_type(context)?;
TypeDefinition::Function {
parameter_types,
return_type: Box::new(return_type),
}
}
Value::String(_) => TypeDefinition::String,
Value::Float(_) => TypeDefinition::Float,
Value::Integer(_) => TypeDefinition::Integer,
Value::Boolean(_) => TypeDefinition::Boolean,
Value::Empty => TypeDefinition::Empty,
};
Ok(r#type)
} }
pub fn is_table(&self) -> bool { pub fn is_table(&self) -> bool {

View File

@ -0,0 +1 @@
src/

View File

@ -0,0 +1,5 @@
{
"arrowParens": "avoid",
"printWidth": 40,
"singleQuote": true
}

View File

@ -27,7 +27,8 @@ x <int> = y
(statement (statement
(assignment (assignment
(identifier) (identifier)
(type) (type_definition
(type))
(assignment_operator) (assignment_operator)
(statement (statement
(expression (expression

View File

@ -12,10 +12,11 @@ async { (output 'Whaddup') }
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function (expression
(identifier))
(expression (expression
(value (value
(string)))))))))) (string)))))))))
================================================================================ ================================================================================
Complex Async Statements Complex Async Statements

View File

@ -10,10 +10,11 @@ Simple Function Call
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function (expression
(identifier))
(expression (expression
(value (value
(string)))))))) (string)))))))
================================================================================ ================================================================================
Nested Function Call Nested Function Call
@ -27,10 +28,10 @@ Nested Function Call
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function
(expression (expression
(function_call (identifier))
(built_in_function))) (expression
(identifier))
(expression (expression
(value (value
(integer)))))))) (integer)))))))

View File

@ -28,9 +28,10 @@ for i in [1, 2, 3] {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function
(expression (expression
(identifier)))))))))) (identifier))
(expression
(identifier)))))))))
================================================================================ ================================================================================
Nested For Loop Nested For Loop
@ -60,6 +61,7 @@ for list in list_of_lists {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function
(expression (expression
(identifier))))))))))))) (identifier))
(expression
(identifier))))))))))))

View File

@ -2,7 +2,7 @@
Simple Function Simple Function
================================================================================ ================================================================================
|| <str> { "Hiya" } || { "Hiya" }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -11,7 +11,6 @@ Simple Function
(expression (expression
(value (value
(function (function
(type)
(block (block
(statement (statement
(expression (expression
@ -22,7 +21,7 @@ Simple Function
Function Assignment Function Assignment
================================================================================ ================================================================================
x = || <str> { "Hiya" } x <fn num -> str> = |number| { "Hiya" }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -30,12 +29,16 @@ x = || <str> { "Hiya" }
(statement (statement
(assignment (assignment
(identifier) (identifier)
(type_definition
(type
(type)
(type)))
(assignment_operator) (assignment_operator)
(statement (statement
(expression (expression
(value (value
(function (function
(type) (identifier)
(block (block
(statement (statement
(expression (expression
@ -64,7 +67,7 @@ Function Call
Complex Function Complex Function
================================================================================ ================================================================================
|message <str> number <int>| { |message number| {
(output message) (output message)
(output number) (output number)
} }
@ -76,25 +79,23 @@ Complex Function
(expression (expression
(value (value
(function (function
(parameter
(identifier) (identifier)
(type))
(parameter
(identifier) (identifier)
(type))
(block (block
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function
(expression (expression
(identifier)))))) (identifier))
(expression
(identifier)))))
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function
(expression (expression
(identifier)))))))))))) (identifier))
(expression
(identifier)))))))))))
================================================================================ ================================================================================
Complex Function Call Complex Function Call

View File

@ -1,105 +0,0 @@
================================================================================
Table Declaration
================================================================================
table |messages numbers| [
['hiya' 42]
['foo' 57]
['bar' 99.99]
]
--------------------------------------------------------------------------------
(root
(statement
(expression
(value
(table
(identifier_list
(identifier)
(identifier))
(expression
(value
(list
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(integer))))))
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(integer))))))
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(float))))))))))))))
================================================================================
Table Access
================================================================================
select |number| from foobar {
text == 'answer'
}
--------------------------------------------------------------------------------
(root
(statement
(select
(identifier_list
(identifier))
(expression
(identifier))
(block
(statement
(expression
(logic
(expression
(identifier))
(logic_operator)
(expression
(value
(string))))))))))
================================================================================
Table Insert
================================================================================
insert into foobar [
['bob was here', 0]
]
--------------------------------------------------------------------------------
(root
(statement
(insert
(identifier)
(expression
(value
(list
(expression
(value
(list
(expression
(value
(string)))
(expression
(value
(integer))))))))))))

View File

@ -18,10 +18,11 @@ while true {
(statement (statement
(expression (expression
(function_call (function_call
(built_in_function (expression
(identifier))
(expression (expression
(value (value
(string))))))))))) (string))))))))))
================================================================================ ================================================================================
Nested While Loop Nested While Loop

View File

@ -13,7 +13,8 @@ Simple Yield
(expression (expression
(value (value
(integer))) (integer)))
(built_in_function))))) (expression
(identifier))))))
================================================================================ ================================================================================
Yield Chain Yield Chain

View File

@ -3,21 +3,25 @@ module.exports = grammar({
word: $ => $.identifier, word: $ => $.identifier,
extras: $ => [ /\s/, $._comment ], extras: $ => [/\s/, $._comment],
rules: { rules: {
root: $ => prec(1, repeat1($.statement)), root: $ =>
prec(1, repeat1($.statement)),
_comment: $ => /[#][^#\n]*[#|\n]/, _comment: $ => /[#][^#\n]*[#|\n]/,
block: $ => seq( block: $ =>
seq(
optional('async'), optional('async'),
'{', '{',
repeat1($.statement), repeat1($.statement),
'}', '}',
), ),
statement: $ => prec.left(seq( statement: $ =>
prec.left(
seq(
choice( choice(
$.assignment, $.assignment,
$.block, $.block,
@ -25,22 +29,30 @@ module.exports = grammar({
$.for, $.for,
$.if_else, $.if_else,
$.index_assignment, $.index_assignment,
$.insert,
$.match, $.match,
$.return, $.return,
$.select,
$.use, $.use,
$.while, $.while,
), ),
optional(';'), optional(';'),
)), ),
),
expression: $ => prec.right(choice( expression: $ =>
prec.right(
choice(
$._expression_kind, $._expression_kind,
seq('(', $._expression_kind, ')'), seq(
)), '(',
$._expression_kind,
')',
),
),
),
_expression_kind: $ => prec.right(choice( _expression_kind: $ =>
prec.right(
choice(
$.function_call, $.function_call,
$.identifier, $.identifier,
$.index, $.index,
@ -48,16 +60,24 @@ module.exports = grammar({
$.math, $.math,
$.value, $.value,
$.yield, $.yield,
)), ),
),
_expression_list: $ => repeat1(prec.right(seq( _expression_list: $ =>
repeat1(
prec.right(
seq(
$.expression, $.expression,
optional(','), optional(','),
))), ),
),
),
identifier: $ => /[_a-zA-Z]+[_a-zA-Z0-9]?/, identifier: $ =>
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
value: $ => choice( value: $ =>
choice(
$.integer, $.integer,
$.float, $.float,
$.string, $.string,
@ -68,236 +88,320 @@ module.exports = grammar({
$.map, $.map,
), ),
integer: $ => token(prec.left(seq( integer: $ =>
token(
prec.left(
seq(
optional('-'), optional('-'),
repeat1( repeat1(
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') choice(
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
),
),
),
),
), ),
))),
float: $ => token(prec.left(seq( float: $ =>
token(
prec.left(
seq(
optional('-'), optional('-'),
repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')), repeat1(
choice(
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
),
),
'.', '.',
repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')), repeat1(
))), choice(
'1',
string: $ => /("[^"]*?")|('[^']*?')|(`[^`]*?`)/, '2',
'3',
boolean: $ => choice( '4',
'true', '5',
'false', '6',
'7',
'8',
'9',
'0',
),
),
),
),
), ),
list: $ => seq( string: $ =>
/("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
boolean: $ =>
choice('true', 'false'),
list: $ =>
seq(
'[', '[',
repeat(prec.left(seq($.expression, optional(',')))), repeat(
prec.left(
seq(
$.expression,
optional(','),
),
),
),
']', ']',
), ),
map: $ => seq( map: $ =>
seq(
'{', '{',
repeat(seq( repeat(
seq(
$.identifier, $.identifier,
"=", '=',
$.statement, $.statement,
optional(',') optional(','),
)), ),
),
'}', '}',
), ),
index: $ => prec.left(1, seq( index: $ =>
prec.left(
1,
seq(
$.expression, $.expression,
':', ':',
$.expression, $.expression,
optional(seq( optional(
'..', seq('..', $.expression),
$.expression, ),
)), ),
)), ),
math: $ => prec.left(seq( math: $ =>
prec.left(
seq(
$.expression, $.expression,
$.math_operator, $.math_operator,
$.expression, $.expression,
)), ),
math_operator: $ => choice(
'+',
'-',
'*',
'/',
'%',
), ),
logic: $ => prec.right(seq( math_operator: $ =>
choice('+', '-', '*', '/', '%'),
logic: $ =>
prec.right(
seq(
$.expression, $.expression,
$.logic_operator, $.logic_operator,
$.expression, $.expression,
)), ),
),
logic_operator: $ => choice( logic_operator: $ =>
choice(
'==', '==',
'!=', '!=',
'&&', '&&',
'||', '||',
'>', '>',
'<', '<',
">=", '>=',
"<=", '<=',
), ),
assignment: $ => seq( assignment: $ =>
field('identifier', $.identifier), seq(
optional(field('type', $.type)), field(
field('assignment_operator', $.assignment_operator), 'identifier',
$.identifier,
),
optional(
field(
'type',
$.type_definition,
),
),
field(
'assignment_operator',
$.assignment_operator,
),
field('statement', $.statement), field('statement', $.statement),
), ),
index_assignment: $ => seq( index_assignment: $ =>
seq(
$.index, $.index,
$.assignment_operator, $.assignment_operator,
$.statement, $.statement,
), ),
assignment_operator: $ => prec.right(choice( assignment_operator: $ =>
"=", prec.right(
"+=", choice('=', '+=', '-='),
"-=", ),
)),
if_else: $ => prec.right(seq( if_else: $ =>
prec.right(
seq(
$.if, $.if,
repeat($.else_if), repeat($.else_if),
optional($.else), optional($.else),
)), ),
if: $ => seq(
'if',
$.expression,
$.block,
), ),
else_if: $ => seq( if: $ =>
seq('if', $.expression, $.block),
else_if: $ =>
seq(
'else if', 'else if',
$.expression, $.expression,
$.block, $.block,
), ),
else: $ => seq( else: $ => seq('else', $.block),
'else',
$.block,
),
match: $ => prec.right(seq( match: $ =>
prec.right(
seq(
'match', 'match',
$.expression, $.expression,
repeat1(seq( repeat1(
seq(
$.expression, $.expression,
'=>', '=>',
$.block, $.block,
)), ),
)), ),
),
),
while: $ => seq( while: $ =>
seq(
'while', 'while',
$.expression, $.expression,
$.block, $.block,
), ),
for: $ => seq( for: $ =>
choice( seq(
'for', choice('for', 'async for'),
'async for',
),
$.identifier, $.identifier,
'in', 'in',
$.expression, $.expression,
$.block, $.block,
), ),
select: $ => prec.right(seq( identifier_list: $ =>
'select', prec.right(
$.identifier_list, choice(
'from',
$.expression,
optional($.block),
)),
insert: $ => prec.right(seq(
'insert',
'into',
$.identifier,
$.expression,
)),
identifier_list: $ => prec.right(choice(
seq( seq(
'|', '|',
repeat(seq($.identifier, optional(','))), repeat(
seq(
$.identifier,
optional(','),
),
),
'|', '|',
), ),
)), ),
),
table: $ => prec.right(seq( table: $ =>
prec.right(
seq(
'table', 'table',
$.identifier_list, $.identifier_list,
$.expression, $.expression,
)), ),
return: $ => seq(
'return',
$.expression,
), ),
use: $ => seq( return: $ =>
'use', seq('return', $.expression),
$.string,
),
type: $ => seq( use: $ => seq('use', $.string),
'<',
type_definition: $ =>
seq('<', $.type, '>'),
type: $ =>
prec.right(
choice( choice(
'any', 'any',
'bool', 'bool',
seq(
'fn', 'fn',
'int', repeat(
'list', seq(
'map',
'str',
'table',
),
'>',
),
function: $ => seq(
'|',
repeat($.parameter),
'|',
optional($.type),
$.block,
),
parameter: $ => seq(
$.identifier,
$.type, $.type,
optional(','), optional(','),
), ),
),
optional(seq('->', $.type)),
),
'int',
seq('list', $.type),
'map',
'num',
'str',
),
),
function_call: $ => prec.right(1, seq( function: $ =>
seq(
'|',
repeat(
seq(
$.identifier,
optional(','),
),
),
'|',
$.block,
),
function_call: $ =>
prec.right(
1,
seq(
'(', '(',
$.expression, $.expression,
optional($._expression_list), optional($._expression_list),
')', ')',
)), ),
),
yield: $ => prec.left(seq( yield: $ =>
prec.left(
seq(
$.expression, $.expression,
'->', '->',
'(', '(',
$.expression, $.expression,
optional($._expression_list), optional($._expression_list),
')', ')',
)), ),
} ),
},
}); });

View File

@ -0,0 +1,407 @@
module.exports = grammar({
name: "dust",
word: $ => $.identifier,
extras: $ => [/\s/, $._comment],
rules: {
root: $ =>
prec(1, repeat1($.statement)),
_comment: $ => /[#][^#\n]*[#|\n]/,
block: $ =>
seq(
optional("async"),
"{",
repeat1($.statement),
"}",
),
statement: $ =>
prec.left(
seq(
choice(
$.assignment,
$.block,
$.expression,
$.for,
$.if_else,
$.index_assignment,
$.match,
$.return,
$.use,
$.while,
),
optional(";"),
),
),
expression: $ =>
prec.right(
choice(
$._expression_kind,
seq(
"(",
$._expression_kind,
")",
),
),
),
_expression_kind: $ =>
prec.right(
choice(
$.function_call,
$.identifier,
$.index,
$.logic,
$.math,
$.value,
$.yield,
),
),
_expression_list: $ =>
repeat1(
prec.right(
seq(
$.expression,
optional(","),
),
),
),
identifier: $ =>
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
value: $ =>
choice(
$.integer,
$.float,
$.string,
$.boolean,
$.list,
$.function,
$.table,
$.map,
),
integer: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
float: $ =>
token(
prec.left(
seq(
optional("-"),
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
".",
repeat1(
choice(
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
),
),
),
),
),
string: $ =>
/("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
boolean: $ =>
choice("true", "false"),
list: $ =>
seq(
"[",
repeat(
prec.left(
seq(
$.expression,
optional(","),
),
),
),
"]",
),
map: $ =>
seq(
"{",
repeat(
seq(
$.identifier,
"=",
$.statement,
optional(","),
),
),
"}",
),
index: $ =>
prec.left(
1,
seq(
$.expression,
":",
$.expression,
optional(
seq("..", $.expression),
),
),
),
math: $ =>
prec.left(
seq(
$.expression,
$.math_operator,
$.expression,
),
),
math_operator: $ =>
choice("+", "-", "*", "/", "%"),
logic: $ =>
prec.right(
seq(
$.expression,
$.logic_operator,
$.expression,
),
),
logic_operator: $ =>
choice(
"==",
"!=",
"&&",
"||",
">",
"<",
">=",
"<=",
),
assignment: $ =>
seq(
field(
"identifier",
$.identifier,
),
optional(
field(
"type",
$.type_definition,
),
),
field(
"assignment_operator",
$.assignment_operator,
),
field("statement", $.statement),
),
index_assignment: $ =>
seq(
$.index,
$.assignment_operator,
$.statement,
),
assignment_operator: $ =>
prec.right(
choice("=", "+=", "-="),
),
if_else: $ =>
prec.right(
seq(
$.if,
repeat($.else_if),
optional($.else),
),
),
if: $ =>
seq("if", $.expression, $.block),
else_if: $ =>
seq(
"else if",
$.expression,
$.block,
),
else: $ => seq("else", $.block),
match: $ =>
prec.right(
seq(
"match",
$.expression,
repeat1(
seq(
$.expression,
"=>",
$.block,
),
),
),
),
while: $ =>
seq(
"while",
$.expression,
$.block,
),
for: $ =>
seq(
choice("for", "async for"),
$.identifier,
"in",
$.expression,
$.block,
),
identifier_list: $ =>
prec.right(
choice(
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
),
),
),
table: $ =>
prec.right(
seq(
"table",
$.identifier_list,
$.expression,
),
),
return: $ =>
seq("return", $.expression),
use: $ => seq("use", $.string),
type_definition: $ =>
seq("<", $.type, ">"),
type: $ =>
prec.right(
choice(
"any",
"bool",
seq(
"fn",
repeat(
seq(
$.type,
optional(","),
),
),
optional(seq("->", $.type)),
),
"int",
seq("list", $.type),
"map",
"num",
"str",
),
),
function: $ =>
seq(
"|",
repeat(
seq(
$.identifier,
optional(","),
),
),
"|",
$.block,
),
function_call: $ =>
prec.right(
1,
seq(
"(",
$.expression,
optional($._expression_list),
")",
),
),
yield: $ =>
prec.left(
seq(
$.expression,
"->",
"(",
$.expression,
optional($._expression_list),
")",
),
),
},
});

View File

@ -7,11 +7,12 @@
"": { "": {
"name": "tree-sitter-dust", "name": "tree-sitter-dust",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "MIT",
"dependencies": { "dependencies": {
"nan": "^2.18.0" "nan": "^2.18.0"
}, },
"devDependencies": { "devDependencies": {
"prettier": "3.1.0",
"tree-sitter-cli": "^0.20.8" "tree-sitter-cli": "^0.20.8"
} }
}, },
@ -20,6 +21,21 @@
"resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz",
"integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w=="
}, },
"node_modules/prettier": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz",
"integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/tree-sitter-cli": { "node_modules/tree-sitter-cli": {
"version": "0.20.8", "version": "0.20.8",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz", "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz",

View File

@ -18,6 +18,7 @@
"nan": "^2.18.0" "nan": "^2.18.0"
}, },
"devDependencies": { "devDependencies": {
"prettier": "3.1.0",
"tree-sitter-cli": "^0.20.8" "tree-sitter-cli": "^0.20.8"
}, },
"main": "bindings/node" "main": "bindings/node"

View File

@ -82,10 +82,6 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "index_assignment" "name": "index_assignment"
}, },
{
"type": "SYMBOL",
"name": "insert"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "match" "name": "match"
@ -94,10 +90,6 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "return" "name": "return"
}, },
{
"type": "SYMBOL",
"name": "select"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "use" "name": "use"
@ -723,7 +715,7 @@
"name": "type", "name": "type",
"content": { "content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "type" "name": "type_definition"
} }
}, },
{ {
@ -954,68 +946,6 @@
} }
] ]
}, },
"select": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "select"
},
{
"type": "SYMBOL",
"name": "identifier_list"
},
{
"type": "STRING",
"value": "from"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "block"
},
{
"type": "BLANK"
}
]
}
]
}
},
"insert": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "insert"
},
{
"type": "STRING",
"value": "into"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "expression"
}
]
}
},
"identifier_list": { "identifier_list": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
@ -1109,7 +1039,7 @@
} }
] ]
}, },
"type": { "type_definition": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
@ -1117,6 +1047,19 @@
"value": "<" "value": "<"
}, },
{ {
"type": "SYMBOL",
"name": "type"
},
{
"type": "STRING",
"value": ">"
}
]
},
"type": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
@ -1127,37 +1070,74 @@
"type": "STRING", "type": "STRING",
"value": "bool" "value": "bool"
}, },
{
"type": "SEQ",
"members": [
{ {
"type": "STRING", "type": "STRING",
"value": "fn" "value": "fn"
}, },
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "type"
}
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "->"
},
{
"type": "SYMBOL",
"name": "type"
}
]
},
{
"type": "BLANK"
}
]
}
]
},
{ {
"type": "STRING", "type": "STRING",
"value": "int" "value": "int"
}, },
{
"type": "SEQ",
"members": [
{ {
"type": "STRING", "type": "STRING",
"value": "list" "value": "list"
}, },
{
"type": "SYMBOL",
"name": "type"
}
]
},
{ {
"type": "STRING", "type": "STRING",
"value": "map" "value": "map"
}, },
{
"type": "STRING",
"value": "num"
},
{ {
"type": "STRING", "type": "STRING",
"value": "str" "value": "str"
},
{
"type": "STRING",
"value": "table"
} }
] ]
},
{
"type": "STRING",
"value": ">"
} }
]
}, },
"function": { "function": {
"type": "SEQ", "type": "SEQ",
@ -1169,43 +1149,12 @@
{ {
"type": "REPEAT", "type": "REPEAT",
"content": { "content": {
"type": "SYMBOL",
"name": "parameter"
}
},
{
"type": "STRING",
"value": "|"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "type"
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "block"
}
]
},
"parameter": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "identifier" "name": "identifier"
}, },
{
"type": "SYMBOL",
"name": "type"
},
{ {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
@ -1219,6 +1168,17 @@
] ]
} }
] ]
}
},
{
"type": "STRING",
"value": "|"
},
{
"type": "SYMBOL",
"name": "block"
}
]
}, },
"function_call": { "function_call": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",

View File

@ -38,7 +38,7 @@
"required": false, "required": false,
"types": [ "types": [
{ {
"type": "type", "type": "type_definition",
"named": true "named": true
} }
] ]
@ -179,11 +179,7 @@
"named": true "named": true
}, },
{ {
"type": "parameter", "type": "identifier",
"named": true
},
{
"type": "type",
"named": true "named": true
} }
] ]
@ -299,25 +295,6 @@
] ]
} }
}, },
{
"type": "insert",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "expression",
"named": true
},
{
"type": "identifier",
"named": true
}
]
}
},
{ {
"type": "list", "type": "list",
"named": true, "named": true,
@ -419,25 +396,6 @@
"named": true, "named": true,
"fields": {} "fields": {}
}, },
{
"type": "parameter",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "type",
"named": true
}
]
}
},
{ {
"type": "return", "type": "return",
"named": true, "named": true,
@ -468,29 +426,6 @@
] ]
} }
}, },
{
"type": "select",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "block",
"named": true
},
{
"type": "expression",
"named": true
},
{
"type": "identifier_list",
"named": true
}
]
}
},
{ {
"type": "statement", "type": "statement",
"named": true, "named": true,
@ -523,10 +458,6 @@
"type": "index_assignment", "type": "index_assignment",
"named": true "named": true
}, },
{
"type": "insert",
"named": true
},
{ {
"type": "match", "type": "match",
"named": true "named": true
@ -535,10 +466,6 @@
"type": "return", "type": "return",
"named": true "named": true
}, },
{
"type": "select",
"named": true
},
{ {
"type": "use", "type": "use",
"named": true "named": true
@ -572,7 +499,32 @@
{ {
"type": "type", "type": "type",
"named": true, "named": true,
"fields": {} "fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "type",
"named": true
}
]
}
},
{
"type": "type_definition",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "type",
"named": true
}
]
}
}, },
{ {
"type": "use", "type": "use",
@ -806,10 +758,6 @@
"type": "for", "type": "for",
"named": false "named": false
}, },
{
"type": "from",
"named": false
},
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
@ -822,10 +770,6 @@
"type": "in", "type": "in",
"named": false "named": false
}, },
{
"type": "insert",
"named": false
},
{ {
"type": "int", "type": "int",
"named": false "named": false
@ -834,10 +778,6 @@
"type": "integer", "type": "integer",
"named": true "named": true
}, },
{
"type": "into",
"named": false
},
{ {
"type": "list", "type": "list",
"named": false "named": false
@ -851,11 +791,11 @@
"named": false "named": false
}, },
{ {
"type": "return", "type": "num",
"named": false "named": false
}, },
{ {
"type": "select", "type": "return",
"named": false "named": false
}, },
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `dust -c '(length (from_json input))' -p seaCreatures.json` | 2.9 ± 0.4 | 2.5 | 6.7 | 1.00 |
| `jq 'length' seaCreatures.json` | 36.7 ± 4.4 | 34.7 | 65.0 | 12.59 ± 2.14 |
| `node --eval "require('node:fs').readFile('seaCreatures.json', (err, data)=>{console.log(JSON.parse(data).length)})"` | 241.2 ± 13.3 | 227.7 | 273.2 | 82.63 ± 11.00 |
| `nu -c 'open seaCreatures.json \| length'` | 54.0 ± 3.3 | 50.3 | 69.2 | 18.49 ± 2.51 |
| `dust -c '(length (from_json input))' -p jq_data.json` | 7.9 ± 0.8 | 6.6 | 12.5 | 2.70 ± 0.43 |
| `jq 'length' jq_data.json` | 44.8 ± 0.6 | 43.5 | 47.3 | 15.36 ± 1.87 |
| `node --eval "require('node:fs').readFile('jq_data.json', (err, data)=>{console.log(JSON.parse(data).length)})"` | 245.2 ± 7.1 | 235.4 | 259.7 | 84.00 ± 10.46 |
| `nu -c 'open jq_data.json \| length'` | 65.9 ± 5.0 | 62.0 | 90.5 | 22.57 ± 3.22 |
| `dust -c '(length (from_json input))' -p dielectron.json` | 1079.5 ± 22.7 | 1043.8 | 1121.5 | 369.86 ± 45.46 |
| `jq 'length' dielectron.json` | 1365.0 ± 20.3 | 1318.5 | 1400.1 | 467.67 ± 57.07 |
| `node --eval "require('node:fs').readFile('dielectron.json', (err, data)=>{console.log(JSON.parse(data).length)})"` | 1910.8 ± 47.9 | 1855.9 | 1985.7 | 654.66 ± 80.97 |
| `nu -c 'open dielectron.json \| length'` | 2001.2 ± 65.1 | 1923.2 | 2112.7 | 685.65 ± 85.98 |