Refine memory management

This commit is contained in:
Jeff 2024-04-22 07:56:03 -04:00
parent bcd8e7c669
commit c659b56105
19 changed files with 174 additions and 144 deletions

View File

@ -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<Action, RuntimeError> {
let action = self.statement.run(context, clear_variables)?;
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
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);

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
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();

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let mut previous = Action::None;
for statement in self.statements {
previous = statement.run(_context, _clear_variables)?;
previous = statement.run(_context, _manage_memory)?;
}
Ok(previous)

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
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 {

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
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)
}
}
}

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
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<bool, RuntimeError> {
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 {

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
loop {
for statement in &self.statements {
let action = statement.clone().run(_context, false)?;

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
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 {

View File

@ -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();

View File

@ -101,14 +101,14 @@ impl AbstractTree {
pub fn run(
self,
context: &mut Context,
clear_variables: bool,
manage_memory: bool,
) -> Result<Option<Value>, Vec<Error>> {
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<Statement>, Vec<Error>> {
fn validate(
self,
context: &mut Context,
add_variable_uses: bool,
) -> Result<Vec<Statement>, Vec<Error>> {
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<usize> for AbstractTree {
pub trait AbstractNode: Sized {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError>;
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>;
}

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError> {
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
}
}

View File

@ -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<Action, RuntimeError> {
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let struct_type = Type::Structure {
name: self.name.clone(),
fields: self.fields,

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
Ok(Action::None)
}
}

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
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 {

View File

@ -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<Action, RuntimeError> {
fn run(self, _context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> {
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(_) => {}

View File

@ -13,18 +13,14 @@ use crate::{
#[derive(Clone, Debug)]
pub struct Context {
variables: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
is_clean: bool,
}
impl Context {
pub fn new() -> Self {
Self {
variables: Arc::new(RwLock::new(BTreeMap::new())),
}
}
pub fn with_data(data: BTreeMap<Identifier, (ValueData, UsageData)>) -> 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<Option<Value>, 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,9 +129,14 @@ impl Context {
}
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
if self.is_clean {
return Ok(());
}
self.variables
.write()?
.retain(|identifier, (_, usage_data)| {
.retain(|identifier, (value_data, usage_data)| {
if let ValueData::Value(_) = value_data {
let usage = usage_data.inner().read().unwrap();
if usage.actual < usage.expected {
@ -133,10 +144,15 @@ impl Context {
} else {
log::trace!("Removing variable {identifier}.");
false
}
} else {
false
}
});
self.is_clean = true;
Ok(())
}