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) 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)?; let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition { if let Some(WithPosition {
@ -64,13 +64,13 @@ impl AbstractNode for Assignment {
context.set_type(self.identifier.item.clone(), statement_type)?; context.set_type(self.identifier.item.clone(), statement_type)?;
} }
self.statement.validate(context)?; self.statement.validate(context, manage_memory)?;
Ok(()) 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 action = self.statement.run(context, clear_variables)?; let action = self.statement.run(context, manage_memory)?;
let right = match action { let right = match action {
Action::Return(value) => value, Action::Return(value) => value,
r#break => return Ok(r#break), r#break => return Ok(r#break),
@ -81,7 +81,13 @@ impl AbstractNode for Assignment {
context.set_value(self.identifier.item, right)?; context.set_value(self.identifier.item, right)?;
} }
AssignmentOperator::AddAssign => { 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()) { let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => { (ValueInner::Integer(left), ValueInner::Integer(right)) => {
let sum = left.saturating_add(*right); let sum = left.saturating_add(*right);
@ -120,7 +126,13 @@ impl AbstractNode for Assignment {
} }
} }
AssignmentOperator::SubAssign => { 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()) { let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => { (ValueInner::Integer(left), ValueInner::Integer(right)) => {
let difference = left.saturating_sub(*right); let difference = left.saturating_sub(*right);

View File

@ -25,15 +25,15 @@ impl AbstractNode for AsyncBlock {
self.statements.last().unwrap().expected_type(_context) 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 { for statement in &self.statements {
statement.validate(_context)?; statement.validate(_context, manage_memory)?;
} }
Ok(()) 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 statement_count = self.statements.len();
let final_result = RwLock::new(Ok(Action::None)); let final_result = RwLock::new(Ok(Action::None));
@ -41,7 +41,7 @@ impl AbstractNode for AsyncBlock {
.into_par_iter() .into_par_iter()
.enumerate() .enumerate()
.find_map_first(|(index, statement)| { .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 { if index == statement_count - 1 {
let get_write_lock = final_result.write(); 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 { for statement in &self.statements {
statement.validate(_context)?; statement.validate(_context, _manage_memory)?;
} }
Ok(()) 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; let mut previous = Action::None;
for statement in self.statements { for statement in self.statements {
previous = statement.run(_context, _clear_variables)?; previous = statement.run(_context, _manage_memory)?;
} }
Ok(previous) 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 { match self {
BuiltInFunctionCall::ReadLine => Ok(()), BuiltInFunctionCall::ReadLine => Ok(()),
BuiltInFunctionCall::Sleep(expression) => expression.validate(_context), BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory),
BuiltInFunctionCall::WriteLine(expression) => expression.validate(_context), 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 { match self {
BuiltInFunctionCall::ReadLine => { BuiltInFunctionCall::ReadLine => {
let mut buffer = String::new(); let mut buffer = String::new();
@ -44,7 +46,7 @@ impl AbstractNode for BuiltInFunctionCall {
Ok(Action::Return(Value::string(buffer))) Ok(Action::Return(Value::string(buffer)))
} }
BuiltInFunctionCall::Sleep(expression) => { 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 { let value = if let Action::Return(value) = action {
value value
} else { } else {
@ -60,7 +62,7 @@ impl AbstractNode for BuiltInFunctionCall {
Ok(Action::None) Ok(Action::None)
} }
BuiltInFunctionCall::WriteLine(expression) => { 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 { let value = if let Action::Return(value) = action {
value value
} else { } 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 { 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) => { 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 { if found {
Ok(()) Ok(())
@ -76,24 +82,30 @@ impl AbstractNode for Expression {
}) })
} }
} }
Expression::MapIndex(map_index) => map_index.item.validate(context), Expression::MapIndex(map_index) => map_index.item.validate(context, manage_memory),
Expression::ListIndex(list_index) => list_index.item.validate(context), Expression::ListIndex(list_index) => list_index.item.validate(context, manage_memory),
Expression::Logic(logic) => logic.item.validate(context), Expression::Logic(logic) => logic.item.validate(context, manage_memory),
Expression::Math(math) => math.item.validate(context), Expression::Math(math) => math.item.validate(context, manage_memory),
Expression::Value(value_node) => value_node.item.validate(context), Expression::Value(value_node) => value_node.item.validate(context, manage_memory),
Expression::BuiltInFunctionCall(built_in_function_call) => { 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 { match self {
Expression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {
function_call.item.run(context, _clear_variables) function_call.item.run(context, manage_memory)
} }
Expression::Identifier(identifier) => { 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)) Ok(Action::Return(value))
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -104,13 +116,13 @@ impl AbstractNode for Expression {
)) ))
} }
} }
Expression::MapIndex(map_index) => map_index.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, _clear_variables), Expression::ListIndex(list_index) => list_index.item.run(context, manage_memory),
Expression::Logic(logic) => logic.item.run(context, _clear_variables), Expression::Logic(logic) => logic.item.run(context, manage_memory),
Expression::Math(math) => math.item.run(context, _clear_variables), Expression::Math(math) => math.item.run(context, manage_memory),
Expression::Value(value_node) => value_node.item.run(context, _clear_variables), Expression::Value(value_node) => value_node.item.run(context, manage_memory),
Expression::BuiltInFunctionCall(built_in_function_call) => { 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> { fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
self.function.validate(context)?; self.function.validate(context, manage_memory)?;
for expression in &self.arguments { for expression in &self.arguments {
expression.validate(context)?; expression.validate(context, manage_memory)?;
} }
let function_node_type = self.function.expected_type(context)?; 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) self.if_block.item.expected_type(_context)
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
self.if_expression.validate(context)?; self.if_expression.validate(context, manage_memory)?;
self.if_block.item.validate(context)?; self.if_block.item.validate(context, manage_memory)?;
let expected_type = self.if_block.item.expected_type(context)?; let expected_type = self.if_block.item.expected_type(context)?;
let if_expression_type = self.if_expression.expected_type(context)?; let if_expression_type = self.if_expression.expected_type(context)?;
if let Type::Boolean = if_expression_type { if let Type::Boolean = if_expression_type {
if let Some(else_block) = &self.else_block { 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)?; let actual = else_block.item.expected_type(context)?;
@ -67,7 +67,7 @@ impl AbstractNode for IfElse {
let expression_type = expression.expected_type(context)?; let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type { if let Type::Boolean = expression_type {
block.item.validate(context)?; block.item.validate(context, manage_memory)?;
let actual = block.item.expected_type(context)?; let actual = block.item.expected_type(context)?;

View File

@ -47,9 +47,9 @@ impl AbstractNode for ListIndex {
} }
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
self.left.validate(context)?; self.left.validate(context, _manage_memory)?;
self.right.validate(context)?; self.right.validate(context, _manage_memory)?;
let left_type = self.left.expected_type(context)?; let left_type = self.left.expected_type(context)?;

View File

@ -25,7 +25,7 @@ impl AbstractNode for Logic {
Ok(Type::Boolean) Ok(Type::Boolean)
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self { match self {
Logic::Equal(left, right) Logic::Equal(left, right)
| Logic::NotEqual(left, right) | Logic::NotEqual(left, right)
@ -33,6 +33,9 @@ impl AbstractNode for Logic {
| Logic::Less(left, right) | Logic::Less(left, right)
| Logic::GreaterOrEqual(left, right) | Logic::GreaterOrEqual(left, right)
| Logic::LessOrEqual(left, right) => { | Logic::LessOrEqual(left, right) => {
left.validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?;
let left_type = left.expected_type(context)?; let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?; let right_type = right.expected_type(context)?;
@ -47,6 +50,9 @@ impl AbstractNode for Logic {
Ok(()) Ok(())
} }
Logic::And(left, right) | Logic::Or(left, right) => { 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 left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?; let right_type = right.expected_type(context)?;
@ -69,6 +75,8 @@ impl AbstractNode for Logic {
Ok(()) Ok(())
} }
Logic::Not(expression) => { Logic::Not(expression) => {
expression.validate(context, _manage_memory)?;
let expression_type = expression.expected_type(context)?; let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type { 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 run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
let expression_position = expression.position(); 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 { let value = if let Action::Return(value) = action {
value value
} else { } else {
@ -100,7 +108,7 @@ impl AbstractNode for Logic {
let run_and_expect_boolean = |expression: Expression| -> Result<bool, RuntimeError> { let run_and_expect_boolean = |expression: Expression| -> Result<bool, RuntimeError> {
let expression_position = expression.position(); 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 { let value = if let Action::Return(value) = action {
value value
} else { } else {

View File

@ -21,15 +21,15 @@ impl AbstractNode for Loop {
Ok(Type::None) 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 { for statement in &self.statements {
statement.validate(_context)?; statement.validate(_context, false)?;
} }
Ok(()) 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 { loop {
for statement in &self.statements { for statement in &self.statements {
let action = statement.clone().run(_context, false)?; let action = statement.clone().run(_context, false)?;

View File

@ -105,13 +105,13 @@ impl AbstractNode for MapIndex {
}) })
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
self.collection.validate(context) 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 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 { let collection = if let Action::Return(value) = action {
value value
} else { } 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 { match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_position = left.position(); let left_position = left.position();

View File

@ -101,14 +101,14 @@ impl AbstractTree {
pub fn run( pub fn run(
self, self,
context: &mut Context, context: &mut Context,
clear_variables: bool, manage_memory: bool,
) -> Result<Option<Value>, Vec<Error>> { ) -> Result<Option<Value>, Vec<Error>> {
let valid_statements = self.validate(context)?; let valid_statements = self.validate(context, manage_memory)?;
let mut previous_value = None; let mut previous_value = None;
for statement in valid_statements { for statement in valid_statements {
let position = statement.position(); let position = statement.position();
let run = statement.run(context, clear_variables); let run = statement.run(context, manage_memory);
match run { match run {
Ok(action) => match action { Ok(action) => match action {
@ -128,12 +128,16 @@ impl AbstractTree {
Ok(previous_value) 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 errors = Vec::new();
let mut valid_statements = Vec::new(); let mut valid_statements = Vec::new();
for statement in self.0 { for statement in self.0 {
let validation = statement.validate(context); let validation = statement.validate(context, add_variable_uses);
if let Err(validation_error) = validation { if let Err(validation_error) = validation {
errors.push(Error::Validation { errors.push(Error::Validation {
@ -179,6 +183,6 @@ impl Index<usize> for AbstractTree {
pub trait AbstractNode: Sized { pub trait AbstractNode: Sized {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>; fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context) -> Result<(), ValidationError>; fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError>; 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 { match self {
Statement::Assignment(assignment) => assignment.item.validate(_context), Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory),
Statement::AsyncBlock(async_block) => async_block.item.validate(_context), Statement::AsyncBlock(async_block) => {
Statement::Block(block) => block.item.validate(_context), async_block.item.validate(_context, _manage_memory)
}
Statement::Block(block) => block.item.validate(_context, _manage_memory),
Statement::Break(_) => Ok(()), Statement::Break(_) => Ok(()),
Statement::Expression(expression) => expression.validate(_context), Statement::Expression(expression) => expression.validate(_context, _manage_memory),
Statement::IfElse(if_else) => if_else.item.validate(_context), Statement::IfElse(if_else) => if_else.item.validate(_context, _manage_memory),
Statement::Loop(r#loop) => r#loop.item.validate(_context), Statement::Loop(r#loop) => r#loop.item.validate(_context, _manage_memory),
Statement::While(r#while) => r#while.item.validate(_context), Statement::While(r#while) => r#while.item.validate(_context, _manage_memory),
Statement::StructureDefinition(structure_definition) => { 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 { let result = match self {
Statement::Assignment(assignment) => { Statement::Assignment(assignment) => assignment.item.run(context, manage_memory),
let run_result = assignment.item.run(context, clear_variables); Statement::AsyncBlock(async_block) => async_block.item.run(context, manage_memory),
Statement::Block(block) => block.item.run(context, manage_memory),
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::Break(_) => Ok(Action::Break), Statement::Break(_) => Ok(Action::Break),
Statement::Expression(expression) => { Statement::Expression(expression) => expression.run(context, manage_memory),
let run_result = expression.run(context, clear_variables); Statement::IfElse(if_else) => if_else.item.run(context, manage_memory),
Statement::Loop(r#loop) => r#loop.item.run(context, manage_memory),
if clear_variables { Statement::While(r#while) => r#while.item.run(context, manage_memory),
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::StructureDefinition(structure_definition) => { Statement::StructureDefinition(structure_definition) => {
let run_result = structure_definition.item.run(context, clear_variables); structure_definition.item.run(context, manage_memory)
if clear_variables {
context.clean()?;
}
run_result
} }
}; };
if manage_memory {
context.clean()?;
}
result result
} }
} }

View File

@ -23,11 +23,11 @@ impl AbstractNode for StructureDefinition {
Ok(Type::None) Ok(Type::None)
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
Ok(()) 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 { let struct_type = Type::Structure {
name: self.name.clone(), name: self.name.clone(),
fields: self.fields, fields: self.fields,

View File

@ -148,11 +148,11 @@ impl AbstractNode for Type {
Ok(Type::None) Ok(Type::None)
} }
fn validate(&self, _: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
Ok(()) 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) Ok(Action::None)
} }
} }

View File

@ -91,7 +91,7 @@ impl AbstractNode for ValueNode {
Ok(r#type) 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 { if let ValueNode::Map(map_assignments) = self {
for (_identifier, r#type, expression) in map_assignments { for (_identifier, r#type, expression) in map_assignments {
if let Some(expected_type) = r#type { 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())?; 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)?; let actual_return_type = body.item.expected_type(&function_context)?;
@ -181,7 +181,7 @@ impl AbstractNode for ValueNode {
Ok(()) 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 { let value = match self {
ValueNode::Boolean(boolean) => Value::boolean(boolean), ValueNode::Boolean(boolean) => Value::boolean(boolean),
ValueNode::Float(float) => Value::float(float), ValueNode::Float(float) => Value::float(float),
@ -191,7 +191,7 @@ impl AbstractNode for ValueNode {
for expression in expression_list { for expression in expression_list {
let expression_position = expression.position(); 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 { let value = if let Action::Return(value) = action {
WithPosition { WithPosition {
item: value, item: value,
@ -213,7 +213,7 @@ impl AbstractNode for ValueNode {
for (identifier, _type, expression) in property_list { for (identifier, _type, expression) in property_list {
let expression_position = expression.position(); 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 { let value = if let Action::Return(value) = action {
value value
} else { } else {
@ -243,7 +243,7 @@ impl AbstractNode for ValueNode {
for (identifier, expression) in expressions { for (identifier, expression) in expressions {
let expression_position = expression.position(); 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 { let value = if let Action::Return(value) = action {
value value
} else { } else {

View File

@ -27,23 +27,23 @@ impl AbstractNode for While {
Ok(Type::None) Ok(Type::None)
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
self.expression.validate(_context)?; self.expression.validate(_context, _manage_memory)?;
for statement in &self.statements { for statement in &self.statements {
statement.validate(_context)?; statement.validate(_context, _manage_memory)?;
} }
Ok(()) 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 get_boolean = || -> Result<Value, RuntimeError> {
let expression_position = self.expression.position(); let expression_position = self.expression.position();
let action = self let action = self
.expression .expression
.clone() .clone()
.run(&mut _context.clone(), _clear_variables)?; .run(&mut _context.clone(), _manage_memory)?;
if let Action::Return(value) = action { if let Action::Return(value) = action {
Ok(value) Ok(value)
@ -58,7 +58,7 @@ impl AbstractNode for While {
for statement in &self.statements { for statement in &self.statements {
let action = statement let action = statement
.clone() .clone()
.run(&mut _context.clone(), _clear_variables)?; .run(&mut _context.clone(), _manage_memory)?;
match action { match action {
Action::Return(_) => {} Action::Return(_) => {}

View File

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