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)?;
|
let statement_type = self.statement.expected_type(context)?;
|
||||||
|
|
||||||
if let Some(WithPosition {
|
if let Some(WithPosition {
|
||||||
node: expected_type,
|
item: expected_type,
|
||||||
position: expected_position,
|
position: expected_position,
|
||||||
}) = &self.r#type
|
}) = &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 {
|
} else {
|
||||||
context.set_type(self.identifier.node.clone(), statement_type)?;
|
context.set_type(self.identifier.item.clone(), statement_type)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.statement.validate(context)?;
|
self.statement.validate(context)?;
|
||||||
@ -78,10 +78,10 @@ impl AbstractNode for Assignment {
|
|||||||
|
|
||||||
match self.operator {
|
match self.operator {
|
||||||
AssignmentOperator::Assign => {
|
AssignmentOperator::Assign => {
|
||||||
context.set_value(self.identifier.node, right)?;
|
context.set_value(self.identifier.item, right)?;
|
||||||
}
|
}
|
||||||
AssignmentOperator::AddAssign => {
|
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()) {
|
let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
|
||||||
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||||
let sum = left.saturating_add(*right);
|
let sum = left.saturating_add(*right);
|
||||||
@ -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 {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::VariableNotFound {
|
ValidationError::VariableNotFound {
|
||||||
identifier: self.identifier.node,
|
identifier: self.identifier.item,
|
||||||
position: self.identifier.position,
|
position: self.identifier.position,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssignmentOperator::SubAssign => {
|
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()) {
|
let new_value = match (left.inner().as_ref(), right.inner().as_ref()) {
|
||||||
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||||
let difference = left.saturating_sub(*right);
|
let difference = left.saturating_sub(*right);
|
||||||
@ -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 {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::VariableNotFound {
|
ValidationError::VariableNotFound {
|
||||||
identifier: self.identifier.node,
|
identifier: self.identifier.item,
|
||||||
position: self.identifier.position,
|
position: self.identifier.position,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -249,7 +249,7 @@ mod tests {
|
|||||||
let validation = Assignment::new(
|
let validation = Assignment::new(
|
||||||
Identifier::new("foobar").with_position((0, 0)),
|
Identifier::new("foobar").with_position((0, 0)),
|
||||||
Some(WithPosition {
|
Some(WithPosition {
|
||||||
node: Type::Boolean,
|
item: Type::Boolean,
|
||||||
position: (0, 0).into(),
|
position: (0, 0).into(),
|
||||||
}),
|
}),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
|
@ -39,50 +39,50 @@ impl Expression {
|
|||||||
impl AbstractNode for Expression {
|
impl AbstractNode for Expression {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||||
match self {
|
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) => {
|
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)
|
Ok(r#type)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::VariableNotFound {
|
Err(ValidationError::VariableNotFound {
|
||||||
identifier: identifier.node.clone(),
|
identifier: identifier.item.clone(),
|
||||||
position: identifier.position,
|
position: identifier.position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
|
Expression::MapIndex(map_index) => map_index.item.expected_type(_context),
|
||||||
Expression::ListIndex(list_index) => list_index.node.expected_type(_context),
|
Expression::ListIndex(list_index) => list_index.item.expected_type(_context),
|
||||||
Expression::Logic(logic) => logic.node.expected_type(_context),
|
Expression::Logic(logic) => logic.item.expected_type(_context),
|
||||||
Expression::Math(math) => math.node.expected_type(_context),
|
Expression::Math(math) => math.item.expected_type(_context),
|
||||||
Expression::Value(value_node) => value_node.node.expected_type(_context),
|
Expression::Value(value_node) => value_node.item.expected_type(_context),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
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> {
|
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Expression::FunctionCall(function_call) => function_call.node.validate(context),
|
Expression::FunctionCall(function_call) => function_call.item.validate(context),
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let found = context.add_expected_use(&identifier.node)?;
|
let found = context.add_expected_use(&identifier.item)?;
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::VariableNotFound {
|
Err(ValidationError::VariableNotFound {
|
||||||
identifier: identifier.node.clone(),
|
identifier: identifier.item.clone(),
|
||||||
position: identifier.position,
|
position: identifier.position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::MapIndex(map_index) => map_index.node.validate(context),
|
Expression::MapIndex(map_index) => map_index.item.validate(context),
|
||||||
Expression::ListIndex(list_index) => list_index.node.validate(context),
|
Expression::ListIndex(list_index) => list_index.item.validate(context),
|
||||||
Expression::Logic(logic) => logic.node.validate(context),
|
Expression::Logic(logic) => logic.item.validate(context),
|
||||||
Expression::Math(math) => math.node.validate(context),
|
Expression::Math(math) => math.item.validate(context),
|
||||||
Expression::Value(value_node) => value_node.node.validate(context),
|
Expression::Value(value_node) => value_node.item.validate(context),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
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> {
|
fn run(self, context: &mut Context, _clear_variables: bool) -> Result<Action, RuntimeError> {
|
||||||
match self {
|
match self {
|
||||||
Expression::FunctionCall(function_call) => {
|
Expression::FunctionCall(function_call) => {
|
||||||
function_call.node.run(context, _clear_variables)
|
function_call.item.run(context, _clear_variables)
|
||||||
}
|
}
|
||||||
Expression::Identifier(identifier) => {
|
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))
|
Ok(Action::Return(value))
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::VariableNotFound {
|
ValidationError::VariableNotFound {
|
||||||
identifier: identifier.node.clone(),
|
identifier: identifier.item.clone(),
|
||||||
position: identifier.position,
|
position: identifier.position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::MapIndex(map_index) => map_index.node.run(context, _clear_variables),
|
Expression::MapIndex(map_index) => map_index.item.run(context, _clear_variables),
|
||||||
Expression::ListIndex(list_index) => list_index.node.run(context, _clear_variables),
|
Expression::ListIndex(list_index) => list_index.item.run(context, _clear_variables),
|
||||||
Expression::Logic(logic) => logic.node.run(context, _clear_variables),
|
Expression::Logic(logic) => logic.item.run(context, _clear_variables),
|
||||||
Expression::Math(math) => math.node.run(context, _clear_variables),
|
Expression::Math(math) => math.item.run(context, _clear_variables),
|
||||||
Expression::Value(value_node) => value_node.node.run(context, _clear_variables),
|
Expression::Value(value_node) => value_node.item.run(context, _clear_variables),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
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)?;
|
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 {
|
||||||
Ok(return_type.node)
|
Ok(return_type.item)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
actual: function_node_type,
|
actual: function_node_type,
|
||||||
@ -58,13 +58,13 @@ impl AbstractNode for FunctionCall {
|
|||||||
for (type_parameter, type_argument) in
|
for (type_parameter, type_argument) in
|
||||||
parameter_types.iter().zip(self.type_arguments.iter())
|
parameter_types.iter().zip(self.type_arguments.iter())
|
||||||
{
|
{
|
||||||
if let Type::Argument(_) = type_parameter.node {
|
if let Type::Argument(_) = type_parameter.item {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_parameter
|
type_parameter
|
||||||
.node
|
.item
|
||||||
.check(&type_argument.node)
|
.check(&type_argument.item)
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: type_argument.position,
|
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()) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let actual = expression.expected_type(context)?;
|
let actual = expression.expected_type(context)?;
|
||||||
|
|
||||||
type_parameter.node.check(&actual).map_err(|conflict| {
|
type_parameter.item.check(&actual).map_err(|conflict| {
|
||||||
ValidationError::TypeCheck {
|
ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: expression.position(),
|
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 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 {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -121,7 +121,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
for expression in self.arguments {
|
for expression in self.arguments {
|
||||||
let expression_position = expression.position();
|
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 {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -138,8 +138,8 @@ impl AbstractNode for FunctionCall {
|
|||||||
for (type_parameter, type_argument) in function
|
for (type_parameter, type_argument) in function
|
||||||
.type_parameters()
|
.type_parameters()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r#type| r#type.node.clone())
|
.map(|r#type| r#type.item.clone())
|
||||||
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
|
.zip(self.type_arguments.into_iter().map(|r#type| r#type.item))
|
||||||
{
|
{
|
||||||
if let Type::Argument(identifier) = type_parameter {
|
if let Type::Argument(identifier) = type_parameter {
|
||||||
function_context.set_type(identifier, type_argument)?;
|
function_context.set_type(identifier, type_argument)?;
|
||||||
@ -147,6 +147,8 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function_context.inherit_data_from(&context)?;
|
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 {
|
impl AbstractNode for IfElse {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
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> {
|
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
self.if_expression.validate(context)?;
|
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)?;
|
let if_expression_type = self.if_expression.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Boolean = if_expression_type {
|
if let Type::Boolean = if_expression_type {
|
||||||
if let Some(else_block) = &self.else_block {
|
if let Some(else_block) = &self.else_block {
|
||||||
else_block.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
|
expected_type
|
||||||
.check(&actual)
|
.check(&actual)
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
conflict,
|
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(),
|
expected_position: self.if_expression.position(),
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -67,15 +67,15 @@ impl AbstractNode for IfElse {
|
|||||||
let expression_type = expression.expected_type(context)?;
|
let expression_type = expression.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Boolean = expression_type {
|
if let Type::Boolean = expression_type {
|
||||||
block.node.validate(context)?;
|
block.item.validate(context)?;
|
||||||
|
|
||||||
let actual = block.node.expected_type(context)?;
|
let actual = block.item.expected_type(context)?;
|
||||||
|
|
||||||
expected_type
|
expected_type
|
||||||
.check(&actual)
|
.check(&actual)
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
conflict,
|
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(),
|
expected_position: self.if_expression.position(),
|
||||||
})?;
|
})?;
|
||||||
} else {
|
} else {
|
||||||
@ -102,7 +102,7 @@ impl AbstractNode for IfElse {
|
|||||||
|
|
||||||
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
|
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
|
||||||
if *if_boolean {
|
if *if_boolean {
|
||||||
self.if_block.node.run(context, _clear_variables)
|
self.if_block.item.run(context, _clear_variables)
|
||||||
} else {
|
} else {
|
||||||
for (expression, block) in self.else_ifs {
|
for (expression, block) in self.else_ifs {
|
||||||
let expression_position = expression.position();
|
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 let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
|
||||||
if *else_if_boolean {
|
if *else_if_boolean {
|
||||||
return block.node.run(context, _clear_variables);
|
return block.item.run(context, _clear_variables);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
@ -130,7 +130,7 @@ impl AbstractNode for IfElse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(else_statement) = self.else_block {
|
if let Some(else_statement) = self.else_block {
|
||||||
else_statement.node.run(context, _clear_variables)
|
else_statement.item.run(context, _clear_variables)
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,11 @@ impl AbstractNode for ListIndex {
|
|||||||
|
|
||||||
if let (
|
if let (
|
||||||
Expression::Value(WithPosition {
|
Expression::Value(WithPosition {
|
||||||
node: ValueNode::List(expression_list),
|
item: ValueNode::List(expression_list),
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
Expression::Value(WithPosition {
|
Expression::Value(WithPosition {
|
||||||
node: ValueNode::Integer(index),
|
item: ValueNode::Integer(index),
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
) = (&self.left, &self.right)
|
) = (&self.left, &self.right)
|
||||||
@ -98,7 +98,7 @@ impl AbstractNode for ListIndex {
|
|||||||
let found_item = list.get(index as usize);
|
let found_item = list.get(index as usize);
|
||||||
|
|
||||||
if let Some(item) = found_item {
|
if let Some(item) = found_item {
|
||||||
Ok(Action::Return(item.node.clone()))
|
Ok(Action::Return(item.item.clone()))
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,21 @@ impl AbstractNode for MapIndex {
|
|||||||
(&self.collection, &self.index)
|
(&self.collection, &self.index)
|
||||||
{
|
{
|
||||||
let collection =
|
let collection =
|
||||||
if let Some(collection) = context.use_value(&collection_identifier.node)? {
|
if let Some(collection) = context.use_value(&collection_identifier.item)? {
|
||||||
collection
|
collection
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::VariableNotFound {
|
return Err(ValidationError::VariableNotFound {
|
||||||
identifier: collection_identifier.node.clone(),
|
identifier: collection_identifier.item.clone(),
|
||||||
position: collection_identifier.position,
|
position: collection_identifier.position,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
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)?)
|
Ok(value.r#type(context)?)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::PropertyNotFound {
|
Err(ValidationError::PropertyNotFound {
|
||||||
identifier: index.node.clone(),
|
identifier: index.item.clone(),
|
||||||
position: index.position,
|
position: index.position,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ impl AbstractNode for MapIndex {
|
|||||||
|
|
||||||
if let (
|
if let (
|
||||||
Expression::Value(WithPosition {
|
Expression::Value(WithPosition {
|
||||||
node: ValueNode::Map(properties),
|
item: ValueNode::Map(properties),
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
index,
|
index,
|
||||||
@ -61,9 +61,9 @@ impl AbstractNode for MapIndex {
|
|||||||
properties
|
properties
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(property, type_option, expression)| {
|
.find_map(|(property, type_option, expression)| {
|
||||||
if property == &index.node {
|
if property == &index.item {
|
||||||
if let Some(r#type) = type_option {
|
if let Some(r#type) = type_option {
|
||||||
Some(r#type.node.expected_type(context))
|
Some(r#type.item.expected_type(context))
|
||||||
} else {
|
} else {
|
||||||
Some(expression.expected_type(context))
|
Some(expression.expected_type(context))
|
||||||
}
|
}
|
||||||
@ -80,14 +80,14 @@ impl AbstractNode for MapIndex {
|
|||||||
|
|
||||||
if let (
|
if let (
|
||||||
Expression::Value(WithPosition {
|
Expression::Value(WithPosition {
|
||||||
node: ValueNode::Structure { fields, .. },
|
item: ValueNode::Structure { fields, .. },
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
index,
|
index,
|
||||||
) = (&self.collection, &self.index)
|
) = (&self.collection, &self.index)
|
||||||
{
|
{
|
||||||
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
|
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))
|
Some(expression.expected_type(context))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -122,7 +122,7 @@ impl AbstractNode for MapIndex {
|
|||||||
|
|
||||||
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
||||||
let action = map
|
let action = map
|
||||||
.get(&self.index.node)
|
.get(&self.index.item)
|
||||||
.map(|value| Action::Return(value.clone()))
|
.map(|value| Action::Return(value.clone()))
|
||||||
.unwrap_or(Action::None);
|
.unwrap_or(Action::None);
|
||||||
|
|
||||||
|
@ -48,14 +48,14 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct WithPosition<T> {
|
pub struct WithPosition<T> {
|
||||||
pub node: T,
|
pub item: T,
|
||||||
pub position: SourcePosition,
|
pub position: SourcePosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WithPos: Sized {
|
pub trait WithPos: Sized {
|
||||||
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
|
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
|
||||||
WithPosition {
|
WithPosition {
|
||||||
node: self,
|
item: self,
|
||||||
position: span.into(),
|
position: span.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,48 +40,48 @@ impl Statement {
|
|||||||
impl AbstractNode for Statement {
|
impl AbstractNode for Statement {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.node.expected_type(_context),
|
Statement::Assignment(assignment) => assignment.item.expected_type(_context),
|
||||||
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
|
Statement::AsyncBlock(async_block) => async_block.item.expected_type(_context),
|
||||||
Statement::Block(block) => block.node.expected_type(_context),
|
Statement::Block(block) => block.item.expected_type(_context),
|
||||||
Statement::Break(_) => Ok(Type::None),
|
Statement::Break(_) => Ok(Type::None),
|
||||||
Statement::Expression(expression) => expression.expected_type(_context),
|
Statement::Expression(expression) => expression.expected_type(_context),
|
||||||
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
|
Statement::IfElse(if_else) => if_else.item.expected_type(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.node.expected_type(_context),
|
Statement::Loop(r#loop) => r#loop.item.expected_type(_context),
|
||||||
Statement::While(r#while) => r#while.node.expected_type(_context),
|
Statement::While(r#while) => r#while.item.expected_type(_context),
|
||||||
Statement::StructureDefinition(structure_definition) => {
|
Statement::StructureDefinition(structure_definition) => {
|
||||||
structure_definition.node.expected_type(_context)
|
structure_definition.item.expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.node.validate(_context),
|
Statement::Assignment(assignment) => assignment.item.validate(_context),
|
||||||
Statement::AsyncBlock(async_block) => async_block.node.validate(_context),
|
Statement::AsyncBlock(async_block) => async_block.item.validate(_context),
|
||||||
Statement::Block(block) => block.node.validate(_context),
|
Statement::Block(block) => block.item.validate(_context),
|
||||||
Statement::Break(_) => Ok(()),
|
Statement::Break(_) => Ok(()),
|
||||||
Statement::Expression(expression) => expression.validate(_context),
|
Statement::Expression(expression) => expression.validate(_context),
|
||||||
Statement::IfElse(if_else) => if_else.node.validate(_context),
|
Statement::IfElse(if_else) => if_else.item.validate(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.node.validate(_context),
|
Statement::Loop(r#loop) => r#loop.item.validate(_context),
|
||||||
Statement::While(r#while) => r#while.node.validate(_context),
|
Statement::While(r#while) => r#while.item.validate(_context),
|
||||||
Statement::StructureDefinition(structure_definition) => {
|
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> {
|
fn run(self, context: &mut Context, clear_variables: bool) -> Result<Action, RuntimeError> {
|
||||||
let result = match self {
|
let result = match self {
|
||||||
Statement::Assignment(assignment) => assignment.node.run(context, clear_variables),
|
Statement::Assignment(assignment) => assignment.item.run(context, clear_variables),
|
||||||
Statement::AsyncBlock(async_block) => async_block.node.run(context, clear_variables),
|
Statement::AsyncBlock(async_block) => async_block.item.run(context, clear_variables),
|
||||||
Statement::Block(block) => block.node.run(context, clear_variables),
|
Statement::Block(block) => block.item.run(context, clear_variables),
|
||||||
Statement::Break(_) => Ok(Action::Break),
|
Statement::Break(_) => Ok(Action::Break),
|
||||||
Statement::Expression(expression) => expression.run(context, clear_variables),
|
Statement::Expression(expression) => expression.run(context, clear_variables),
|
||||||
Statement::IfElse(if_else) => if_else.node.run(context, clear_variables),
|
Statement::IfElse(if_else) => if_else.item.run(context, clear_variables),
|
||||||
Statement::Loop(r#loop) => r#loop.node.run(context, clear_variables),
|
Statement::Loop(r#loop) => r#loop.item.run(context, clear_variables),
|
||||||
Statement::While(r#while) => r#while.node.run(context, clear_variables),
|
Statement::While(r#while) => r#while.item.run(context, clear_variables),
|
||||||
Statement::StructureDefinition(structure_definition) => {
|
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)) => {
|
(Type::ListOf(left), Type::ListOf(right)) => {
|
||||||
if let Ok(()) = left.node.check(&right.node) {
|
if let Ok(()) = left.item.check(&right.item) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
|
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
|
||||||
for r#type in list_exact {
|
for r#type in list_exact {
|
||||||
list_of.node.check(&r#type.node)?;
|
list_of.item.check(&r#type.item)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
|
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
|
||||||
for r#type in list_exact {
|
for r#type in list_exact {
|
||||||
r#type.node.check(&list_of.node)?;
|
r#type.item.check(&list_of.item)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
(Type::ListExact(left), Type::ListExact(right)) => {
|
(Type::ListExact(left), Type::ListExact(right)) => {
|
||||||
for (left, right) in left.iter().zip(right.iter()) {
|
for (left, right) in left.iter().zip(right.iter()) {
|
||||||
left.node.check(&right.node)?;
|
left.item.check(&right.item)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -96,7 +96,7 @@ impl Type {
|
|||||||
for ((left_field_name, left_type), (right_field_name, right_type)) in
|
for ((left_field_name, left_type), (right_field_name, right_type)) in
|
||||||
left_fields.iter().zip(right_fields.iter())
|
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 {
|
return Err(TypeConflict {
|
||||||
actual: other.clone(),
|
actual: other.clone(),
|
||||||
@ -118,11 +118,11 @@ impl Type {
|
|||||||
return_type: right_return,
|
return_type: right_return,
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if left_return.node == right_return.node {
|
if left_return.item == right_return.item {
|
||||||
for (left_parameter, right_parameter) in
|
for (left_parameter, right_parameter) in
|
||||||
left_parameters.iter().zip(right_parameters.iter())
|
left_parameters.iter().zip(right_parameters.iter())
|
||||||
{
|
{
|
||||||
if left_parameter.node != right_parameter.node {
|
if left_parameter.item != right_parameter.item {
|
||||||
return Err(TypeConflict {
|
return Err(TypeConflict {
|
||||||
actual: other.clone(),
|
actual: other.clone(),
|
||||||
expected: self.clone(),
|
expected: self.clone(),
|
||||||
@ -165,15 +165,15 @@ impl Display for Type {
|
|||||||
Type::Float => write!(f, "float"),
|
Type::Float => write!(f, "float"),
|
||||||
Type::Integer => write!(f, "int"),
|
Type::Integer => write!(f, "int"),
|
||||||
Type::List => write!(f, "list"),
|
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) => {
|
Type::ListExact(item_types) => {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
|
||||||
for (index, item_type) in item_types.into_iter().enumerate() {
|
for (index, item_type) in item_types.into_iter().enumerate() {
|
||||||
if index == item_types.len() - 1 {
|
if index == item_types.len() - 1 {
|
||||||
write!(f, "{}", item_type.node)?;
|
write!(f, "{}", item_type.item)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}, ", item_type.node)?;
|
write!(f, "{}, ", item_type.item)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,10 +190,10 @@ impl Display for Type {
|
|||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
|
|
||||||
for r#type in parameter_types {
|
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::Structure { name, .. } => write!(f, "{name}"),
|
||||||
Type::Argument(identifier) => write!(f, "{identifier}"),
|
Type::Argument(identifier) => write!(f, "{identifier}"),
|
||||||
|
@ -75,14 +75,14 @@ impl AbstractNode for ValueNode {
|
|||||||
types.push((
|
types.push((
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
WithPosition {
|
WithPosition {
|
||||||
node: r#type,
|
item: r#type,
|
||||||
position: expression.position(),
|
position: expression.position(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Structure {
|
Type::Structure {
|
||||||
name: name.node.clone(),
|
name: name.item.clone(),
|
||||||
fields: types,
|
fields: types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ impl AbstractNode for ValueNode {
|
|||||||
if let Some(expected_type) = r#type {
|
if let Some(expected_type) = r#type {
|
||||||
let actual_type = expression.expected_type(context)?;
|
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 {
|
ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: expression.position(),
|
actual_position: expression.position(),
|
||||||
@ -122,21 +122,21 @@ impl AbstractNode for ValueNode {
|
|||||||
function_context.inherit_types_from(context)?;
|
function_context.inherit_types_from(context)?;
|
||||||
|
|
||||||
for r#type in type_arguments {
|
for r#type in type_arguments {
|
||||||
if let Type::Argument(identifier) = &r#type.node {
|
if let Type::Argument(identifier) = &r#type.item {
|
||||||
function_context.set_type(identifier.clone(), r#type.node.clone())?;
|
function_context.set_type(identifier.clone(), r#type.item.clone())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (identifier, r#type) in parameters {
|
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
|
return_type
|
||||||
.node
|
.item
|
||||||
.check(&actual_return_type)
|
.check(&actual_return_type)
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
@ -152,9 +152,9 @@ impl AbstractNode for ValueNode {
|
|||||||
fields: expressions,
|
fields: expressions,
|
||||||
} = self
|
} = self
|
||||||
{
|
{
|
||||||
if !context.contains(&name.node)? {
|
if !context.contains(&name.item)? {
|
||||||
return Err(ValidationError::VariableNotFound {
|
return Err(ValidationError::VariableNotFound {
|
||||||
identifier: name.node.clone(),
|
identifier: name.item.clone(),
|
||||||
position: name.position,
|
position: name.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -162,12 +162,12 @@ impl AbstractNode for ValueNode {
|
|||||||
if let Some(Type::Structure {
|
if let Some(Type::Structure {
|
||||||
name: _,
|
name: _,
|
||||||
fields: types,
|
fields: types,
|
||||||
}) = context.get_type(&name.node)?
|
}) = context.get_type(&name.item)?
|
||||||
{
|
{
|
||||||
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
||||||
let actual_type = expression.expected_type(context)?;
|
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 {
|
ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: expression.position(),
|
actual_position: expression.position(),
|
||||||
@ -194,7 +194,7 @@ impl AbstractNode for ValueNode {
|
|||||||
let action = expression.run(_context, _clear_variables)?;
|
let action = expression.run(_context, _clear_variables)?;
|
||||||
let value = if let Action::Return(value) = action {
|
let value = if let Action::Return(value) = action {
|
||||||
WithPosition {
|
WithPosition {
|
||||||
node: value,
|
item: value,
|
||||||
position: expression_position,
|
position: expression_position,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,8 +3,6 @@ use std::{
|
|||||||
sync::{Arc, RwLock, RwLockReadGuard},
|
sync::{Arc, RwLock, RwLockReadGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::Type,
|
abstract_tree::Type,
|
||||||
error::{RwLockPoisonError, ValidationError},
|
error::{RwLockPoisonError, ValidationError},
|
||||||
@ -14,19 +12,19 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
inner: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
|
variables: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
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 {
|
pub fn with_data(data: BTreeMap<Identifier, (ValueData, UsageData)>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(RwLock::new(data)),
|
variables: Arc::new(RwLock::new(data)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,14 +32,16 @@ impl Context {
|
|||||||
&self,
|
&self,
|
||||||
) -> Result<RwLockReadGuard<BTreeMap<Identifier, (ValueData, UsageData)>>, RwLockPoisonError>
|
) -> 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> {
|
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 {
|
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()));
|
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> {
|
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()));
|
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> {
|
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> {
|
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.");
|
log::trace!("Using {identifier}'s type.");
|
||||||
|
|
||||||
let r#type = match value_data {
|
let r#type = match value_data {
|
||||||
@ -79,7 +83,8 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
|
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.");
|
log::trace!("Using {identifier}'s value.");
|
||||||
|
|
||||||
@ -92,9 +97,9 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> {
|
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> {
|
||||||
log::info!("Setting {identifier} to type {}.", r#type);
|
log::debug!("Setting {identifier} to type {}.", r#type);
|
||||||
|
|
||||||
self.inner
|
self.variables
|
||||||
.write()?
|
.write()?
|
||||||
.insert(identifier, (ValueData::Type(r#type), UsageData::new()));
|
.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> {
|
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 mut variables = self.variables.write()?;
|
||||||
let old_usage_data = inner.remove(&identifier).map(|(_, usage_data)| usage_data);
|
let old_usage_data = variables
|
||||||
|
.remove(&identifier)
|
||||||
|
.map(|(_, usage_data)| usage_data);
|
||||||
|
|
||||||
if let Some(usage_data) = old_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 {
|
} else {
|
||||||
inner.insert(identifier, (ValueData::Value(value), UsageData::new()));
|
variables.insert(identifier, (ValueData::Value(value), UsageData::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -118,7 +125,7 @@ impl Context {
|
|||||||
|
|
||||||
pub fn remove(&self, identifier: &Identifier) -> Result<Option<ValueData>, RwLockPoisonError> {
|
pub fn remove(&self, identifier: &Identifier) -> Result<Option<ValueData>, RwLockPoisonError> {
|
||||||
let removed = self
|
let removed = self
|
||||||
.inner
|
.variables
|
||||||
.write()?
|
.write()?
|
||||||
.remove(identifier)
|
.remove(identifier)
|
||||||
.map(|(value_data, _)| value_data);
|
.map(|(value_data, _)| value_data);
|
||||||
@ -127,31 +134,25 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
|
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
|
||||||
let clean_variables = self
|
self.variables
|
||||||
.inner
|
|
||||||
.write()?
|
.write()?
|
||||||
.clone()
|
.retain(|identifier, (_, usage_data)| {
|
||||||
.into_par_iter()
|
|
||||||
.filter(|(identifier, (_, usage_data))| {
|
|
||||||
if usage_data.actual < usage_data.expected {
|
if usage_data.actual < usage_data.expected {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
log::debug!("Removing variable {identifier}.");
|
log::trace!("Removing variable {identifier}.");
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.collect();
|
|
||||||
|
|
||||||
self.inner = Arc::new(RwLock::new(clean_variables));
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
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}.");
|
log::trace!("Adding expected use for variable {identifier}.");
|
||||||
|
|
||||||
usage_data.expected += 1;
|
usage_data.expected += 1;
|
||||||
|
@ -1520,7 +1520,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Statement::Expression(Expression::Value(WithPosition {
|
if let Statement::Expression(Expression::Value(WithPosition {
|
||||||
node: ValueNode::Float(float),
|
item: ValueNode::Float(float),
|
||||||
..
|
..
|
||||||
})) = &parse(&lex("NaN").unwrap()).unwrap()[0]
|
})) = &parse(&lex("NaN").unwrap()).unwrap()[0]
|
||||||
{
|
{
|
||||||
|
@ -107,9 +107,9 @@ impl Display for Value {
|
|||||||
|
|
||||||
for (index, value) in list.into_iter().enumerate() {
|
for (index, value) in list.into_iter().enumerate() {
|
||||||
if index == list.len() - 1 {
|
if index == list.len() - 1 {
|
||||||
write!(f, "{}", value.node)?;
|
write!(f, "{}", value.item)?;
|
||||||
} else {
|
} 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() {
|
for (index, r#type) in type_arguments.into_iter().enumerate() {
|
||||||
if index == type_arguments.len() - 1 {
|
if index == type_arguments.len() - 1 {
|
||||||
write!(f, "{}", r#type.node)?;
|
write!(f, "{}", r#type.item)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{} ", r#type.node)?;
|
write!(f, "{} ", r#type.item)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,13 +149,13 @@ impl Display for Value {
|
|||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
|
|
||||||
for (identifier, r#type) in parameters {
|
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 } => {
|
ValueInner::Structure { name, fields } => {
|
||||||
write!(f, "{}\n{{", name.node)?;
|
write!(f, "{}\n{{", name.item)?;
|
||||||
|
|
||||||
for (key, value) in fields {
|
for (key, value) in fields {
|
||||||
writeln!(f, "{key} = {value},")?;
|
writeln!(f, "{key} = {value},")?;
|
||||||
@ -207,7 +207,7 @@ impl ValueInner {
|
|||||||
let mut types = Vec::with_capacity(values.len());
|
let mut types = Vec::with_capacity(values.len());
|
||||||
|
|
||||||
for value in values {
|
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)
|
Type::ListExact(types)
|
||||||
@ -224,11 +224,11 @@ impl ValueInner {
|
|||||||
return_type: Box::new(function.return_type.clone()),
|
return_type: Box::new(function.return_type.clone()),
|
||||||
},
|
},
|
||||||
ValueInner::Structure { name, .. } => {
|
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
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::VariableNotFound {
|
return Err(ValidationError::VariableNotFound {
|
||||||
identifier: name.node.clone(),
|
identifier: name.item.clone(),
|
||||||
position: name.position,
|
position: name.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -316,11 +316,12 @@ impl Function {
|
|||||||
self,
|
self,
|
||||||
arguments: Vec<Value>,
|
arguments: Vec<Value>,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
|
clear_variables: bool,
|
||||||
) -> Result<Action, RuntimeError> {
|
) -> Result<Action, RuntimeError> {
|
||||||
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) {
|
for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) {
|
||||||
context.set_value(identifier.clone(), value)?;
|
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