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