From 4846b3f74d049ae327cc0cb7f319683646258374 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 20 Aug 2024 12:09:17 -0400 Subject: [PATCH] Fix parsing bug that fixes garbage collection bug --- dust-lang/src/analyzer.rs | 12 ++++++------ dust-lang/src/context.rs | 13 +++++++------ dust-lang/src/parser.rs | 4 ++-- dust-lang/src/vm.rs | 18 +++++++----------- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 17b2eee..d040842 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -93,7 +93,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> { identifier.inner.clone(), r#type, identifier.position, - ); + )?; } else { return Err(AnalysisError::ExpectedValueFromExpression { expression: value.clone(), @@ -166,7 +166,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> { field_access_expression.inner.as_ref(); self.context - .update_last_position(&field.inner, field.position); + .update_last_position(&field.inner, field.position)?; self.analyze_expression(container)?; } Expression::Grouped(expression) => { @@ -174,7 +174,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> { } Expression::Identifier(identifier) => { self.context - .update_last_position(&identifier.inner, identifier.position); + .update_last_position(&identifier.inner, identifier.position)?; } Expression::If(if_expression) => self.analyze_if(&if_expression.inner)?, Expression::List(list_expression) => match list_expression.inner.as_ref() { @@ -291,7 +291,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { StructExpression::Fields { name, fields } => { self.context - .update_last_position(&name.inner, name.position); + .update_last_position(&name.inner, name.position)?; for (_, expression) in fields { self.analyze_expression(expression)?; @@ -438,8 +438,8 @@ impl From for AnalysisError { impl AnalysisError { pub fn position(&self) -> Option { let position = match self { - AnalysisError::AstError(ast_error) => return None, - AnalysisError::ContextError(context_error) => return None, + AnalysisError::AstError(ast_error) => return ast_error.position(), + AnalysisError::ContextError(_) => return None, AnalysisError::ExpectedBoolean { actual } => actual.position(), AnalysisError::ExpectedIdentifier { actual } => actual.position(), diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index f0aa1f1..b79e8a4 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -204,13 +204,13 @@ impl Context { } /// Collects garbage up to the given position, removing all variables with lesser positions. - pub fn collect_garbage(&self, position: Span) -> Result<(), ContextError> { - log::trace!("Collecting garbage up to {position:?}"); + pub fn collect_garbage(&self, position_end: usize) -> Result<(), ContextError> { + log::trace!("Collecting garbage up to {position_end}"); let mut variables = self.associations.write()?; variables.retain(|identifier, (_, last_used)| { - let should_drop = position.0 > last_used.0 && position.1 > last_used.1; + let should_drop = position_end >= last_used.1; if should_drop { log::trace!("Removing {identifier}"); @@ -327,8 +327,6 @@ mod tests { #[test] fn context_removes_variables() { - env_logger::builder().is_test(true).try_init().unwrap(); - let source = " let x = 5; let y = 10; @@ -337,7 +335,10 @@ mod tests { "; let context = Context::new(); - run_with_context(source, context.clone()).unwrap(); + assert_eq!( + run_with_context(source, context.clone()), + Ok(Some(Value::Integer(15))) + ); assert_eq!(context.association_count().unwrap(), 0); } diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index cf1b696..40cfddf 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -636,7 +636,7 @@ impl<'src> Parser<'src> { let condition = self.parse_expression(0)?; let block = self.parse_block()?; - let position = (start_position.0, self.current_position.1); + let position = (start_position.0, block.position.1); Ok(Expression::while_loop(condition, block, position)) } @@ -1228,7 +1228,7 @@ mod tests { )]), (28, 38), ), - (15, 39), + (15, 38), ), (15, 39) )), diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 58aaabf..e98c1e5 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -57,7 +57,7 @@ pub fn run(source: &str) -> Result, DustError> { /// ``` pub fn run_with_context(source: &str, context: Context) -> Result, DustError> { let abstract_syntax_tree = parse(source)?; - let mut analyzer = Analyzer::new(&abstract_syntax_tree, context.clone()); + let analyzer = Analyzer::new(&abstract_syntax_tree, context.clone()); analyzer .analyze() @@ -159,14 +159,14 @@ impl Vm { }; let constructor = struct_type.constructor(); - self.context.set_constructor(name, constructor); + self.context.set_constructor(name, constructor)?; Ok(None) } }; if collect_garbage { - // self.context.collect_garbage(position); + self.context.collect_garbage(position.1)?; } result.map_err(|error| RuntimeError::Statement { @@ -187,7 +187,7 @@ impl Vm { .run_expression(value, collect_garbage)? .expect_value(value_position)?; - self.context.set_variable_value(identifier.inner, value); + self.context.set_variable_value(identifier.inner, value)?; Ok(()) } @@ -199,7 +199,7 @@ impl Vm { .into_mutable(); self.context - .set_variable_value(identifier.inner, mutable_value); + .set_variable_value(identifier.inner, mutable_value)?; Ok(()) } @@ -872,13 +872,7 @@ impl Vm { let mut previous_value = None; for statement in statements { - let position = statement.position(); - previous_value = self.run_statement(statement, collect_garbage)?; - - if collect_garbage { - // self.context.collect_garbage(position); - } } Ok(Evaluation::Return(previous_value)) @@ -1468,6 +1462,8 @@ mod tests { #[test] fn while_loop() { + env_logger::builder().is_test(true).try_init().ok(); + let input = "let mut x = 0; while x < 5 { x += 1 } x"; assert_eq!(run(input), Ok(Some(Value::mutable_from(5))));