use super::*;
impl<'ast, 'name> Parser<'_, 'ast, 'name, '_>
where
'name: 'ast,
{
pub(in crate::parser) fn push_local_scope(&mut self) {
self.locals.scope_offsets.push(self.locals.stack.len());
}
pub(in crate::parser) fn pop_local_scope(&mut self) {
let Some(offset) = self.locals.scope_offsets.pop() else {
unreachable!("parser local scope is balanced");
};
debug_assert!(offset <= self.locals.stack.len());
self.restore_locals(offset);
}
pub(in crate::parser) fn declare_local(
&mut self,
name: AstName<'ast>,
location: Location,
annotation: Option<Type<'ast>>,
is_const: bool,
is_exported: bool,
) -> &'ast Local<'ast> {
let shadow_slot = {
let (slot, _) = self.locals.map.try_insert(name, None);
slot as *mut Option<&'ast Local<'ast>>
};
let shadow = unsafe { *shadow_slot };
let local = self.arena.alloc_local(Local::new(LocalInit {
name,
location,
shadow,
function_depth: self.contexts.functions.len(),
loop_depth: self.current_function().loop_depth,
annotation,
is_const,
is_exported,
}));
unsafe { *shadow_slot = Some(local) };
self.locals.stack.push(local);
local
}
#[inline(always)]
pub(in crate::parser) fn visible_local(
&self,
name: AstName<'ast>,
) -> Option<&'ast Local<'ast>> {
self.locals.map.get(&name).copied().flatten()
}
pub(in crate::parser) fn restore_locals(&mut self, offset: usize) {
let stack_len = self.locals.stack.len();
for index in (offset..stack_len).rev() {
let local = self.locals.stack[index];
self.locals.map.insert(local.name, local.shadow);
}
self.locals.stack.truncate(offset);
}
#[inline(always)]
pub(in crate::parser) fn local_is_type_function_capture(&self, local: &Local<'_>) -> bool {
let Some(depth) = self.locals.type_function_local_depth else {
return false;
};
local.function_depth < depth
}
}