golem_wasm/analysis/
wave.rs1use crate::analysis::{
2 AnalysedFunction, AnalysedType, TypeEnum, TypeFlags, TypeList, TypeOption, TypeRecord,
3 TypeResult, TypeTuple, TypeVariant,
4};
5use std::borrow::Cow;
6use std::fmt::Display;
7use wasm_wave::wasm::{DisplayType, WasmFunc, WasmType, WasmTypeKind};
8
9impl WasmType for AnalysedType {
10 fn kind(&self) -> WasmTypeKind {
11 match self {
12 AnalysedType::Bool(_) => WasmTypeKind::Bool,
13 AnalysedType::S8(_) => WasmTypeKind::S8,
14 AnalysedType::U8(_) => WasmTypeKind::U8,
15 AnalysedType::S16(_) => WasmTypeKind::S16,
16 AnalysedType::U16(_) => WasmTypeKind::U16,
17 AnalysedType::S32(_) => WasmTypeKind::S32,
18 AnalysedType::U32(_) => WasmTypeKind::U32,
19 AnalysedType::S64(_) => WasmTypeKind::S64,
20 AnalysedType::U64(_) => WasmTypeKind::U64,
21 AnalysedType::F32(_) => WasmTypeKind::F32,
22 AnalysedType::F64(_) => WasmTypeKind::F64,
23 AnalysedType::Chr(_) => WasmTypeKind::Char,
24 AnalysedType::Str(_) => WasmTypeKind::String,
25 AnalysedType::List(_) => WasmTypeKind::List,
26 AnalysedType::Tuple(_) => WasmTypeKind::Tuple,
27 AnalysedType::Record(_) => WasmTypeKind::Record,
28 AnalysedType::Flags(_) => WasmTypeKind::Flags,
29 AnalysedType::Enum(_) => WasmTypeKind::Enum,
30 AnalysedType::Option(_) => WasmTypeKind::Option,
31 AnalysedType::Result { .. } => WasmTypeKind::Result,
32 AnalysedType::Variant(_) => WasmTypeKind::Variant,
33 AnalysedType::Handle(_) => WasmTypeKind::Unsupported,
34 }
35 }
36
37 fn list_element_type(&self) -> Option<Self> {
38 if let AnalysedType::List(TypeList { inner: ty, .. }) = self {
39 Some(*ty.clone())
40 } else {
41 None
42 }
43 }
44
45 fn record_fields(&self) -> Box<dyn Iterator<Item = (Cow<'_, str>, Self)> + '_> {
46 if let AnalysedType::Record(TypeRecord { fields, .. }) = self {
47 Box::new(
48 fields
49 .iter()
50 .map(|pair| (Cow::Borrowed(pair.name.as_str()), pair.typ.clone())),
51 )
52 } else {
53 Box::new(std::iter::empty())
54 }
55 }
56
57 fn tuple_element_types(&self) -> Box<dyn Iterator<Item = Self> + '_> {
58 if let AnalysedType::Tuple(TypeTuple { items, .. }) = self {
59 Box::new(items.clone().into_iter())
60 } else {
61 Box::new(std::iter::empty())
62 }
63 }
64
65 fn variant_cases(&self) -> Box<dyn Iterator<Item = (Cow<'_, str>, Option<Self>)> + '_> {
66 if let AnalysedType::Variant(TypeVariant { cases, .. }) = self {
67 Box::new(
68 cases
69 .iter()
70 .map(|case| (Cow::Borrowed(case.name.as_str()), case.typ.clone())),
71 )
72 } else {
73 Box::new(std::iter::empty())
74 }
75 }
76
77 fn enum_cases(&self) -> Box<dyn Iterator<Item = Cow<'_, str>> + '_> {
78 if let AnalysedType::Enum(TypeEnum { cases, .. }) = self {
79 Box::new(cases.iter().map(|name| Cow::Borrowed(name.as_str())))
80 } else {
81 Box::new(std::iter::empty())
82 }
83 }
84
85 fn option_some_type(&self) -> Option<Self> {
86 if let AnalysedType::Option(TypeOption { inner, .. }) = self {
87 Some(*inner.clone())
88 } else {
89 None
90 }
91 }
92
93 fn result_types(&self) -> Option<(Option<Self>, Option<Self>)> {
94 if let AnalysedType::Result(TypeResult { ok, err, .. }) = self {
95 Some((
96 ok.as_ref().map(|t| *t.clone()),
97 err.as_ref().map(|t| *t.clone()),
98 ))
99 } else {
100 None
101 }
102 }
103
104 fn flags_names(&self) -> Box<dyn Iterator<Item = Cow<'_, str>> + '_> {
105 if let AnalysedType::Flags(TypeFlags { names, .. }) = self {
106 Box::new(names.iter().map(|name| Cow::Borrowed(name.as_str())))
107 } else {
108 Box::new(std::iter::empty())
109 }
110 }
111}
112
113impl WasmFunc for AnalysedFunction {
114 type Type = AnalysedType;
115
116 fn params(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
117 Box::new(self.parameters.iter().map(|p| p.typ.clone()))
118 }
119
120 fn param_names(&self) -> Box<dyn Iterator<Item = Cow<'_, str>> + '_> {
121 Box::new(
122 self.parameters
123 .iter()
124 .map(|p| Cow::Borrowed(p.name.as_str())),
125 )
126 }
127
128 fn results(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
129 Box::new(self.result.iter().map(|r| r.typ.clone()))
130 }
131}
132
133pub struct DisplayNamedFunc<T: WasmFunc> {
136 pub name: String,
137 pub func: T,
138}
139
140impl<T: WasmFunc> Display for DisplayNamedFunc<T> {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 f.write_str(&self.name)?;
143 f.write_str("(")?;
144 let mut param_names = self.func.param_names();
145 for (idx, ty) in self.func.params().enumerate() {
146 if idx != 0 {
147 f.write_str(", ")?;
148 }
149 if let Some(name) = param_names.next() {
150 write!(f, "{name}: ")?;
151 }
152 DisplayType(&ty).fmt(f)?
153 }
154 f.write_str(")")?;
155
156 let results = self.func.results().collect::<Vec<_>>();
157 if results.is_empty() {
158 return Ok(());
159 }
160
161 let mut result_names = self.func.result_names();
162 if results.len() == 1 {
163 let ty = DisplayType(&results.into_iter().next().unwrap()).to_string();
164 if let Some(name) = result_names.next() {
165 write!(f, " -> ({name}: {ty})")
166 } else {
167 write!(f, " -> {ty}")
168 }
169 } else {
170 f.write_str(" -> (")?;
171 for (idx, ty) in results.into_iter().enumerate() {
172 if idx != 0 {
173 f.write_str(", ")?;
174 }
175 if let Some(name) = result_names.next() {
176 write!(f, "{name}: ")?;
177 }
178 DisplayType(&ty).fmt(f)?;
179 }
180 f.write_str(")")
181 }
182 }
183}