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

View File

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

View File

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