Refine memory management
This commit is contained in:
parent
70face6765
commit
8478d59000
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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}"),
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
{
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user