use std::collections::HashMap;
use std::collections::HashSet;
use crate::ast::ParamConvention;
use crate::ir::{BindingId, IrExpr, ResolvedType};
use super::ENV_PARAM_NAME;
#[derive(Clone, Default)]
pub(super) struct CaptureCtx {
captured_bindings: HashSet<BindingId>,
capture_names: HashMap<BindingId, String>,
env_ty: Option<ResolvedType>,
}
impl CaptureCtx {
pub(super) fn module_level() -> Self {
Self::default()
}
pub(super) fn for_closure(
captures: &[(BindingId, String, ParamConvention, ResolvedType)],
env_ty: ResolvedType,
) -> Self {
Self {
captured_bindings: captures.iter().map(|(bid, _, _, _)| *bid).collect(),
capture_names: captures
.iter()
.map(|(bid, name, _, _)| (*bid, name.clone()))
.collect(),
env_ty: Some(env_ty),
}
}
pub(super) fn is_captured(&self, id: BindingId) -> bool {
self.captured_bindings.contains(&id)
}
pub(super) fn capture_name(&self, id: BindingId) -> Option<&str> {
self.capture_names.get(&id).map(String::as_str)
}
pub(super) const fn env_ty(&self) -> Option<&ResolvedType> {
self.env_ty.as_ref()
}
}
pub(super) fn env_field_access(
field: String,
ty: ResolvedType,
env_ty: Option<&ResolvedType>,
) -> IrExpr {
IrExpr::FieldAccess {
object: Box::new(IrExpr::Reference {
path: vec![ENV_PARAM_NAME.to_string()],
target: crate::ir::ReferenceTarget::Unresolved,
ty: env_ty.cloned().unwrap_or(ResolvedType::Error),
span: crate::ir::IrSpan::default(),
}),
field,
field_idx: crate::ir::FieldIdx(0),
ty,
span: crate::ir::IrSpan::default(),
}
}