Refine memory management

This commit is contained in:
Jeff 2024-04-22 08:25:20 -04:00
parent c659b56105
commit d400b8bb6a
19 changed files with 100 additions and 44 deletions

View File

@ -39,11 +39,11 @@ impl Assignment {
}
impl AbstractNode for Assignment {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition {

View File

@ -21,11 +21,11 @@ impl AsyncBlock {
}
impl AbstractNode for AsyncBlock {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.statements.last().unwrap().expected_type(_context)
}
fn validate(&self, _context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, manage_memory)?;
}
@ -33,7 +33,7 @@ impl AbstractNode for AsyncBlock {
Ok(())
}
fn run(self, _context: &mut Context, manage_memory: 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(), manage_memory);
let result = statement.run(&mut _context.clone(), false);
if index == statement_count - 1 {
let get_write_lock = final_result.write();

View File

@ -21,7 +21,7 @@ impl Block {
}
impl AbstractNode for Block {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
if let Some(statement) = self.statements.last() {
statement.expected_type(_context)
} else {
@ -29,7 +29,11 @@ impl AbstractNode for Block {
}
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, _manage_memory)?;
}
@ -88,6 +92,6 @@ mod tests {
)),
]);
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
assert_eq!(block.expected_type(&mut Context::new()), Ok(Type::Integer))
}
}

View File

@ -18,7 +18,7 @@ pub enum BuiltInFunctionCall {
}
impl AbstractNode for BuiltInFunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
BuiltInFunctionCall::ReadLine => Ok(Type::String),
BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
@ -26,7 +26,11 @@ impl AbstractNode for BuiltInFunctionCall {
}
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
match self {
BuiltInFunctionCall::ReadLine => Ok(()),
BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory),

View File

@ -37,7 +37,7 @@ impl Expression {
}
impl AbstractNode for Expression {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.item.expected_type(_context),
Expression::Identifier(identifier) => {
@ -61,7 +61,7 @@ impl AbstractNode for Expression {
}
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
match self {
Expression::FunctionCall(function_call) => {
function_call.item.validate(context, manage_memory)

View File

@ -28,7 +28,7 @@ impl FunctionCall {
}
impl AbstractNode for FunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type {
@ -41,7 +41,7 @@ impl AbstractNode for FunctionCall {
}
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
self.function.validate(context, manage_memory)?;
for expression in &self.arguments {

View File

@ -31,11 +31,11 @@ impl IfElse {
}
impl AbstractNode for IfElse {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
self.if_block.item.expected_type(_context)
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
self.if_expression.validate(context, manage_memory)?;
self.if_block.item.validate(context, manage_memory)?;

View File

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

View File

@ -21,11 +21,11 @@ pub enum Logic {
}
impl AbstractNode for Logic {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::Boolean)
}
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self {
Logic::Equal(left, right)
| Logic::NotEqual(left, right)

View File

@ -17,11 +17,15 @@ impl Loop {
}
impl AbstractNode for Loop {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, false)?;
}

View File

@ -23,7 +23,7 @@ impl MapIndex {
}
impl AbstractNode for MapIndex {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
if let (Expression::Identifier(collection_identifier), index) =
(&self.collection, &self.index)
{
@ -105,7 +105,11 @@ impl AbstractNode for MapIndex {
})
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
self.collection.validate(_context, _manage_memory)
}

View File

@ -17,7 +17,7 @@ pub enum Math {
}
impl AbstractNode for Math {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Math::Add(left, right)
| Math::Subtract(left, right)
@ -40,7 +40,7 @@ impl AbstractNode for Math {
}
}
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
match self {
Math::Add(left, right) => {
let left_position = left.position();

View File

@ -182,7 +182,7 @@ impl Index<usize> for AbstractTree {
}
pub trait AbstractNode: Sized {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>;
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>;
}

View File

@ -38,7 +38,7 @@ impl Statement {
}
impl AbstractNode for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.item.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.item.expected_type(_context),
@ -54,7 +54,11 @@ impl AbstractNode for Statement {
}
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory),
Statement::AsyncBlock(async_block) => {

View File

@ -19,11 +19,15 @@ impl StructureDefinition {
}
impl AbstractNode for StructureDefinition {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -144,11 +144,15 @@ impl Type {
}
impl AbstractNode for Type {
fn expected_type(&self, _: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -31,7 +31,7 @@ pub enum ValueNode {
}
impl AbstractNode for ValueNode {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,
ValueNode::Float(_) => Type::Float,
@ -91,7 +91,7 @@ impl AbstractNode for ValueNode {
Ok(r#type)
}
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(&self, context: &mut 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 {
@ -117,7 +117,7 @@ impl AbstractNode for ValueNode {
body,
} = self
{
let function_context = Context::new();
let mut function_context = Context::new();
function_context.inherit_types_from(context)?;
@ -131,9 +131,9 @@ impl AbstractNode for ValueNode {
function_context.set_type(identifier.clone(), r#type.item.clone())?;
}
body.item.validate(&function_context, _manage_memory)?;
body.item.validate(&mut function_context, _manage_memory)?;
let actual_return_type = body.item.expected_type(&function_context)?;
let actual_return_type = body.item.expected_type(&mut function_context)?;
return_type
.item

View File

@ -23,11 +23,15 @@ impl While {
}
impl AbstractNode for While {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
self.expression.validate(_context, _manage_memory)?;
for statement in &self.statements {

View File

@ -78,12 +78,16 @@ impl Context {
}
}
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
pub fn use_value(
&mut self,
identifier: &Identifier,
) -> Result<Option<Value>, RwLockPoisonError> {
if let Some((ValueData::Value(value), usage_data)) = self.variables.read()?.get(identifier)
{
log::trace!("Using {identifier}'s value.");
usage_data.inner().write()?.actual += 1;
self.is_clean = false;
Ok(Some(value.clone()))
} else {
@ -111,7 +115,11 @@ impl Context {
Ok(())
}
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
pub fn set_value(
&mut self,
identifier: Identifier,
value: Value,
) -> Result<(), RwLockPoisonError> {
log::debug!("Setting {identifier} to value {value}.");
let mut variables = self.variables.write()?;
@ -156,6 +164,22 @@ impl Context {
Ok(())
}
pub fn is_clean(&mut self) -> Result<bool, RwLockPoisonError> {
if self.is_clean {
Ok(true)
} else {
for (_, (_, usage_data)) in self.variables.read()?.iter() {
let usage_data = usage_data.inner().read().unwrap();
if usage_data.actual > usage_data.expected {
return Ok(false);
}
}
Ok(true)
}
}
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
if let Some((_, usage_data)) = self.variables.read()?.get(identifier) {
log::trace!("Adding expected use for variable {identifier}.");