use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
value::ValueInner,
};
use super::{AbstractNode, Evaluation, Expression, SourcePosition, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MapIndex {
collection: Expression,
index: Expression,
}
impl MapIndex {
pub fn new(left: Expression, right: Expression) -> Self {
Self {
collection: left,
index: right,
}
}
}
impl AbstractNode for MapIndex {
fn define_and_validate(
&self,
context: &Context,
_manage_memory: bool,
scope: SourcePosition,
) -> Result<(), ValidationError> {
self.collection
.define_and_validate(context, _manage_memory, scope)?;
let collection_type = if let Some(r#type) = self.collection.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedValueStatement(
self.collection.position(),
));
};
if let (Type::Map(fields), Expression::Identifier(identifier)) =
(collection_type, &self.index)
{
if !fields.contains_key(&identifier.node) {
return Err(ValidationError::FieldNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
});
}
}
if let Expression::Identifier(_) = &self.index {
Ok(())
} else {
self.index
.define_and_validate(context, _manage_memory, scope)
}
}
fn evaluate(
self,
context: &Context,
_manage_memory: bool,
scope: SourcePosition,
) -> Result