1
0

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 { 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) 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)?; let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition { if let Some(WithPosition {

View File

@ -21,11 +21,11 @@ impl AsyncBlock {
} }
impl AbstractNode for 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) 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 { for statement in &self.statements {
statement.validate(_context, manage_memory)?; statement.validate(_context, manage_memory)?;
} }
@ -33,7 +33,7 @@ impl AbstractNode for AsyncBlock {
Ok(()) 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 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(), manage_memory); let result = statement.run(&mut _context.clone(), false);
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

@ -21,7 +21,7 @@ impl Block {
} }
impl AbstractNode for 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() { if let Some(statement) = self.statements.last() {
statement.expected_type(_context) statement.expected_type(_context)
} else { } 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 { for statement in &self.statements {
statement.validate(_context, _manage_memory)?; 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 { 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 { match self {
BuiltInFunctionCall::ReadLine => Ok(Type::String), BuiltInFunctionCall::ReadLine => Ok(Type::String),
BuiltInFunctionCall::Sleep(_) => Ok(Type::None), 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 { match self {
BuiltInFunctionCall::ReadLine => Ok(()), BuiltInFunctionCall::ReadLine => Ok(()),
BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory), BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory),

View File

@ -37,7 +37,7 @@ impl Expression {
} }
impl AbstractNode for 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 { match self {
Expression::FunctionCall(function_call) => function_call.item.expected_type(_context), Expression::FunctionCall(function_call) => function_call.item.expected_type(_context),
Expression::Identifier(identifier) => { 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 { match self {
Expression::FunctionCall(function_call) => { Expression::FunctionCall(function_call) => {
function_call.item.validate(context, manage_memory) function_call.item.validate(context, manage_memory)

View File

@ -28,7 +28,7 @@ impl FunctionCall {
} }
impl AbstractNode for 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)?; let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type { 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)?; self.function.validate(context, manage_memory)?;
for expression in &self.arguments { for expression in &self.arguments {

View File

@ -31,11 +31,11 @@ impl IfElse {
} }
impl AbstractNode for 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) 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_expression.validate(context, manage_memory)?;
self.if_block.item.validate(context, manage_memory)?; self.if_block.item.validate(context, manage_memory)?;

View File

@ -18,7 +18,7 @@ impl ListIndex {
} }
impl AbstractNode for 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)?; let left_type = self.left.expected_type(_context)?;
if let ( 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.left.validate(context, _manage_memory)?;
self.right.validate(context, _manage_memory)?; self.right.validate(context, _manage_memory)?;

View File

@ -21,11 +21,11 @@ pub enum Logic {
} }
impl AbstractNode for 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) 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 { match self {
Logic::Equal(left, right) Logic::Equal(left, right)
| Logic::NotEqual(left, right) | Logic::NotEqual(left, right)

View File

@ -17,11 +17,15 @@ impl Loop {
} }
impl AbstractNode for 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) 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 { for statement in &self.statements {
statement.validate(_context, false)?; statement.validate(_context, false)?;
} }

View File

@ -23,7 +23,7 @@ impl MapIndex {
} }
impl AbstractNode for 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) = if let (Expression::Identifier(collection_identifier), index) =
(&self.collection, &self.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) self.collection.validate(_context, _manage_memory)
} }

View File

@ -17,7 +17,7 @@ pub enum Math {
} }
impl AbstractNode for 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 { match self {
Math::Add(left, right) Math::Add(left, right)
| Math::Subtract(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 { match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_position = left.position(); let left_position = left.position();

View File

@ -182,7 +182,7 @@ 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: &mut Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>; fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>;
fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>; fn run(self, context: &mut Context, manage_memory: bool) -> Result<Action, RuntimeError>;
} }

View File

@ -38,7 +38,7 @@ impl Statement {
} }
impl AbstractNode for 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 { match self {
Statement::Assignment(assignment) => assignment.item.expected_type(_context), Statement::Assignment(assignment) => assignment.item.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.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 { match self {
Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory), Statement::Assignment(assignment) => assignment.item.validate(_context, _manage_memory),
Statement::AsyncBlock(async_block) => { Statement::AsyncBlock(async_block) => {

View File

@ -19,11 +19,15 @@ impl StructureDefinition {
} }
impl AbstractNode for 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) 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(()) Ok(())
} }

View File

@ -144,11 +144,15 @@ impl Type {
} }
impl AbstractNode for 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) 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(()) Ok(())
} }

View File

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

View File

@ -23,11 +23,15 @@ impl While {
} }
impl AbstractNode for 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) 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)?; self.expression.validate(_context, _manage_memory)?;
for statement in &self.statements { 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) if let Some((ValueData::Value(value), usage_data)) = self.variables.read()?.get(identifier)
{ {
log::trace!("Using {identifier}'s value."); log::trace!("Using {identifier}'s value.");
usage_data.inner().write()?.actual += 1; usage_data.inner().write()?.actual += 1;
self.is_clean = false;
Ok(Some(value.clone())) Ok(Some(value.clone()))
} else { } else {
@ -111,7 +115,11 @@ impl Context {
Ok(()) 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}."); log::debug!("Setting {identifier} to value {value}.");
let mut variables = self.variables.write()?; let mut variables = self.variables.write()?;
@ -156,6 +164,22 @@ impl Context {
Ok(()) 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> { pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
if let Some((_, usage_data)) = self.variables.read()?.get(identifier) { if let Some((_, usage_data)) = self.variables.read()?.get(identifier) {
log::trace!("Adding expected use for variable {identifier}."); log::trace!("Adding expected use for variable {identifier}.");