use crate::external_map::ExternalMap;
use crate::ir::{TypeDeclaration, TypeKind};
use crate::parse::scope::{PendingImport, ScopeArena, ScopeId};
use crate::util::diagnostics::DiagnosticCollector;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TypeId(u32);
impl TypeId {
pub fn index(self) -> usize {
self.0 as usize
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ModuleId(u32);
#[derive(Clone, Debug)]
pub struct ParsedModule {
pub specifier: String,
pub scope: ScopeId,
pub types: Vec<TypeId>,
}
#[derive(Clone, Debug)]
pub struct GlobalContext {
pub scopes: ScopeArena,
pub diagnostics: DiagnosticCollector,
pub external_map: ExternalMap,
pub pending_imports: Vec<PendingImport>,
types: Vec<TypeDeclaration>,
modules: Vec<ParsedModule>,
module_index: std::collections::HashMap<String, ModuleId>,
}
impl GlobalContext {
pub fn new() -> Self {
Self {
scopes: ScopeArena::new(),
diagnostics: DiagnosticCollector::new(),
external_map: ExternalMap::new(),
pending_imports: Vec::new(),
types: Vec::new(),
modules: Vec::new(),
module_index: std::collections::HashMap::new(),
}
}
pub fn warn(&mut self, message: impl Into<String>) {
self.diagnostics.warn(message);
}
pub fn info(&mut self, message: impl Into<String>) {
self.diagnostics.info(message);
}
pub fn create_root_scope(&mut self) -> ScopeId {
self.scopes.create_root()
}
pub fn create_child_scope(&mut self, parent: ScopeId) -> ScopeId {
self.scopes.create_child(parent)
}
pub fn register_module(&mut self, specifier: String, scope: ScopeId) -> ModuleId {
let id = ModuleId(self.modules.len() as u32);
self.module_index.insert(specifier.clone(), id);
self.modules.push(ParsedModule {
specifier,
scope,
types: Vec::new(),
});
id
}
pub fn find_module(&self, specifier: &str) -> Option<ModuleId> {
self.module_index.get(specifier).copied()
}
pub fn get_module(&self, id: ModuleId) -> &ParsedModule {
&self.modules[id.0 as usize]
}
pub fn get_module_mut(&mut self, id: ModuleId) -> &mut ParsedModule {
&mut self.modules[id.0 as usize]
}
pub fn insert_type(&mut self, decl: TypeDeclaration) -> TypeId {
let id = TypeId(self.types.len() as u32);
self.types.push(decl);
id
}
pub fn get_type(&self, id: TypeId) -> &TypeDeclaration {
&self.types[id.index()]
}
pub fn type_arena(&self) -> &[TypeDeclaration] {
&self.types
}
pub fn resolve_path(&self, scope: ScopeId, path: &str) -> Option<TypeId> {
let mut segments = path.split('.');
let first = segments.next()?;
let mut current_id = self.scopes.resolve(scope, first)?;
for segment in segments {
let decl = self.get_type(current_id);
match &decl.kind {
TypeKind::Namespace(ns) => {
current_id = self.scopes.resolve(ns.child_scope, segment)?;
}
_ => return None, }
}
Some(current_id)
}
pub fn iter_types(&self) -> impl Iterator<Item = (TypeId, &TypeDeclaration)> {
self.types
.iter()
.enumerate()
.map(|(i, d)| (TypeId(i as u32), d))
}
}
impl Default for GlobalContext {
fn default() -> Self {
Self::new()
}
}