Begin changes for new type definitions
This commit is contained in:
parent
5ffb797b5f
commit
bc2615a1ed
407
grammar.js
Normal file
407
grammar.js
Normal 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),
|
||||||
|
")",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
170
src/abstract_tree/type_defintion.rs
Normal file
170
src/abstract_tree/type_defintion.rs
Normal 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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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')
|
||||||
",
|
",
|
||||||
),
|
),
|
@ -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;
|
||||||
|
24
src/main.rs
24
src/main.rs
@ -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) => {
|
||||||
|
@ -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,66 +28,38 @@ 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 {
|
|
||||||
r#type.check(&return_value)?;
|
|
||||||
} else if !return_value.is_empty() {
|
|
||||||
return Err(Error::ExpectedEmpty {
|
|
||||||
actual: return_value.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(return_value)
|
Ok(return_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Map) -> Result<TypeDefinition> {
|
||||||
|
self.body.expected_type(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
1
tree-sitter-dust/.prettierignore
Normal file
1
tree-sitter-dust/.prettierignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
src/
|
5
tree-sitter-dust/.prettierrc
Normal file
5
tree-sitter-dust/.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"printWidth": 40,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
@ -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
|
||||||
|
@ -12,10 +12,11 @@ async { (output 'Whaddup') }
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(function_call
|
(function_call
|
||||||
(built_in_function
|
(expression
|
||||||
(expression
|
(identifier))
|
||||||
(value
|
(expression
|
||||||
(string))))))))))
|
(value
|
||||||
|
(string)))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Complex Async Statements
|
Complex Async Statements
|
||||||
|
@ -10,10 +10,11 @@ Simple Function Call
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(function_call
|
(function_call
|
||||||
(built_in_function
|
(expression
|
||||||
(expression
|
(identifier))
|
||||||
(value
|
(expression
|
||||||
(string))))))))
|
(value
|
||||||
|
(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
|
(identifier))
|
||||||
(function_call
|
(expression
|
||||||
(built_in_function)))
|
(identifier))
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))))))
|
(integer)))))))
|
||||||
|
@ -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))))))))))))
|
||||||
|
@ -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)
|
(identifier)
|
||||||
(type))
|
|
||||||
(parameter
|
|
||||||
(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
|
||||||
|
@ -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))))))))))))
|
|
@ -18,10 +18,11 @@ while true {
|
|||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(function_call
|
(function_call
|
||||||
(built_in_function
|
(expression
|
||||||
(expression
|
(identifier))
|
||||||
(value
|
(expression
|
||||||
(string)))))))))))
|
(value
|
||||||
|
(string))))))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Nested While Loop
|
Nested While Loop
|
||||||
|
@ -13,7 +13,8 @@ Simple Yield
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer)))
|
(integer)))
|
||||||
(built_in_function)))))
|
(expression
|
||||||
|
(identifier))))))
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
Yield Chain
|
Yield Chain
|
||||||
|
@ -3,301 +3,405 @@ 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: $ =>
|
||||||
optional('async'),
|
seq(
|
||||||
'{',
|
optional('async'),
|
||||||
repeat1($.statement),
|
'{',
|
||||||
'}',
|
repeat1($.statement),
|
||||||
),
|
'}',
|
||||||
|
|
||||||
statement: $ => prec.left(seq(
|
|
||||||
choice(
|
|
||||||
$.assignment,
|
|
||||||
$.block,
|
|
||||||
$.expression,
|
|
||||||
$.for,
|
|
||||||
$.if_else,
|
|
||||||
$.index_assignment,
|
|
||||||
$.insert,
|
|
||||||
$.match,
|
|
||||||
$.return,
|
|
||||||
$.select,
|
|
||||||
$.use,
|
|
||||||
$.while,
|
|
||||||
),
|
),
|
||||||
optional(';'),
|
|
||||||
)),
|
|
||||||
|
|
||||||
expression: $ => prec.right(choice(
|
statement: $ =>
|
||||||
$._expression_kind,
|
prec.left(
|
||||||
seq('(', $._expression_kind, ')'),
|
seq(
|
||||||
)),
|
choice(
|
||||||
|
$.assignment,
|
||||||
|
$.block,
|
||||||
|
$.expression,
|
||||||
|
$.for,
|
||||||
|
$.if_else,
|
||||||
|
$.index_assignment,
|
||||||
|
$.match,
|
||||||
|
$.return,
|
||||||
|
$.use,
|
||||||
|
$.while,
|
||||||
|
),
|
||||||
|
optional(';'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
_expression_kind: $ => prec.right(choice(
|
expression: $ =>
|
||||||
$.function_call,
|
prec.right(
|
||||||
$.identifier,
|
choice(
|
||||||
$.index,
|
$._expression_kind,
|
||||||
$.logic,
|
seq(
|
||||||
$.math,
|
'(',
|
||||||
$.value,
|
$._expression_kind,
|
||||||
$.yield,
|
')',
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
_expression_list: $ => repeat1(prec.right(seq(
|
_expression_kind: $ =>
|
||||||
$.expression,
|
prec.right(
|
||||||
optional(','),
|
choice(
|
||||||
))),
|
$.function_call,
|
||||||
|
$.identifier,
|
||||||
|
$.index,
|
||||||
|
$.logic,
|
||||||
|
$.math,
|
||||||
|
$.value,
|
||||||
|
$.yield,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
identifier: $ => /[_a-zA-Z]+[_a-zA-Z0-9]?/,
|
_expression_list: $ =>
|
||||||
|
|
||||||
value: $ => choice(
|
|
||||||
$.integer,
|
|
||||||
$.float,
|
|
||||||
$.string,
|
|
||||||
$.boolean,
|
|
||||||
$.list,
|
|
||||||
$.function,
|
|
||||||
$.table,
|
|
||||||
$.map,
|
|
||||||
),
|
|
||||||
|
|
||||||
integer: $ => token(prec.left(seq(
|
|
||||||
optional('-'),
|
|
||||||
repeat1(
|
repeat1(
|
||||||
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')
|
prec.right(
|
||||||
|
seq(
|
||||||
|
$.expression,
|
||||||
|
optional(','),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))),
|
|
||||||
|
|
||||||
float: $ => token(prec.left(seq(
|
identifier: $ =>
|
||||||
optional('-'),
|
/[_a-zA-Z]+[_a-zA-Z0-9]?/,
|
||||||
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: $ => /("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
|
value: $ =>
|
||||||
|
|
||||||
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)),
|
|
||||||
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(
|
choice(
|
||||||
'for',
|
$.integer,
|
||||||
'async for',
|
$.float,
|
||||||
|
$.string,
|
||||||
|
$.boolean,
|
||||||
|
$.list,
|
||||||
|
$.function,
|
||||||
|
$.table,
|
||||||
|
$.map,
|
||||||
),
|
),
|
||||||
$.identifier,
|
|
||||||
'in',
|
|
||||||
$.expression,
|
|
||||||
$.block,
|
|
||||||
),
|
|
||||||
|
|
||||||
select: $ => prec.right(seq(
|
integer: $ =>
|
||||||
'select',
|
token(
|
||||||
$.identifier_list,
|
prec.left(
|
||||||
'from',
|
seq(
|
||||||
$.expression,
|
optional('-'),
|
||||||
optional($.block),
|
repeat1(
|
||||||
)),
|
choice(
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'0',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
insert: $ => prec.right(seq(
|
float: $ =>
|
||||||
'insert',
|
token(
|
||||||
'into',
|
prec.left(
|
||||||
$.identifier,
|
seq(
|
||||||
$.expression,
|
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',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
identifier_list: $ => prec.right(choice(
|
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(
|
seq(
|
||||||
'|',
|
'|',
|
||||||
repeat(seq($.identifier, optional(','))),
|
repeat(
|
||||||
|
seq(
|
||||||
|
$.identifier,
|
||||||
|
optional(','),
|
||||||
|
),
|
||||||
|
),
|
||||||
'|',
|
'|',
|
||||||
|
$.block,
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
|
|
||||||
table: $ => prec.right(seq(
|
function_call: $ =>
|
||||||
'table',
|
prec.right(
|
||||||
$.identifier_list,
|
1,
|
||||||
$.expression,
|
seq(
|
||||||
)),
|
'(',
|
||||||
|
$.expression,
|
||||||
return: $ => seq(
|
optional($._expression_list),
|
||||||
'return',
|
')',
|
||||||
$.expression,
|
),
|
||||||
),
|
|
||||||
|
|
||||||
use: $ => seq(
|
|
||||||
'use',
|
|
||||||
$.string,
|
|
||||||
),
|
|
||||||
|
|
||||||
type: $ => seq(
|
|
||||||
'<',
|
|
||||||
choice(
|
|
||||||
'any',
|
|
||||||
'bool',
|
|
||||||
'fn',
|
|
||||||
'int',
|
|
||||||
'list',
|
|
||||||
'map',
|
|
||||||
'str',
|
|
||||||
'table',
|
|
||||||
),
|
),
|
||||||
'>',
|
|
||||||
),
|
|
||||||
|
|
||||||
function: $ => seq(
|
yield: $ =>
|
||||||
'|',
|
prec.left(
|
||||||
repeat($.parameter),
|
seq(
|
||||||
'|',
|
$.expression,
|
||||||
optional($.type),
|
'->',
|
||||||
$.block,
|
'(',
|
||||||
),
|
$.expression,
|
||||||
|
optional($._expression_list),
|
||||||
parameter: $ => seq(
|
')',
|
||||||
$.identifier,
|
),
|
||||||
$.type,
|
),
|
||||||
optional(','),
|
},
|
||||||
),
|
|
||||||
|
|
||||||
function_call: $ => prec.right(1, seq(
|
|
||||||
'(',
|
|
||||||
$.expression,
|
|
||||||
optional($._expression_list),
|
|
||||||
')',
|
|
||||||
)),
|
|
||||||
|
|
||||||
yield: $ => prec.left(seq(
|
|
||||||
$.expression,
|
|
||||||
'->',
|
|
||||||
'(',
|
|
||||||
$.expression,
|
|
||||||
optional($._expression_list),
|
|
||||||
')',
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
407
tree-sitter-dust/grammar.js.new
Normal file
407
tree-sitter-dust/grammar.js.new
Normal 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),
|
||||||
|
")",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
18
tree-sitter-dust/package-lock.json
generated
18
tree-sitter-dust/package-lock.json
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
|
@ -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,41 +1047,8 @@
|
|||||||
"value": "<"
|
"value": "<"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "SYMBOL",
|
||||||
"members": [
|
"name": "type"
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "any"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "bool"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "fn"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "int"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "list"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "map"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "str"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "table"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
@ -1159,6 +1056,89 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "PREC_RIGHT",
|
||||||
|
"value": 0,
|
||||||
|
"content": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"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",
|
||||||
|
"value": "int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "type"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "num"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "str"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"function": {
|
"function": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
@ -1169,57 +1149,37 @@
|
|||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"type": "SEQ",
|
||||||
"name": "parameter"
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ","
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "|"
|
"value": "|"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "block"
|
"name": "block"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"parameter": {
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "identifier"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": ","
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"function_call": {
|
"function_call": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
|
@ -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
@ -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 |
|
|
Loading…
Reference in New Issue
Block a user