1
0

Refine memory management

This commit is contained in:
Jeff 2024-04-22 03:41:21 -04:00
parent 70face6765
commit 8478d59000
13 changed files with 173 additions and 169 deletions

View File

@ -47,7 +47,7 @@ impl AbstractNode for Assignment {
let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition {
node: expected_type,
item: expected_type,
position: expected_position,
}) = &self.r#type
{
@ -59,9 +59,9 @@ impl AbstractNode for Assignment {
}
})?;
context.set_type(self.identifier.node.clone(), expected_type.clone())?;
context.set_type(self.identifier.item.clone(), expected_type.clone())?;
} else {
context.set_type(self.identifier.node.clone(), statement_type)?;
context.set_type(self.identifier.item.clone(), statement_type)?;
}
self.statement.validate(context)?;
@ -78,10 +78,10 @@ impl AbstractNode for Assignment {
match self.operator {
AssignmentOperator::Assign => {
context.set_value(self.identifier.node, right)?;
context.set_value(self.identifier.item, right)?;
}
AssignmentOperator::AddAssign => {
if let Some(left) = context.use_value(&self.identifier.node)? {
if let Some(left) = context.use_value(&self.identifier.item)? {
let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
let sum = left.saturating_add(*right);
@ -109,18 +109,18 @@ impl AbstractNode for Assignment {
))
}
};
context.set_value(self.identifier.node, new_value)?;
context.set_value(self.identifier.item, new_value)?;
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: self.identifier.node,
identifier: self.identifier.item,
position: self.identifier.position,
},
));
}
}
AssignmentOperator::SubAssign => {
if let Some(left) = context.use_value(&self.identifier.node)? {
if let Some(left) = context.use_value(&self.identifier.item)? {
let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
let difference = left.saturating_sub(*right);
@ -148,11 +148,11 @@ impl AbstractNode for Assignment {
))
}
};
context.set_value(self.identifier.node, new_value)?;
context.set_value(self.identifier.item, new_value)?;
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: self.identifier.node,
identifier: self.identifier.item,
position: self.identifier.position,
},
));
@ -249,7 +249,7 @@ mod tests {
let validation = Assignment::new(
Identifier::new("foobar").with_position((0, 0)),
Some(WithPosition {
node: Type::Boolean,
item: Type::Boolean,
position: (0, 0).into(),
}),
AssignmentOperator::Assign,

View File

@ -39,50 +39,50 @@ impl Expression {
impl AbstractNode for Expression {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.node.expected_type(_context),
Expression::FunctionCall(function_call) => function_call.item.expected_type(_context),
Expression::Identifier(identifier) => {
if let Some(r#type) = _context.get_type(&identifier.node)? {
if let Some(r#type) = _context.get_type(&identifier.item)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
identifier: identifier.item.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
Expression::ListIndex(list_index) => list_index.node.expected_type(_context),
Expression::Logic(logic) => logic.node.expected_type(_context),
Expression::Math(math) => math.node.expected_type(_context),
Expression::Value(value_node) => value_node.node.expected_type(_context),
Expression::MapIndex(map_index) => map_index.item.expected_type(_context),
Expression::ListIndex(list_index) => list_index.item.expected_type(_context),
Expression::Logic(logic) => logic.item.expected_type(_context),
Expression::Math(math) => math.item.expected_type(_context),
Expression::Value(value_node) => value_node.item.expected_type(_context),
Expression::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.expected_type(_context)
built_in_function_call.item.expected_type(_context)
}
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.node.validate(context),
Expression::FunctionCall(function_call) => function_call.item.validate(context),
Expression::Identifier(identifier) => {
let found = context.add_expected_use(&identifier.node)?;
let found = context.add_expected_use(&identifier.item)?;
if found {
Ok(())
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
identifier: identifier.item.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.node.validate(context),
Expression::ListIndex(list_index) => list_index.node.validate(context),
Expression::Logic(logic) => logic.node.validate(context),
Expression::Math(math) => math.node.validate(context),
Expression::Value(value_node) => value_node.node.validate(context),
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::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.validate(context)
built_in_function_call.item.validate(context)
}
}
}
@ -90,27 +90,27 @@ impl AbstractNode for Expression {
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
match self {
Expression::FunctionCall(function_call) => {
function_call.node.run(context, _clear_variables)
function_call.item.run(context, _clear_variables)
}
Expression::Identifier(identifier) => {
if let Some(value) = context.use_value(&identifier.node)? {
if let Some(value) = context.use_value(&identifier.item)? {
Ok(Action::Return(value))
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
identifier: identifier.item.clone(),
position: identifier.position,
},
))
}
}
Expression::MapIndex(map_index) => map_index.node.run(context, _clear_variables),
Expression::ListIndex(list_index) => list_index.node.run(context, _clear_variables),
Expression::Logic(logic) => logic.node.run(context, _clear_variables),
Expression::Math(math) => math.node.run(context, _clear_variables),
Expression::Value(value_node) => value_node.node.run(context, _clear_variables),
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::BuiltInFunctionCall(built_in_function_call) => {
built_in_function_call.node.run(context, _clear_variables)
built_in_function_call.item.run(context, _clear_variables)
}
}
}

View File

@ -32,7 +32,7 @@ impl AbstractNode for FunctionCall {
let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type {
Ok(return_type.node)
Ok(return_type.item)
} else {
Err(ValidationError::ExpectedFunction {
actual: function_node_type,
@ -58,13 +58,13 @@ impl AbstractNode for FunctionCall {
for (type_parameter, type_argument) in
parameter_types.iter().zip(self.type_arguments.iter())
{
if let Type::Argument(_) = type_parameter.node {
if let Type::Argument(_) = type_parameter.item {
continue;
}
type_parameter
.node
.check(&type_argument.node)
.item
.check(&type_argument.item)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: type_argument.position,
@ -73,13 +73,13 @@ impl AbstractNode for FunctionCall {
}
for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) {
if let Type::Argument(_) = type_parameter.node {
if let Type::Argument(_) = type_parameter.item {
continue;
}
let actual = expression.expected_type(context)?;
type_parameter.node.check(&actual).map_err(|conflict| {
type_parameter.item.check(&actual).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position(),
@ -97,9 +97,9 @@ impl AbstractNode for FunctionCall {
}
}
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError> {
let function_position = self.function.position();
let action = self.function.run(context, _clear_variables)?;
let action = self.function.run(context, clear_variables)?;
let value = if let Action::Return(value) = action {
value
} else {
@ -121,7 +121,7 @@ impl AbstractNode for FunctionCall {
for expression in self.arguments {
let expression_position = expression.position();
let action = expression.run(context, _clear_variables)?;
let action = expression.run(context, clear_variables)?;
let value = if let Action::Return(value) = action {
value
} else {
@ -138,8 +138,8 @@ impl AbstractNode for FunctionCall {
for (type_parameter, type_argument) in function
.type_parameters()
.iter()
.map(|r#type| r#type.node.clone())
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
.map(|r#type| r#type.item.clone())
.zip(self.type_arguments.into_iter().map(|r#type| r#type.item))
{
if let Type::Argument(identifier) = type_parameter {
function_context.set_type(identifier, type_argument)?;
@ -147,6 +147,8 @@ impl AbstractNode for FunctionCall {
}
function_context.inherit_data_from(&context)?;
function.clone().call(arguments, &mut function_context)
function
.clone()
.call(arguments, &mut function_context, clear_variables)
}
}

View File

@ -32,27 +32,27 @@ impl IfElse {
impl AbstractNode for IfElse {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
self.if_block.node.expected_type(_context)
self.if_block.item.expected_type(_context)
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
self.if_expression.validate(context)?;
self.if_block.node.validate(context)?;
self.if_block.item.validate(context)?;
let expected_type = self.if_block.node.expected_type(context)?;
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.node.validate(context)?;
else_block.item.validate(context)?;
let actual = else_block.node.expected_type(context)?;
let actual = else_block.item.expected_type(context)?;
expected_type
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
actual_position: self.if_block.item.last_statement().position(),
expected_position: self.if_expression.position(),
})?;
}
@ -67,15 +67,15 @@ impl AbstractNode for IfElse {
let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type {
block.node.validate(context)?;
block.item.validate(context)?;
let actual = block.node.expected_type(context)?;
let actual = block.item.expected_type(context)?;
expected_type
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.node.last_statement().position(),
actual_position: self.if_block.item.last_statement().position(),
expected_position: self.if_expression.position(),
})?;
} else {
@ -102,7 +102,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean {
self.if_block.node.run(context, _clear_variables)
self.if_block.item.run(context, _clear_variables)
} else {
for (expression, block) in self.else_ifs {
let expression_position = expression.position();
@ -117,7 +117,7 @@ impl AbstractNode for IfElse {
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
if *else_if_boolean {
return block.node.run(context, _clear_variables);
return block.item.run(context, _clear_variables);
}
} else {
return Err(RuntimeError::ValidationFailure(
@ -130,7 +130,7 @@ impl AbstractNode for IfElse {
}
if let Some(else_statement) = self.else_block {
else_statement.node.run(context, _clear_variables)
else_statement.item.run(context, _clear_variables)
} else {
Ok(Action::None)
}

View File

@ -23,11 +23,11 @@ impl AbstractNode for ListIndex {
if let (
Expression::Value(WithPosition {
node: ValueNode::List(expression_list),
item: ValueNode::List(expression_list),
..
}),
Expression::Value(WithPosition {
node: ValueNode::Integer(index),
item: ValueNode::Integer(index),
..
}),
) = (&self.left, &self.right)
@ -98,7 +98,7 @@ impl AbstractNode for ListIndex {
let found_item = list.get(index as usize);
if let Some(item) = found_item {
Ok(Action::Return(item.node.clone()))
Ok(Action::Return(item.item.clone()))
} else {
Ok(Action::None)
}

View File

@ -28,21 +28,21 @@ impl AbstractNode for MapIndex {
(&self.collection, &self.index)
{
let collection =
if let Some(collection) = context.use_value(&collection_identifier.node)? {
if let Some(collection) = context.use_value(&collection_identifier.item)? {
collection
} else {
return Err(ValidationError::VariableNotFound {
identifier: collection_identifier.node.clone(),
identifier: collection_identifier.item.clone(),
position: collection_identifier.position,
});
};
if let ValueInner::Map(map) = collection.inner().as_ref() {
return if let Some(value) = map.get(&index.node) {
return if let Some(value) = map.get(&index.item) {
Ok(value.r#type(context)?)
} else {
Err(ValidationError::PropertyNotFound {
identifier: index.node.clone(),
identifier: index.item.clone(),
position: index.position,
})
};
@ -51,7 +51,7 @@ impl AbstractNode for MapIndex {
if let (
Expression::Value(WithPosition {
node: ValueNode::Map(properties),
item: ValueNode::Map(properties),
..
}),
index,
@ -61,9 +61,9 @@ impl AbstractNode for MapIndex {
properties
.iter()
.find_map(|(property, type_option, expression)| {
if property == &index.node {
if property == &index.item {
if let Some(r#type) = type_option {
Some(r#type.node.expected_type(context))
Some(r#type.item.expected_type(context))
} else {
Some(expression.expected_type(context))
}
@ -80,14 +80,14 @@ impl AbstractNode for MapIndex {
if let (
Expression::Value(WithPosition {
node: ValueNode::Structure { fields, .. },
item: ValueNode::Structure { fields, .. },
..
}),
index,
) = (&self.collection, &self.index)
{
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
if property == &index.node {
if property == &index.item {
Some(expression.expected_type(context))
} else {
None
@ -122,7 +122,7 @@ impl AbstractNode for MapIndex {
if let ValueInner::Map(map) = collection.inner().as_ref() {
let action = map
.get(&self.index.node)
.get(&self.index.item)
.map(|value| Action::Return(value.clone()))
.unwrap_or(Action::None);

View File

@ -48,14 +48,14 @@ use crate::{
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct WithPosition<T> {
pub node: T,
pub item: T,
pub position: SourcePosition,
}
pub trait WithPos: Sized {
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
WithPosition {
node: self,
item: self,
position: span.into(),
}
}

View File

@ -40,48 +40,48 @@ impl Statement {
impl AbstractNode for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.node.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
Statement::Block(block) => block.node.expected_type(_context),
Statement::Assignment(assignment) => assignment.item.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.item.expected_type(_context),
Statement::Block(block) => block.item.expected_type(_context),
Statement::Break(_) => Ok(Type::None),
Statement::Expression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
Statement::Loop(r#loop) => r#loop.node.expected_type(_context),
Statement::While(r#while) => r#while.node.expected_type(_context),
Statement::IfElse(if_else) => if_else.item.expected_type(_context),
Statement::Loop(r#loop) => r#loop.item.expected_type(_context),
Statement::While(r#while) => r#while.item.expected_type(_context),
Statement::StructureDefinition(structure_definition) => {
structure_definition.node.expected_type(_context)
structure_definition.item.expected_type(_context)
}
}
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.node.validate(_context),
Statement::AsyncBlock(async_block) => async_block.node.validate(_context),
Statement::Block(block) => block.node.validate(_context),
Statement::Assignment(assignment) => assignment.item.validate(_context),
Statement::AsyncBlock(async_block) => async_block.item.validate(_context),
Statement::Block(block) => block.item.validate(_context),
Statement::Break(_) => Ok(()),
Statement::Expression(expression) => expression.validate(_context),
Statement::IfElse(if_else) => if_else.node.validate(_context),
Statement::Loop(r#loop) => r#loop.node.validate(_context),
Statement::While(r#while) => r#while.node.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::StructureDefinition(structure_definition) => {
structure_definition.node.validate(_context)
structure_definition.item.validate(_context)
}
}
}
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError> {
let result = match self {
Statement::Assignment(assignment) => assignment.node.run(context, clear_variables),
Statement::AsyncBlock(async_block) => async_block.node.run(context, clear_variables),
Statement::Block(block) => block.node.run(context, clear_variables),
Statement::Assignment(assignment) => assignment.item.run(context, clear_variables),
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::Expression(expression) => expression.run(context, clear_variables),
Statement::IfElse(if_else) => if_else.node.run(context, clear_variables),
Statement::Loop(r#loop) => r#loop.node.run(context, clear_variables),
Statement::While(r#while) => r#while.node.run(context, clear_variables),
Statement::IfElse(if_else) => if_else.item.run(context, clear_variables),
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) => {
structure_definition.node.run(context, clear_variables)
structure_definition.item.run(context, clear_variables)
}
};

View File

@ -57,27 +57,27 @@ impl Type {
}
}
(Type::ListOf(left), Type::ListOf(right)) => {
if let Ok(()) = left.node.check(&right.node) {
if let Ok(()) = left.item.check(&right.item) {
return Ok(());
}
}
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
for r#type in list_exact {
list_of.node.check(&r#type.node)?;
list_of.item.check(&r#type.item)?;
}
return Ok(());
}
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
for r#type in list_exact {
r#type.node.check(&list_of.node)?;
r#type.item.check(&list_of.item)?;
}
return Ok(());
}
(Type::ListExact(left), Type::ListExact(right)) => {
for (left, right) in left.iter().zip(right.iter()) {
left.node.check(&right.node)?;
left.item.check(&right.item)?;
}
return Ok(());
@ -96,7 +96,7 @@ impl Type {
for ((left_field_name, left_type), (right_field_name, right_type)) in
left_fields.iter().zip(right_fields.iter())
{
if left_field_name != right_field_name || left_type.node != right_type.node
if left_field_name != right_field_name || left_type.item != right_type.item
{
return Err(TypeConflict {
actual: other.clone(),
@ -118,11 +118,11 @@ impl Type {
return_type: right_return,
},
) => {
if left_return.node == right_return.node {
if left_return.item == right_return.item {
for (left_parameter, right_parameter) in
left_parameters.iter().zip(right_parameters.iter())
{
if left_parameter.node != right_parameter.node {
if left_parameter.item != right_parameter.item {
return Err(TypeConflict {
actual: other.clone(),
expected: self.clone(),
@ -165,15 +165,15 @@ impl Display for Type {
Type::Float => write!(f, "float"),
Type::Integer => write!(f, "int"),
Type::List => write!(f, "list"),
Type::ListOf(item_type) => write!(f, "list({})", item_type.node),
Type::ListOf(item_type) => write!(f, "list({})", item_type.item),
Type::ListExact(item_types) => {
write!(f, "[")?;
for (index, item_type) in item_types.into_iter().enumerate() {
if index == item_types.len() - 1 {
write!(f, "{}", item_type.node)?;
write!(f, "{}", item_type.item)?;
} else {
write!(f, "{}, ", item_type.node)?;
write!(f, "{}, ", item_type.item)?;
}
}
@ -190,10 +190,10 @@ impl Display for Type {
write!(f, "(")?;
for r#type in parameter_types {
write!(f, "{} ", r#type.node)?;
write!(f, "{} ", r#type.item)?;
}
write!(f, ") : {}", return_type.node)
write!(f, ") : {}", return_type.item)
}
Type::Structure { name, .. } => write!(f, "{name}"),
Type::Argument(identifier) => write!(f, "{identifier}"),

View File

@ -75,14 +75,14 @@ impl AbstractNode for ValueNode {
types.push((
identifier.clone(),
WithPosition {
node: r#type,
item: r#type,
position: expression.position(),
},
));
}
Type::Structure {
name: name.node.clone(),
name: name.item.clone(),
fields: types,
}
}
@ -97,7 +97,7 @@ impl AbstractNode for ValueNode {
if let Some(expected_type) = r#type {
let actual_type = expression.expected_type(context)?;
expected_type.node.check(&actual_type).map_err(|conflict| {
expected_type.item.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position(),
@ -122,21 +122,21 @@ impl AbstractNode for ValueNode {
function_context.inherit_types_from(context)?;
for r#type in type_arguments {
if let Type::Argument(identifier) = &r#type.node {
function_context.set_type(identifier.clone(), r#type.node.clone())?;
if let Type::Argument(identifier) = &r#type.item {
function_context.set_type(identifier.clone(), r#type.item.clone())?;
}
}
for (identifier, r#type) in parameters {
function_context.set_type(identifier.clone(), r#type.node.clone())?;
function_context.set_type(identifier.clone(), r#type.item.clone())?;
}
body.node.validate(&function_context)?;
body.item.validate(&function_context)?;
let actual_return_type = body.node.expected_type(&function_context)?;
let actual_return_type = body.item.expected_type(&function_context)?;
return_type
.node
.item
.check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
@ -152,9 +152,9 @@ impl AbstractNode for ValueNode {
fields: expressions,
} = self
{
if !context.contains(&name.node)? {
if !context.contains(&name.item)? {
return Err(ValidationError::VariableNotFound {
identifier: name.node.clone(),
identifier: name.item.clone(),
position: name.position,
});
}
@ -162,12 +162,12 @@ impl AbstractNode for ValueNode {
if let Some(Type::Structure {
name: _,
fields: types,
}) = context.get_type(&name.node)?
}) = context.get_type(&name.item)?
{
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
let actual_type = expression.expected_type(context)?;
expected_type.node.check(&actual_type).map_err(|conflict| {
expected_type.item.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position(),
@ -194,7 +194,7 @@ impl AbstractNode for ValueNode {
let action = expression.run(_context, _clear_variables)?;
let value = if let Action::Return(value) = action {
WithPosition {
node: value,
item: value,
position: expression_position,
}
} else {

View File

@ -3,8 +3,6 @@ use std::{
sync::{Arc, RwLock, RwLockReadGuard},
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::{
abstract_tree::Type,
error::{RwLockPoisonError, ValidationError},
@ -14,19 +12,19 @@ use crate::{
#[derive(Clone, Debug)]
pub struct Context {
inner: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
variables: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
}
impl Context {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(BTreeMap::new())),
variables: Arc::new(RwLock::new(BTreeMap::new())),
}
}
pub fn with_data(data: BTreeMap<Identifier, (ValueData, UsageData)>) -> Self {
Self {
inner: Arc::new(RwLock::new(data)),
variables: Arc::new(RwLock::new(data)),
}
}
@ -34,14 +32,16 @@ impl Context {
&self,
) -> Result<RwLockReadGuard<BTreeMap<Identifier, (ValueData, UsageData)>>, RwLockPoisonError>
{
Ok(self.inner.read()?)
Ok(self.variables.read()?)
}
pub fn inherit_types_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
let mut self_data = self.inner.write()?;
let mut self_data = self.variables.write()?;
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
for (identifier, (value_data, usage_data)) in other.variables.read()?.iter() {
if let ValueData::Type(Type::Function { .. }) = value_data {
log::trace!("Inheriting type of variable {identifier}.");
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
}
}
@ -50,9 +50,11 @@ impl Context {
}
pub fn inherit_data_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
let mut self_data = self.inner.write()?;
let mut self_data = self.variables.write()?;
for (identifier, (value_data, usage_data)) in other.variables.read()?.iter() {
log::trace!("Inheriting variable {identifier}.");
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
}
@ -60,11 +62,13 @@ impl Context {
}
pub fn contains(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
Ok(self.inner.read()?.contains_key(identifier))
log::trace!("Checking that {identifier} exists.");
Ok(self.variables.read()?.contains_key(identifier))
}
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
if let Some((value_data, _)) = self.inner.read()?.get(identifier) {
if let Some((value_data, _)) = self.variables.read()?.get(identifier) {
log::trace!("Using {identifier}'s type.");
let r#type = match value_data {
@ -79,7 +83,8 @@ impl Context {
}
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
if let Some((ValueData::Value(value), usage_data)) = self.inner.write()?.get_mut(identifier)
if let Some((ValueData::Value(value), usage_data)) =
self.variables.write()?.get_mut(identifier)
{
log::trace!("Using {identifier}'s value.");
@ -92,9 +97,9 @@ impl Context {
}
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> {
log::info!("Setting {identifier} to type {}.", r#type);
log::debug!("Setting {identifier} to type {}.", r#type);
self.inner
self.variables
.write()?
.insert(identifier, (ValueData::Type(r#type), UsageData::new()));
@ -102,15 +107,17 @@ impl Context {
}
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
log::info!("Setting {identifier} to value {value}.");
log::debug!("Setting {identifier} to value {value}.");
let mut inner = self.inner.write()?;
let old_usage_data = inner.remove(&identifier).map(|(_, usage_data)| usage_data);
let mut variables = self.variables.write()?;
let old_usage_data = variables
.remove(&identifier)
.map(|(_, usage_data)| usage_data);
if let Some(usage_data) = old_usage_data {
inner.insert(identifier, (ValueData::Value(value), usage_data));
variables.insert(identifier, (ValueData::Value(value), usage_data));
} else {
inner.insert(identifier, (ValueData::Value(value), UsageData::new()));
variables.insert(identifier, (ValueData::Value(value), UsageData::new()));
}
Ok(())
@ -118,7 +125,7 @@ impl Context {
pub fn remove(&self, identifier: &Identifier) -> Result<Option<ValueData>, RwLockPoisonError> {
let removed = self
.inner
.variables
.write()?
.remove(identifier)
.map(|(value_data, _)| value_data);
@ -127,31 +134,25 @@ impl Context {
}
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
let clean_variables = self
.inner
self.variables
.write()?
.clone()
.into_par_iter()
.filter(|(identifier, (_, usage_data))| {
.retain(|identifier, (_, usage_data)| {
if usage_data.actual < usage_data.expected {
true
} else {
log::debug!("Removing variable {identifier}.");
log::trace!("Removing variable {identifier}.");
false
}
})
.collect();
self.inner = Arc::new(RwLock::new(clean_variables));
});
Ok(())
}
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
let mut inner = self.inner.write()?;
let mut variables = self.variables.write()?;
if let Some((_, usage_data)) = inner.get_mut(identifier) {
if let Some((_, usage_data)) = variables.get_mut(identifier) {
log::trace!("Adding expected use for variable {identifier}.");
usage_data.expected += 1;

View File

@ -1520,7 +1520,7 @@ mod tests {
);
if let Statement::Expression(Expression::Value(WithPosition {
node: ValueNode::Float(float),
item: ValueNode::Float(float),
..
})) = &parse(&lex("NaN").unwrap()).unwrap()[0]
{

View File

@ -107,9 +107,9 @@ impl Display for Value {
for (index, value) in list.into_iter().enumerate() {
if index == list.len() - 1 {
write!(f, "{}", value.node)?;
write!(f, "{}", value.item)?;
} else {
write!(f, "{}, ", value.node)?;
write!(f, "{}, ", value.item)?;
}
}
@ -137,9 +137,9 @@ impl Display for Value {
for (index, r#type) in type_arguments.into_iter().enumerate() {
if index == type_arguments.len() - 1 {
write!(f, "{}", r#type.node)?;
write!(f, "{}", r#type.item)?;
} else {
write!(f, "{} ", r#type.node)?;
write!(f, "{} ", r#type.item)?;
}
}
@ -149,13 +149,13 @@ impl Display for Value {
write!(f, "(")?;
for (identifier, r#type) in parameters {
write!(f, "{identifier}: {}", r#type.node)?;
write!(f, "{identifier}: {}", r#type.item)?;
}
write!(f, "): {} {:?}", return_type.node, body.node)
write!(f, "): {} {:?}", return_type.item, body.item)
}
ValueInner::Structure { name, fields } => {
write!(f, "{}\n{{", name.node)?;
write!(f, "{}\n{{", name.item)?;
for (key, value) in fields {
writeln!(f, "{key} = {value},")?;
@ -207,7 +207,7 @@ impl ValueInner {
let mut types = Vec::with_capacity(values.len());
for value in values {
types.push(value.node.r#type(context)?.with_position(value.position));
types.push(value.item.r#type(context)?.with_position(value.position));
}
Type::ListExact(types)
@ -224,11 +224,11 @@ impl ValueInner {
return_type: Box::new(function.return_type.clone()),
},
ValueInner::Structure { name, .. } => {
if let Some(r#type) = context.get_type(&name.node)? {
if let Some(r#type) = context.get_type(&name.item)? {
r#type
} else {
return Err(ValidationError::VariableNotFound {
identifier: name.node.clone(),
identifier: name.item.clone(),
position: name.position,
});
}
@ -316,11 +316,12 @@ impl Function {
self,
arguments: Vec<Value>,
context: &mut Context,
clear_variables: bool,
) -> Result<Action, RuntimeError> {
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) {
context.set_value(identifier.clone(), value)?;
}
self.body.node.run(context, true)
self.body.item.run(context, clear_variables)
}
}