deimos-lang/dmc-lib/src/semantic_analysis/mod.rs

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
}