Add async statements
This commit is contained in:
parent
4e8d320c77
commit
2ccd28bbf4
18
README.md
18
README.md
@ -11,9 +11,8 @@ A basic dust program:
|
|||||||
Dust can do two (or more) things at the same time with effortless concurrency:
|
Dust can do two (or more) things at the same time with effortless concurrency:
|
||||||
|
|
||||||
```dust
|
```dust
|
||||||
(run
|
async (output 'will this one finish first?')
|
||||||
(output 'will this one finish first?')
|
async (output 'or will this one?')
|
||||||
(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.
|
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
|
## 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.
|
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.
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
suspects = ["White", "Green"];
|
|
||||||
rooms = ["Library", "Kitchen"];
|
rooms = ["Library", "Kitchen"];
|
||||||
|
suspects = ["White", "Green"];
|
||||||
weapons = ["Rope", "Lead Pipe"];
|
weapons = ["Rope", "Lead Pipe"];
|
||||||
|
|
||||||
|
show_card = function <card> {
|
||||||
|
(remove rooms card)
|
||||||
|
(remove suspects card)
|
||||||
|
(remove weapons card)
|
||||||
|
}
|
||||||
|
|
||||||
make_guess = function <current_room> {
|
make_guess = function <current_room> {
|
||||||
if (length suspects) == 1
|
if (length suspects) == 1
|
||||||
&& (length rooms) == 1
|
&& (length rooms) == 1
|
||||||
&& (length weapons) == 1
|
&& (length weapons) == 1
|
||||||
then
|
{
|
||||||
(output 'It was '
|
(output 'It was '
|
||||||
+ suspects.0
|
+ suspects.0
|
||||||
+ ' in the '
|
+ ' in the '
|
||||||
@ -14,8 +20,8 @@ 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 '
|
||||||
@ -24,3 +30,4 @@ make_guess = function <current_room> {
|
|||||||
+ (random weapons)
|
+ (random weapons)
|
||||||
+ '!')
|
+ '!')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
23
src/abstract_tree/async.rs
Normal file
23
src/abstract_tree/async.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
//! Top-level unit of Dust code.
|
//! Top-level unit of Dust code.
|
||||||
|
|
||||||
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
@ -19,6 +20,16 @@ impl Item {
|
|||||||
pub fn new(statements: Vec<Statement>) -> Self {
|
pub fn new(statements: Vec<Statement>) -> Self {
|
||||||
Self { statements }
|
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 {
|
impl AbstractTree for Item {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
//! examples.
|
//! examples.
|
||||||
|
|
||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
|
pub mod r#async;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
pub mod function_call;
|
pub mod function_call;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
r#while::While, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
|
r#async::Async, r#while::While, AbstractTree, Assignment, Error, Expression, IfElse, Match,
|
||||||
VariableMap,
|
Result, Value, VariableMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract representation of a statement.
|
/// Abstract representation of a statement.
|
||||||
@ -17,6 +17,7 @@ pub enum Statement {
|
|||||||
IfElse(Box<IfElse>),
|
IfElse(Box<IfElse>),
|
||||||
Match(Match),
|
Match(Match),
|
||||||
While(Box<While>),
|
While(Box<While>),
|
||||||
|
Run(Box<Async>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Statement {
|
impl AbstractTree for Statement {
|
||||||
@ -41,8 +42,11 @@ 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::Run(Box::new(Async::from_syntax_node(
|
||||||
|
source, child,
|
||||||
|
)?))),
|
||||||
_ => Err(Error::UnexpectedSyntaxNode {
|
_ => Err(Error::UnexpectedSyntaxNode {
|
||||||
expected: "assignment, expression, if...else or tool",
|
expected: "assignment, expression, if...else, while, tool or async",
|
||||||
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(),
|
||||||
@ -57,6 +61,7 @@ impl AbstractTree for Statement {
|
|||||||
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),
|
||||||
Statement::While(r#while) => r#while.run(source, context),
|
Statement::While(r#while) => r#while.run(source, context),
|
||||||
|
Statement::Run(run) => run.run(source, context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,14 @@ use std::fs::read_to_string;
|
|||||||
use rand::{random, thread_rng, Rng};
|
use rand::{random, thread_rng, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Tool {
|
pub enum Tool {
|
||||||
Assert,
|
Assert,
|
||||||
AssertEqual,
|
AssertEqual,
|
||||||
Output,
|
Output,
|
||||||
|
Run,
|
||||||
Read,
|
Read,
|
||||||
Help,
|
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 => {
|
Tool::Output => {
|
||||||
if values.len() != 1 {
|
if values.len() != 1 {
|
||||||
return Err(Error::ExpectedToolArgumentAmount {
|
return Err(Error::ExpectedToolArgumentAmount {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit b47907ee26b42990e5170ba9521de5ae66d596ef
|
Subproject commit 0f58ea5a7a05d49d99bbe24b9da03eea5249cbd7
|
Loading…
Reference in New Issue
Block a user