From 010dbc96ffbb98a04d0f976d4659f9db6a76ff53 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 4 Feb 2026 19:11:05 +0000 Subject: [PATCH] pr 04.b --- .../src/analysis/symbols/mod.rs | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/crates/prometeu-compiler/src/analysis/symbols/mod.rs b/crates/prometeu-compiler/src/analysis/symbols/mod.rs index 7b7b194b..ab238950 100644 --- a/crates/prometeu-compiler/src/analysis/symbols/mod.rs +++ b/crates/prometeu-compiler/src/analysis/symbols/mod.rs @@ -1,6 +1,8 @@ +use crate::common::diagnostics::{Diagnostic, DiagnosticLevel}; use crate::common::spans::Span; use prometeu_analysis::NameId; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct SymbolId(pub u32); @@ -17,6 +19,13 @@ pub enum SymbolKind { Local, } +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub enum Namespace { + Type, + Value, + Service, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Symbol { pub name: NameId, @@ -31,6 +40,18 @@ pub struct SymbolArena { pub symbols: Vec, } +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct DefKey { + pub module: u32, + pub name: NameId, + pub namespace: Namespace, +} + +#[derive(Debug, Default, Clone)] +pub struct DefIndex { + symbols: HashMap, +} + impl SymbolArena { pub fn new() -> Self { Self { symbols: Vec::new() } @@ -47,6 +68,32 @@ impl SymbolArena { } } +impl DefIndex { + pub fn new() -> Self { + Self { + symbols: HashMap::new(), + } + } + + pub fn insert_symbol(&mut self, key: DefKey, symbol_id: SymbolId) -> Result<(), Diagnostic> { + if self.symbols.contains_key(&key) { + return Err(Diagnostic { + level: DiagnosticLevel::Error, + code: Some("E_RESOLVE_DUPLICATE_SYMBOL".to_string()), + message: "Duplicate symbol in the same module and namespace".to_string(), + span: None, + }); + } + + self.symbols.insert(key, symbol_id); + Ok(()) + } + + pub fn get(&self, key: DefKey) -> Option { + self.symbols.get(&key).copied() + } +} + #[cfg(test)] mod tests { use super::*; @@ -82,4 +129,40 @@ mod tests { assert_eq!(arena.get(id).module, symbol.module); assert_eq!(arena.get(id).decl_span, symbol.decl_span); } + + #[test] + fn def_index_duplicate_in_same_namespace_errors() { + let mut index = DefIndex::new(); + let key = DefKey { + module: 1, + name: NameId(10), + namespace: Namespace::Type, + }; + + assert!(index.insert_symbol(key, SymbolId(0)).is_ok()); + let err = index.insert_symbol(key, SymbolId(1)).unwrap_err(); + + assert_eq!(err.code, Some("E_RESOLVE_DUPLICATE_SYMBOL".to_string())); + } + + #[test] + fn def_index_allows_same_name_in_different_namespace() { + let mut index = DefIndex::new(); + let name = NameId(11); + let type_key = DefKey { + module: 2, + name, + namespace: Namespace::Type, + }; + let value_key = DefKey { + module: 2, + name, + namespace: Namespace::Value, + }; + + assert!(index.insert_symbol(type_key, SymbolId(0)).is_ok()); + assert!(index.insert_symbol(value_key, SymbolId(1)).is_ok()); + assert_eq!(index.get(type_key), Some(SymbolId(0))); + assert_eq!(index.get(value_key), Some(SymbolId(1))); + } } \ No newline at end of file