linera_wit_parser/
mangle.rs

1//! Canonical ABI name mangling.
2//!
3//! This file implements the name mangling scheme defined [here]
4//! [here]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#canonical-module-type
5
6use crate::{
7    Case, EnumCase, Field, Flag, Function, Interface, ResourceId, Stream, Type, TypeDefKind,
8    UnionCase,
9};
10
11const CABI_VERSION: &str = "0.1";
12
13enum PreSpace {
14    False,
15}
16
17impl Interface {
18    pub fn mangle_funcname(&self, func: &Function) -> String {
19        self.mangle_funcname_with_name(&func.name, func)
20    }
21
22    pub fn mangle_start_funcname(&self, func: &Function) -> String {
23        self.mangle_funcname_with_name(&format!("cabi_start{{cabi={}}}", CABI_VERSION), func)
24    }
25
26    fn mangle_funcname_with_name(&self, name: &str, func: &Function) -> String {
27        format!(
28            "{}: func{} -> {}",
29            name,
30            self.mangle_funcvec(&func.params, PreSpace::False),
31            self.mangle_valtype(func.result)
32        )
33    }
34
35    fn mangle_funcvec(&self, es: &[(String, Type)], _pre_space: PreSpace) -> String {
36        format!(
37            "({})",
38            es.iter()
39                .map(|e| format!("{}: {}", e.0, self.mangle_valtype(e.1)))
40                .collect::<Vec<_>>()
41                .join(", ")
42        )
43    }
44
45    fn mangle_valtype(&self, t: Type) -> String {
46        match t {
47            Type::Unit => "unit".to_owned(),
48            Type::Bool => "bool".to_owned(),
49            Type::S8 => "s8".to_owned(),
50            Type::U8 => "u8".to_owned(),
51            Type::S16 => "s16".to_owned(),
52            Type::U16 => "u16".to_owned(),
53            Type::S32 => "s32".to_owned(),
54            Type::U32 => "u32".to_owned(),
55            Type::S64 => "s64".to_owned(),
56            Type::U64 => "u64".to_owned(),
57            Type::Float32 => "float32".to_owned(),
58            Type::Float64 => "float64".to_owned(),
59            Type::Char => "char".to_owned(),
60            Type::String => "string".to_owned(),
61            Type::Handle(id) => self.mangle_handletype(id),
62            Type::Id(id) => self.mangle_valtypedef(&self.types[id].kind),
63        }
64    }
65
66    fn mangle_valtypedef(&self, kind: &TypeDefKind) -> String {
67        match kind {
68            TypeDefKind::List(t) => format!("list<{}>", self.mangle_valtype(*t)),
69            TypeDefKind::Record(r) => self.mangle_recordtype(&r.fields),
70            TypeDefKind::Tuple(t) => self.mangle_tupletype(&t.types),
71            TypeDefKind::Flags(f) => self.mangle_flags(&f.flags),
72            TypeDefKind::Variant(v) => self.mangle_varianttype(&v.cases),
73            TypeDefKind::Enum(e) => self.mangle_enumtype(&e.cases),
74            TypeDefKind::Union(u) => self.mangle_uniontype(&u.cases),
75            TypeDefKind::Option(t) => self.mangle_optiontype(*t),
76            TypeDefKind::Result(r) => self.mangle_resulttype(r.ok, r.err),
77            TypeDefKind::Future(t) => self.mangle_futuretype(*t),
78            TypeDefKind::Stream(s) => self.mangle_streamtype(s),
79            TypeDefKind::Type(t) => self.mangle_valtype(*t),
80        }
81    }
82
83    fn mangle_recordtype(&self, fields: &[Field]) -> String {
84        format!(
85            "record {{ {} }}",
86            fields
87                .iter()
88                .map(|f| format!("{}: {}", f.name, self.mangle_valtype(f.ty)))
89                .collect::<Vec<_>>()
90                .join(", ")
91        )
92    }
93
94    fn mangle_tupletype(&self, ts: &[Type]) -> String {
95        format!(
96            "tuple<{}>",
97            ts.iter()
98                .map(|t| self.mangle_valtype(*t))
99                .collect::<Vec<_>>()
100                .join(", ")
101        )
102    }
103
104    fn mangle_flags(&self, labels: &[Flag]) -> String {
105        format!(
106            "flags {{ {} }}",
107            labels
108                .iter()
109                .map(|f| f.name.clone())
110                .collect::<Vec<_>>()
111                .join(", ")
112        )
113    }
114
115    fn mangle_varianttype(&self, cases: &[Case]) -> String {
116        format!(
117            "variant {{ {} }}",
118            cases
119                .iter()
120                .map(|c| format!("{}{}", c.name, format!("({})", self.mangle_valtype(c.ty)),))
121                .collect::<Vec<_>>()
122                .join(", ")
123        )
124    }
125
126    fn mangle_enumtype(&self, labels: &[EnumCase]) -> String {
127        format!(
128            "enum {{ {} }}",
129            labels
130                .iter()
131                .map(|l| l.name.clone())
132                .collect::<Vec<_>>()
133                .join(", ")
134        )
135    }
136
137    fn mangle_uniontype(&self, cases: &[UnionCase]) -> String {
138        format!(
139            "union {{ {} }}",
140            cases
141                .iter()
142                .map(|case| self.mangle_valtype(case.ty))
143                .collect::<Vec<_>>()
144                .join(", ")
145        )
146    }
147
148    fn mangle_optiontype(&self, t: Type) -> String {
149        format!("option<{}>", self.mangle_valtype(t))
150    }
151
152    fn mangle_resulttype(&self, ok: Type, error: Type) -> String {
153        format!(
154            "result<{}, {}>",
155            self.mangle_valtype(ok),
156            self.mangle_valtype(error)
157        )
158    }
159
160    fn mangle_handletype(&self, id: ResourceId) -> String {
161        format!("handle<{}>", self.resources[id].name)
162    }
163
164    fn mangle_futuretype(&self, ty: Type) -> String {
165        format!("future<{}>", self.mangle_valtype(ty))
166    }
167
168    fn mangle_streamtype(&self, stream: &Stream) -> String {
169        format!(
170            "stream<{}, {}>",
171            self.mangle_valtype(stream.element),
172            self.mangle_valtype(stream.end)
173        )
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::{
181        Docs, Enum, Flag, Flags, FunctionKind, Record, Resource, Result_, Tuple, Union, Variant,
182    };
183
184    #[test]
185    fn test_funcname() {
186        let interface = Interface::default();
187
188        assert_eq!(
189            interface.mangle_funcname(&Function {
190                docs: Docs::default(),
191                name: "foo".to_owned(),
192                kind: FunctionKind::Freestanding,
193                params: Vec::new(),
194                result: Type::Unit
195            }),
196            "foo: func() -> unit"
197        );
198        assert_eq!(
199            interface.mangle_funcname(&Function {
200                docs: Docs::default(),
201                name: "foo".to_owned(),
202                kind: FunctionKind::Freestanding,
203                params: vec![("a".to_owned(), Type::S64)],
204                result: Type::S32
205            }),
206            "foo: func(a: s64) -> s32"
207        );
208        assert_eq!(
209            interface.mangle_funcname(&Function {
210                docs: Docs::default(),
211                name: "foo".to_owned(),
212                kind: FunctionKind::Freestanding,
213                params: vec![("a".to_owned(), Type::S64), ("b".to_owned(), Type::U64)],
214                result: Type::S32
215            }),
216            "foo: func(a: s64, b: u64) -> s32"
217        );
218    }
219
220    #[test]
221    fn test_start_funcname() {
222        let interface = Interface::default();
223
224        assert_eq!(
225            interface.mangle_start_funcname(&Function {
226                docs: Docs::default(),
227                name: "foo".to_owned(),
228                kind: FunctionKind::Freestanding,
229                params: Vec::new(),
230                result: Type::Unit
231            }),
232            format!("cabi_start{{cabi={}}}: func() -> unit", CABI_VERSION)
233        );
234    }
235
236    #[test]
237    fn test_types() {
238        let iface = Interface::default();
239        assert_eq!(iface.mangle_valtype(Type::Unit), "unit");
240        assert_eq!(iface.mangle_valtype(Type::Bool), "bool");
241        assert_eq!(iface.mangle_valtype(Type::S8), "s8");
242        assert_eq!(iface.mangle_valtype(Type::U8), "u8");
243        assert_eq!(iface.mangle_valtype(Type::S16), "s16");
244        assert_eq!(iface.mangle_valtype(Type::U16), "u16");
245        assert_eq!(iface.mangle_valtype(Type::S32), "s32");
246        assert_eq!(iface.mangle_valtype(Type::U32), "u32");
247        assert_eq!(iface.mangle_valtype(Type::S64), "s64");
248        assert_eq!(iface.mangle_valtype(Type::U64), "u64");
249        assert_eq!(iface.mangle_valtype(Type::Float32), "float32");
250        assert_eq!(iface.mangle_valtype(Type::Float64), "float64");
251        assert_eq!(iface.mangle_valtype(Type::Char), "char");
252        assert_eq!(iface.mangle_valtype(Type::String), "string");
253    }
254
255    #[test]
256    fn test_listtype() {
257        let iface = Interface::default();
258        assert_eq!(
259            iface.mangle_valtypedef(&TypeDefKind::List(Type::U16)),
260            "list<u16>"
261        );
262    }
263
264    #[test]
265    fn test_recordtype() {
266        let iface = Interface::default();
267        assert_eq!(
268            iface.mangle_valtypedef(&TypeDefKind::Record(Record { fields: Vec::new() })),
269            "record {  }"
270        );
271        assert_eq!(
272            iface.mangle_valtypedef(&TypeDefKind::Record(Record {
273                fields: vec![Field {
274                    name: "x".to_owned(),
275                    docs: Docs::default(),
276                    ty: Type::Float32
277                }]
278            })),
279            "record { x: float32 }"
280        );
281        assert_eq!(
282            iface.mangle_valtypedef(&TypeDefKind::Record(Record {
283                fields: vec![
284                    Field {
285                        name: "x".to_owned(),
286                        docs: Docs::default(),
287                        ty: Type::Float32
288                    },
289                    Field {
290                        name: "y".to_owned(),
291                        docs: Docs::default(),
292                        ty: Type::Float64
293                    }
294                ]
295            })),
296            "record { x: float32, y: float64 }"
297        );
298    }
299
300    #[test]
301    fn test_tupletype() {
302        let iface = Interface::default();
303        assert_eq!(
304            iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple { types: Vec::new() })),
305            "tuple<>"
306        );
307        assert_eq!(
308            iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple {
309                types: vec![Type::Float32]
310            })),
311            "tuple<float32>"
312        );
313        assert_eq!(
314            iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple {
315                types: vec![Type::Float32, Type::Float64]
316            })),
317            "tuple<float32, float64>"
318        );
319    }
320
321    #[test]
322    fn test_flags() {
323        let iface = Interface::default();
324        assert_eq!(
325            iface.mangle_valtypedef(&TypeDefKind::Flags(Flags { flags: Vec::new() })),
326            "flags {  }"
327        );
328        assert_eq!(
329            iface.mangle_valtypedef(&TypeDefKind::Flags(Flags {
330                flags: vec![Flag {
331                    name: "red".to_owned(),
332                    docs: Docs::default()
333                }]
334            })),
335            "flags { red }"
336        );
337        assert_eq!(
338            iface.mangle_valtypedef(&TypeDefKind::Flags(Flags {
339                flags: vec![
340                    Flag {
341                        name: "red".to_owned(),
342                        docs: Docs::default()
343                    },
344                    Flag {
345                        name: "green".to_owned(),
346                        docs: Docs::default()
347                    }
348                ]
349            })),
350            "flags { red, green }"
351        );
352    }
353
354    #[test]
355    fn test_varianttype() {
356        let iface = Interface::default();
357        assert_eq!(
358            iface.mangle_valtypedef(&TypeDefKind::Variant(Variant { cases: Vec::new() })),
359            "variant {  }"
360        );
361        assert_eq!(
362            iface.mangle_valtypedef(&TypeDefKind::Variant(Variant {
363                cases: vec![Case {
364                    name: "x".to_owned(),
365                    docs: Docs::default(),
366                    ty: Type::Float32
367                }]
368            })),
369            "variant { x(float32) }"
370        );
371        assert_eq!(
372            iface.mangle_valtypedef(&TypeDefKind::Variant(Variant {
373                cases: vec![
374                    Case {
375                        name: "x".to_owned(),
376                        docs: Docs::default(),
377                        ty: Type::Float32
378                    },
379                    Case {
380                        name: "y".to_owned(),
381                        docs: Docs::default(),
382                        ty: Type::Float64
383                    }
384                ]
385            })),
386            "variant { x(float32), y(float64) }"
387        );
388    }
389
390    #[test]
391    fn test_enumtype() {
392        let iface = Interface::default();
393        assert_eq!(
394            iface.mangle_valtypedef(&TypeDefKind::Enum(Enum { cases: Vec::new() })),
395            "enum {  }"
396        );
397        assert_eq!(
398            iface.mangle_valtypedef(&TypeDefKind::Enum(Enum {
399                cases: vec![EnumCase {
400                    name: "x".to_owned(),
401                    docs: Docs::default(),
402                }]
403            })),
404            "enum { x }"
405        );
406        assert_eq!(
407            iface.mangle_valtypedef(&TypeDefKind::Enum(Enum {
408                cases: vec![
409                    EnumCase {
410                        name: "x".to_owned(),
411                        docs: Docs::default(),
412                    },
413                    EnumCase {
414                        name: "y".to_owned(),
415                        docs: Docs::default(),
416                    }
417                ]
418            })),
419            "enum { x, y }"
420        );
421    }
422
423    #[test]
424    fn test_uniontype() {
425        let iface = Interface::default();
426        assert_eq!(
427            iface.mangle_valtypedef(&TypeDefKind::Union(Union { cases: Vec::new() })),
428            "union {  }"
429        );
430        assert_eq!(
431            iface.mangle_valtypedef(&TypeDefKind::Union(Union {
432                cases: vec![UnionCase {
433                    docs: Docs::default(),
434                    ty: Type::Float32
435                }]
436            })),
437            "union { float32 }"
438        );
439        assert_eq!(
440            iface.mangle_valtypedef(&TypeDefKind::Union(Union {
441                cases: vec![
442                    UnionCase {
443                        docs: Docs::default(),
444                        ty: Type::Float32
445                    },
446                    UnionCase {
447                        docs: Docs::default(),
448                        ty: Type::Float64
449                    }
450                ]
451            })),
452            "union { float32, float64 }"
453        );
454    }
455
456    #[test]
457    fn test_optiontype() {
458        let iface = Interface::default();
459        assert_eq!(
460            iface.mangle_valtypedef(&TypeDefKind::Option(Type::S8)),
461            "option<s8>"
462        );
463    }
464
465    #[test]
466    fn test_resulttype() {
467        let iface = Interface::default();
468        assert_eq!(
469            iface.mangle_valtypedef(&TypeDefKind::Result(Result_ {
470                ok: Type::S32,
471                err: Type::U32
472            })),
473            "result<s32, u32>"
474        );
475    }
476
477    #[test]
478    fn test_handletype() {
479        let mut iface = Interface::default();
480        let id = iface.resources.alloc(Resource {
481            name: "thing".to_owned(),
482            docs: Docs::default(),
483            foreign_module: None,
484            supertype: None,
485        });
486        assert_eq!(iface.mangle_valtype(Type::Handle(id)), "handle<thing>");
487    }
488
489    #[test]
490    fn test_futuretype() {
491        let iface = Interface::default();
492        assert_eq!(
493            iface.mangle_valtypedef(&TypeDefKind::Future(Type::S8)),
494            "future<s8>"
495        );
496    }
497
498    #[test]
499    fn test_streamtype() {
500        let iface = Interface::default();
501        assert_eq!(
502            iface.mangle_valtypedef(&TypeDefKind::Stream(Stream {
503                element: Type::S8,
504                end: Type::U8
505            })),
506            "stream<s8, u8>"
507        );
508    }
509}