use std::collections::HashMap;
use crate::error::{Result, RuntimeError};
use crate::format::{Literal, Story};
use super::ExecutionState;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LoopControl {
Break,
Continue,
}
#[derive(Debug, Clone)]
pub struct RuntimeContext {
stories: Vec<Story>,
stack: Vec<ExecutionState>,
archive_variables: Literal,
global_variables: Literal,
loop_control: Option<LoopControl>,
}
impl Default for RuntimeContext {
fn default() -> Self {
Self {
stories: Vec::new(),
stack: Vec::new(),
archive_variables: Literal::Object(Default::default()),
global_variables: Literal::Object(Default::default()),
loop_control: None,
}
}
}
impl RuntimeContext {
pub fn new() -> Self {
Self::default()
}
pub fn stories(&self) -> &Vec<Story> {
&self.stories
}
pub fn stories_mut(&mut self) -> &mut Vec<Story> {
&mut self.stories
}
pub fn stack(&self) -> &Vec<ExecutionState> {
&self.stack
}
pub fn stack_mut(&mut self) -> &mut Vec<ExecutionState> {
&mut self.stack
}
pub fn archive_variables(&self) -> &Literal {
&self.archive_variables
}
pub fn archive_variables_mut(&mut self) -> &mut Literal {
&mut self.archive_variables
}
pub fn global_variables(&self) -> &Literal {
&self.global_variables
}
pub fn global_variables_mut(&mut self) -> &mut Literal {
&mut self.global_variables
}
pub fn current_paragraph_locals(&self) -> Option<&HashMap<String, Literal>> {
self.stack.iter().rev().find_map(|state| state.locals.as_ref())
}
pub fn current_paragraph_locals_mut(&mut self) -> Option<&mut HashMap<String, Literal>> {
self.stack
.iter_mut()
.rev()
.find_map(|state| state.locals.as_mut())
}
pub fn get_local(&self, name: &str) -> Option<&Literal> {
self.current_paragraph_locals()
.and_then(|locals| locals.get(name))
}
pub fn set_local(&mut self, name: String, value: Literal) -> Result<()> {
let locals = self
.current_paragraph_locals_mut()
.ok_or(RuntimeError::ParagraphScopeUnavailable)?;
locals.insert(name, value);
Ok(())
}
pub fn set_locals(&mut self, variables: HashMap<String, Literal>) -> Result<()> {
let locals = self
.current_paragraph_locals_mut()
.ok_or(RuntimeError::ParagraphScopeUnavailable)?;
locals.extend(variables);
Ok(())
}
pub fn set_loop_control(&mut self, control: LoopControl) {
self.loop_control = Some(control);
}
pub fn take_loop_control(&mut self) -> Option<LoopControl> {
self.loop_control.take()
}
}