pub(crate) mod errors;
pub(crate) mod stream_map_key;
use self::stream_map_key::StreamMapKey;
use crate::execution_step::value_types::StreamMap;
use crate::execution_step::ExecutionResult;
use crate::execution_step::Generation;
use crate::execution_step::ValueAggregate;
use air_parser::ast::Span;
use air_parser::AirPos;
use air_trace_handler::TraceHandler;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::fmt;
pub(crate) struct StreamMapValueDescriptor<'stream_name> {
pub value: ValueAggregate,
pub name: &'stream_name str,
pub generation: Generation,
pub position: AirPos,
}
impl<'stream_name> StreamMapValueDescriptor<'stream_name> {
pub fn new(value: ValueAggregate, name: &'stream_name str, generation: Generation, position: AirPos) -> Self {
Self {
value,
name,
generation,
position,
}
}
}
pub(crate) struct StreamMapDescriptor {
pub(super) span: Span,
pub(super) stream_map: StreamMap,
}
impl StreamMapDescriptor {
pub(super) fn global(stream_map: StreamMap) -> Self {
Self {
span: Span::new(0.into(), usize::MAX.into()),
stream_map,
}
}
pub(super) fn restricted(stream_map: StreamMap, span: Span) -> Self {
Self { span, stream_map }
}
}
impl fmt::Display for StreamMapDescriptor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, " <{}> - <{}>: {}", self.span.left, self.span.right, self.stream_map)
}
}
pub(super) fn find_closest<'d>(
descriptors: impl DoubleEndedIterator<Item = &'d StreamMapDescriptor>,
position: AirPos,
) -> Option<&'d StreamMap> {
descriptors
.rev()
.find(|d| d.span.contains_position(position))
.map(|d| &d.stream_map)
}
pub(super) fn find_closest_mut<'d>(
descriptors: impl DoubleEndedIterator<Item = &'d mut StreamMapDescriptor>,
position: AirPos,
) -> Option<&'d mut StreamMap> {
descriptors
.rev()
.find(|d| d.span.contains_position(position))
.map(|d| &mut d.stream_map)
}
#[derive(Default)]
pub(crate) struct StreamMaps {
stream_maps: HashMap<String, Vec<StreamMapDescriptor>>,
}
impl StreamMaps {
pub(crate) fn get(&self, name: &str, position: AirPos) -> Option<&StreamMap> {
self.stream_maps
.get(name)
.and_then(|descriptors| find_closest(descriptors.iter(), position))
}
pub(crate) fn get_mut(&mut self, name: &str, position: AirPos) -> Option<&mut StreamMap> {
self.stream_maps
.get_mut(name)
.and_then(|descriptors| find_closest_mut(descriptors.iter_mut(), position))
}
pub(crate) fn add_stream_map_value(
&mut self,
key: StreamMapKey,
value_descriptor: StreamMapValueDescriptor<'_>,
) -> ExecutionResult<()> {
let StreamMapValueDescriptor {
value,
name,
generation,
position,
} = value_descriptor;
match self.get_mut(name, position) {
Some(stream_map) => stream_map.insert(key, &value, generation),
None => {
let mut stream_map = StreamMap::new();
stream_map.insert(key, &value, generation)?;
let descriptor = StreamMapDescriptor::global(stream_map);
self.stream_maps.insert(name.to_string(), vec![descriptor]);
Ok(())
}
}
}
pub(crate) fn meet_scope_start(&mut self, name: impl Into<String>, span: Span) {
let name = name.into();
let new_stream_map = StreamMap::new();
let new_descriptor = StreamMapDescriptor::restricted(new_stream_map, span);
match self.stream_maps.entry(name) {
Occupied(mut entry) => {
entry.get_mut().push(new_descriptor);
}
Vacant(entry) => {
entry.insert(vec![new_descriptor]);
}
}
}
pub(crate) fn meet_scope_end(&mut self, name: String, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
let stream_map_descriptors = self.stream_maps.get_mut(&name).unwrap();
let mut last_descriptor = stream_map_descriptors.pop().unwrap();
if stream_map_descriptors.is_empty() {
self.stream_maps.remove(&name);
}
last_descriptor.stream_map.compactify(trace_ctx)
}
pub(crate) fn compactify(&mut self, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
for (_, descriptors) in self.stream_maps.iter_mut() {
for descriptor in descriptors.iter_mut() {
descriptor.stream_map.compactify(trace_ctx)?;
}
}
Ok(())
}
}
impl fmt::Display for StreamMaps {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (name, descriptors) in self.stream_maps.iter() {
if let Some(last_descriptor) = descriptors.last() {
writeln!(f, "{name} => {last_descriptor}")?;
}
}
Ok(())
}
}