From c659b561058b2146b2a09dd7ad9507a32c240fe2 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 22 Apr 2024 07:56:03 -0400 Subject: [PATCH] Refine memory management --- dust-lang/src/abstract_tree/assignment.rs | 24 +++++-- dust-lang/src/abstract_tree/async_block.rs | 8 +-- dust-lang/src/abstract_tree/block.rs | 8 +-- .../abstract_tree/built_in_function_call.rs | 14 ++-- dust-lang/src/abstract_tree/expression.rs | 48 ++++++++----- dust-lang/src/abstract_tree/function_call.rs | 6 +- dust-lang/src/abstract_tree/if_else.rs | 10 +-- dust-lang/src/abstract_tree/list_index.rs | 6 +- dust-lang/src/abstract_tree/logic.rs | 16 +++-- dust-lang/src/abstract_tree/loop.rs | 6 +- dust-lang/src/abstract_tree/map_index.rs | 8 +-- dust-lang/src/abstract_tree/math.rs | 2 +- dust-lang/src/abstract_tree/mod.rs | 18 +++-- dust-lang/src/abstract_tree/statement.rs | 72 +++++++------------ .../src/abstract_tree/structure_definition.rs | 4 +- dust-lang/src/abstract_tree/type.rs | 4 +- dust-lang/src/abstract_tree/value_node.rs | 12 ++-- dust-lang/src/abstract_tree/while.rs | 12 ++-- dust-lang/src/context.rs | 40 +++++++---- 19 files changed, 174 insertions(+), 144 deletions(-) diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index 04a1a92..423f4b1 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -43,7 +43,7 @@ impl AbstractNode for Assignment { Ok(Type::None) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { + fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { let statement_type = self.statement.expected_type(context)?; if let Some(WithPosition { @@ -64,13 +64,13 @@ impl AbstractNode for Assignment { context.set_type(self.identifier.item.clone(), statement_type)?; } - self.statement.validate(context)?; + self.statement.validate(context, manage_memory)?; Ok(()) } - fn run(self, context: &mut Context, clear_variables: bool) -> Result { - let action = self.statement.run(context, clear_variables)?; + fn run(self, context: &mut Context, manage_memory: bool) -> Result { + let action = self.statement.run(context, manage_memory)?; let right = match action { Action::Return(value) => value, r#break => return Ok(r#break), @@ -81,7 +81,13 @@ impl AbstractNode for Assignment { context.set_value(self.identifier.item, right)?; } AssignmentOperator::AddAssign => { - if let Some(left) = context.use_value(&self.identifier.item)? { + let left_option = if manage_memory { + context.use_value(&self.identifier.item)? + } else { + context.get_value(&self.identifier.item)? + }; + + if let Some(left) = left_option { let new_value = match (left.inner().as_ref(), right.inner().as_ref()) { (ValueInner::Integer(left), ValueInner::Integer(right)) => { let sum = left.saturating_add(*right); @@ -120,7 +126,13 @@ impl AbstractNode for Assignment { } } AssignmentOperator::SubAssign => { - if let Some(left) = context.use_value(&self.identifier.item)? { + let left_option = if manage_memory { + context.use_value(&self.identifier.item)? + } else { + context.get_value(&self.identifier.item)? + }; + + if let Some(left) = left_option { let new_value = match (left.inner().as_ref(), right.inner().as_ref()) { (ValueInner::Integer(left), ValueInner::Integer(right)) => { let difference = left.saturating_sub(*right); diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index 8451fab..cc92d80 100644 --- a/dust-lang/src/abstract_tree/async_block.rs +++ b/dust-lang/src/abstract_tree/async_block.rs @@ -25,15 +25,15 @@ impl AbstractNode for AsyncBlock { self.statements.last().unwrap().expected_type(_context) } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, manage_memory: bool) -> Result<(), ValidationError> { for statement in &self.statements { - statement.validate(_context)?; + statement.validate(_context, manage_memory)?; } Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, manage_memory: bool) -> Result { let statement_count = self.statements.len(); let final_result = RwLock::new(Ok(Action::None)); @@ -41,7 +41,7 @@ impl AbstractNode for AsyncBlock { .into_par_iter() .enumerate() .find_map_first(|(index, statement)| { - let result = statement.run(&mut _context.clone(), _clear_variables); + let result = statement.run(&mut _context.clone(), manage_memory); if index == statement_count - 1 { let get_write_lock = final_result.write(); diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index f060335..e43b560 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -29,19 +29,19 @@ impl AbstractNode for Block { } } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { for statement in &self.statements { - statement.validate(_context)?; + statement.validate(_context, _manage_memory)?; } Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { let mut previous = Action::None; for statement in self.statements { - previous = statement.run(_context, _clear_variables)?; + previous = statement.run(_context, _manage_memory)?; } Ok(previous) diff --git a/dust-lang/src/abstract_tree/built_in_function_call.rs b/dust-lang/src/abstract_tree/built_in_function_call.rs index 82e25df..8190580 100644 --- a/dust-lang/src/abstract_tree/built_in_function_call.rs +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -26,15 +26,17 @@ impl AbstractNode for BuiltInFunctionCall { } } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { BuiltInFunctionCall::ReadLine => Ok(()), - BuiltInFunctionCall::Sleep(expression) => expression.validate(_context), - BuiltInFunctionCall::WriteLine(expression) => expression.validate(_context), + BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory), + BuiltInFunctionCall::WriteLine(expression) => { + expression.validate(_context, _manage_memory) + } } } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { match self { BuiltInFunctionCall::ReadLine => { let mut buffer = String::new(); @@ -44,7 +46,7 @@ impl AbstractNode for BuiltInFunctionCall { Ok(Action::Return(Value::string(buffer))) } BuiltInFunctionCall::Sleep(expression) => { - let action = expression.clone().run(context, _clear_variables)?; + let action = expression.clone().run(context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { @@ -60,7 +62,7 @@ impl AbstractNode for BuiltInFunctionCall { Ok(Action::None) } BuiltInFunctionCall::WriteLine(expression) => { - let action = expression.clone().run(context, _clear_variables)?; + let action = expression.clone().run(context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 6631522..40933e1 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -61,11 +61,17 @@ impl AbstractNode for Expression { } } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { + fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { match self { - Expression::FunctionCall(function_call) => function_call.item.validate(context), + Expression::FunctionCall(function_call) => { + function_call.item.validate(context, manage_memory) + } Expression::Identifier(identifier) => { - let found = context.add_expected_use(&identifier.item)?; + let found = if manage_memory { + context.add_expected_use(&identifier.item)? + } else { + context.contains(&identifier.item)? + }; if found { Ok(()) @@ -76,24 +82,30 @@ impl AbstractNode for Expression { }) } } - Expression::MapIndex(map_index) => map_index.item.validate(context), - Expression::ListIndex(list_index) => list_index.item.validate(context), - Expression::Logic(logic) => logic.item.validate(context), - Expression::Math(math) => math.item.validate(context), - Expression::Value(value_node) => value_node.item.validate(context), + Expression::MapIndex(map_index) => map_index.item.validate(context, manage_memory), + Expression::ListIndex(list_index) => list_index.item.validate(context, manage_memory), + Expression::Logic(logic) => logic.item.validate(context, manage_memory), + Expression::Math(math) => math.item.validate(context, manage_memory), + Expression::Value(value_node) => value_node.item.validate(context, manage_memory), Expression::BuiltInFunctionCall(built_in_function_call) => { - built_in_function_call.item.validate(context) + built_in_function_call.item.validate(context, manage_memory) } } } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, manage_memory: bool) -> Result { match self { Expression::FunctionCall(function_call) => { - function_call.item.run(context, _clear_variables) + function_call.item.run(context, manage_memory) } Expression::Identifier(identifier) => { - if let Some(value) = context.use_value(&identifier.item)? { + let value_option = if manage_memory { + context.use_value(&identifier.item)? + } else { + context.get_value(&identifier.item)? + }; + + if let Some(value) = value_option { Ok(Action::Return(value)) } else { Err(RuntimeError::ValidationFailure( @@ -104,13 +116,13 @@ impl AbstractNode for Expression { )) } } - Expression::MapIndex(map_index) => map_index.item.run(context, _clear_variables), - Expression::ListIndex(list_index) => list_index.item.run(context, _clear_variables), - Expression::Logic(logic) => logic.item.run(context, _clear_variables), - Expression::Math(math) => math.item.run(context, _clear_variables), - Expression::Value(value_node) => value_node.item.run(context, _clear_variables), + Expression::MapIndex(map_index) => map_index.item.run(context, manage_memory), + Expression::ListIndex(list_index) => list_index.item.run(context, manage_memory), + Expression::Logic(logic) => logic.item.run(context, manage_memory), + Expression::Math(math) => math.item.run(context, manage_memory), + Expression::Value(value_node) => value_node.item.run(context, manage_memory), Expression::BuiltInFunctionCall(built_in_function_call) => { - built_in_function_call.item.run(context, _clear_variables) + built_in_function_call.item.run(context, manage_memory) } } } diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 36cd862..dac1e8f 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -41,11 +41,11 @@ impl AbstractNode for FunctionCall { } } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { - self.function.validate(context)?; + fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { + self.function.validate(context, manage_memory)?; for expression in &self.arguments { - expression.validate(context)?; + expression.validate(context, manage_memory)?; } let function_node_type = self.function.expected_type(context)?; diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index 10ade52..3ae0e7c 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -35,16 +35,16 @@ impl AbstractNode for IfElse { self.if_block.item.expected_type(_context) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { - self.if_expression.validate(context)?; - self.if_block.item.validate(context)?; + fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { + self.if_expression.validate(context, manage_memory)?; + self.if_block.item.validate(context, manage_memory)?; let expected_type = self.if_block.item.expected_type(context)?; let if_expression_type = self.if_expression.expected_type(context)?; if let Type::Boolean = if_expression_type { if let Some(else_block) = &self.else_block { - else_block.item.validate(context)?; + else_block.item.validate(context, manage_memory)?; let actual = else_block.item.expected_type(context)?; @@ -67,7 +67,7 @@ impl AbstractNode for IfElse { let expression_type = expression.expected_type(context)?; if let Type::Boolean = expression_type { - block.item.validate(context)?; + block.item.validate(context, manage_memory)?; let actual = block.item.expected_type(context)?; diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 7c1cff4..ec27318 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -47,9 +47,9 @@ impl AbstractNode for ListIndex { } } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { - self.left.validate(context)?; - self.right.validate(context)?; + fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + self.left.validate(context, _manage_memory)?; + self.right.validate(context, _manage_memory)?; let left_type = self.left.expected_type(context)?; diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 07869f7..e2aa975 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -25,7 +25,7 @@ impl AbstractNode for Logic { Ok(Type::Boolean) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { + fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Logic::Equal(left, right) | Logic::NotEqual(left, right) @@ -33,6 +33,9 @@ impl AbstractNode for Logic { | Logic::Less(left, right) | Logic::GreaterOrEqual(left, right) | Logic::LessOrEqual(left, right) => { + left.validate(context, _manage_memory)?; + right.validate(context, _manage_memory)?; + let left_type = left.expected_type(context)?; let right_type = right.expected_type(context)?; @@ -47,6 +50,9 @@ impl AbstractNode for Logic { Ok(()) } Logic::And(left, right) | Logic::Or(left, right) => { + left.validate(context, _manage_memory)?; + right.validate(context, _manage_memory)?; + let left_type = left.expected_type(context)?; let right_type = right.expected_type(context)?; @@ -69,6 +75,8 @@ impl AbstractNode for Logic { Ok(()) } Logic::Not(expression) => { + expression.validate(context, _manage_memory)?; + let expression_type = expression.expected_type(context)?; if let Type::Boolean = expression_type { @@ -83,10 +91,10 @@ impl AbstractNode for Logic { } } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { let run_and_expect_value = |expression: Expression| -> Result { let expression_position = expression.position(); - let action = expression.run(&mut context.clone(), _clear_variables)?; + let action = expression.run(&mut context.clone(), _manage_memory)?; let value = if let Action::Return(value) = action { value } else { @@ -100,7 +108,7 @@ impl AbstractNode for Logic { let run_and_expect_boolean = |expression: Expression| -> Result { let expression_position = expression.position(); - let action = expression.run(&mut context.clone(), _clear_variables)?; + let action = expression.run(&mut context.clone(), _manage_memory)?; let value = if let Action::Return(value) = action { value } else { diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index 02b7940..a2cdd78 100644 --- a/dust-lang/src/abstract_tree/loop.rs +++ b/dust-lang/src/abstract_tree/loop.rs @@ -21,15 +21,15 @@ impl AbstractNode for Loop { Ok(Type::None) } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { for statement in &self.statements { - statement.validate(_context)?; + statement.validate(_context, false)?; } Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { loop { for statement in &self.statements { let action = statement.clone().run(_context, false)?; diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index d6560e3..9452d78 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -105,13 +105,13 @@ impl AbstractNode for MapIndex { }) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { - self.collection.validate(context) + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + self.collection.validate(_context, _manage_memory) } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { let collection_position = self.collection.position(); - let action = self.collection.run(context, _clear_variables)?; + let action = self.collection.run(context, _manage_memory)?; let collection = if let Action::Return(value) = action { value } else { diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index 96223a1..293bf13 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -40,7 +40,7 @@ impl AbstractNode for Math { } } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { + fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { Math::Add(left, right) => { let left_position = left.position(); diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 12f1ee5..a1191e7 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -101,14 +101,14 @@ impl AbstractTree { pub fn run( self, context: &mut Context, - clear_variables: bool, + manage_memory: bool, ) -> Result, Vec> { - let valid_statements = self.validate(context)?; + let valid_statements = self.validate(context, manage_memory)?; let mut previous_value = None; for statement in valid_statements { let position = statement.position(); - let run = statement.run(context, clear_variables); + let run = statement.run(context, manage_memory); match run { Ok(action) => match action { @@ -128,12 +128,16 @@ impl AbstractTree { Ok(previous_value) } - fn validate(self, context: &mut Context) -> Result, Vec> { + fn validate( + self, + context: &mut Context, + add_variable_uses: bool, + ) -> Result, Vec> { let mut errors = Vec::new(); let mut valid_statements = Vec::new(); for statement in self.0 { - let validation = statement.validate(context); + let validation = statement.validate(context, add_variable_uses); if let Err(validation_error) = validation { errors.push(Error::Validation { @@ -179,6 +183,6 @@ impl Index for AbstractTree { pub trait AbstractNode: Sized { fn expected_type(&self, context: &Context) -> Result; - fn validate(&self, context: &Context) -> Result<(), ValidationError>; - fn run(self, context: &mut Context, clear_variables: bool) -> Result; + fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>; + fn run(self, context: &mut Context, manage_memory: bool) -> Result; } diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index fd47c96..bed7991 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -54,67 +54,43 @@ impl AbstractNode for Statement { } } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { match self { - Statement::Assignment(assignment) => assignment.item.validate(_context), - Statement::AsyncBlock(async_block) => async_block.item.validate(_context), - Statement::Block(block) => block.item.validate(_context), + Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory), + Statement::AsyncBlock(async_block) => { + async_block.item.validate(_context, _manage_memory) + } + Statement::Block(block) => block.item.validate(_context, _manage_memory), Statement::Break(_) => Ok(()), - Statement::Expression(expression) => expression.validate(_context), - Statement::IfElse(if_else) => if_else.item.validate(_context), - Statement::Loop(r#loop) => r#loop.item.validate(_context), - Statement::While(r#while) => r#while.item.validate(_context), + Statement::Expression(expression) => expression.validate(_context, _manage_memory), + Statement::IfElse(if_else) => if_else.item.validate(_context, _manage_memory), + Statement::Loop(r#loop) => r#loop.item.validate(_context, _manage_memory), + Statement::While(r#while) => r#while.item.validate(_context, _manage_memory), Statement::StructureDefinition(structure_definition) => { - structure_definition.item.validate(_context) + structure_definition.item.validate(_context, _manage_memory) } } } - fn run(self, context: &mut Context, clear_variables: bool) -> Result { + fn run(self, context: &mut Context, manage_memory: bool) -> Result { let result = match self { - Statement::Assignment(assignment) => { - let run_result = assignment.item.run(context, clear_variables); - - if clear_variables { - context.clean()?; - } - - run_result - } - Statement::AsyncBlock(async_block) => async_block.item.run(context, clear_variables), - Statement::Block(block) => block.item.run(context, clear_variables), + Statement::Assignment(assignment) => assignment.item.run(context, manage_memory), + Statement::AsyncBlock(async_block) => async_block.item.run(context, manage_memory), + Statement::Block(block) => block.item.run(context, manage_memory), Statement::Break(_) => Ok(Action::Break), - Statement::Expression(expression) => { - let run_result = expression.run(context, clear_variables); - - if clear_variables { - context.clean()?; - } - - run_result - } - Statement::IfElse(if_else) => { - let run_result = if_else.item.run(context, clear_variables); - - if clear_variables { - context.clean()?; - } - - run_result - } - Statement::Loop(r#loop) => r#loop.item.run(context, clear_variables), - Statement::While(r#while) => r#while.item.run(context, clear_variables), + Statement::Expression(expression) => expression.run(context, manage_memory), + Statement::IfElse(if_else) => if_else.item.run(context, manage_memory), + Statement::Loop(r#loop) => r#loop.item.run(context, manage_memory), + Statement::While(r#while) => r#while.item.run(context, manage_memory), Statement::StructureDefinition(structure_definition) => { - let run_result = structure_definition.item.run(context, clear_variables); - - if clear_variables { - context.clean()?; - } - - run_result + structure_definition.item.run(context, manage_memory) } }; + if manage_memory { + context.clean()?; + } + result } } diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 18fb543..abee81f 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -23,11 +23,11 @@ impl AbstractNode for StructureDefinition { Ok(Type::None) } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { Ok(()) } - fn run(self, context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { let struct_type = Type::Structure { name: self.name.clone(), fields: self.fields, diff --git a/dust-lang/src/abstract_tree/type.rs b/dust-lang/src/abstract_tree/type.rs index 0d35e19..fdec583 100644 --- a/dust-lang/src/abstract_tree/type.rs +++ b/dust-lang/src/abstract_tree/type.rs @@ -148,11 +148,11 @@ impl AbstractNode for Type { Ok(Type::None) } - fn validate(&self, _: &Context) -> Result<(), ValidationError> { + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { Ok(Action::None) } } diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 645b289..27280c9 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -91,7 +91,7 @@ impl AbstractNode for ValueNode { Ok(r#type) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { + fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { if let ValueNode::Map(map_assignments) = self { for (_identifier, r#type, expression) in map_assignments { if let Some(expected_type) = r#type { @@ -131,7 +131,7 @@ impl AbstractNode for ValueNode { function_context.set_type(identifier.clone(), r#type.item.clone())?; } - body.item.validate(&function_context)?; + body.item.validate(&function_context, _manage_memory)?; let actual_return_type = body.item.expected_type(&function_context)?; @@ -181,7 +181,7 @@ impl AbstractNode for ValueNode { Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { let value = match self { ValueNode::Boolean(boolean) => Value::boolean(boolean), ValueNode::Float(float) => Value::float(float), @@ -191,7 +191,7 @@ impl AbstractNode for ValueNode { for expression in expression_list { let expression_position = expression.position(); - let action = expression.run(_context, _clear_variables)?; + let action = expression.run(_context, _manage_memory)?; let value = if let Action::Return(value) = action { WithPosition { item: value, @@ -213,7 +213,7 @@ impl AbstractNode for ValueNode { for (identifier, _type, expression) in property_list { let expression_position = expression.position(); - let action = expression.run(_context, _clear_variables)?; + let action = expression.run(_context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { @@ -243,7 +243,7 @@ impl AbstractNode for ValueNode { for (identifier, expression) in expressions { let expression_position = expression.position(); - let action = expression.run(_context, _clear_variables)?; + let action = expression.run(_context, _manage_memory)?; let value = if let Action::Return(value) = action { value } else { diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index 472eb7c..ddc92fa 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -27,23 +27,23 @@ impl AbstractNode for While { Ok(Type::None) } - fn validate(&self, _context: &Context) -> Result<(), ValidationError> { - self.expression.validate(_context)?; + fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + self.expression.validate(_context, _manage_memory)?; for statement in &self.statements { - statement.validate(_context)?; + statement.validate(_context, _manage_memory)?; } Ok(()) } - fn run(self, _context: &mut Context, _clear_variables: bool) -> Result { + fn run(self, _context: &mut Context, _manage_memory: bool) -> Result { let get_boolean = || -> Result { let expression_position = self.expression.position(); let action = self .expression .clone() - .run(&mut _context.clone(), _clear_variables)?; + .run(&mut _context.clone(), _manage_memory)?; if let Action::Return(value) = action { Ok(value) @@ -58,7 +58,7 @@ impl AbstractNode for While { for statement in &self.statements { let action = statement .clone() - .run(&mut _context.clone(), _clear_variables)?; + .run(&mut _context.clone(), _manage_memory)?; match action { Action::Return(_) => {} diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 5ffd058..6d1aef2 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -13,18 +13,14 @@ use crate::{ #[derive(Clone, Debug)] pub struct Context { variables: Arc>>, + is_clean: bool, } impl Context { pub fn new() -> Self { Self { variables: Arc::new(RwLock::new(BTreeMap::new())), - } - } - - pub fn with_data(data: BTreeMap) -> Self { - Self { - variables: Arc::new(RwLock::new(data)), + is_clean: true, } } @@ -95,6 +91,16 @@ impl Context { } } + pub fn get_value(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { + if let Some((ValueData::Value(value), _)) = self.variables.read()?.get(identifier) { + log::trace!("Getting {identifier}'s value."); + + Ok(Some(value.clone())) + } else { + Ok(None) + } + } + pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> { log::debug!("Setting {identifier} to type {}.", r#type); @@ -123,20 +129,30 @@ impl Context { } pub fn clean(&mut self) -> Result<(), RwLockPoisonError> { + if self.is_clean { + return Ok(()); + } + self.variables .write()? - .retain(|identifier, (_, usage_data)| { - let usage = usage_data.inner().read().unwrap(); + .retain(|identifier, (value_data, usage_data)| { + if let ValueData::Value(_) = value_data { + let usage = usage_data.inner().read().unwrap(); - if usage.actual < usage.expected { - true + if usage.actual < usage.expected { + true + } else { + log::trace!("Removing variable {identifier}."); + + false + } } else { - log::trace!("Removing variable {identifier}."); - false } }); + self.is_clean = true; + Ok(()) }