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.")
create_random_numbers = |count| => {
numbers = []
numbers = [];
while (length numbers) < count {
numbers += (random_integer)
}
}
do_second = async {
{
(create_random_numbers 1000)
(output "Made 1000 numbers")
}
{
(create_random_numbers 100)
(output "Made 100 numbers")
}
{
(create_random_numbers 10)
(output "Made 10 numbers")
}
do_a_lot = async {
(create_random_numbers 1000)
(output "Made 1000 numbers")
}
do_first = async {
{
(create_random_numbers 400)
(output "Made 400 numbers")
}
{
(create_random_numbers 40)
(output "Made 40 numbers")
}
{
(create_random_numbers 4)
(output "Made 4 numbers")
}
do_some = async {
(create_random_numbers 100)
(output "Made 100 numbers")
}
do_first.await
do_second.await
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

@ -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::Table(table) => table.len(),
Value::String(string) => string.chars().count(),
Value::Function(_) => todo!(),
Value::Float(_) => todo!(),
Value::Integer(_) => todo!(),
Value::Boolean(_) => todo!(),
Value::Empty => todo!(),
_ => {
return Err(Error::ExpectedCollection {
actual: value.clone(),
});
}
};
Ok(Value::Integer(length as i64))

View File

@ -7,7 +7,7 @@
//! examples.
pub mod assignment;
pub mod r#async;
pub mod r#await;
pub mod block;
pub mod built_in_function;
pub mod expression;
@ -33,8 +33,8 @@ pub mod r#while;
pub use {
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
function_call::*, identifier::*, if_else::*, index::*, insert::*, logic::*, math::*,
r#async::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*, sublist::*,
transform::*, value_node::*,
r#await::*, r#await::*, r#for::*, r#match::*, r#while::*, remove::*, select::*, statement::*,
sublist::*, transform::*, value_node::*,
};
use tree_sitter::Node;

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
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,
};
@ -13,11 +13,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Statement {
Assignment(Box<Assignment>),
Await(Await),
Expression(Expression),
IfElse(Box<IfElse>),
Match(Match),
While(Box<While>),
Async(Box<Async>),
Async(Box<Await>),
For(Box<For>),
Transform(Box<Transform>),
Filter(Box<Filter>),
@ -37,6 +38,7 @@ impl AbstractTree for Statement {
"assignment" => Ok(Statement::Assignment(Box::new(
Assignment::from_syntax_node(source, child)?,
))),
"await" => Ok(Statement::Await(Await::from_syntax_node(source, child)?)),
"expression" => Ok(Self::Expression(Expression::from_syntax_node(
source, child,
)?)),
@ -49,7 +51,7 @@ impl AbstractTree for Statement {
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
source, child,
)?))),
"async" => Ok(Statement::Async(Box::new(Async::from_syntax_node(
"async" => Ok(Statement::Async(Box::new(Await::from_syntax_node(
source, child,
)?))),
"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> {
match self {
Statement::Assignment(assignment) => assignment.run(source, context),
Statement::Await(r#await) => r#await.run(source, context),
Statement::Expression(expression) => expression.run(source, context),
Statement::IfElse(if_else) => if_else.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))
}
_ => {
return Err(Error::UnexpectedSyntaxNode {
expected:
"string, integer, float, boolean, list, table, map, function or empty",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
})
"future" => {
let block_node = child.child(1).unwrap();
let block = Block::from_syntax_node(source, block_node)?;
ValueType::Future(block)
}
_ => return Err(Error::UnexpectedSyntaxNode {
expected:
"string, integer, float, boolean, list, table, map, function, future or empty",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
}),
};
Ok(ValueNode {
@ -203,6 +207,7 @@ impl AbstractTree for ValueNode {
Value::Table(table)
}
ValueType::Function(function) => Value::Function(function.clone()),
ValueType::Future(block) => Value::Future(block.clone()),
};
Ok(value)

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values.
use crate::{
error::{Error, Result},
Function, List, Map, Table, ValueType,
Block, Function, List, Map, Table, ValueType,
};
use json::JsonValue;
@ -32,14 +32,15 @@ pub mod value_type;
/// value that can be treated as any other.
#[derive(Debug, Clone, Default)]
pub enum Value {
Boolean(bool),
Float(f64),
Function(Function),
Future(Block),
Integer(i64),
List(List),
Map(Map),
Table(Table),
Function(Function),
String(String),
Float(f64),
Integer(i64),
Boolean(bool),
Table(Table),
#[default]
Empty,
}
@ -391,6 +392,8 @@ impl Ord for Value {
(Value::Table(_), _) => Ordering::Greater,
(Value::Function(left), Value::Function(right)) => left.cmp(right),
(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, _) => Ordering::Less,
}
@ -421,6 +424,7 @@ impl Serialize for Value {
Value::Map(inner) => inner.serialize(serializer),
Value::Table(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::Table(table) => write!(f, "{table}"),
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())])
.unwrap();
table
}
Value::Future(block) => {
let mut table = Table::new(vec!["future".to_string()]);
table.insert(vec![Value::Future(block.clone())]).unwrap();
table
}
}

View File

@ -5,7 +5,7 @@ use std::{
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`.
#[derive(Clone, Serialize, Deserialize, PartialOrd, Ord)]
@ -23,6 +23,7 @@ pub enum ValueType {
rows: Box<Expression>,
},
Function(Function),
Future(Block),
}
impl Eq for ValueType {}
@ -84,6 +85,7 @@ impl Display for ValueType {
write!(f, "table")
}
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::Future(block) => ValueType::Future(block.clone()),
}
}
}

View File

@ -101,7 +101,7 @@ Complex Function Call
(foobar
"hi"
42
{
map {
x = 1
y = 2
}
@ -124,13 +124,20 @@ Complex Function Call
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer))))
(identifier)
(statement
(expression
(value
(integer))))))))))))
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))))

View File

@ -1,5 +1,5 @@
================================================================================
Simple Async Statements
Simple Future
================================================================================
async { (output 'Whaddup') }
@ -22,9 +22,8 @@ async { (output 'Whaddup') }
(string))))))))))))))
================================================================================
Complex Async Statements
Complex Future
================================================================================
async {
if 1 % 2 == 0 {
true
@ -35,6 +34,10 @@ async {
'foobar'
}
async { 123 }
'foo'
--------------------------------------------------------------------------------
(root
@ -76,4 +79,17 @@ async {
(statement
(expression
(value
(string)))))))))))
(string)))))))))
(statement
(expression
(value
(future
(block
(statement
(expression
(value
(integer)))))))))
(statement
(expression
(value
(string))))))

View File

@ -1,10 +1,10 @@
==================
================================================================================
Simple Map
==================
================================================================================
{ answer = 42 }
map { answer = 42 }
---
--------------------------------------------------------------------------------
(root
(block
@ -12,27 +12,31 @@ Simple Map
(expression
(value
(map
(identifier)
(statement
(expression
(value
(integer))))))))))
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))
==================
================================================================================
Nested Maps
==================
================================================================================
x = {
y = {
x = map {
y = map {
foo = 'bar'
z = {
z = map {
message = 'hiya'
}
}
f = 12
}
---
--------------------------------------------------------------------------------
(root
(block
@ -44,28 +48,46 @@ x = {
(expression
(value
(map
(identifier)
(statement
(expression
(value
(map
(identifier)
(statement
(expression
(value
(string))))
(identifier)
(statement
(expression
(value
(map
(identifier)
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(map
(block
(statement
(expression
(value
(string))))))))))))
(identifier)
(statement
(expression
(value
(integer))))))))))))
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(string))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(map
(block
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(string))))))))))))))))))))
(statement
(assignment
(identifier)
(assignment_operator)
(statement
(expression
(value
(integer)))))))))))))))

View File

@ -7,7 +7,6 @@ module.exports = grammar({
conflicts: $ => [
[$.block],
[$.map, $.assignment_operator],
],
rules: {
@ -23,6 +22,7 @@ module.exports = grammar({
statement: $ => prec.right(seq(
choice(
$.assignment,
$.await,
$.expression,
$.filter,
$.find,
@ -44,7 +44,7 @@ module.exports = grammar({
seq('(', $._expression_kind, ')'),
)),
_expression_kind: $ => prec.left(1, choice(
_expression_kind: $ => prec.right(1, choice(
$.function_call,
$.identifier,
$.index,
@ -92,25 +92,26 @@ module.exports = grammar({
list: $ => seq(
'[',
$._expression_list,
repeat(prec.right(seq($.expression, optional(',')))),
']',
),
map: $ => seq(
'{',
repeat(seq(
$.identifier,
"=",
$.statement,
optional(',')
)),
'}',
'map',
$.block,
),
future: $ => seq(
'async',
$.block,
),
await: $ => seq(
'await',
'{',
$._expression_list,
'}',
),
index: $ => prec.left(seq(
$.expression,

View File

@ -59,6 +59,10 @@
"type": "SYMBOL",
"name": "assignment"
},
{
"type": "SYMBOL",
"name": "await"
},
{
"type": "SYMBOL",
"name": "expression"
@ -155,7 +159,7 @@
}
},
"_expression_kind": {
"type": "PREC_LEFT",
"type": "PREC_RIGHT",
"value": 1,
"content": {
"type": "CHOICE",
@ -481,8 +485,32 @@
"value": "["
},
{
"type": "SYMBOL",
"name": "_expression_list"
"type": "REPEAT",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
}
},
{
"type": "STRING",
@ -495,43 +523,11 @@
"members": [
{
"type": "STRING",
"value": "{"
"value": "map"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "statement"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}
},
{
"type": "STRING",
"value": "}"
"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": {
"type": "PREC_LEFT",
"value": 0,
@ -1411,10 +1428,6 @@
"conflicts": [
[
"block"
],
[
"map",
"assignment_operator"
]
],
"precedences": [],

View File

@ -27,6 +27,21 @@
"named": true,
"fields": {}
},
{
"type": "await",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "expression",
"named": true
}
]
}
},
{
"type": "block",
"named": true,
@ -384,7 +399,7 @@
"fields": {},
"children": {
"multiple": true,
"required": true,
"required": false,
"types": [
{
"type": "expression",
@ -422,15 +437,11 @@
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"multiple": false,
"required": true,
"types": [
{
"type": "identifier",
"named": true
},
{
"type": "statement",
"type": "block",
"named": true
}
]
@ -575,6 +586,10 @@
"type": "assignment",
"named": true
},
{
"type": "await",
"named": true
},
{
"type": "expression",
"named": true
@ -846,6 +861,10 @@
"type": "async",
"named": false
},
{
"type": "await",
"named": false
},
{
"type": "bash",
"named": false
@ -934,6 +953,10 @@
"type": "length",
"named": false
},
{
"type": "map",
"named": false
},
{
"type": "match",
"named": false

File diff suppressed because it is too large Load Diff