This commit is contained in:
bQUARKz 2026-02-04 19:43:56 +00:00
parent a7669c9a8f
commit 9a62b7b643
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
2 changed files with 76 additions and 1 deletions

View File

@ -1 +1,2 @@
pub mod symbols; pub mod symbols;
pub mod types;

View File

@ -0,0 +1,74 @@
use crate::analysis::symbols::SymbolId;
use prometeu_analysis::interner::NameId;
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct TypeId(pub u32);
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TypeKind {
Primitive { name: NameId },
Optional { inner: TypeId },
Result { ok: TypeId, err: TypeId },
Array { inner: TypeId, len: Option<u32> },
Struct { sym: SymbolId },
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct TypeArena {
pub types: Vec<TypeKind>,
}
impl TypeArena {
pub fn new() -> Self {
Self { types: Vec::new() }
}
/// Interna um tipo na arena. Atualmente apenas adiciona ao final (append-only),
/// sem realizar de-duplicação.
pub fn intern_type(&mut self, kind: TypeKind) -> TypeId {
let id = TypeId(self.types.len() as u32);
self.types.push(kind);
id
}
pub fn kind(&self, id: TypeId) -> &TypeKind {
&self.types[id.0 as usize]
}
}
#[cfg(test)]
mod tests {
use super::*;
// Mock de NameId e SymbolId para testes simplificados se necessário,
// ou usar valores reais.
#[test]
fn type_arena_push_is_append_only() {
let mut arena = TypeArena::new();
let name = NameId(0);
let t1 = arena.intern_type(TypeKind::Primitive { name });
let t2 = arena.intern_type(TypeKind::Optional { inner: t1 });
assert_eq!(t1.0, 0);
assert_eq!(t2.0, 1);
assert_eq!(arena.types.len(), 2);
}
#[test]
fn type_arena_index_is_stable() {
let mut arena = TypeArena::new();
let name = NameId(0);
let t1 = arena.intern_type(TypeKind::Primitive { name });
let t2 = arena.intern_type(TypeKind::Optional { inner: t1 });
assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. }));
assert!(matches!(arena.kind(t2), TypeKind::Optional { .. }));
// Adicionar mais tipos não deve mudar os anteriores
let t3 = arena.intern_type(TypeKind::Array { inner: t1, len: None });
assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. }));
assert!(matches!(arena.kind(t2), TypeKind::Optional { .. }));
assert!(matches!(arena.kind(t3), TypeKind::Array { .. }));
}
}