1use crate::{
5 arena::{map::ArenaMap, Arena, Idx},
6 Path,
7};
8use mun_syntax::{ast, AstPtr};
9use rustc_hash::FxHashMap;
10use std::ops::Index;
11
12pub type LocalTypeRefId = Idx<TypeRef>;
14
15#[derive(Clone, PartialEq, Eq, Hash, Debug)]
17pub enum TypeRef {
18 Path(Path),
19 Array(LocalTypeRefId),
20 Never,
21 Tuple(Vec<LocalTypeRefId>),
22 Error,
23}
24
25#[derive(Default, Debug, Eq, PartialEq)]
26pub struct TypeRefSourceMap {
27 type_ref_map: FxHashMap<AstPtr<ast::TypeRef>, LocalTypeRefId>,
28 type_ref_map_back: ArenaMap<LocalTypeRefId, AstPtr<ast::TypeRef>>,
29}
30
31impl TypeRefSourceMap {
32 pub(crate) fn type_ref_syntax(&self, expr: LocalTypeRefId) -> Option<AstPtr<ast::TypeRef>> {
35 self.type_ref_map_back.get(expr).cloned()
36 }
37
38 pub(crate) fn syntax_type_ref(&self, ptr: AstPtr<ast::TypeRef>) -> Option<LocalTypeRefId> {
41 self.type_ref_map.get(&ptr).cloned()
42 }
43}
44
45#[derive(Default, Debug, Eq, PartialEq, Clone)]
49pub struct TypeRefMap {
50 type_refs: Arena<TypeRef>,
51}
52
53impl TypeRefMap {
54 pub(crate) fn builder() -> TypeRefMapBuilder {
55 TypeRefMapBuilder {
56 map: Default::default(),
57 source_map: Default::default(),
58 }
59 }
60
61 pub fn iter(&self) -> impl Iterator<Item = (LocalTypeRefId, &TypeRef)> {
63 self.type_refs.iter()
64 }
65}
66
67impl Index<LocalTypeRefId> for TypeRefMap {
68 type Output = TypeRef;
69
70 fn index(&self, pat: LocalTypeRefId) -> &Self::Output {
71 &self.type_refs[pat]
72 }
73}
74
75#[derive(Debug, Eq, PartialEq)]
77pub(crate) struct TypeRefMapBuilder {
78 map: TypeRefMap,
79 source_map: TypeRefSourceMap,
80}
81
82impl TypeRefMapBuilder {
83 fn alloc_type_ref(&mut self, type_ref: TypeRef, ptr: AstPtr<ast::TypeRef>) -> LocalTypeRefId {
86 let id = self.map.type_refs.alloc(type_ref);
87 self.source_map.type_ref_map.insert(ptr.clone(), id);
88 self.source_map.type_ref_map_back.insert(id, ptr);
89 id
90 }
91
92 pub fn alloc_from_node_opt(&mut self, node: Option<&ast::TypeRef>) -> LocalTypeRefId {
95 if let Some(node) = node {
96 self.alloc_from_node(node)
97 } else {
98 self.error()
99 }
100 }
101
102 pub fn alloc_from_node(&mut self, node: &ast::TypeRef) -> LocalTypeRefId {
104 use mun_syntax::ast::TypeRefKind::*;
105 let ptr = AstPtr::new(node);
106 let type_ref = match node.kind() {
107 PathType(path) => path
108 .path()
109 .and_then(Path::from_ast)
110 .map(TypeRef::Path)
111 .unwrap_or(TypeRef::Error),
112 NeverType(_) => TypeRef::Never,
113 ArrayType(inner) => TypeRef::Array(self.alloc_from_node_opt(inner.type_ref().as_ref())),
114 };
115 self.alloc_type_ref(type_ref, ptr)
116 }
117
118 pub fn unit(&mut self) -> LocalTypeRefId {
121 self.map.type_refs.alloc(TypeRef::Tuple(vec![]))
122 }
123
124 pub fn error(&mut self) -> LocalTypeRefId {
126 self.map.type_refs.alloc(TypeRef::Error)
127 }
128
129 pub fn finish(self) -> (TypeRefMap, TypeRefSourceMap) {
132 (self.map, self.source_map)
133 }
134}