use std::collections::{HashMap, HashSet};
use crate::ast::{SNode, TypedParam};
use super::{
module_scope_node_slices, parameter_scope, BindingId, BindingOwner, LexicalAnalysis,
MatchPatternCatalog, Scope,
};
pub fn module_match_pattern_catalog_with_visible(
program: &[SNode],
visible_type_declarations: &[SNode],
) -> MatchPatternCatalog {
let mut catalog = MatchPatternCatalog::default();
catalog.extend_declarations(visible_type_declarations);
for nodes in module_scope_node_slices(program) {
catalog.extend_declarations(nodes);
}
catalog
}
pub fn lexically_resolved_identifier_spans(
params: &[TypedParam],
body: &[SNode],
source: Option<&str>,
match_patterns: &MatchPatternCatalog,
) -> HashSet<(usize, usize)> {
analyze_callable(params, body, source, match_patterns).lexically_resolved
}
pub fn resolved_identifier_bindings_with_source(
params: &[TypedParam],
body: &[SNode],
source: Option<&str>,
match_patterns: &MatchPatternCatalog,
) -> HashMap<(usize, usize), BindingId> {
analyze_callable(params, body, source, match_patterns).resolved
}
fn analyze_callable<'source>(
params: &[TypedParam],
body: &[SNode],
source: Option<&'source str>,
match_patterns: &MatchPatternCatalog,
) -> LexicalAnalysis<'source> {
let mut analysis = LexicalAnalysis::new_with_source(match_patterns, source);
let mut visible_params = Scope::new();
for param in params {
if let Some(default) = ¶m.default_value {
analysis.walk_node(
default,
std::slice::from_ref(&visible_params),
false,
&BindingOwner::Current,
);
}
visible_params.extend(parameter_scope(
std::slice::from_ref(param),
&BindingOwner::Current,
));
}
analysis.walk_body_with_bindings(
body,
Vec::new(),
false,
BindingOwner::Current,
parameter_scope(params, &BindingOwner::Current),
);
analysis
}