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
|
||||
(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.
|
||||
|
@ -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 '
|
||||
@ -24,3 +30,4 @@ make_guess = function <current_room> {
|
||||
+ (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.
|
||||
|
||||
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 {
|
||||
|
@ -7,6 +7,7 @@
|
||||
//! examples.
|
||||
|
||||
pub mod assignment;
|
||||
pub mod r#async;
|
||||
pub mod expression;
|
||||
pub mod function_call;
|
||||
pub mod identifier;
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user