1
0

Compare commits

...

3 Commits

Author SHA1 Message Date
2178c67499 Implement await statements 2023-11-03 21:16:55 -04:00
bc1b88a5fa Begin adding futures 2023-11-03 19:39:34 -04:00
8ca97300d3 Clean up 2023-11-03 18:04:45 -04:00
29 changed files with 65295 additions and 82183 deletions

33
examples/async.ds Normal file
View 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.")

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values. //! Types that represent runtime values.
use crate::{ use crate::{
error::{Error, Result}, error::{Error, Result},
Function, List, Map, Table, 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:?}"),
} }
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -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": [],

View File

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