use std::{
cell::{Cell, OnceCell},
ops,
};
use hashbrown::HashMap;
use index_vec::IndexVec;
use indexmap::{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) has_pagination_cursor: bool,
pub(super) deps: IndexMap<StmtId, DepKind>,
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,
pub(super) planning: Cell<bool>,
}
index_vec::define_index_type! {
pub(crate) struct StmtId = u32;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum DepKind {
Statement,
Effect,
}
impl StatementInfo {
pub(super) fn new(deps: IndexMap<StmtId, DepKind>) -> StatementInfo {
StatementInfo {
stmt: None,
has_pagination_cursor: false,
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,
planning: Cell::new(false),
}
}
pub(super) fn stmt(&self) -> &stmt::Statement {
self.stmt.as_deref().unwrap()
}
pub(super) fn add_dep(&mut self, target: StmtId, kind: DepKind) {
let entry = self.deps.entry(target).or_insert(kind);
if kind == DepKind::Statement {
*entry = DepKind::Statement;
}
}
}
#[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: IndexMap<StmtId, DepKind>) -> 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]
}
pub(super) fn statements(&self) -> impl Iterator<Item = &StatementInfo> {
self.store.iter()
}
}
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)
}
}