179 lines
5.0 KiB
Rust
179 lines
5.0 KiB
Rust
use crate::ast::NodeId;
|
|
use crate::ast::compilation_unit::CompilationUnit;
|
|
use crate::ast::statement::Statement;
|
|
use crate::diagnostic::Diagnostics;
|
|
use crate::semantic_analysis::collect_scopes::{
|
|
collect_scopes_in_compilation_unit, collect_scopes_in_statement,
|
|
};
|
|
use crate::semantic_analysis::collect_symbols::{
|
|
SymbolCollectionResult, collect_symbols_in_compilation_unit,
|
|
};
|
|
use crate::semantic_analysis::collect_types::collect_types;
|
|
use crate::semantic_analysis::resolve_names::{
|
|
NameResolutionResult, resolve_names_in_compilation_unit, resolve_names_in_statement,
|
|
};
|
|
use crate::semantic_analysis::resolve_types::{
|
|
ResolveTypesResult, resolve_types_in_compilation_unit, resolve_types_in_statement,
|
|
};
|
|
use crate::semantic_analysis::scope::{Scope, ScopeId};
|
|
use crate::semantic_analysis::symbol::{Symbol, SymbolId};
|
|
use crate::semantic_analysis::type_info::{TypeInfo, TypeInfoId};
|
|
use std::collections::HashMap;
|
|
|
|
mod collect_scopes;
|
|
mod collect_symbols;
|
|
mod collect_types;
|
|
mod diagnostic_helpers;
|
|
mod resolve_names;
|
|
mod resolve_types;
|
|
pub mod scope;
|
|
pub mod symbol;
|
|
pub mod type_info;
|
|
|
|
pub struct AnalysisContext {
|
|
root_scope_id: ScopeId,
|
|
scopes: Vec<Scope>,
|
|
nodes_to_scopes: HashMap<NodeId, ScopeId>,
|
|
symbols: Vec<Symbol>,
|
|
nodes_to_symbols: HashMap<NodeId, SymbolId>,
|
|
type_infos: Vec<TypeInfo>,
|
|
symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>,
|
|
nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
|
|
}
|
|
|
|
impl AnalysisContext {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
root_scope_id: 0, // pushed in vec! below
|
|
scopes: vec![Scope::new(None)],
|
|
nodes_to_scopes: HashMap::new(),
|
|
symbols: Vec::new(),
|
|
nodes_to_symbols: HashMap::new(),
|
|
type_infos: Vec::new(),
|
|
symbols_to_type_infos: HashMap::new(),
|
|
nodes_to_type_infos: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn root_scope_id(&self) -> ScopeId {
|
|
self.root_scope_id
|
|
}
|
|
|
|
pub fn scopes(&self) -> &[Scope] {
|
|
&self.scopes
|
|
}
|
|
|
|
pub fn scopes_mut(&mut self) -> &mut Vec<Scope> {
|
|
&mut self.scopes
|
|
}
|
|
|
|
pub fn symbols(&self) -> &[Symbol] {
|
|
&self.symbols
|
|
}
|
|
|
|
pub fn nodes_to_symbols(&self) -> &HashMap<NodeId, SymbolId> {
|
|
&self.nodes_to_symbols
|
|
}
|
|
|
|
pub fn type_infos(&self) -> &[TypeInfo] {
|
|
&self.type_infos
|
|
}
|
|
|
|
pub fn symbols_to_type_infos(&self) -> &HashMap<SymbolId, TypeInfoId> {
|
|
&self.symbols_to_type_infos
|
|
}
|
|
|
|
pub fn nodes_to_type_infos(&self) -> &HashMap<NodeId, TypeInfoId> {
|
|
&self.nodes_to_type_infos
|
|
}
|
|
}
|
|
|
|
pub fn analyze_compilation_unit(
|
|
compilation_unit: &CompilationUnit,
|
|
ctx: &mut AnalysisContext,
|
|
) -> Diagnostics {
|
|
let mut diagnostics = Diagnostics::new();
|
|
|
|
collect_scopes_in_compilation_unit(
|
|
compilation_unit,
|
|
&mut ctx.scopes,
|
|
&mut ctx.nodes_to_scopes,
|
|
ctx.root_scope_id,
|
|
);
|
|
|
|
let SymbolCollectionResult(mut collect_symbols_diagnostics) =
|
|
collect_symbols_in_compilation_unit(
|
|
compilation_unit,
|
|
&mut ctx.scopes,
|
|
&ctx.nodes_to_scopes,
|
|
&mut ctx.symbols,
|
|
);
|
|
diagnostics.append(&mut collect_symbols_diagnostics);
|
|
|
|
let NameResolutionResult(mut resolve_names_diagnostics) = resolve_names_in_compilation_unit(
|
|
compilation_unit,
|
|
&mut ctx.scopes,
|
|
&mut ctx.symbols,
|
|
&mut ctx.nodes_to_scopes,
|
|
&mut ctx.nodes_to_symbols,
|
|
);
|
|
diagnostics.append(&mut resolve_names_diagnostics);
|
|
|
|
collect_types(
|
|
compilation_unit,
|
|
&ctx.nodes_to_symbols,
|
|
&mut ctx.type_infos,
|
|
&mut ctx.symbols_to_type_infos,
|
|
);
|
|
|
|
let ResolveTypesResult(mut resolve_types_diagnostics) = resolve_types_in_compilation_unit(
|
|
compilation_unit,
|
|
&ctx.nodes_to_symbols,
|
|
&mut ctx.type_infos,
|
|
&mut ctx.symbols_to_type_infos,
|
|
&mut ctx.nodes_to_type_infos,
|
|
);
|
|
diagnostics.append(&mut resolve_types_diagnostics);
|
|
|
|
diagnostics
|
|
}
|
|
|
|
pub fn analyze_statement(
|
|
statement: &Statement,
|
|
ctx: &mut AnalysisContext,
|
|
function_scope_id: ScopeId,
|
|
) -> Diagnostics {
|
|
let mut diagnostics = Diagnostics::new();
|
|
|
|
collect_scopes_in_statement(
|
|
statement,
|
|
&mut ctx.scopes,
|
|
&mut ctx.nodes_to_scopes,
|
|
function_scope_id,
|
|
);
|
|
|
|
// collect symbols for a statement is currently a no-op, so not needed here
|
|
|
|
let NameResolutionResult(mut resolve_names_diagnostics) = resolve_names_in_statement(
|
|
statement,
|
|
&mut ctx.scopes,
|
|
&mut ctx.symbols,
|
|
&mut ctx.nodes_to_scopes,
|
|
&mut ctx.nodes_to_symbols,
|
|
);
|
|
diagnostics.append(&mut resolve_names_diagnostics);
|
|
|
|
// collect types for a statement is currently a no-op, so not needed here
|
|
|
|
let ResolveTypesResult(mut resolve_types_diagnostics) = resolve_types_in_statement(
|
|
statement,
|
|
&ctx.nodes_to_symbols,
|
|
&mut ctx.type_infos,
|
|
&mut ctx.symbols_to_type_infos,
|
|
&mut ctx.nodes_to_type_infos,
|
|
);
|
|
diagnostics.append(&mut resolve_types_diagnostics);
|
|
|
|
diagnostics
|
|
}
|