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 crate::common::spans::Span;
|
||||||
use prometeu_analysis::NameId;
|
use prometeu_analysis::NameId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
pub struct SymbolId(pub u32);
|
pub struct SymbolId(pub u32);
|
||||||
@ -17,6 +19,13 @@ pub enum SymbolKind {
|
|||||||
Local,
|
Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum Namespace {
|
||||||
|
Type,
|
||||||
|
Value,
|
||||||
|
Service,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
pub name: NameId,
|
pub name: NameId,
|
||||||
@ -31,6 +40,18 @@ pub struct SymbolArena {
|
|||||||
pub symbols: Vec<Symbol>,
|
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 {
|
impl SymbolArena {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { symbols: Vec::new() }
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -82,4 +129,40 @@ mod tests {
|
|||||||
assert_eq!(arena.get(id).module, symbol.module);
|
assert_eq!(arena.get(id).module, symbol.module);
|
||||||
assert_eq!(arena.get(id).decl_span, symbol.decl_span);
|
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