1
0
dust/src/abstract_tree/block.rs

101 lines
3.2 KiB
Rust
Raw Normal View History

use std::sync::RwLock;
2023-11-11 01:44:03 +00:00
use rayon::prelude::*;
2023-10-31 17:04:22 +00:00
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
2023-12-05 22:08:22 +00:00
use crate::{AbstractTree, Error, Map, Result, Statement, Type, Value};
2023-10-31 17:04:22 +00:00
2023-12-06 19:13:22 +00:00
/// Abstract representation of a block.
///
/// A block is almost identical to the root except that it must have curly
/// braces and can optionally be asynchronous. A block evaluates to the value of
/// its final statement but an async block will short-circuit if a statement
/// results in an error. Note that this will be the first statement to encounter
/// an error at runtime, not necessarilly the first statement as they are
/// written.
2023-10-31 17:04:22 +00:00
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block {
2023-11-11 01:44:03 +00:00
is_async: bool,
statements: Vec<Statement>,
2023-11-04 03:42:10 +00:00
}
2023-10-31 17:04:22 +00:00
impl AbstractTree for Block {
2023-11-30 03:54:46 +00:00
fn from_syntax_node(source: &str, node: Node, context: &Map) -> Result<Self> {
2023-11-27 22:53:12 +00:00
Error::expect_syntax_node(source, "block", node)?;
2023-10-31 17:04:22 +00:00
2023-11-11 01:44:03 +00:00
let first_child = node.child(0).unwrap();
let is_async = first_child.kind() == "async";
2023-11-12 18:20:41 +00:00
let statement_count = if is_async {
node.child_count() - 3
} else {
node.child_count() - 2
};
2023-10-31 17:04:22 +00:00
let mut statements = Vec::with_capacity(statement_count);
for index in 1..node.child_count() - 1 {
2023-10-31 17:04:22 +00:00
let child_node = node.child(index).unwrap();
2023-11-12 18:20:41 +00:00
if child_node.is_named() {
2023-11-30 03:54:46 +00:00
let statement = Statement::from_syntax_node(source, child_node, context)?;
2023-10-31 17:04:22 +00:00
statements.push(statement);
}
}
2023-11-11 01:44:03 +00:00
Ok(Block {
is_async,
statements,
})
2023-10-31 17:04:22 +00:00
}
2023-11-30 00:23:42 +00:00
fn run(&self, source: &str, context: &Map) -> Result<Value> {
2023-11-11 01:44:03 +00:00
if self.is_async {
let statements = &self.statements;
2023-12-31 14:14:43 +00:00
let final_result = RwLock::new(Ok(Value::none()));
2023-10-31 17:04:22 +00:00
2023-11-11 01:44:03 +00:00
statements
.into_par_iter()
.enumerate()
.find_map_first(|(index, statement)| {
if let Statement::Return(expression) = statement {
2023-12-30 03:39:50 +00:00
return Some(expression.run(source, context));
}
2023-12-30 03:39:50 +00:00
let result = statement.run(source, context);
2023-10-31 17:04:22 +00:00
2023-11-11 01:44:03 +00:00
if result.is_err() {
Some(result)
} else if index == statements.len() - 1 {
let _ = final_result.write().unwrap().as_mut().map(|_| result);
None
2023-11-11 01:44:03 +00:00
} else {
None
}
})
2023-12-31 14:14:43 +00:00
.unwrap_or(final_result.into_inner()?)
2023-11-11 01:44:03 +00:00
} else {
2023-11-12 18:20:41 +00:00
let mut prev_result = None;
2023-11-11 01:44:03 +00:00
2023-11-12 18:20:41 +00:00
for statement in &self.statements {
if let Statement::Return(expression) = statement {
return expression.run(source, context);
}
prev_result = Some(statement.run(source, context));
2023-11-12 18:20:41 +00:00
}
2023-11-11 01:44:03 +00:00
2023-12-31 14:14:43 +00:00
prev_result.unwrap_or(Ok(Value::none()))
2023-11-11 01:44:03 +00:00
}
2023-10-31 17:04:22 +00:00
}
2023-11-30 00:23:42 +00:00
2023-12-05 22:08:22 +00:00
fn expected_type(&self, context: &Map) -> Result<Type> {
if self.is_async {
2023-12-05 22:08:22 +00:00
Ok(Type::Any)
} else {
self.statements.last().unwrap().expected_type(context)
}
2023-11-30 00:23:42 +00:00
}
2023-10-31 17:04:22 +00:00
}