pr 05.a
This commit is contained in:
parent
a7669c9a8f
commit
9a62b7b643
@ -1 +1,2 @@
|
||||
pub mod symbols;
|
||||
pub mod symbols;
|
||||
pub mod types;
|
||||
74
crates/prometeu-compiler/src/analysis/types.rs
Normal file
74
crates/prometeu-compiler/src/analysis/types.rs
Normal 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 { .. }));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user