Refine memory management
This commit is contained in:
parent
bcd8e7c669
commit
c659b56105
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)?;
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(_) => {}
|
||||
|
@ -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,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(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user