use std::collections::BTreeMap;
use nanoid::nanoid;
use crate::SVal;
use super::{IntoDataRef, SDataRef, SNodeRef, Symbol, SymbolTable};
#[derive(Debug, Clone)]
pub struct SProcesses {
pub processes: BTreeMap<String, SProcess>,
}
impl Default for SProcesses {
fn default() -> Self {
Self::new()
}
}
impl SProcesses {
pub fn new() -> Self {
let mut processes = BTreeMap::new();
processes.insert("main".to_string(), SProcess::new("main"));
Self {
processes
}
}
pub fn spawn(&mut self) -> String {
let pid = nanoid!();
let process = SProcess::new(&pid);
self.processes.insert(pid.clone(), process);
pid
}
pub fn kill(&mut self, pid: &str) {
self.processes.remove(pid);
}
pub fn get(&self, pid: &str) -> Option<&SProcess> {
self.processes.get(pid)
}
pub fn get_mut(&mut self, pid: &str) -> Option<&mut SProcess> {
self.processes.get_mut(pid)
}
pub fn main(&self) -> Option<&SProcess> {
self.get("main")
}
pub fn main_mut(&mut self) -> Option<&mut SProcess> {
self.get_mut("main")
}
}
#[derive(Debug, Clone)]
pub struct SProcess {
pub pid: String,
pub self_stack: Vec<SNodeRef>,
pub stack: Vec<SVal>,
pub table: SymbolTable,
pub call_stack: Vec<SDataRef>,
pub bubble_control_flow: u8,
}
impl SProcess {
pub fn new(id: &str) -> Self {
Self {
pid: id.to_owned(),
self_stack: Default::default(),
stack: Default::default(),
table: Default::default(),
call_stack: Default::default(),
bubble_control_flow: 0,
}
}
pub fn self_ptr(&self) -> Option<SNodeRef> {
if let Some(last) = self.self_stack.last() {
return Some(last.clone());
}
None
}
pub fn new_table(&mut self) -> SymbolTable {
let current = self.table.clone();
self.table = SymbolTable::default();
return current;
}
pub fn set_table(&mut self, table: SymbolTable) {
self.table = table;
}
pub fn push_call_stack(&mut self, dref: impl IntoDataRef) {
self.call_stack.push(dref.data_ref());
}
pub fn pop_call_stack(&mut self) {
self.call_stack.pop();
}
pub fn add_variable<T>(&mut self, name: &str, value: T) where T: Into<SVal> {
let symbol = Symbol::Variable(value.into());
self.table.insert(name, symbol);
}
pub fn set_variable<T>(&mut self, name: &str, value: T) -> bool where T: Into<SVal> {
self.table.set_variable(name, &value.into())
}
pub fn drop(&mut self, name: &str) -> Option<Symbol> {
self.table.remove(name)
}
pub fn get_symbol(&mut self, name: &str) -> Option<&Symbol> {
self.table.get(name)
}
pub fn has_symbol(&mut self, name: &str) -> bool {
self.table.get(name).is_some()
}
pub fn push<T>(&mut self, value: T) where T: Into<SVal> {
let val: SVal = value.into();
if !val.is_void() { self.stack.push(val);
}
}
pub fn pop(&mut self) -> Option<SVal> {
self.stack.pop()
}
pub fn clean(&mut self) {
self.stack.clear();
self.table = Default::default();
self.self_stack.clear();
self.bubble_control_flow = 0;
}
}