Fix parsing bug that fixes garbage collection bug

This commit is contained in:
Jeff 2024-08-20 12:09:17 -04:00
parent 2e7acbeb64
commit 4846b3f74d
4 changed files with 22 additions and 25 deletions

View File

@ -93,7 +93,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> {
identifier.inner.clone(), identifier.inner.clone(),
r#type, r#type,
identifier.position, identifier.position,
); )?;
} else { } else {
return Err(AnalysisError::ExpectedValueFromExpression { return Err(AnalysisError::ExpectedValueFromExpression {
expression: value.clone(), expression: value.clone(),
@ -166,7 +166,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> {
field_access_expression.inner.as_ref(); field_access_expression.inner.as_ref();
self.context self.context
.update_last_position(&field.inner, field.position); .update_last_position(&field.inner, field.position)?;
self.analyze_expression(container)?; self.analyze_expression(container)?;
} }
Expression::Grouped(expression) => { Expression::Grouped(expression) => {
@ -174,7 +174,7 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> {
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
self.context 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::If(if_expression) => self.analyze_if(&if_expression.inner)?,
Expression::List(list_expression) => match list_expression.inner.as_ref() { 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() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Fields { name, fields } => { StructExpression::Fields { name, fields } => {
self.context self.context
.update_last_position(&name.inner, name.position); .update_last_position(&name.inner, name.position)?;
for (_, expression) in fields { for (_, expression) in fields {
self.analyze_expression(expression)?; self.analyze_expression(expression)?;
@ -438,8 +438,8 @@ impl From<ContextError> for AnalysisError {
impl AnalysisError { impl AnalysisError {
pub fn position(&self) -> Option<Span> { pub fn position(&self) -> Option<Span> {
let position = match self { let position = match self {
AnalysisError::AstError(ast_error) => return None, AnalysisError::AstError(ast_error) => return ast_error.position(),
AnalysisError::ContextError(context_error) => return None, AnalysisError::ContextError(_) => return None,
AnalysisError::ExpectedBoolean { actual } => actual.position(), AnalysisError::ExpectedBoolean { actual } => actual.position(),
AnalysisError::ExpectedIdentifier { actual } => actual.position(), AnalysisError::ExpectedIdentifier { actual } => actual.position(),

View File

@ -204,13 +204,13 @@ impl Context {
} }
/// Collects garbage up to the given position, removing all variables with lesser positions. /// Collects garbage up to the given position, removing all variables with lesser positions.
pub fn collect_garbage(&self, position: Span) -> Result<(), ContextError> { pub fn collect_garbage(&self, position_end: usize) -> Result<(), ContextError> {
log::trace!("Collecting garbage up to {position:?}"); log::trace!("Collecting garbage up to {position_end}");
let mut variables = self.associations.write()?; let mut variables = self.associations.write()?;
variables.retain(|identifier, (_, last_used)| { 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 { if should_drop {
log::trace!("Removing {identifier}"); log::trace!("Removing {identifier}");
@ -327,8 +327,6 @@ mod tests {
#[test] #[test]
fn context_removes_variables() { fn context_removes_variables() {
env_logger::builder().is_test(true).try_init().unwrap();
let source = " let source = "
let x = 5; let x = 5;
let y = 10; let y = 10;
@ -337,7 +335,10 @@ mod tests {
"; ";
let context = Context::new(); 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); assert_eq!(context.association_count().unwrap(), 0);
} }

View File

@ -636,7 +636,7 @@ impl<'src> Parser<'src> {
let condition = self.parse_expression(0)?; let condition = self.parse_expression(0)?;
let block = self.parse_block()?; 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)) Ok(Expression::while_loop(condition, block, position))
} }
@ -1228,7 +1228,7 @@ mod tests {
)]), )]),
(28, 38), (28, 38),
), ),
(15, 39), (15, 38),
), ),
(15, 39) (15, 39)
)), )),

View File

@ -57,7 +57,7 @@ pub fn run(source: &str) -> Result<Option<Value>, DustError> {
/// ``` /// ```
pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> { pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> {
let abstract_syntax_tree = parse(source)?; 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 analyzer
.analyze() .analyze()
@ -159,14 +159,14 @@ impl Vm {
}; };
let constructor = struct_type.constructor(); let constructor = struct_type.constructor();
self.context.set_constructor(name, constructor); self.context.set_constructor(name, constructor)?;
Ok(None) Ok(None)
} }
}; };
if collect_garbage { if collect_garbage {
// self.context.collect_garbage(position); self.context.collect_garbage(position.1)?;
} }
result.map_err(|error| RuntimeError::Statement { result.map_err(|error| RuntimeError::Statement {
@ -187,7 +187,7 @@ impl Vm {
.run_expression(value, collect_garbage)? .run_expression(value, collect_garbage)?
.expect_value(value_position)?; .expect_value(value_position)?;
self.context.set_variable_value(identifier.inner, value); self.context.set_variable_value(identifier.inner, value)?;
Ok(()) Ok(())
} }
@ -199,7 +199,7 @@ impl Vm {
.into_mutable(); .into_mutable();
self.context self.context
.set_variable_value(identifier.inner, mutable_value); .set_variable_value(identifier.inner, mutable_value)?;
Ok(()) Ok(())
} }
@ -872,13 +872,7 @@ impl Vm {
let mut previous_value = None; let mut previous_value = None;
for statement in statements { for statement in statements {
let position = statement.position();
previous_value = self.run_statement(statement, collect_garbage)?; previous_value = self.run_statement(statement, collect_garbage)?;
if collect_garbage {
// self.context.collect_garbage(position);
}
} }
Ok(Evaluation::Return(previous_value)) Ok(Evaluation::Return(previous_value))
@ -1468,6 +1462,8 @@ mod tests {
#[test] #[test]
fn while_loop() { fn while_loop() {
env_logger::builder().is_test(true).try_init().ok();
let input = "let mut x = 0; while x < 5 { x += 1 } x"; let input = "let mut x = 0; while x < 5 { x += 1 } x";
assert_eq!(run(input), Ok(Some(Value::mutable_from(5)))); assert_eq!(run(input), Ok(Some(Value::mutable_from(5))));