Begin implementing async blocks

This commit is contained in:
Jeff 2024-03-20 17:05:37 -04:00
parent 96afe7d3a3
commit e29e092875
9 changed files with 162 additions and 4 deletions

46
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View 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()
}
}

View File

@ -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,

View File

@ -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),

View File

@ -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)

View File

@ -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),

View File

@ -1,5 +1,3 @@
extern crate chumsky;
pub mod abstract_tree;
pub mod context;
pub mod error;

View File

@ -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!(