use std::{
cell::{Cell, OnceCell},
ops,
};
use hashbrown::{HashMap, HashSet};
use index_vec::IndexVec;
use indexmap::IndexSet;
use toasty_core::stmt;
use crate::engine::{SelectItems, mir};
#[derive(Debug)]
pub(super) struct HirStatement {
store: IndexVec<StmtId, StatementInfo>,
}
#[derive(Debug)]
pub(super) struct StatementInfo {
pub(super) stmt: Option<Box<stmt::Statement>>,
pub(super) deps: HashSet<StmtId>,
pub(super) args: Vec<Arg>,
pub(super) back_refs: HashMap<StmtId, BackRef>,
pub(super) load_data_statement: Cell<Option<mir::NodeId>>,
pub(super) load_data_select_items: OnceCell<SelectItems>,
pub(super) output: Cell<Option<mir::NodeId>>,
pub(super) independent: bool,
}
index_vec::define_index_type! {
pub(crate) struct StmtId = u32;
}
impl StatementInfo {
pub(super) fn new(deps: HashSet<StmtId>) -> StatementInfo {
StatementInfo {
stmt: None,
deps,
args: vec![],
back_refs: HashMap::new(),
load_data_statement: Cell::new(None),
load_data_select_items: OnceCell::new(),
output: Cell::new(None),
independent: true,
}
}
pub(super) fn stmt(&self) -> &stmt::Statement {
self.stmt.as_deref().unwrap()
}
}
#[derive(Debug, Default)]
pub(super) struct BackRef {
pub(super) exprs: IndexSet<stmt::ExprReference>,
pub(super) node_id: Cell<Option<mir::NodeId>>,
}
#[derive(Debug)]
pub(super) enum Arg {
Sub {
stmt_id: StmtId,
returning: bool,
input: Cell<Option<usize>>,
batch_load_index: Cell<Option<usize>>,
},
Ref {
target_expr_ref: stmt::ExprReference,
stmt_id: StmtId,
nesting: usize,
data_load_input: Cell<Option<usize>>,
returning_input: Cell<Option<usize>>,
batch_load_index: Cell<Option<usize>>,
},
}
impl HirStatement {
pub(super) fn new() -> HirStatement {
HirStatement {
store: IndexVec::new(),
}
}
pub(super) fn insert(&mut self, info: StatementInfo) -> StmtId {
self.store.push(info)
}
pub(super) fn new_statement_info(&mut self, deps: HashSet<StmtId>) -> StmtId {
self.insert(StatementInfo::new(deps))
}
pub(super) fn root_id(&self) -> StmtId {
StmtId::from(0)
}
pub(super) fn root(&self) -> &StatementInfo {
let root_id = self.root_id();
&self.store[root_id]
}
}
impl ops::Index<StmtId> for HirStatement {
type Output = StatementInfo;
fn index(&self, index: StmtId) -> &Self::Output {
self.store.index(index)
}
}
impl ops::IndexMut<StmtId> for HirStatement {
fn index_mut(&mut self, index: StmtId) -> &mut Self::Output {
self.store.index_mut(index)
}
}
impl ops::Index<&StmtId> for HirStatement {
type Output = StatementInfo;
fn index(&self, index: &StmtId) -> &Self::Output {
self.store.index(*index)
}
}