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, nodes_to_scopes: HashMap, symbols: Vec, nodes_to_symbols: HashMap, type_infos: Vec, symbols_to_type_infos: HashMap, nodes_to_type_infos: HashMap, } 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 { &mut self.scopes } pub fn symbols(&self) -> &[Symbol] { &self.symbols } pub fn nodes_to_symbols(&self) -> &HashMap { &self.nodes_to_symbols } pub fn type_infos(&self) -> &[TypeInfo] { &self.type_infos } pub fn symbols_to_type_infos(&self) -> &HashMap { &self.symbols_to_type_infos } pub fn nodes_to_type_infos(&self) -> &HashMap { &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 }