pr 05.c
This commit is contained in:
parent
00ad4730c8
commit
4cee158206
@ -1,6 +1,6 @@
|
|||||||
use crate::analysis::symbols::SymbolId;
|
use crate::analysis::symbols::{SymbolArena, SymbolId};
|
||||||
use crate::frontends::pbs::ast::NodeId;
|
use crate::frontends::pbs::ast::NodeId;
|
||||||
use prometeu_analysis::interner::NameId;
|
use prometeu_analysis::interner::{NameId, NameInterner};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
#[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)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct TypeFacts {
|
pub struct TypeFacts {
|
||||||
pub node_type: Vec<Option<TypeId>>,
|
pub node_type: Vec<Option<TypeId>>,
|
||||||
@ -122,14 +159,78 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn type_facts_auto_grows_for_symbol_ids() {
|
fn format_type_optional() {
|
||||||
let mut facts = TypeFacts::new();
|
let mut arena = TypeArena::new();
|
||||||
let sid = SymbolId(20);
|
let mut interner = NameInterner::new();
|
||||||
let tid = TypeId(2);
|
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);
|
let formatted = format_type(opt_t, &arena, &interner, None);
|
||||||
facts.set_symbol_type(sid, tid);
|
assert_eq!(formatted, "optional<int>");
|
||||||
assert_eq!(facts.get_symbol_type(sid), Some(tid));
|
}
|
||||||
assert!(facts.symbol_type.len() > 20);
|
|
||||||
|
#[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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user