This commit is contained in:
bQUARKz 2026-02-04 19:11:05 +00:00
parent a1053eefd5
commit 010dbc96ff
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8

View File

@ -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<Symbol>,
}
#[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<DefKey, SymbolId>,
}
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<SymbolId> {
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)));
}
}