1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use crate::utils::state::{ensure_list, mutate_list}; use duckscript::types::runtime::StateValue; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; static SCOPE_STACK_STATE_KEY: &str = "scope_stack"; pub(crate) fn push( variables: &mut HashMap<String, String>, state: &mut HashMap<String, StateValue>, copy: &[String], ) -> Result<(), String> { ensure_list(SCOPE_STACK_STATE_KEY, state); match mutate_list(SCOPE_STACK_STATE_KEY.to_string(), state, |list| { list.push(StateValue::Any(Rc::new(RefCell::new(variables.clone())))); Ok(None) }) { Ok(_) => { let mut new_variables = HashMap::new(); for key in copy { let value = variables.remove(key); new_variables.insert(key, value); } variables.clear(); for (key, value) in new_variables { variables.insert(key.to_string(), value.unwrap()); } Ok(()) } Err(error) => Err(error), } } pub(crate) fn pop( variables: &mut HashMap<String, String>, state: &mut HashMap<String, StateValue>, copy: &[String], ) -> Result<(), String> { ensure_list(SCOPE_STACK_STATE_KEY, state); match mutate_list( SCOPE_STACK_STATE_KEY.to_string(), state, |list| match list.pop() { Some(state_value) => match state_value { StateValue::Any(rc_value) => { let value_any = rc_value.borrow(); match value_any.downcast_ref::<HashMap<String, String>>() { Some(old_variables) => { let mut new_variables = HashMap::new(); for key in copy { let value = variables.remove(key); new_variables.insert(key, value); } variables.clear(); for (key, value) in old_variables { variables.insert(key.to_string(), value.clone()); } for (key, value) in new_variables { variables.insert(key.to_string(), value.unwrap()); } Ok(None) } None => Err("Scope stack not available, invalid type.".to_string()), } } _ => Err("Scope stack not available, invalid state value type.".to_string()), }, None => Err("Reached end of scope stack.".to_string()), }, ) { Ok(_) => Ok(()), Err(error) => Err(error), } }