1use crate::{
2 Function, FunctionKind, InterfaceId, Resolve, Type, TypeDef, TypeDefKind, TypeId, WorldId,
3 WorldItem,
4};
5use indexmap::IndexSet;
6
7#[derive(Default)]
8pub struct LiveTypes {
9 set: IndexSet<TypeId>,
10}
11
12impl LiveTypes {
13 pub fn iter(&self) -> impl Iterator<Item = TypeId> + '_ {
14 self.set.iter().copied()
15 }
16
17 pub fn len(&self) -> usize {
18 self.set.len()
19 }
20
21 pub fn add_interface(&mut self, resolve: &Resolve, iface: InterfaceId) {
22 self.visit_interface(resolve, iface);
23 }
24
25 pub fn add_world(&mut self, resolve: &Resolve, world: WorldId) {
26 self.visit_world(resolve, world);
27 }
28
29 pub fn add_world_item(&mut self, resolve: &Resolve, item: &WorldItem) {
30 self.visit_world_item(resolve, item);
31 }
32
33 pub fn add_func(&mut self, resolve: &Resolve, func: &Function) {
34 self.visit_func(resolve, func);
35 }
36
37 pub fn add_type_id(&mut self, resolve: &Resolve, ty: TypeId) {
38 self.visit_type_id(resolve, ty);
39 }
40
41 pub fn add_type(&mut self, resolve: &Resolve, ty: &Type) {
42 self.visit_type(resolve, ty);
43 }
44}
45
46impl TypeIdVisitor for LiveTypes {
47 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
48 !self.set.contains(&id)
49 }
50
51 fn after_visit_type_id(&mut self, id: TypeId) {
52 assert!(self.set.insert(id));
53 }
54}
55
56pub trait TypeIdVisitor {
59 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
64 let _ = id;
65 true
66 }
67
68 fn after_visit_type_id(&mut self, id: TypeId) {
70 let _ = id;
71 }
72
73 fn visit_interface(&mut self, resolve: &Resolve, iface: InterfaceId) {
74 let iface = &resolve.interfaces[iface];
75 for (_, id) in iface.types.iter() {
76 self.visit_type_id(resolve, *id);
77 }
78 for (_, func) in iface.functions.iter() {
79 self.visit_func(resolve, func);
80 }
81 }
82
83 fn visit_world(&mut self, resolve: &Resolve, world: WorldId) {
84 let world = &resolve.worlds[world];
85 for (_, item) in world.imports.iter().chain(world.exports.iter()) {
86 self.visit_world_item(resolve, item);
87 }
88 }
89
90 fn visit_world_item(&mut self, resolve: &Resolve, item: &WorldItem) {
91 match item {
92 WorldItem::Interface { id, .. } => self.visit_interface(resolve, *id),
93 WorldItem::Function(f) => self.visit_func(resolve, f),
94 WorldItem::Type(t) => self.visit_type_id(resolve, *t),
95 }
96 }
97
98 fn visit_func(&mut self, resolve: &Resolve, func: &Function) {
99 match func.kind {
100 FunctionKind::Static(id) => self.visit_type_id(resolve, id),
104
105 FunctionKind::Method(_) | FunctionKind::Constructor(_) => {}
108
109 FunctionKind::Freestanding => {}
110 }
111
112 for (_, ty) in func.params.iter() {
113 self.visit_type(resolve, ty);
114 }
115 if let Some(ty) = &func.result {
116 self.visit_type(resolve, ty);
117 }
118 }
119
120 fn visit_type_id(&mut self, resolve: &Resolve, ty: TypeId) {
121 if self.before_visit_type_id(ty) {
122 self.visit_type_def(resolve, &resolve.types[ty]);
123 self.after_visit_type_id(ty);
124 }
125 }
126
127 fn visit_type_def(&mut self, resolve: &Resolve, ty: &TypeDef) {
128 match &ty.kind {
129 TypeDefKind::Type(t)
130 | TypeDefKind::List(t)
131 | TypeDefKind::Option(t)
132 | TypeDefKind::Future(Some(t))
133 | TypeDefKind::Stream(Some(t)) => self.visit_type(resolve, t),
134 TypeDefKind::Handle(handle) => match handle {
135 crate::Handle::Own(ty) => self.visit_type_id(resolve, *ty),
136 crate::Handle::Borrow(ty) => self.visit_type_id(resolve, *ty),
137 },
138 TypeDefKind::Resource => {}
139 TypeDefKind::Record(r) => {
140 for field in r.fields.iter() {
141 self.visit_type(resolve, &field.ty);
142 }
143 }
144 TypeDefKind::Tuple(r) => {
145 for ty in r.types.iter() {
146 self.visit_type(resolve, ty);
147 }
148 }
149 TypeDefKind::Variant(v) => {
150 for case in v.cases.iter() {
151 if let Some(ty) = &case.ty {
152 self.visit_type(resolve, ty);
153 }
154 }
155 }
156 TypeDefKind::Result(r) => {
157 if let Some(ty) = &r.ok {
158 self.visit_type(resolve, ty);
159 }
160 if let Some(ty) = &r.err {
161 self.visit_type(resolve, ty);
162 }
163 }
164 TypeDefKind::ErrorContext
165 | TypeDefKind::Flags(_)
166 | TypeDefKind::Enum(_)
167 | TypeDefKind::Future(None)
168 | TypeDefKind::Stream(None) => {}
169 TypeDefKind::Unknown => unreachable!(),
170 }
171 }
172
173 fn visit_type(&mut self, resolve: &Resolve, ty: &Type) {
174 match ty {
175 Type::Id(id) => self.visit_type_id(resolve, *id),
176 _ => {}
177 }
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::{LiveTypes, Resolve};
184
185 fn live(wit: &str, ty: &str) -> Vec<String> {
186 let mut resolve = Resolve::default();
187 resolve.push_str("test.wit", wit).unwrap();
188 let (_, interface) = resolve.interfaces.iter().next_back().unwrap();
189 let ty = interface.types[ty];
190 let mut live = LiveTypes::default();
191 live.add_type_id(&resolve, ty);
192
193 live.iter()
194 .filter_map(|ty| resolve.types[ty].name.clone())
195 .collect()
196 }
197
198 #[test]
199 fn no_deps() {
200 let types = live(
201 "
202 package foo:bar;
203
204 interface foo {
205 type t = u32;
206 }
207 ",
208 "t",
209 );
210 assert_eq!(types, ["t"]);
211 }
212
213 #[test]
214 fn one_dep() {
215 let types = live(
216 "
217 package foo:bar;
218
219 interface foo {
220 type t = u32;
221 type u = t;
222 }
223 ",
224 "u",
225 );
226 assert_eq!(types, ["t", "u"]);
227 }
228
229 #[test]
230 fn chain() {
231 let types = live(
232 "
233 package foo:bar;
234
235 interface foo {
236 resource t1;
237 record t2 {
238 x: t1,
239 }
240 variant t3 {
241 x(t2),
242 }
243 flags t4 { a }
244 enum t5 { a }
245 type t6 = tuple<t5, t4, t3>;
246 }
247 ",
248 "t6",
249 );
250 assert_eq!(types, ["t5", "t4", "t1", "t2", "t3", "t6"]);
251 }
252}