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