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