2024-01-06 10:00:36 +00:00
|
|
|
use std::{
|
|
|
|
fmt::{self, Display, Formatter},
|
|
|
|
sync::RwLock,
|
|
|
|
};
|
2023-11-16 06:59:48 +00:00
|
|
|
|
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);
|
|
|
|
|
2023-11-16 06:59:48 +00:00
|
|
|
for index in 1..node.child_count() - 1 {
|
2023-10-31 17:04:22 +00:00
|
|
|
let child_node = node.child(index).unwrap();
|
|
|
|
|
2023-12-31 19:04:10 +00:00
|
|
|
if child_node.kind() == "statement" {
|
2023-11-30 03:54:46 +00:00
|
|
|
let statement = Statement::from_syntax_node(source, child_node, context)?;
|
2023-12-31 19:04:10 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-01-06 03:26:37 +00:00
|
|
|
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
|
2024-01-04 00:57:06 +00:00
|
|
|
for statement in &self.statements {
|
|
|
|
if let Statement::Return(inner_statement) = statement {
|
2024-01-06 03:26:37 +00:00
|
|
|
return inner_statement.check_type(_source, _context);
|
2024-01-04 00:57:06 +00:00
|
|
|
} else {
|
2024-01-06 03:26:37 +00:00
|
|
|
statement.check_type(_source, _context)?;
|
2024-01-04 00:57:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
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)| {
|
2023-12-30 03:39:50 +00:00
|
|
|
let result = statement.run(source, context);
|
2023-12-31 19:04:10 +00:00
|
|
|
let is_last_statement = index == statements.len() - 1;
|
|
|
|
let is_return_statement = if let Statement::Return(_) = statement {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
2023-10-31 17:04:22 +00:00
|
|
|
|
2023-12-31 19:04:10 +00:00
|
|
|
if is_return_statement || result.is_err() {
|
2023-11-11 01:44:03 +00:00
|
|
|
Some(result)
|
2023-12-31 19:04:10 +00:00
|
|
|
} else if is_last_statement {
|
|
|
|
let get_write_lock = final_result.write();
|
|
|
|
|
|
|
|
match get_write_lock {
|
|
|
|
Ok(mut final_result) => {
|
|
|
|
*final_result = result;
|
|
|
|
None
|
|
|
|
}
|
|
|
|
Err(error) => Some(Err(error.into())),
|
|
|
|
}
|
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 {
|
2023-12-31 19:04:10 +00:00
|
|
|
if let Statement::Return(inner_statement) = statement {
|
|
|
|
return inner_statement.run(source, context);
|
|
|
|
}
|
|
|
|
|
2023-11-16 06:59:48 +00:00
|
|
|
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> {
|
2023-12-31 23:10:42 +00:00
|
|
|
if let Some(statement) = self.statements.iter().find(|statement| {
|
|
|
|
if let Statement::Return(_) = statement {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
statement.expected_type(context)
|
|
|
|
} else if let Some(statement) = self.statements.last() {
|
2023-12-31 21:46:21 +00:00
|
|
|
statement.expected_type(context)
|
|
|
|
} else {
|
|
|
|
Ok(Type::None)
|
|
|
|
}
|
2023-11-30 00:23:42 +00:00
|
|
|
}
|
2023-10-31 17:04:22 +00:00
|
|
|
}
|
2024-01-06 10:00:36 +00:00
|
|
|
|
|
|
|
impl Display for Block {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
if self.is_async {
|
2024-01-06 10:29:38 +00:00
|
|
|
writeln!(f, "async {{")?;
|
2024-01-06 10:00:36 +00:00
|
|
|
} else {
|
2024-01-06 10:29:38 +00:00
|
|
|
writeln!(f, "{{")?;
|
2024-01-06 10:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for statement in &self.statements {
|
2024-01-06 10:29:38 +00:00
|
|
|
writeln!(f, " {statement}")?;
|
2024-01-06 10:00:36 +00:00
|
|
|
}
|
|
|
|
|
2024-01-06 10:29:38 +00:00
|
|
|
writeln!(f, "}}")
|
2024-01-06 10:00:36 +00:00
|
|
|
}
|
|
|
|
}
|