Begin implementing async blocks
This commit is contained in:
parent
96afe7d3a3
commit
e29e092875
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -288,6 +288,31 @@ version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.27.0"
|
||||
@ -351,6 +376,7 @@ dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"rand",
|
||||
"rayon",
|
||||
"stanza",
|
||||
]
|
||||
|
||||
@ -883,6 +909,26 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
|
@ -16,4 +16,5 @@ colored = "2.1.0"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4.21"
|
||||
rand = "0.8.5"
|
||||
rayon = "1.9.0"
|
||||
stanza = "0.5.1"
|
||||
|
56
dust-lang/src/abstract_tree/async_block.rs
Normal file
56
dust-lang/src/abstract_tree/async_block.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
error::{RuntimeError, ValidationError},
|
||||
};
|
||||
|
||||
use super::{AbstractNode, Action, Statement, Type, WithPosition};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub struct AsyncBlock {
|
||||
statements: Vec<WithPosition<Statement>>,
|
||||
}
|
||||
|
||||
impl AsyncBlock {
|
||||
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
|
||||
Self { statements }
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractNode for AsyncBlock {
|
||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||
self.statements.last().unwrap().node.expected_type(_context)
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
for statement in &self.statements {
|
||||
statement.node.validate(_context)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
||||
let statement_count = self.statements.len();
|
||||
|
||||
self.statements
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.find_map_any(|(index, statement)| {
|
||||
let result = statement.node.run(_context);
|
||||
|
||||
match result {
|
||||
Ok(action) => {
|
||||
if index == statement_count - 1 {
|
||||
Some(Ok(action))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(runtime_error) => Some(Err(runtime_error)),
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod assignment;
|
||||
pub mod async_block;
|
||||
pub mod block;
|
||||
pub mod expression;
|
||||
pub mod function_call;
|
||||
@ -21,6 +22,7 @@ use chumsky::span::{SimpleSpan, Span};
|
||||
|
||||
pub use self::{
|
||||
assignment::{Assignment, AssignmentOperator},
|
||||
async_block::AsyncBlock,
|
||||
block::Block,
|
||||
expression::Expression,
|
||||
function_call::FunctionCall,
|
||||
|
@ -4,13 +4,14 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
AbstractNode, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type,
|
||||
While,
|
||||
AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop,
|
||||
StructureDefinition, Type, While,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum Statement {
|
||||
Assignment(Assignment),
|
||||
AsyncBlock(AsyncBlock),
|
||||
Block(Block),
|
||||
Break,
|
||||
Expression(Expression),
|
||||
@ -33,6 +34,7 @@ impl AbstractNode for Statement {
|
||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
||||
Statement::AsyncBlock(async_block) => async_block.expected_type(_context),
|
||||
Statement::Block(block) => block.expected_type(_context),
|
||||
Statement::Break => Ok(Type::None),
|
||||
Statement::Expression(expression) => expression.expected_type(_context),
|
||||
@ -48,6 +50,7 @@ impl AbstractNode for Statement {
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.validate(_context),
|
||||
Statement::AsyncBlock(async_block) => async_block.validate(_context),
|
||||
Statement::Block(block) => block.validate(_context),
|
||||
Statement::Break => Ok(()),
|
||||
Statement::Expression(expression) => expression.validate(_context),
|
||||
@ -63,6 +66,7 @@ impl AbstractNode for Statement {
|
||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.run(_context),
|
||||
Statement::AsyncBlock(async_block) => async_block.run(_context),
|
||||
Statement::Block(block) => block.run(_context),
|
||||
Statement::Break => Ok(Action::Break),
|
||||
Statement::Expression(expression) => expression.run(_context),
|
||||
|
@ -247,6 +247,12 @@ impl From<RwLockPoisonError> for RuntimeError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<PoisonError<T>> for RuntimeError {
|
||||
fn from(_: PoisonError<T>) -> Self {
|
||||
RuntimeError::RwLockPoison(RwLockPoisonError)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValidationError> for RuntimeError {
|
||||
fn from(error: ValidationError) -> Self {
|
||||
RuntimeError::ValidationFailure(error)
|
||||
|
@ -19,6 +19,7 @@ pub enum Token<'src> {
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum Keyword {
|
||||
Any,
|
||||
Async,
|
||||
Bool,
|
||||
Break,
|
||||
Else,
|
||||
@ -39,6 +40,7 @@ impl Display for Keyword {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Keyword::Any => write!(f, "any"),
|
||||
Keyword::Async => write!(f, "async"),
|
||||
Keyword::Bool => write!(f, "bool"),
|
||||
Keyword::Break => write!(f, "break"),
|
||||
Keyword::Else => write!(f, "else"),
|
||||
@ -255,6 +257,7 @@ pub fn lexer<'src>() -> impl Parser<
|
||||
|
||||
let keyword = choice((
|
||||
just("any").to(Keyword::Any),
|
||||
just("async").to(Keyword::Async),
|
||||
just("bool").to(Keyword::Bool),
|
||||
just("break").to(Keyword::Break),
|
||||
just("else").to(Keyword::Else),
|
||||
|
@ -1,5 +1,3 @@
|
||||
extern crate chumsky;
|
||||
|
||||
pub mod abstract_tree;
|
||||
pub mod context;
|
||||
pub mod error;
|
||||
|
@ -395,6 +395,21 @@ pub fn parser<'src>() -> impl Parser<
|
||||
Statement::Expression(node).with_position(position)
|
||||
});
|
||||
|
||||
let async_block = just(Token::Keyword(Keyword::Async))
|
||||
.ignore_then(
|
||||
positioned_statement
|
||||
.clone()
|
||||
.repeated()
|
||||
.collect()
|
||||
.delimited_by(
|
||||
just(Token::Control(Control::CurlyOpen)),
|
||||
just(Token::Control(Control::CurlyClose)),
|
||||
),
|
||||
)
|
||||
.map_with(|statements, state| {
|
||||
Statement::AsyncBlock(AsyncBlock::new(statements)).with_position(state.span())
|
||||
});
|
||||
|
||||
let r#break = just(Token::Keyword(Keyword::Break))
|
||||
.map_with(|_, state| Statement::Break.with_position(state.span()));
|
||||
|
||||
@ -485,6 +500,7 @@ pub fn parser<'src>() -> impl Parser<
|
||||
});
|
||||
|
||||
choice((
|
||||
async_block,
|
||||
structure_definition,
|
||||
if_else,
|
||||
assignment,
|
||||
@ -506,6 +522,32 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn async_block() {
|
||||
assert_eq!(
|
||||
parse(
|
||||
&lex("
|
||||
async {
|
||||
1
|
||||
2
|
||||
3
|
||||
}
|
||||
")
|
||||
.unwrap()
|
||||
)
|
||||
.unwrap()[0]
|
||||
.node,
|
||||
Statement::AsyncBlock(AsyncBlock::new(vec![
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
|
||||
.with_position((53, 54)),
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(2)))
|
||||
.with_position((79, 80)),
|
||||
Statement::Expression(Expression::Value(ValueNode::Integer(3)))
|
||||
.with_position((105, 106)),
|
||||
]))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structure_instance() {
|
||||
assert_eq!(
|
||||
|
Loading…
Reference in New Issue
Block a user