pr 04.b
This commit is contained in:
parent
a1053eefd5
commit
010dbc96ff
@ -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)));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user