From bbb45aa97e9f83f791b96ba07fd51762ce276eb1 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 29 Aug 2024 13:07:06 -0400 Subject: [PATCH] Improve context stacks --- dust-lang/src/analyzer.rs | 56 +++++++++++++++++++-------------------- dust-lang/src/context.rs | 51 ++++++++++++++++++++++++++++------- dust-lang/src/vm.rs | 16 +++++------ 3 files changed, 78 insertions(+), 45 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 3d75fb3..978dc1b 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -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, } 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 { diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 5008453..729361f 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -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>>, + 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, 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(); diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 8127ca1..4b53f19 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -40,7 +40,7 @@ use crate::{ pub fn run(source: &str) -> Result, 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) -> Result { 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 { - self.context_stack.push(); + self.context_stack.move_up(); let evaluation = match block { BlockExpression::Async(statements) => self