meta-language 1.0.0

A self-describing links-network core for lossless language representation
Documentation
use super::{BTreeSet, Declaration, ProgramScope, ProgramSourceMapping, SemanticToken};

pub(super) fn hoist_var_declarations(
    declarations: &mut [Declaration],
    tokens: &[SemanticToken],
    syntax: &[ProgramSourceMapping],
    scopes: &[ProgramScope],
) {
    let function_bodies = syntax
        .iter()
        .filter(|fact| {
            matches!(
                fact.term.as_str(),
                "function_declaration"
                    | "function_expression"
                    | "generator_function_declaration"
                    | "generator_function"
                    | "arrow_function"
                    | "method_definition"
            )
        })
        .flat_map(|function| {
            syntax.iter().filter_map(move |block| {
                (block.term == "statement_block"
                    && block.range.start >= function.range.start
                    && block.range.end == function.range.end)
                    .then_some(block.range.start + 1)
            })
        })
        .collect::<BTreeSet<_>>();

    for declaration in declarations.iter_mut().filter(|item| item.kind == "var") {
        let mut scope = tokens[declaration.token].scope;
        while let Some(parent) = scopes[scope].parent.as_ref() {
            if function_bodies.contains(&scopes[scope].range.start) {
                break;
            }
            scope = scopes
                .iter()
                .position(|candidate| &candidate.id == parent)
                .expect("parent scope exists");
        }
        declaration.scope = scope;
    }
}