This commit is contained in:
bQUARKz 2026-02-04 19:48:32 +00:00
parent 00ad4730c8
commit 4cee158206
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
2 changed files with 111 additions and 10 deletions

View File

@ -1,6 +1,6 @@
use crate::analysis::symbols::SymbolId;
use crate::analysis::symbols::{SymbolArena, SymbolId};
use crate::frontends::pbs::ast::NodeId;
use prometeu_analysis::interner::NameId;
use prometeu_analysis::interner::{NameId, NameInterner};
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
@ -38,6 +38,43 @@ impl TypeArena {
}
}
pub fn format_type(
type_id: TypeId,
arena: &TypeArena,
interner: &NameInterner,
symbols: Option<&SymbolArena>,
) -> String {
let kind = arena.kind(type_id);
match kind {
TypeKind::Primitive { name } => interner.resolve(*name).to_string(),
TypeKind::Optional { inner } => {
let inner_str = format_type(*inner, arena, interner, symbols);
format!("optional<{}>", inner_str)
}
TypeKind::Result { ok, err } => {
let ok_str = format_type(*ok, arena, interner, symbols);
let err_str = format_type(*err, arena, interner, symbols);
format!("result<{}, {}>", ok_str, err_str)
}
TypeKind::Array { inner, len } => {
let inner_str = format_type(*inner, arena, interner, symbols);
if let Some(n) = len {
format!("array<{}>[{}]", inner_str, n)
} else {
format!("array<{}>", inner_str)
}
}
TypeKind::Struct { sym } => {
if let Some(symbol_arena) = symbols {
let symbol = symbol_arena.get(*sym);
interner.resolve(symbol.name).to_string()
} else {
format!("struct#{}", sym.0)
}
}
}
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct TypeFacts {
pub node_type: Vec<Option<TypeId>>,
@ -122,14 +159,78 @@ mod tests {
}
#[test]
fn type_facts_auto_grows_for_symbol_ids() {
let mut facts = TypeFacts::new();
let sid = SymbolId(20);
let tid = TypeId(2);
fn format_type_optional() {
let mut arena = TypeArena::new();
let mut interner = NameInterner::new();
let int_name = interner.intern("int");
let int_t = arena.intern_type(TypeKind::Primitive { name: int_name });
let opt_t = arena.intern_type(TypeKind::Optional { inner: int_t });
assert_eq!(facts.get_symbol_type(sid), None);
facts.set_symbol_type(sid, tid);
assert_eq!(facts.get_symbol_type(sid), Some(tid));
assert!(facts.symbol_type.len() > 20);
let formatted = format_type(opt_t, &arena, &interner, None);
assert_eq!(formatted, "optional<int>");
}
#[test]
fn format_type_result() {
let mut arena = TypeArena::new();
let mut interner = NameInterner::new();
let int_name = interner.intern("int");
let string_name = interner.intern("string");
let int_t = arena.intern_type(TypeKind::Primitive { name: int_name });
let string_t = arena.intern_type(TypeKind::Primitive { name: string_name });
let res_t = arena.intern_type(TypeKind::Result { ok: int_t, err: string_t });
let formatted = format_type(res_t, &arena, &interner, None);
assert_eq!(formatted, "result<int, string>");
}
#[test]
fn format_type_array_len() {
let mut arena = TypeArena::new();
let mut interner = NameInterner::new();
let bool_name = interner.intern("bool");
let bool_t = arena.intern_type(TypeKind::Primitive { name: bool_name });
let arr_dynamic = arena.intern_type(TypeKind::Array { inner: bool_t, len: None });
let arr_fixed = arena.intern_type(TypeKind::Array { inner: bool_t, len: Some(10) });
assert_eq!(format_type(arr_dynamic, &arena, &interner, None), "array<bool>");
assert_eq!(format_type(arr_fixed, &arena, &interner, None), "array<bool>[10]");
}
#[test]
fn format_type_struct_with_arena() {
use crate::analysis::symbols::{Symbol, SymbolKind};
use crate::common::spans::Span;
let mut arena = TypeArena::new();
let mut interner = NameInterner::new();
let mut symbols = SymbolArena::new();
let my_struct_name = interner.intern("MyStruct");
let sym_id = symbols.insert(Symbol {
name: my_struct_name,
kind: SymbolKind::Struct,
exported: false,
module: 0,
decl_span: Span::new(0, 0, 0),
});
let struct_t = arena.intern_type(TypeKind::Struct { sym: sym_id });
let formatted = format_type(struct_t, &arena, &interner, Some(&symbols));
assert_eq!(formatted, "MyStruct");
}
#[test]
fn format_type_struct_fallback() {
let mut arena = TypeArena::new();
let interner = NameInterner::new();
let sym_id = SymbolId(42);
let struct_t = arena.intern_type(TypeKind::Struct { sym: sym_id });
let formatted = format_type(struct_t, &arena, &interner, None);
assert_eq!(formatted, "struct#42");
}
}