Fix parsing bug that fixes garbage collection bug
This commit is contained in:
parent
2e7acbeb64
commit
4846b3f74d
@ -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(),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
)),
|
)),
|
||||||
|
@ -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))));
|
||||||
|
Loading…
Reference in New Issue
Block a user