1use anyhow::Result;
2use std::collections::{btree_map::Entry, BTreeMap, HashMap};
3use std::fmt::{self, Write};
4use std::ops::Deref;
5use std::path::Path;
6use wit_parser::*;
7
8pub use wit_parser;
9mod ns;
10
11pub use ns::Ns;
12
13#[derive(Copy, Clone, Eq, PartialEq)]
37pub enum Direction {
38 Import,
39 Export,
40}
41
42pub trait Generator {
43 fn preprocess_all(&mut self, imports: &[Interface], exports: &[Interface]) {
44 drop((imports, exports));
45 }
46
47 fn preprocess_one(&mut self, iface: &Interface, dir: Direction) {
48 drop((iface, dir));
49 }
50
51 fn type_record(
52 &mut self,
53 iface: &Interface,
54 id: TypeId,
55 name: &str,
56 record: &Record,
57 docs: &Docs,
58 );
59 fn type_flags(&mut self, iface: &Interface, id: TypeId, name: &str, flags: &Flags, docs: &Docs);
60 fn type_tuple(&mut self, iface: &Interface, id: TypeId, name: &str, flags: &Tuple, docs: &Docs);
61 fn type_variant(
62 &mut self,
63 iface: &Interface,
64 id: TypeId,
65 name: &str,
66 variant: &Variant,
67 docs: &Docs,
68 );
69 fn type_option(
70 &mut self,
71 iface: &Interface,
72 id: TypeId,
73 name: &str,
74 payload: &Type,
75 docs: &Docs,
76 );
77 fn type_result(
78 &mut self,
79 iface: &Interface,
80 id: TypeId,
81 name: &str,
82 result: &Result_,
83 docs: &Docs,
84 );
85 fn type_union(&mut self, iface: &Interface, id: TypeId, name: &str, union: &Union, docs: &Docs);
86 fn type_enum(&mut self, iface: &Interface, id: TypeId, name: &str, enum_: &Enum, docs: &Docs);
87 fn type_resource(&mut self, iface: &Interface, ty: ResourceId);
88 fn type_alias(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
89 fn type_list(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
90 fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
91
92 fn preprocess_resources(&mut self, iface: &Interface, dir: Direction) {
93 drop((iface, dir));
94 }
95
96 fn preprocess_functions(&mut self, iface: &Interface, dir: Direction) {
97 drop((iface, dir));
98 }
99 fn import(&mut self, iface: &Interface, func: &Function);
100 fn export(&mut self, iface: &Interface, func: &Function);
101 fn finish_functions(&mut self, iface: &Interface, dir: Direction) {
102 drop((iface, dir));
103 }
104
105 fn finish_one(&mut self, iface: &Interface, files: &mut Files);
106
107 fn finish_all(&mut self, files: &mut Files) {
108 drop(files);
109 }
110
111 fn generate_one(&mut self, iface: &Interface, dir: Direction, files: &mut Files) {
112 self.preprocess_one(iface, dir);
113
114 for (id, ty) in iface.types.iter() {
115 let name = match &ty.name {
117 Some(name) => name,
118 None => continue,
119 };
120 match &ty.kind {
121 TypeDefKind::Record(record) => self.type_record(iface, id, name, record, &ty.docs),
122 TypeDefKind::Flags(flags) => self.type_flags(iface, id, name, flags, &ty.docs),
123 TypeDefKind::Tuple(tuple) => self.type_tuple(iface, id, name, tuple, &ty.docs),
124 TypeDefKind::Enum(enum_) => self.type_enum(iface, id, name, enum_, &ty.docs),
125 TypeDefKind::Variant(variant) => {
126 self.type_variant(iface, id, name, variant, &ty.docs)
127 }
128 TypeDefKind::Option(t) => self.type_option(iface, id, name, t, &ty.docs),
129 TypeDefKind::Result(r) => self.type_result(iface, id, name, r, &ty.docs),
130 TypeDefKind::Union(u) => self.type_union(iface, id, name, u, &ty.docs),
131 TypeDefKind::List(t) => self.type_list(iface, id, name, t, &ty.docs),
132 TypeDefKind::Type(t) => self.type_alias(iface, id, name, t, &ty.docs),
133 TypeDefKind::Future(_) => todo!("generate for future"),
134 TypeDefKind::Stream(_) => todo!("generate for stream"),
135 }
136 }
137
138 self.preprocess_resources(iface, dir);
139
140 for (id, _resource) in iface.resources.iter() {
141 self.type_resource(iface, id);
142 }
143
144 self.preprocess_functions(iface, dir);
145
146 for f in iface.functions.iter() {
147 match dir {
148 Direction::Import => self.import(iface, &f),
149 Direction::Export => self.export(iface, &f),
150 }
151 }
152
153 self.finish_functions(iface, dir);
154
155 self.finish_one(iface, files)
156 }
157
158 fn generate_all(&mut self, imports: &[Interface], exports: &[Interface], files: &mut Files) {
159 self.preprocess_all(imports, exports);
160
161 for imp in imports {
162 self.generate_one(imp, Direction::Import, files);
163 }
164
165 for exp in exports {
166 self.generate_one(exp, Direction::Export, files);
167 }
168
169 self.finish_all(files);
170 }
171}
172
173#[derive(Default)]
174pub struct Types {
175 type_info: HashMap<TypeId, TypeInfo>,
176}
177
178#[derive(Default, Clone, Copy)]
179pub struct TypeInfo {
180 pub param: bool,
183
184 pub result: bool,
187
188 pub has_list: bool,
190
191 pub has_handle: bool,
193}
194
195impl std::ops::BitOrAssign for TypeInfo {
196 fn bitor_assign(&mut self, rhs: Self) {
197 self.param |= rhs.param;
198 self.result |= rhs.result;
199 self.has_list |= rhs.has_list;
200 self.has_handle |= rhs.has_handle;
201 }
202}
203
204impl Types {
205 pub fn analyze(&mut self, iface: &Interface) {
206 for (t, _) in iface.types.iter() {
207 self.type_id_info(iface, t);
208 }
209 for f in iface.functions.iter() {
210 for (_, ty) in f.params.iter() {
211 self.set_param_result_ty(iface, ty, true, false);
212 }
213 self.set_param_result_ty(iface, &f.result, false, true);
214 }
215 }
216
217 pub fn get(&self, id: TypeId) -> TypeInfo {
218 self.type_info[&id]
219 }
220
221 pub fn type_id_info(&mut self, iface: &Interface, ty: TypeId) -> TypeInfo {
222 if let Some(info) = self.type_info.get(&ty) {
223 return *info;
224 }
225 let mut info = TypeInfo::default();
226 match &iface.types[ty].kind {
227 TypeDefKind::Record(r) => {
228 for field in r.fields.iter() {
229 info |= self.type_info(iface, &field.ty);
230 }
231 }
232 TypeDefKind::Tuple(t) => {
233 for ty in t.types.iter() {
234 info |= self.type_info(iface, ty);
235 }
236 }
237 TypeDefKind::Flags(_) => {}
238 TypeDefKind::Enum(_) => {}
239 TypeDefKind::Variant(v) => {
240 for case in v.cases.iter() {
241 info |= self.type_info(iface, &case.ty);
242 }
243 }
244 TypeDefKind::List(ty) => {
245 info = self.type_info(iface, ty);
246 info.has_list = true;
247 }
248 TypeDefKind::Type(ty) => {
249 info = self.type_info(iface, ty);
250 }
251 TypeDefKind::Option(ty) => {
252 info = self.type_info(iface, ty);
253 }
254 TypeDefKind::Result(r) => {
255 info = self.type_info(iface, &r.ok);
256 info |= self.type_info(iface, &r.err);
257 }
258 TypeDefKind::Union(u) => {
259 for case in u.cases.iter() {
260 info |= self.type_info(iface, &case.ty);
261 }
262 }
263 TypeDefKind::Future(ty) => {
264 info = self.type_info(iface, ty);
265 }
266 TypeDefKind::Stream(stream) => {
267 info = self.type_info(iface, &stream.element);
268 info |= self.type_info(iface, &stream.end);
269 }
270 }
271 self.type_info.insert(ty, info);
272 return info;
273 }
274
275 pub fn type_info(&mut self, iface: &Interface, ty: &Type) -> TypeInfo {
276 let mut info = TypeInfo::default();
277 match ty {
278 Type::Handle(_) => info.has_handle = true,
279 Type::String => info.has_list = true,
280 Type::Id(id) => return self.type_id_info(iface, *id),
281 _ => {}
282 }
283 info
284 }
285
286 fn set_param_result_id(&mut self, iface: &Interface, ty: TypeId, param: bool, result: bool) {
287 match &iface.types[ty].kind {
288 TypeDefKind::Record(r) => {
289 for field in r.fields.iter() {
290 self.set_param_result_ty(iface, &field.ty, param, result)
291 }
292 }
293 TypeDefKind::Tuple(t) => {
294 for ty in t.types.iter() {
295 self.set_param_result_ty(iface, ty, param, result)
296 }
297 }
298 TypeDefKind::Flags(_) => {}
299 TypeDefKind::Enum(_) => {}
300 TypeDefKind::Variant(v) => {
301 for case in v.cases.iter() {
302 self.set_param_result_ty(iface, &case.ty, param, result)
303 }
304 }
305 TypeDefKind::List(ty) | TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => {
306 self.set_param_result_ty(iface, ty, param, result)
307 }
308 TypeDefKind::Result(r) => {
309 self.set_param_result_ty(iface, &r.ok, param, result);
310 self.set_param_result_ty(iface, &r.err, param, result);
311 }
312 TypeDefKind::Union(u) => {
313 for case in u.cases.iter() {
314 self.set_param_result_ty(iface, &case.ty, param, result)
315 }
316 }
317 TypeDefKind::Future(ty) => self.set_param_result_ty(iface, ty, param, result),
318 TypeDefKind::Stream(stream) => {
319 self.set_param_result_ty(iface, &stream.element, param, result);
320 self.set_param_result_ty(iface, &stream.end, param, result);
321 }
322 }
323 }
324
325 fn set_param_result_ty(&mut self, iface: &Interface, ty: &Type, param: bool, result: bool) {
326 match ty {
327 Type::Id(id) => {
328 self.type_id_info(iface, *id);
329 let info = self.type_info.get_mut(id).unwrap();
330 if (param && !info.param) || (result && !info.result) {
331 info.param = info.param || param;
332 info.result = info.result || result;
333 self.set_param_result_id(iface, *id, param, result);
334 }
335 }
336 _ => {}
337 }
338 }
339}
340
341#[derive(Default)]
342pub struct Files {
343 files: BTreeMap<String, Vec<u8>>,
344}
345
346impl Files {
347 pub fn push(&mut self, name: &str, contents: &[u8]) {
348 match self.files.entry(name.to_owned()) {
349 Entry::Vacant(entry) => {
350 entry.insert(contents.to_owned());
351 }
352 Entry::Occupied(ref mut entry) => {
353 entry.get_mut().extend_from_slice(contents);
354 }
355 }
356 }
357
358 pub fn iter(&self) -> impl Iterator<Item = (&'_ str, &'_ [u8])> {
359 self.files.iter().map(|p| (p.0.as_str(), p.1.as_slice()))
360 }
361}
362
363pub fn load(path: impl AsRef<Path>) -> Result<Interface> {
364 Interface::parse_file(path)
365}
366
367#[derive(Default)]
368pub struct Source {
369 s: String,
370 indent: usize,
371}
372
373impl Source {
374 pub fn push_str(&mut self, src: &str) {
375 let lines = src.lines().collect::<Vec<_>>();
376 for (i, line) in lines.iter().enumerate() {
377 let trimmed = line.trim();
378 if trimmed.starts_with("}") && self.s.ends_with(" ") {
379 self.s.pop();
380 self.s.pop();
381 }
382 self.s.push_str(if lines.len() == 1 {
383 line
384 } else {
385 line.trim_start()
386 });
387 if trimmed.ends_with('{') {
388 self.indent += 1;
389 }
390 if trimmed.starts_with('}') {
391 self.indent -= 1;
392 }
393 if i != lines.len() - 1 || src.ends_with("\n") {
394 self.newline();
395 }
396 }
397 }
398
399 pub fn indent(&mut self, amt: usize) {
400 self.indent += amt;
401 }
402
403 pub fn deindent(&mut self, amt: usize) {
404 self.indent -= amt;
405 }
406
407 fn newline(&mut self) {
408 self.s.push_str("\n");
409 for _ in 0..self.indent {
410 self.s.push_str(" ");
411 }
412 }
413
414 pub fn as_mut_string(&mut self) -> &mut String {
415 &mut self.s
416 }
417}
418
419impl Write for Source {
420 fn write_str(&mut self, s: &str) -> fmt::Result {
421 self.push_str(s);
422 Ok(())
423 }
424}
425
426impl Deref for Source {
427 type Target = str;
428 fn deref(&self) -> &str {
429 &self.s
430 }
431}
432
433impl From<Source> for String {
434 fn from(s: Source) -> String {
435 s.s
436 }
437}
438
439#[macro_export]
446macro_rules! uwrite {
447 ($dst:expr, $($arg:tt)*) => {
448 write!($dst, $($arg)*).unwrap()
449 };
450}
451
452#[macro_export]
459macro_rules! uwriteln {
460 ($dst:expr, $($arg:tt)*) => {
461 writeln!($dst, $($arg)*).unwrap()
462 };
463}
464
465#[cfg(test)]
466mod tests {
467 use super::{Generator, Source};
468
469 #[test]
470 fn simple_append() {
471 let mut s = Source::default();
472 s.push_str("x");
473 assert_eq!(s.s, "x");
474 s.push_str("y");
475 assert_eq!(s.s, "xy");
476 s.push_str("z ");
477 assert_eq!(s.s, "xyz ");
478 s.push_str(" a ");
479 assert_eq!(s.s, "xyz a ");
480 s.push_str("\na");
481 assert_eq!(s.s, "xyz a \na");
482 }
483
484 #[test]
485 fn newline_remap() {
486 let mut s = Source::default();
487 s.push_str("function() {\n");
488 s.push_str("y\n");
489 s.push_str("}\n");
490 assert_eq!(s.s, "function() {\n y\n}\n");
491 }
492
493 #[test]
494 fn if_else() {
495 let mut s = Source::default();
496 s.push_str("if() {\n");
497 s.push_str("y\n");
498 s.push_str("} else if () {\n");
499 s.push_str("z\n");
500 s.push_str("}\n");
501 assert_eq!(s.s, "if() {\n y\n} else if () {\n z\n}\n");
502 }
503
504 #[test]
505 fn trim_ws() {
506 let mut s = Source::default();
507 s.push_str(
508 "function() {
509 x
510 }",
511 );
512 assert_eq!(s.s, "function() {\n x\n}");
513 }
514
515 #[test]
516 fn generator_is_object_safe() {
517 fn _assert(_: &dyn Generator) {}
518 }
519}