Implement await statements

This commit is contained in:
Jeff 2023-11-03 21:16:55 -04:00
parent bc1b88a5fa
commit 2178c67499
17 changed files with 61308 additions and 69777 deletions

View File

@ -2,44 +2,32 @@
(output "This will print second.") (output "This will print second.")
create_random_numbers = |count| => { create_random_numbers = |count| => {
numbers = [] numbers = [];
while (length numbers) < count { while (length numbers) < count {
numbers += (random_integer) numbers += (random_integer)
} }
} }
do_second = async { do_a_lot = async {
{
(create_random_numbers 1000) (create_random_numbers 1000)
(output "Made 1000 numbers") (output "Made 1000 numbers")
} }
{
do_some = async {
(create_random_numbers 100) (create_random_numbers 100)
(output "Made 100 numbers") (output "Made 100 numbers")
} }
{
do_a_little = async {
(create_random_numbers 10) (create_random_numbers 10)
(output "Made 10 numbers") (output "Made 10 numbers")
} }
}
do_first = async { await {
{ do_a_lot
(create_random_numbers 400) do_some
(output "Made 400 numbers") do_a_little
} }
{
(create_random_numbers 40)
(output "Made 40 numbers")
}
{
(create_random_numbers 4)
(output "Made 4 numbers")
}
}
do_first.await
do_second.await
(output "This will print last.") (output "This will print last.")

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

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

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

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

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

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

@ -1,5 +1,5 @@
================================================================================ ================================================================================
Simple Async Statements Simple Future
================================================================================ ================================================================================
async { (output 'Whaddup') } async { (output 'Whaddup') }
@ -22,9 +22,8 @@ async { (output 'Whaddup') }
(string)))))))))))))) (string))))))))))))))
================================================================================ ================================================================================
Complex Async Statements Complex Future
================================================================================ ================================================================================
async { async {
if 1 % 2 == 0 { if 1 % 2 == 0 {
true true
@ -35,6 +34,10 @@ async {
'foobar' 'foobar'
} }
async { 123 }
'foo'
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
(root (root
@ -76,4 +79,17 @@ async {
(statement (statement
(expression (expression
(value (value
(string))))))))))) (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,7 +7,6 @@ module.exports = grammar({
conflicts: $ => [ conflicts: $ => [
[$.block], [$.block],
[$.map, $.assignment_operator],
], ],
rules: { rules: {
@ -23,6 +22,7 @@ module.exports = grammar({
statement: $ => prec.right(seq( statement: $ => prec.right(seq(
choice( choice(
$.assignment, $.assignment,
$.await,
$.expression, $.expression,
$.filter, $.filter,
$.find, $.find,
@ -44,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,
@ -92,19 +92,13 @@ module.exports = grammar({
list: $ => seq( list: $ => seq(
'[', '[',
$._expression_list, repeat(prec.right(seq($.expression, optional(',')))),
']', ']',
), ),
map: $ => seq( map: $ => seq(
'{', 'map',
repeat(seq( $.block,
$.identifier,
"=",
$.statement,
optional(',')
)),
'}',
), ),
future: $ => seq( future: $ => seq(
@ -112,6 +106,13 @@ module.exports = grammar({
$.block, $.block,
), ),
await: $ => seq(
'await',
'{',
$._expression_list,
'}',
),
index: $ => prec.left(seq( index: $ => prec.left(seq(
$.expression, $.expression,
':', ':',

View File

@ -59,6 +59,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "assignment" "name": "assignment"
}, },
{
"type": "SYMBOL",
"name": "await"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "expression" "name": "expression"
@ -155,7 +159,7 @@
} }
}, },
"_expression_kind": { "_expression_kind": {
"type": "PREC_LEFT", "type": "PREC_RIGHT",
"value": 1, "value": 1,
"content": { "content": {
"type": "CHOICE", "type": "CHOICE",
@ -480,39 +484,17 @@
"type": "STRING", "type": "STRING",
"value": "[" "value": "["
}, },
{
"type": "SYMBOL",
"name": "_expression_list"
},
{
"type": "STRING",
"value": "]"
}
]
},
"map": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{ {
"type": "REPEAT", "type": "REPEAT",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": { "content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "identifier" "name": "expression"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -528,10 +510,24 @@
} }
] ]
} }
}
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "}" "value": "]"
}
]
},
"map": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "map"
},
{
"type": "SYMBOL",
"name": "block"
} }
] ]
}, },
@ -548,6 +544,27 @@
} }
] ]
}, },
"await": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "await"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "SYMBOL",
"name": "_expression_list"
},
{
"type": "STRING",
"value": "}"
}
]
},
"index": { "index": {
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
@ -1411,10 +1428,6 @@
"conflicts": [ "conflicts": [
[ [
"block" "block"
],
[
"map",
"assignment_operator"
] ]
], ],
"precedences": [], "precedences": [],

View File

@ -27,6 +27,21 @@
"named": true, "named": true,
"fields": {} "fields": {}
}, },
{
"type": "await",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "expression",
"named": true
}
]
}
},
{ {
"type": "block", "type": "block",
"named": true, "named": true,
@ -384,7 +399,7 @@
"fields": {}, "fields": {},
"children": { "children": {
"multiple": true, "multiple": true,
"required": true, "required": false,
"types": [ "types": [
{ {
"type": "expression", "type": "expression",
@ -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
} }
] ]
@ -575,6 +586,10 @@
"type": "assignment", "type": "assignment",
"named": true "named": true
}, },
{
"type": "await",
"named": true
},
{ {
"type": "expression", "type": "expression",
"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