Improve context stacks

This commit is contained in:
Jeff 2024-08-29 13:07:06 -04:00
parent 21b63b5942
commit bbb45aa97e
3 changed files with 78 additions and 45 deletions

View File

@ -35,7 +35,7 @@ use crate::{
pub fn analyze(source: &str) -> Result<(), DustError> {
let abstract_tree = parse(source)?;
let context_stack = ContextStack::with_core_library();
let mut analyzer = Analyzer::new(&abstract_tree, context_stack);
let mut analyzer = Analyzer::new(&abstract_tree, &context_stack);
analyzer.analyze();
@ -55,18 +55,18 @@ pub fn analyze(source: &str) -> Result<(), DustError> {
/// let input = "x = 1 + false";
/// let abstract_tree = parse(input).unwrap();
/// let context_stack = ContextStack::new();
/// let mut analyzer = Analyzer::new(&abstract_tree, context_stack);
/// let mut analyzer = Analyzer::new(&abstract_tree, &context_stack);
/// let result = analyzer.analyze();
///
/// assert!(!analyzer.errors.is_empty());
pub struct Analyzer<'a> {
abstract_tree: &'a AbstractSyntaxTree,
context_stack: ContextStack,
context_stack: &'a ContextStack,
pub errors: Vec<AnalysisError>,
}
impl<'a> Analyzer<'a> {
pub fn new(abstract_tree: &'a AbstractSyntaxTree, context_stack: ContextStack) -> Self {
pub fn new(abstract_tree: &'a AbstractSyntaxTree, context_stack: &'a ContextStack) -> Self {
Self {
abstract_tree,
context_stack,
@ -81,7 +81,7 @@ impl<'a> Analyzer<'a> {
}
fn analyze_statement(&mut self, statement: &Statement) {
let context = self.context_stack.top();
let context = self.context_stack.current();
match statement {
Statement::Expression(expression) => {
@ -196,7 +196,7 @@ impl<'a> Analyzer<'a> {
}
fn analyze_expression(&mut self, expression: &Expression, statement_position: Span) {
let context = self.context_stack.top();
let context = self.context_stack.current();
match expression {
Expression::Block(block_expression) => self.analyze_block(&block_expression.inner),
@ -360,7 +360,7 @@ impl<'a> Analyzer<'a> {
Expression::Identifier(identifier) => {
let find_identifier = self
.context_stack
.top()
.current()
.update_last_position(&identifier.inner, statement_position);
if let Ok(false) = find_identifier {
@ -546,7 +546,7 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(modifier, statement_position);
let assignee_type_evaluation =
match assignee.type_evaluation(&self.context_stack.top()) {
match assignee.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
@ -555,7 +555,7 @@ impl<'a> Analyzer<'a> {
}
};
let modifier_type_evaluation =
match modifier.type_evaluation(&self.context_stack.top()) {
match modifier.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
@ -615,17 +615,17 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(left, statement_position);
self.analyze_expression(right, statement_position);
let left_type_evaluation = match left.type_evaluation(&self.context_stack.top())
{
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
let left_type_evaluation =
match left.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return;
}
};
return;
}
};
let right_type_evaluation =
match right.type_evaluation(&self.context_stack.top()) {
match right.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
@ -713,17 +713,17 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(left, statement_position);
self.analyze_expression(right, statement_position);
let left_type_evaluation = match left.type_evaluation(&self.context_stack.top())
{
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
let left_type_evaluation =
match left.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return;
}
};
return;
}
};
let right_type_evaluation =
match right.type_evaluation(&self.context_stack.top()) {
match right.type_evaluation(&self.context_stack.current()) {
Ok(evaluation) => evaluation,
Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
@ -787,7 +787,7 @@ impl<'a> Analyzer<'a> {
StructExpression::Fields { name, fields } => {
let update_position = self
.context_stack
.top()
.current()
.update_last_position(&name.inner, statement_position);
if let Err(error) = update_position {

View File

@ -2,26 +2,29 @@
use std::{
collections::HashMap,
fmt::{self, Display, Formatter},
sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
sync::{
atomic::{AtomicUsize, Ordering},
Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard,
},
};
use crate::{ast::Span, core_library, Constructor, Identifier, StructType, Type, Value};
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct ContextStack {
stack: Arc<RwLock<Vec<Context>>>,
current: AtomicUsize,
}
impl ContextStack {
pub fn new() -> Self {
Self {
stack: Arc::new(RwLock::new(vec![Context::new()])),
}
Self::with_context(Context::new())
}
pub fn with_context(context: Context) -> Self {
Self {
stack: Arc::new(RwLock::new(vec![context])),
current: AtomicUsize::new(1),
}
}
@ -29,16 +32,44 @@ impl ContextStack {
Self::with_context(core_library().create_child())
}
pub fn push(&self) {
pub fn move_up(&self) {
let current = self.current.load(Ordering::Relaxed);
let next = current + 1;
let stack_len = self.stack.read().unwrap().len();
if next > stack_len {
self.push();
}
self.current.store(next, Ordering::Relaxed);
}
fn push(&self) {
let mut stack = self.stack.write().unwrap();
let top = stack.last().unwrap().clone();
stack.push(top.create_child());
}
pub fn move_down(&self) {
let current = self.current.load(Ordering::Relaxed);
if current == 1 {
return;
}
self.current.store(current - 1, Ordering::Relaxed);
}
pub fn pop(&self) {
if self.current.load(Ordering::Relaxed) == 1 {
return;
}
let removed = self.stack.write().unwrap().pop();
self.move_down();
if let Some(removed) = removed {
for (identifier, _) in removed.associations.read().unwrap().iter() {
log::trace!("Dropping context with: {}", identifier);
@ -46,8 +77,10 @@ impl ContextStack {
}
}
pub fn top(&self) -> Context {
self.stack.read().unwrap().last().unwrap().clone()
pub fn current(&self) -> Context {
let current_index = self.current.load(Ordering::Relaxed).saturating_sub(1);
self.stack.read().unwrap()[current_index].clone()
}
}
@ -429,7 +462,7 @@ mod tests {
fn run_vm_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> {
let context_stack = ContextStack::with_context(context);
let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree, context_stack.clone());
let mut analyzer = Analyzer::new(&abstract_syntax_tree, &context_stack);
analyzer.analyze();

View File

@ -40,7 +40,7 @@ use crate::{
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let context_stack = ContextStack::with_core_library();
let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree, context_stack.clone());
let mut analyzer = Analyzer::new(&abstract_syntax_tree, &context_stack);
analyzer.analyze();
@ -192,7 +192,7 @@ impl Vm {
let constructor = struct_type.constructor();
self.context_stack
.top()
.current()
.set_constructor(name, constructor)
.map_err(|error| RuntimeError::ContextError {
error,
@ -205,7 +205,7 @@ impl Vm {
if collect_garbage {
self.context_stack
.top()
.current()
.collect_garbage(position.1)
.map_err(|error| RuntimeError::ContextError { error, position })?;
}
@ -235,7 +235,7 @@ impl Vm {
};
self.context_stack
.top()
.current()
.set_variable_value(identifier.inner, new_value)
.map_err(|error| RuntimeError::ContextError { error, position })?;
@ -249,7 +249,7 @@ impl Vm {
.into_mutable();
self.context_stack
.top()
.current()
.set_variable_value(identifier.inner, mutable_value)
.map_err(|error| RuntimeError::ContextError { error, position })?;
@ -352,7 +352,7 @@ impl Vm {
fn run_identifier(&self, identifier: Node<Identifier>) -> Result<Evaluation, RuntimeError> {
let get_data = self
.context_stack
.top()
.current()
.get_data(&identifier.inner)
.map_err(|error| RuntimeError::ContextError {
error,
@ -392,7 +392,7 @@ impl Vm {
let position = name.position;
let constructor = self
.context_stack
.top()
.current()
.get_constructor(&name.inner)
.map_err(|error| RuntimeError::ContextError { error, position })?;
@ -1009,7 +1009,7 @@ impl Vm {
block: BlockExpression,
collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> {
self.context_stack.push();
self.context_stack.move_up();
let evaluation = match block {
BlockExpression::Async(statements) => self