Compare commits
3 Commits
d1b116cc35
...
2178c67499
Author | SHA1 | Date | |
---|---|---|---|
2178c67499 | |||
bc1b88a5fa | |||
8ca97300d3 |
33
examples/async.ds
Normal file
33
examples/async.ds
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
(output "This will print first.")
|
||||||
|
(output "This will print second.")
|
||||||
|
|
||||||
|
create_random_numbers = |count| => {
|
||||||
|
numbers = [];
|
||||||
|
|
||||||
|
while (length numbers) < count {
|
||||||
|
numbers += (random_integer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_a_lot = async {
|
||||||
|
(create_random_numbers 1000)
|
||||||
|
(output "Made 1000 numbers")
|
||||||
|
}
|
||||||
|
|
||||||
|
do_some = async {
|
||||||
|
(create_random_numbers 100)
|
||||||
|
(output "Made 100 numbers")
|
||||||
|
}
|
||||||
|
|
||||||
|
do_a_little = async {
|
||||||
|
(create_random_numbers 10)
|
||||||
|
(output "Made 10 numbers")
|
||||||
|
}
|
||||||
|
|
||||||
|
await {
|
||||||
|
do_a_lot
|
||||||
|
do_some
|
||||||
|
do_a_little
|
||||||
|
}
|
||||||
|
|
||||||
|
(output "This will print last.")
|
@ -3,20 +3,26 @@ suspects = ['White' 'Green']
|
|||||||
weapons = ['Rope' 'Lead_Pipe']
|
weapons = ['Rope' 'Lead_Pipe']
|
||||||
cards = [rooms suspects weapons]
|
cards = [rooms suspects weapons]
|
||||||
|
|
||||||
take_turn = function current_room opponent_card
|
take_turn = |current_room opponent_card| => {
|
||||||
remove_card opponent_card
|
(remove_card opponent_card)
|
||||||
make_guess current_room
|
(make_guess current_room)
|
||||||
|
}
|
||||||
|
|
||||||
remove_card = function opponent_card
|
remove_card = |opponent_card| => {
|
||||||
for card_list in cards
|
for card_list in cards {
|
||||||
removed = remove card from card_list
|
removed = remove card from card_list
|
||||||
card == opponent_card
|
card == opponent_card
|
||||||
|
}
|
||||||
|
|
||||||
if type removed == 'empty'
|
if (type removed) == 'empty'
|
||||||
output 'Card not found.'
|
output 'Card not found.'
|
||||||
|
}
|
||||||
|
|
||||||
make_guess = function current_room
|
make_guess = |current_room| => {
|
||||||
if length suspects == 1 && length rooms == 1 && length weapons == 1
|
if ((length suspects) == 1)
|
||||||
|
&& ((length rooms) == 1)
|
||||||
|
&& ((length weapons) == 1)
|
||||||
|
{
|
||||||
(output 'It was '
|
(output 'It was '
|
||||||
+ suspects:0
|
+ suspects:0
|
||||||
+ ' in the '
|
+ ' in the '
|
||||||
@ -24,7 +30,7 @@ make_guess = function current_room
|
|||||||
+ ' with the '
|
+ ' with the '
|
||||||
+ weapons:0
|
+ weapons:0
|
||||||
+ '!')
|
+ '!')
|
||||||
else
|
} else {
|
||||||
(output 'I accuse '
|
(output 'I accuse '
|
||||||
+ (random suspects)
|
+ (random suspects)
|
||||||
+ ' in the '
|
+ ' in the '
|
||||||
@ -32,5 +38,7 @@ make_guess = function current_room
|
|||||||
+ ' with the '
|
+ ' with the '
|
||||||
+ (random weapons)
|
+ (random weapons)
|
||||||
+ '!')
|
+ '!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(make_guess 'Library')
|
(make_guess 'Library')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
fib = function <i> {
|
fib = |i| => {
|
||||||
if i <= 1 {
|
if i <= 1 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
15
examples/select.ds
Normal file
15
examples/select.ds
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
my_table = table |text number bool| [
|
||||||
|
["a", 1, true]
|
||||||
|
["b", 2, true]
|
||||||
|
["a", 3, true]
|
||||||
|
]
|
||||||
|
|
||||||
|
test_table = table |text bool| [
|
||||||
|
["a", true]
|
||||||
|
["b", true]
|
||||||
|
["a", true]
|
||||||
|
]
|
||||||
|
|
||||||
|
test_select = select |text bool| from my_table;
|
||||||
|
|
||||||
|
(assert_equal test_select, test_table)
|
@ -1,31 +1,31 @@
|
|||||||
my_table = table <text number bool> [
|
my_table = table |text number bool| [
|
||||||
["a", 1, true]
|
["a", 1, true]
|
||||||
["b", 2, true]
|
["b", 2, true]
|
||||||
["a", 3, true]
|
["a", 3, true]
|
||||||
]
|
]
|
||||||
|
|
||||||
test_table = table <text bool> [
|
test_table = table |text bool| [
|
||||||
["a", true]
|
["a", true]
|
||||||
["b", true]
|
["b", true]
|
||||||
["a", true]
|
["a", true]
|
||||||
]
|
]
|
||||||
|
|
||||||
test_select = select <text bool> from my_table
|
test_select = select |text bool| from my_table
|
||||||
|
|
||||||
(assert_equal test_select, test_table)
|
(assert_equal test_select, test_table)
|
||||||
|
|
||||||
test_table = table <text number bool> [
|
test_table = table |text number bool| [
|
||||||
[1, true]
|
[1, true]
|
||||||
[3, true]
|
[3, true]
|
||||||
]
|
]
|
||||||
|
|
||||||
test_select_where = select <number, bool> from my_table {
|
test_select_where = select |number, bool| from my_table {
|
||||||
text == "a"
|
text == "a"
|
||||||
}
|
}
|
||||||
|
|
||||||
(assert_equal test_select_where, test_table)
|
(assert_equal test_select_where, test_table)
|
||||||
|
|
||||||
test_table = table <text number bool> [
|
test_table = table |text number bool| [
|
||||||
["a", 1, true]
|
["a", 1, true]
|
||||||
["b", 2, true]
|
["b", 2, true]
|
||||||
["a", 3, true]
|
["a", 3, true]
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
use rayon::prelude::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tree_sitter::Node;
|
|
||||||
|
|
||||||
use crate::{AbstractTree, Block, Error, Map, Result, Value};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub struct Async {
|
|
||||||
statements: Vec<Block>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractTree for Async {
|
|
||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
|
||||||
debug_assert_eq!("async", node.kind());
|
|
||||||
|
|
||||||
let child_count = node.child_count();
|
|
||||||
let mut statements = Vec::with_capacity(child_count);
|
|
||||||
|
|
||||||
for index in 2..child_count - 1 {
|
|
||||||
let child = node.child(index).unwrap();
|
|
||||||
|
|
||||||
let statement = match child.kind() {
|
|
||||||
"statement" => Block::from_syntax_node(source, child)?,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "comment or statement",
|
|
||||||
actual: child.kind(),
|
|
||||||
location: child.start_position(),
|
|
||||||
relevant_source: source[child.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
statements.push(statement);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Async { statements })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
|
||||||
let statements = &self.statements;
|
|
||||||
|
|
||||||
statements
|
|
||||||
.into_par_iter()
|
|
||||||
.enumerate()
|
|
||||||
.find_map_first(|(index, statement)| {
|
|
||||||
let mut context = context.clone();
|
|
||||||
let result = statement.run(source, &mut context);
|
|
||||||
|
|
||||||
if result.is_err() {
|
|
||||||
Some(result)
|
|
||||||
} else if index == statements.len() - 1 {
|
|
||||||
Some(result)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
53
src/abstract_tree/await.rs
Normal file
53
src/abstract_tree/await.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use rayon::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tree_sitter::Node;
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Expression, Map, Result, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub struct Await {
|
||||||
|
expressions: Vec<Expression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for Await {
|
||||||
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
|
debug_assert_eq!("await", node.kind());
|
||||||
|
|
||||||
|
let mut expressions = Vec::new();
|
||||||
|
|
||||||
|
for index in 2..node.child_count() - 1 {
|
||||||
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.is_named() {
|
||||||
|
let expression = Expression::from_syntax_node(source, child)?;
|
||||||
|
|
||||||
|
expressions.push(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Await { expressions })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
|
let expressions = &self.expressions;
|
||||||
|
|
||||||
|
expressions
|
||||||
|
.into_par_iter()
|
||||||
|
.find_map_first(|expression| {
|
||||||
|
let mut context = context.clone();
|
||||||
|
let value = if let Ok(value) = expression.run(source, &mut context) {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let run_result = match value {
|
||||||
|
Value::Future(block) => block.run(source, &mut context),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(run_result)
|
||||||
|
})
|
||||||
|
.unwrap_or(Ok(Value::Empty))
|
||||||
|
}
|
||||||
|
}
|
@ -94,13 +94,13 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::AssertEqual(expressions)
|
BuiltInFunction::AssertEqual(expressions)
|
||||||
}
|
}
|
||||||
"download" => {
|
"download" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Download(expression)
|
BuiltInFunction::Download(expression)
|
||||||
}
|
}
|
||||||
"help" => {
|
"help" => {
|
||||||
let child_node = node.child(2).unwrap();
|
let child_node = node.child(1).unwrap();
|
||||||
let expression = if child_node.is_named() {
|
let expression = if child_node.is_named() {
|
||||||
Some(Expression::from_syntax_node(source, child_node)?)
|
Some(Expression::from_syntax_node(source, child_node)?)
|
||||||
} else {
|
} else {
|
||||||
@ -110,7 +110,7 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::Help(expression)
|
BuiltInFunction::Help(expression)
|
||||||
}
|
}
|
||||||
"length" => {
|
"length" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Length(expression)
|
BuiltInFunction::Length(expression)
|
||||||
@ -126,7 +126,7 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::OutputError(expressions)
|
BuiltInFunction::OutputError(expressions)
|
||||||
}
|
}
|
||||||
"type" => {
|
"type" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Type(expression)
|
BuiltInFunction::Type(expression)
|
||||||
@ -140,7 +140,7 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::Append(expressions)
|
BuiltInFunction::Append(expressions)
|
||||||
}
|
}
|
||||||
"metadata" => {
|
"metadata" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Metadata(expression)
|
BuiltInFunction::Metadata(expression)
|
||||||
@ -153,13 +153,13 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::Move(expressions)
|
BuiltInFunction::Move(expressions)
|
||||||
}
|
}
|
||||||
"read" => {
|
"read" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Read(expression)
|
BuiltInFunction::Read(expression)
|
||||||
}
|
}
|
||||||
"remove" => {
|
"remove" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::Remove(expression)
|
BuiltInFunction::Remove(expression)
|
||||||
@ -172,25 +172,25 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
BuiltInFunction::Write(expressions)
|
BuiltInFunction::Write(expressions)
|
||||||
}
|
}
|
||||||
"from_json" => {
|
"from_json" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::FromJson(expression)
|
BuiltInFunction::FromJson(expression)
|
||||||
}
|
}
|
||||||
"to_json" => {
|
"to_json" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::ToJson(expression)
|
BuiltInFunction::ToJson(expression)
|
||||||
}
|
}
|
||||||
"to_string" => {
|
"to_string" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::ToString(expression)
|
BuiltInFunction::ToString(expression)
|
||||||
}
|
}
|
||||||
"to_float" => {
|
"to_float" => {
|
||||||
let expression_node = node.child(2).unwrap();
|
let expression_node = node.child(1).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
BuiltInFunction::ToFloat(expression)
|
BuiltInFunction::ToFloat(expression)
|
||||||
@ -320,11 +320,11 @@ impl AbstractTree for BuiltInFunction {
|
|||||||
Value::Map(map) => map.len(),
|
Value::Map(map) => map.len(),
|
||||||
Value::Table(table) => table.len(),
|
Value::Table(table) => table.len(),
|
||||||
Value::String(string) => string.chars().count(),
|
Value::String(string) => string.chars().count(),
|
||||||
Value::Function(_) => todo!(),
|
_ => {
|
||||||
Value::Float(_) => todo!(),
|
return Err(Error::ExpectedCollection {
|
||||||
Value::Integer(_) => todo!(),
|
actual: value.clone(),
|
||||||
Value::Boolean(_) => todo!(),
|
});
|
||||||
Value::Empty => todo!(),
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Integer(length as i64))
|
Ok(Value::Integer(length as i64))
|
||||||
|
@ -18,7 +18,7 @@ impl AbstractTree for Find {
|
|||||||
let expression_node = node.child(3).unwrap();
|
let expression_node = node.child(3).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let item_node = node.child(5).unwrap();
|
let item_node = node.child(4).unwrap();
|
||||||
let item = Block::from_syntax_node(source, item_node)?;
|
let item = Block::from_syntax_node(source, item_node)?;
|
||||||
|
|
||||||
Ok(Find {
|
Ok(Find {
|
||||||
|
@ -33,7 +33,7 @@ impl AbstractTree for For {
|
|||||||
let expression_node = node.child(3).unwrap();
|
let expression_node = node.child(3).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let item_node = node.child(5).unwrap();
|
let item_node = node.child(4).unwrap();
|
||||||
let item = Block::from_syntax_node(source, item_node)?;
|
let item = Block::from_syntax_node(source, item_node)?;
|
||||||
|
|
||||||
Ok(For {
|
Ok(For {
|
||||||
|
@ -48,8 +48,9 @@ impl AbstractTree for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
|
let mut function_context = Map::clone_from(context);
|
||||||
let (name, arguments) = match self {
|
let (name, arguments) = match self {
|
||||||
FunctionCall::BuiltIn(function) => return function.run(source, context),
|
FunctionCall::BuiltIn(function) => return function.run(source, &mut function_context),
|
||||||
FunctionCall::ContextDefined { name, arguments } => (name, arguments),
|
FunctionCall::ContextDefined { name, arguments } => (name, arguments),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +59,6 @@ impl AbstractTree for FunctionCall {
|
|||||||
} else {
|
} else {
|
||||||
return Err(Error::FunctionIdentifierNotFound(name.clone()));
|
return Err(Error::FunctionIdentifierNotFound(name.clone()));
|
||||||
};
|
};
|
||||||
let mut function_context = Map::clone_from(context);
|
|
||||||
|
|
||||||
if let Some(parameters) = definition.identifiers() {
|
if let Some(parameters) = definition.identifiers() {
|
||||||
let parameter_expression_pairs = parameters.iter().zip(arguments.iter());
|
let parameter_expression_pairs = parameters.iter().zip(arguments.iter());
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//! examples.
|
//! examples.
|
||||||
|
|
||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
pub mod r#async;
|
pub mod r#await;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod built_in_function;
|
pub mod built_in_function;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
@ -33,8 +33,8 @@ pub mod r#while;
|
|||||||
pub use {
|
pub use {
|
||||||
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
|
||||||
function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*,
|
function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*,
|
||||||
r#async::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*, sublist::*,
|
r#await::*, r#await::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*,
|
||||||
transform::*, value_node::*,
|
sublist::*, transform::*, value_node::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
@ -18,7 +18,7 @@ impl AbstractTree for Remove {
|
|||||||
let expression_node = node.child(3).unwrap();
|
let expression_node = node.child(3).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let item_node = node.child(5).unwrap();
|
let item_node = node.child(4).unwrap();
|
||||||
let item = Block::from_syntax_node(source, item_node)?;
|
let item = Block::from_syntax_node(source, item_node)?;
|
||||||
|
|
||||||
Ok(Remove {
|
Ok(Remove {
|
||||||
|
@ -7,49 +7,36 @@ use crate::{AbstractTree, Block, Expression, Identifier, Map, Result, Table, Val
|
|||||||
pub struct Select {
|
pub struct Select {
|
||||||
identifiers: Vec<Identifier>,
|
identifiers: Vec<Identifier>,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
item: Option<Block>,
|
block: Option<Block>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Select {
|
impl AbstractTree for Select {
|
||||||
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
|
||||||
let child_count = node.child_count();
|
|
||||||
let mut identifiers = Vec::new();
|
let mut identifiers = Vec::new();
|
||||||
|
let identifier_list = node.child(1).unwrap();
|
||||||
|
|
||||||
for index in 2..child_count - 4 {
|
for index in 1..identifier_list.child_count() - 1 {
|
||||||
let node = node.child(index).unwrap();
|
let node = identifier_list.child(index).unwrap();
|
||||||
|
|
||||||
if node.kind() == "identifier" {
|
if node.is_named() {
|
||||||
let identifier = Identifier::from_syntax_node(source, node)?;
|
let identifier = Identifier::from_syntax_node(source, node)?;
|
||||||
identifiers.push(identifier);
|
identifiers.push(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.kind() == ">" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let final_node = node.child(child_count - 1).unwrap();
|
let expression_node = node.child(3).unwrap();
|
||||||
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let item = if final_node.kind() == "}" {
|
let block = if let Some(block_node) = node.child(4) {
|
||||||
let item_node = node.child(child_count - 2).unwrap();
|
Some(Block::from_syntax_node(source, block_node)?)
|
||||||
|
|
||||||
Some(Block::from_syntax_node(source, item_node)?)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let expression_node = if item.is_some() {
|
|
||||||
node.child(child_count - 4).unwrap()
|
|
||||||
} else {
|
|
||||||
node.child(child_count - 1).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
|
||||||
|
|
||||||
Ok(Select {
|
Ok(Select {
|
||||||
identifiers,
|
identifiers,
|
||||||
expression,
|
expression,
|
||||||
item,
|
block,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +86,7 @@ impl AbstractTree for Select {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(where_clause) = &self.item {
|
if let Some(where_clause) = &self.block {
|
||||||
let should_include = where_clause.run(source, &mut row_context)?.as_boolean()?;
|
let should_include = where_clause.run(source, &mut row_context)?.as_boolean()?;
|
||||||
|
|
||||||
if should_include {
|
if should_include {
|
||||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Assignment, Async, Error, Expression, Filter, Find, For, IfElse, Insert, Map,
|
AbstractTree, Assignment, Await, Error, Expression, Filter, Find, For, IfElse, Insert, Map,
|
||||||
Match, Remove, Result, Select, Transform, Value, While,
|
Match, Remove, Result, Select, Transform, Value, While,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13,11 +13,12 @@ use crate::{
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Assignment(Box<Assignment>),
|
Assignment(Box<Assignment>),
|
||||||
|
Await(Await),
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
IfElse(Box<IfElse>),
|
IfElse(Box<IfElse>),
|
||||||
Match(Match),
|
Match(Match),
|
||||||
While(Box<While>),
|
While(Box<While>),
|
||||||
Async(Box<Async>),
|
Async(Box<Await>),
|
||||||
For(Box<For>),
|
For(Box<For>),
|
||||||
Transform(Box<Transform>),
|
Transform(Box<Transform>),
|
||||||
Filter(Box<Filter>),
|
Filter(Box<Filter>),
|
||||||
@ -37,6 +38,7 @@ impl AbstractTree for Statement {
|
|||||||
"assignment" => Ok(Statement::Assignment(Box::new(
|
"assignment" => Ok(Statement::Assignment(Box::new(
|
||||||
Assignment::from_syntax_node(source, child)?,
|
Assignment::from_syntax_node(source, child)?,
|
||||||
))),
|
))),
|
||||||
|
"await" => Ok(Statement::Await(Await::from_syntax_node(source, child)?)),
|
||||||
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
|
||||||
source, child,
|
source, child,
|
||||||
)?)),
|
)?)),
|
||||||
@ -49,7 +51,7 @@ impl AbstractTree for Statement {
|
|||||||
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
|
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
|
||||||
source, child,
|
source, child,
|
||||||
)?))),
|
)?))),
|
||||||
"async" => Ok(Statement::Async(Box::new(Async::from_syntax_node(
|
"async" => Ok(Statement::Async(Box::new(Await::from_syntax_node(
|
||||||
source, child,
|
source, child,
|
||||||
)?))),
|
)?))),
|
||||||
"for" => Ok(Statement::For(Box::new(For::from_syntax_node(
|
"for" => Ok(Statement::For(Box::new(For::from_syntax_node(
|
||||||
@ -85,6 +87,7 @@ impl AbstractTree for Statement {
|
|||||||
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.run(source, context),
|
Statement::Assignment(assignment) => assignment.run(source, context),
|
||||||
|
Statement::Await(r#await) => r#await.run(source, context),
|
||||||
Statement::Expression(expression) => expression.run(source, context),
|
Statement::Expression(expression) => expression.run(source, context),
|
||||||
Statement::IfElse(if_else) => if_else.run(source, context),
|
Statement::IfElse(if_else) => if_else.run(source, context),
|
||||||
Statement::Match(r#match) => r#match.run(source, context),
|
Statement::Match(r#match) => r#match.run(source, context),
|
||||||
|
@ -19,7 +19,7 @@ impl AbstractTree for Transform {
|
|||||||
let expression_node = node.child(3).unwrap();
|
let expression_node = node.child(3).unwrap();
|
||||||
let expression = Expression::from_syntax_node(source, expression_node)?;
|
let expression = Expression::from_syntax_node(source, expression_node)?;
|
||||||
|
|
||||||
let item_node = node.child(5).unwrap();
|
let item_node = node.child(4).unwrap();
|
||||||
let item = Block::from_syntax_node(source, item_node)?;
|
let item = Block::from_syntax_node(source, item_node)?;
|
||||||
|
|
||||||
Ok(Transform {
|
Ok(Transform {
|
||||||
|
@ -123,15 +123,19 @@ impl AbstractTree for ValueNode {
|
|||||||
|
|
||||||
ValueType::Function(Function::new(parameters, body))
|
ValueType::Function(Function::new(parameters, body))
|
||||||
}
|
}
|
||||||
_ => {
|
"future" => {
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
let block_node = child.child(1).unwrap();
|
||||||
|
let block = Block::from_syntax_node(source, block_node)?;
|
||||||
|
|
||||||
|
ValueType::Future(block)
|
||||||
|
}
|
||||||
|
_ => return Err(Error::UnexpectedSyntaxNode {
|
||||||
expected:
|
expected:
|
||||||
"string, integer, float, boolean, list, table, map, function or empty",
|
"string, integer, float, boolean, list, table, map, function, future or empty",
|
||||||
actual: child.kind(),
|
actual: child.kind(),
|
||||||
location: child.start_position(),
|
location: child.start_position(),
|
||||||
relevant_source: source[child.byte_range()].to_string(),
|
relevant_source: source[child.byte_range()].to_string(),
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ValueNode {
|
Ok(ValueNode {
|
||||||
@ -203,6 +207,7 @@ impl AbstractTree for ValueNode {
|
|||||||
Value::Table(table)
|
Value::Table(table)
|
||||||
}
|
}
|
||||||
ValueType::Function(function) => Value::Function(function.clone()),
|
ValueType::Function(function) => Value::Function(function.clone()),
|
||||||
|
ValueType::Future(block) => Value::Future(block.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
@ -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, ValueType,
|
Block, Function, List, Map, Table, ValueType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
@ -32,14 +32,15 @@ pub mod value_type;
|
|||||||
/// value that can be treated as any other.
|
/// value that can be treated as any other.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
Boolean(bool),
|
||||||
|
Float(f64),
|
||||||
|
Function(Function),
|
||||||
|
Future(Block),
|
||||||
|
Integer(i64),
|
||||||
List(List),
|
List(List),
|
||||||
Map(Map),
|
Map(Map),
|
||||||
Table(Table),
|
|
||||||
Function(Function),
|
|
||||||
String(String),
|
String(String),
|
||||||
Float(f64),
|
Table(Table),
|
||||||
Integer(i64),
|
|
||||||
Boolean(bool),
|
|
||||||
#[default]
|
#[default]
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
@ -391,6 +392,8 @@ impl Ord for Value {
|
|||||||
(Value::Table(_), _) => Ordering::Greater,
|
(Value::Table(_), _) => Ordering::Greater,
|
||||||
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
||||||
(Value::Function(_), _) => Ordering::Greater,
|
(Value::Function(_), _) => Ordering::Greater,
|
||||||
|
(Value::Future(left), Value::Future(right)) => left.cmp(right),
|
||||||
|
(Value::Future(_), _) => Ordering::Greater,
|
||||||
(Value::Empty, Value::Empty) => Ordering::Equal,
|
(Value::Empty, Value::Empty) => Ordering::Equal,
|
||||||
(Value::Empty, _) => Ordering::Less,
|
(Value::Empty, _) => Ordering::Less,
|
||||||
}
|
}
|
||||||
@ -421,6 +424,7 @@ impl Serialize for Value {
|
|||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Map(inner) => inner.serialize(serializer),
|
||||||
Value::Table(inner) => inner.serialize(serializer),
|
Value::Table(inner) => inner.serialize(serializer),
|
||||||
Value::Function(inner) => inner.serialize(serializer),
|
Value::Function(inner) => inner.serialize(serializer),
|
||||||
|
Value::Future(inner) => inner.serialize(serializer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,6 +447,7 @@ impl Display for Value {
|
|||||||
Value::Map(map) => write!(f, "{map}"),
|
Value::Map(map) => write!(f, "{map}"),
|
||||||
Value::Table(table) => write!(f, "{table}"),
|
Value::Table(table) => write!(f, "{table}"),
|
||||||
Value::Function(function) => write!(f, "{function}"),
|
Value::Function(function) => write!(f, "{function}"),
|
||||||
|
Value::Future(block) => write!(f, "{block:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,13 @@ impl From<&Value> for Table {
|
|||||||
.insert(vec![Value::Function(function.clone())])
|
.insert(vec![Value::Function(function.clone())])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
table
|
||||||
|
}
|
||||||
|
Value::Future(block) => {
|
||||||
|
let mut table = Table::new(vec!["future".to_string()]);
|
||||||
|
|
||||||
|
table.insert(vec![Value::Future(block.clone())]).unwrap();
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{value_node::ValueNode, Expression, Function, Identifier, Statement, Value};
|
use crate::{value_node::ValueNode, Block, Expression, Function, Identifier, Statement, Value};
|
||||||
|
|
||||||
/// The type of a `Value`.
|
/// The type of a `Value`.
|
||||||
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
|
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
|
||||||
@ -23,6 +23,7 @@ pub enum ValueType {
|
|||||||
rows: Box<Expression>,
|
rows: Box<Expression>,
|
||||||
},
|
},
|
||||||
Function(Function),
|
Function(Function),
|
||||||
|
Future(Block),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for ValueType {}
|
impl Eq for ValueType {}
|
||||||
@ -84,6 +85,7 @@ impl Display for ValueType {
|
|||||||
write!(f, "table")
|
write!(f, "table")
|
||||||
}
|
}
|
||||||
ValueType::Function(function) => write!(f, "{function}"),
|
ValueType::Function(function) => write!(f, "{function}"),
|
||||||
|
ValueType::Future(_) => write!(f, "future"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,6 +139,7 @@ impl From<&Value> for ValueType {
|
|||||||
))),
|
))),
|
||||||
},
|
},
|
||||||
Value::Function(function) => ValueType::Function(function.clone()),
|
Value::Function(function) => ValueType::Function(function.clone()),
|
||||||
|
Value::Future(block) => ValueType::Future(block.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,13 @@ fn remove_loop() {
|
|||||||
evaluate(&file_contents).unwrap();
|
evaluate(&file_contents).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select() {
|
||||||
|
let file_contents = read_to_string("examples/select.ds").unwrap();
|
||||||
|
|
||||||
|
evaluate(&file_contents).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn table() {
|
fn table() {
|
||||||
let file_contents = read_to_string("examples/table.ds").unwrap();
|
let file_contents = read_to_string("examples/table.ds").unwrap();
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
==================
|
|
||||||
Simple Async Statements
|
|
||||||
==================
|
|
||||||
|
|
||||||
async { (output 'Whaddup') }
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
(root
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(async
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(function_call
|
|
||||||
(built_in_function
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(string))))))))))))
|
|
||||||
|
|
||||||
==================
|
|
||||||
Complex Async Statements
|
|
||||||
==================
|
|
||||||
|
|
||||||
async {
|
|
||||||
if 1 % 2 == 0 {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
'foobar'
|
|
||||||
}
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
(root
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(async
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(if_else
|
|
||||||
(if
|
|
||||||
(expression
|
|
||||||
(logic
|
|
||||||
(expression
|
|
||||||
(math
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(integer)))
|
|
||||||
(math_operator)
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(integer)))))
|
|
||||||
(logic_operator)
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(integer)))))
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(boolean))))))
|
|
||||||
(else
|
|
||||||
(block
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(boolean))))))))
|
|
||||||
(statement
|
|
||||||
(expression
|
|
||||||
(value
|
|
||||||
(string)))))))))
|
|
@ -101,7 +101,7 @@ Complex Function Call
|
|||||||
(foobar
|
(foobar
|
||||||
"hi"
|
"hi"
|
||||||
42
|
42
|
||||||
{
|
map {
|
||||||
x = 1
|
x = 1
|
||||||
y = 2
|
y = 2
|
||||||
}
|
}
|
||||||
@ -124,13 +124,20 @@ Complex Function Call
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(map
|
(map
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))
|
(integer))))))
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))))))))))
|
(integer)))))))))))))))
|
||||||
|
95
tree-sitter-dust/corpus/futures.txt
Normal file
95
tree-sitter-dust/corpus/futures.txt
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
================================================================================
|
||||||
|
Simple Future
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
async { (output 'Whaddup') }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(root
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(future
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(function_call
|
||||||
|
(built_in_function
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(string))))))))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Complex Future
|
||||||
|
================================================================================
|
||||||
|
async {
|
||||||
|
if 1 % 2 == 0 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
async { 123 }
|
||||||
|
|
||||||
|
'foo'
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(root
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(future
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(if_else
|
||||||
|
(if
|
||||||
|
(expression
|
||||||
|
(logic
|
||||||
|
(expression
|
||||||
|
(math
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(integer)))
|
||||||
|
(math_operator)
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(integer)))))
|
||||||
|
(logic_operator)
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(integer)))))
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(boolean))))))
|
||||||
|
(else
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(boolean))))))))
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(string)))))))))
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(future
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(integer)))))))))
|
||||||
|
(statement
|
||||||
|
(expression
|
||||||
|
(value
|
||||||
|
(string))))))
|
@ -1,10 +1,10 @@
|
|||||||
==================
|
================================================================================
|
||||||
Simple Map
|
Simple Map
|
||||||
==================
|
================================================================================
|
||||||
|
|
||||||
{ answer = 42 }
|
map { answer = 42 }
|
||||||
|
|
||||||
---
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
(root
|
(root
|
||||||
(block
|
(block
|
||||||
@ -12,27 +12,31 @@ Simple Map
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(map
|
(map
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))))))))
|
(integer)))))))))))))
|
||||||
|
|
||||||
==================
|
================================================================================
|
||||||
Nested Maps
|
Nested Maps
|
||||||
==================
|
================================================================================
|
||||||
|
|
||||||
x = {
|
x = map {
|
||||||
y = {
|
y = map {
|
||||||
foo = 'bar'
|
foo = 'bar'
|
||||||
z = {
|
z = map {
|
||||||
message = 'hiya'
|
message = 'hiya'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = 12
|
f = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
(root
|
(root
|
||||||
(block
|
(block
|
||||||
@ -44,28 +48,46 @@ x = {
|
|||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(map
|
(map
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(map
|
(map
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(string))))
|
(string))))))
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(map
|
(map
|
||||||
|
(block
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(string))))))))))))
|
(string))))))))))))))))))))
|
||||||
|
(statement
|
||||||
|
(assignment
|
||||||
(identifier)
|
(identifier)
|
||||||
|
(assignment_operator)
|
||||||
(statement
|
(statement
|
||||||
(expression
|
(expression
|
||||||
(value
|
(value
|
||||||
(integer))))))))))))
|
(integer)))))))))))))))
|
||||||
|
@ -7,23 +7,22 @@ module.exports = grammar({
|
|||||||
|
|
||||||
conflicts: $ => [
|
conflicts: $ => [
|
||||||
[$.block],
|
[$.block],
|
||||||
[$.map, $.assignment_operator],
|
|
||||||
],
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
root: $ => repeat1($.block),
|
root: $ => $.block,
|
||||||
|
|
||||||
comment: $ => /[#][^#\n]*[#|\n]/,
|
comment: $ => /[#][^#\n]*[#|\n]/,
|
||||||
|
|
||||||
block: $ => choice(
|
block: $ => prec.right(choice(
|
||||||
repeat1($.statement),
|
repeat1($.statement),
|
||||||
seq('{', repeat1($.statement), '}'),
|
seq('{', repeat1($.statement), '}'),
|
||||||
),
|
)),
|
||||||
|
|
||||||
statement: $ => prec.right(seq(
|
statement: $ => prec.right(seq(
|
||||||
choice(
|
choice(
|
||||||
$.assignment,
|
$.assignment,
|
||||||
$.async,
|
$.await,
|
||||||
$.expression,
|
$.expression,
|
||||||
$.filter,
|
$.filter,
|
||||||
$.find,
|
$.find,
|
||||||
@ -45,7 +44,7 @@ module.exports = grammar({
|
|||||||
seq('(', $._expression_kind, ')'),
|
seq('(', $._expression_kind, ')'),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
_expression_kind: $ => prec.left(1, choice(
|
_expression_kind: $ => prec.right(1, choice(
|
||||||
$.function_call,
|
$.function_call,
|
||||||
$.identifier,
|
$.identifier,
|
||||||
$.index,
|
$.index,
|
||||||
@ -67,6 +66,7 @@ module.exports = grammar({
|
|||||||
$.function,
|
$.function,
|
||||||
$.table,
|
$.table,
|
||||||
$.map,
|
$.map,
|
||||||
|
$.future,
|
||||||
),
|
),
|
||||||
|
|
||||||
integer: $ => token(prec.left(seq(
|
integer: $ => token(prec.left(seq(
|
||||||
@ -92,18 +92,24 @@ module.exports = grammar({
|
|||||||
|
|
||||||
list: $ => seq(
|
list: $ => seq(
|
||||||
'[',
|
'[',
|
||||||
repeat(prec.left(seq($.expression, optional(',')))),
|
repeat(prec.right(seq($.expression, optional(',')))),
|
||||||
']',
|
']',
|
||||||
),
|
),
|
||||||
|
|
||||||
map: $ => seq(
|
map: $ => seq(
|
||||||
|
'map',
|
||||||
|
$.block,
|
||||||
|
),
|
||||||
|
|
||||||
|
future: $ => seq(
|
||||||
|
'async',
|
||||||
|
$.block,
|
||||||
|
),
|
||||||
|
|
||||||
|
await: $ => seq(
|
||||||
|
'await',
|
||||||
'{',
|
'{',
|
||||||
repeat(seq(
|
$._expression_list,
|
||||||
$.identifier,
|
|
||||||
"=",
|
|
||||||
$.statement,
|
|
||||||
optional(',')
|
|
||||||
)),
|
|
||||||
'}',
|
'}',
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -265,11 +271,6 @@ module.exports = grammar({
|
|||||||
$.expression,
|
$.expression,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
async: $ => seq(
|
|
||||||
'async',
|
|
||||||
$.block,
|
|
||||||
),
|
|
||||||
|
|
||||||
identifier_list: $ => prec.right(choice(
|
identifier_list: $ => prec.right(choice(
|
||||||
seq(
|
seq(
|
||||||
'|',
|
'|',
|
||||||
|
@ -3,17 +3,17 @@
|
|||||||
"word": "identifier",
|
"word": "identifier",
|
||||||
"rules": {
|
"rules": {
|
||||||
"root": {
|
"root": {
|
||||||
"type": "REPEAT1",
|
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "block"
|
"name": "block"
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[#][^#\\n]*[#|\\n]"
|
"value": "[#][^#\\n]*[#|\\n]"
|
||||||
},
|
},
|
||||||
"block": {
|
"block": {
|
||||||
|
"type": "PREC_RIGHT",
|
||||||
|
"value": 0,
|
||||||
|
"content": {
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
@ -44,6 +44,7 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"statement": {
|
"statement": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
@ -60,7 +61,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "async"
|
"name": "await"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
@ -158,7 +159,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"_expression_kind": {
|
"_expression_kind": {
|
||||||
"type": "PREC_LEFT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 1,
|
"value": 1,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
@ -256,6 +257,10 @@
|
|||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "map"
|
"name": "map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "future"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -482,7 +487,7 @@
|
|||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "PREC_LEFT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 0,
|
"value": 0,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
@ -518,39 +523,41 @@
|
|||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "{"
|
"value": "map"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "SYMBOL",
|
||||||
"content": {
|
"name": "block"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"future": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "identifier"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "="
|
"value": "async"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "statement"
|
"name": "block"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
"await": {
|
||||||
"type": "CHOICE",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": ","
|
"value": "await"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "STRING",
|
||||||
}
|
"value": "{"
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
]
|
"type": "SYMBOL",
|
||||||
}
|
"name": "_expression_list"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
@ -1119,19 +1126,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"async": {
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "async"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "block"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"identifier_list": {
|
"identifier_list": {
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 0,
|
"value": 0,
|
||||||
@ -1434,10 +1428,6 @@
|
|||||||
"conflicts": [
|
"conflicts": [
|
||||||
[
|
[
|
||||||
"block"
|
"block"
|
||||||
],
|
|
||||||
[
|
|
||||||
"map",
|
|
||||||
"assignment_operator"
|
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"precedences": [],
|
"precedences": [],
|
||||||
|
@ -28,15 +28,15 @@
|
|||||||
"fields": {}
|
"fields": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "async",
|
"type": "await",
|
||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": false,
|
"multiple": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "block",
|
"type": "expression",
|
||||||
"named": true
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -287,6 +287,21 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "future",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": false,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "block",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "identifier_list",
|
"type": "identifier_list",
|
||||||
"named": true,
|
"named": true,
|
||||||
@ -422,15 +437,11 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": false,
|
||||||
"required": false,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "identifier",
|
"type": "block",
|
||||||
"named": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "statement",
|
|
||||||
"named": true
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -530,7 +541,7 @@
|
|||||||
"named": true,
|
"named": true,
|
||||||
"fields": {},
|
"fields": {},
|
||||||
"children": {
|
"children": {
|
||||||
"multiple": true,
|
"multiple": false,
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
@ -576,7 +587,7 @@
|
|||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "async",
|
"type": "await",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -692,6 +703,10 @@
|
|||||||
"type": "function",
|
"type": "function",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "future",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"named": true
|
"named": true
|
||||||
@ -846,6 +861,10 @@
|
|||||||
"type": "async",
|
"type": "async",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "await",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "bash",
|
"type": "bash",
|
||||||
"named": false
|
"named": false
|
||||||
@ -934,6 +953,10 @@
|
|||||||
"type": "length",
|
"type": "length",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "map",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "match",
|
"type": "match",
|
||||||
"named": false
|
"named": false
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user