Add async statements

This commit is contained in:
Jeff 2023-10-16 16:48:02 -04:00
parent 4e8d320c77
commit 2ccd28bbf4
8 changed files with 80 additions and 12 deletions

View File

@ -11,9 +11,8 @@ A basic dust program:
Dust can do two (or more) things at the same time with effortless concurrency:
```dust
(run
(output 'will this one finish first?')
(output 'or will this one?'))
async (output 'will this one finish first?')
async (output 'or will this one?')
```
Dust is an interpreted, general purpose language with first class functions. It is *data-oriented*, with extensive tools to manage structured and relational data. Dust also includes built-in tooling to import and export data in a variety of formats, including JSON, TOML, YAML and CSV.
@ -172,6 +171,19 @@ print = function <input> {
}
```
### Concurrency
As a language written in Rust, Dust features effortless concurrency anywhere in your code.
```dust
if (random_integer) % 2 == 0 {
run {
(output 1 + 1)
(output 1 + 1 == 2)
}
}
```
## Implementation
Dust is formally defined as a Tree Sitter grammar in the tree-sitter-dust module. Tree sitter generates a parser, written in C, from a set of rules defined in Javascript. Dust itself is a rust binary that calls the C parser using FFI.

View File

@ -1,12 +1,18 @@
suspects = ["White", "Green"];
rooms = ["Library", "Kitchen"];
suspects = ["White", "Green"];
weapons = ["Rope", "Lead Pipe"];
show_card = function <card> {
(remove rooms card)
(remove suspects card)
(remove weapons card)
}
make_guess = function <current_room> {
if (length suspects) == 1
&& (length rooms) == 1
&& (length weapons) == 1
then
{
(output 'It was '
+ suspects.0
+ ' in the '
@ -14,8 +20,8 @@ make_guess = function <current_room> {
+ ' with the '
+ weapons.0
+ '!'
);
else
)
} else {
(output 'I accuse '
+ (random suspects)
+ ' in the '
@ -23,4 +29,5 @@ make_guess = function <current_room> {
+ ' with the '
+ (random weapons)
+ '!')
}
}

View File

@ -0,0 +1,23 @@
use serde::{Deserialize, Serialize};
use crate::{AbstractTree, Item};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Async {
item: Item,
}
impl AbstractTree for Async {
fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result<Self> {
debug_assert_eq!("async", node.kind());
let item_node = node.child(2).unwrap();
let item = Item::from_syntax_node(source, item_node)?;
Ok(Async { item })
}
fn run(&self, source: &str, context: &mut crate::VariableMap) -> crate::Result<crate::Value> {
self.item.run_parallel(source, context)
}
}

View File

@ -1,5 +1,6 @@
//! Top-level unit of Dust code.
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
@ -19,6 +20,16 @@ impl Item {
pub fn new(statements: Vec<Statement>) -> Self {
Self { statements }
}
pub fn run_parallel(&self, source: &str, context: &mut VariableMap) -> Result<Value> {
self.statements.par_iter().for_each(|statement| {
let mut context = context.clone();
statement.run(source, &mut context);
});
Ok(Value::Empty)
}
}
impl AbstractTree for Item {

View File

@ -7,6 +7,7 @@
//! examples.
pub mod assignment;
pub mod r#async;
pub mod expression;
pub mod function_call;
pub mod identifier;

View File

@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
r#while::While, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
VariableMap,
r#async::Async, r#while::While, AbstractTree, Assignment, Error, Expression, IfElse, Match,
Result, Value, VariableMap,
};
/// Abstract representation of a statement.
@ -17,6 +17,7 @@ pub enum Statement {
IfElse(Box<IfElse>),
Match(Match),
While(Box<While>),
Run(Box<Async>),
}
impl AbstractTree for Statement {
@ -41,8 +42,11 @@ impl AbstractTree for Statement {
"while" => Ok(Statement::While(Box::new(While::from_syntax_node(
source, child,
)?))),
"async" => Ok(Statement::Run(Box::new(Async::from_syntax_node(
source, child,
)?))),
_ => Err(Error::UnexpectedSyntaxNode {
expected: "assignment, expression, if...else or tool",
expected: "assignment, expression, if...else, while, tool or async",
actual: child.kind(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
@ -57,6 +61,7 @@ impl AbstractTree for Statement {
Statement::IfElse(if_else) => if_else.run(source, context),
Statement::Match(r#match) => r#match.run(source, context),
Statement::While(r#while) => r#while.run(source, context),
Statement::Run(run) => run.run(source, context),
}
}
}

View File

@ -3,13 +3,14 @@ use std::fs::read_to_string;
use rand::{random, thread_rng, Rng};
use serde::{Deserialize, Serialize};
use crate::{Error, Result, Table, Value};
use crate::{evaluate, Error, Result, Table, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum Tool {
Assert,
AssertEqual,
Output,
Run,
Read,
Help,
@ -96,6 +97,14 @@ impl Tool {
});
}
}
Tool::Run => {
Error::expect_tool_argument_amount("run", 1, values.len())?;
let file_path = values[0].as_string()?;
let file_contents = read_to_string(file_path)?;
evaluate(&file_contents)?
}
Tool::Output => {
if values.len() != 1 {
return Err(Error::ExpectedToolArgumentAmount {

@ -1 +1 @@
Subproject commit b47907ee26b42990e5170ba9521de5ae66d596ef
Subproject commit 0f58ea5a7a05d49d99bbe24b9da03eea5249cbd7