wit_bindgen_go/
lib.rs

1use anyhow::Result;
2use heck::{ToLowerCamelCase as _, ToSnakeCase as _, ToUpperCamelCase as _};
3use std::borrow::Cow;
4use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, hash_map};
5use std::fmt;
6use std::fmt::Write as _;
7use std::io::{self, Write as _};
8use std::iter;
9use std::mem;
10use std::process::Command;
11use std::str::FromStr;
12use std::thread;
13use wit_bindgen_core::abi::{
14    self, AbiVariant, Bindgen, Bitcast, FlatTypes, Instruction, LiftLower, WasmType,
15};
16use wit_bindgen_core::wit_parser::{
17    Alignment, ArchitectureSize, Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Handle, Int,
18    InterfaceId, Record, Resolve, Result_, SizeAlign, Tuple, Type, TypeDefKind, TypeId, TypeOwner,
19    Variant, WorldId, WorldKey,
20};
21use wit_bindgen_core::{
22    AsyncFilterSet, Direction, Files, InterfaceGenerator as _, Ns, WorldGenerator, uwriteln,
23};
24
25const MAX_FLAT_PARAMS: usize = 16;
26
27const POINTER_SIZE_EXPRESSION: &str = "4";
28const VARIANT_PAYLOAD_NAME: &str = "payload";
29const ITER_BASE_POINTER: &str = "base";
30const ITER_ELEMENT: &str = "element";
31const IMPORT_RETURN_AREA: &str = "returnArea";
32const EXPORT_RETURN_AREA: &str = "exportReturnArea";
33const SYNC_EXPORT_PINNER: &str = "syncExportPinner";
34const PINNER: &str = "pinner";
35
36#[derive(Default, Debug, Copy, Clone)]
37pub enum Format {
38    #[default]
39    True,
40    False,
41}
42
43impl fmt::Display for Format {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        write!(
46            f,
47            "{}",
48            match self {
49                Self::True => "true",
50                Self::False => "false",
51            }
52        )
53    }
54}
55
56impl FromStr for Format {
57    type Err = String;
58
59    fn from_str(s: &str) -> Result<Format, String> {
60        match s {
61            "true" => Ok(Format::True),
62            "false" => Ok(Format::False),
63            _ => Err(format!("expected `true` or `false`; got `{s}`")),
64        }
65    }
66}
67
68#[derive(Default, Debug, Clone)]
69#[cfg_attr(feature = "clap", derive(clap::Parser))]
70pub struct Opts {
71    /// Whether or not `gofmt` should be used (if present) to format generated
72    /// code.
73    #[cfg_attr(
74        feature = "clap",
75        arg(
76            long,
77            default_value = "true",
78            default_missing_value = "true",
79            num_args = 0..=1,
80            require_equals = true,
81        )
82    )]
83    pub format: Format,
84
85    #[cfg_attr(feature = "clap", clap(flatten))]
86    pub async_: AsyncFilterSet,
87
88    /// If true, generate stub functions for any exported functions and/or
89    /// resources.
90    #[cfg_attr(feature = "clap", clap(long))]
91    pub generate_stubs: bool,
92}
93
94impl Opts {
95    pub fn build(&self) -> Box<dyn WorldGenerator> {
96        Box::new(Go {
97            opts: self.clone(),
98            ..Go::default()
99        })
100    }
101}
102
103#[derive(Default)]
104struct InterfaceData {
105    code: String,
106    imports: BTreeSet<String>,
107    need_unsafe: bool,
108    need_runtime: bool,
109    need_math: bool,
110}
111
112impl InterfaceData {
113    fn extend(&mut self, data: InterfaceData) {
114        self.code.push_str(&data.code);
115        self.imports.extend(data.imports);
116        self.need_unsafe |= data.need_unsafe;
117        self.need_runtime |= data.need_runtime;
118        self.need_math |= data.need_math;
119    }
120
121    fn imports(&self) -> String {
122        self.imports
123            .iter()
124            .map(|v| format!(r#""wit_component/{v}""#))
125            .chain(self.need_unsafe.then(|| r#""unsafe""#.into()))
126            .chain(self.need_runtime.then(|| r#""runtime""#.into()))
127            .chain(self.need_math.then(|| r#""math""#.into()))
128            .collect::<Vec<_>>()
129            .join("\n")
130    }
131
132    fn from_generator_and_code(generator: FunctionGenerator<'_>, code: String) -> Self {
133        Self {
134            code,
135            imports: generator.imports,
136            need_unsafe: generator.need_unsafe,
137            need_runtime: generator.need_pinner,
138            need_math: generator.need_math,
139        }
140    }
141}
142
143impl From<InterfaceGenerator<'_>> for InterfaceData {
144    fn from(generator: InterfaceGenerator<'_>) -> Self {
145        Self {
146            code: generator.src,
147            imports: generator.imports,
148            need_unsafe: generator.need_unsafe,
149            need_runtime: generator.need_runtime,
150            need_math: false,
151        }
152    }
153}
154
155#[derive(Default)]
156struct Go {
157    opts: Opts,
158    src: String,
159    sizes: SizeAlign,
160    return_area_size: ArchitectureSize,
161    return_area_align: Alignment,
162    imports: BTreeSet<String>,
163    tuples: BTreeSet<usize>,
164    need_option: bool,
165    need_result: bool,
166    need_math: bool,
167    need_unit: bool,
168    need_future: bool,
169    need_stream: bool,
170    need_async: bool,
171    need_unsafe: bool,
172    interface_names: HashMap<InterfaceId, WorldKey>,
173    interfaces: BTreeMap<String, InterfaceData>,
174    export_interfaces: BTreeMap<String, InterfaceData>,
175    types: HashSet<TypeId>,
176    resources: HashMap<TypeId, Direction>,
177    futures_and_streams: HashMap<(TypeId, bool), Option<WorldKey>>,
178}
179
180impl Go {
181    fn package_for_owner(
182        &mut self,
183        resolve: &Resolve,
184        owner: Option<&WorldKey>,
185        id: TypeId,
186        local: Option<&WorldKey>,
187        in_import: bool,
188        imports: &mut BTreeSet<String>,
189    ) -> String {
190        let exported = self.has_exported_resource(resolve, Type::Id(id));
191
192        if local == owner && (exported ^ in_import) {
193            String::new()
194        } else {
195            let package = interface_name(resolve, owner);
196            let package = if exported {
197                format!("export_{package}")
198            } else {
199                package
200            };
201            let prefix = format!("{package}.");
202            imports.insert(package);
203            prefix
204        }
205    }
206
207    fn package(
208        &mut self,
209        resolve: &Resolve,
210        id: TypeId,
211        local: Option<&WorldKey>,
212        in_import: bool,
213        imports: &mut BTreeSet<String>,
214    ) -> String {
215        let ty = &resolve.types[id];
216        let owner = match ty.owner {
217            TypeOwner::World(_) => None,
218            TypeOwner::Interface(id) => Some(
219                self.interface_names
220                    .get(&id)
221                    .cloned()
222                    .unwrap_or(WorldKey::Interface(id)),
223            ),
224            TypeOwner::None => unreachable!(),
225        };
226
227        self.package_for_owner(resolve, owner.as_ref(), id, local, in_import, imports)
228    }
229
230    fn type_name(
231        &mut self,
232        resolve: &Resolve,
233        ty: Type,
234        local: Option<&WorldKey>,
235        in_import: bool,
236        imports: &mut BTreeSet<String>,
237    ) -> String {
238        match ty {
239            Type::Bool => "bool".into(),
240            Type::U8 => "uint8".into(),
241            Type::S8 => "int8".into(),
242            Type::U16 => "uint16".into(),
243            Type::S16 => "int16".into(),
244            Type::U32 => "uint32".into(),
245            Type::S32 => "int32".into(),
246            Type::U64 => "uint64".into(),
247            Type::S64 => "int64".into(),
248            Type::F32 => "float32".into(),
249            Type::F64 => "float64".into(),
250            Type::Char => "rune".into(),
251            Type::String => "string".into(),
252            Type::Id(id) => {
253                let ty = &resolve.types[id];
254                match &ty.kind {
255                    TypeDefKind::Record(_)
256                    | TypeDefKind::Flags(_)
257                    | TypeDefKind::Variant(_)
258                    | TypeDefKind::Enum(_)
259                    | TypeDefKind::Resource => {
260                        let package = self.package(resolve, id, local, in_import, imports);
261                        let name = ty.name.as_ref().unwrap().to_upper_camel_case();
262                        format!("{package}{name}")
263                    }
264                    TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
265                        let name =
266                            self.type_name(resolve, Type::Id(*ty), local, in_import, imports);
267                        format!("*{name}")
268                    }
269                    TypeDefKind::Option(ty) => {
270                        imports.insert("wit_types".into());
271                        let ty = self.type_name(resolve, *ty, local, in_import, imports);
272                        format!("wit_types.Option[{ty}]")
273                    }
274                    TypeDefKind::List(ty) => {
275                        let ty = self.type_name(resolve, *ty, local, in_import, imports);
276                        format!("[]{ty}")
277                    }
278                    TypeDefKind::Result(result) => {
279                        imports.insert("wit_types".into());
280                        let ok_type = result
281                            .ok
282                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
283                            .unwrap_or_else(|| {
284                                self.need_unit = true;
285                                "wit_types.Unit".into()
286                            });
287                        let err_type = result
288                            .err
289                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
290                            .unwrap_or_else(|| {
291                                self.need_unit = true;
292                                "wit_types.Unit".into()
293                            });
294                        format!("wit_types.Result[{ok_type}, {err_type}]")
295                    }
296                    TypeDefKind::Tuple(tuple) => {
297                        imports.insert("wit_types".into());
298                        let count = tuple.types.len();
299                        self.tuples.insert(count);
300                        let types = tuple
301                            .types
302                            .iter()
303                            .map(|ty| self.type_name(resolve, *ty, local, in_import, imports))
304                            .collect::<Vec<_>>()
305                            .join(", ");
306                        format!("wit_types.Tuple{count}[{types}]")
307                    }
308                    TypeDefKind::Future(ty) => {
309                        self.need_future = true;
310                        imports.insert("wit_types".into());
311                        let ty = ty
312                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
313                            .unwrap_or_else(|| {
314                                self.need_unit = true;
315                                "wit_types.Unit".into()
316                            });
317                        format!("*wit_types.FutureReader[{ty}]")
318                    }
319                    TypeDefKind::Stream(ty) => {
320                        self.need_stream = true;
321                        imports.insert("wit_types".into());
322                        let ty = ty
323                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
324                            .unwrap_or_else(|| {
325                                self.need_unit = true;
326                                "wit_types.Unit".into()
327                            });
328                        format!("*wit_types.StreamReader[{ty}]")
329                    }
330                    TypeDefKind::Type(ty) => {
331                        self.type_name(resolve, *ty, local, in_import, imports)
332                    }
333                    _ => todo!("{:?}", ty.kind),
334                }
335            }
336            _ => todo!("{ty:?}"),
337        }
338    }
339
340    #[expect(clippy::too_many_arguments)]
341    fn future_or_stream(
342        &mut self,
343        resolve: &Resolve,
344        ty: TypeId,
345        index: usize,
346        in_import: bool,
347        imported_type: bool,
348        interface: Option<&WorldKey>,
349        func_name: &str,
350    ) -> InterfaceData {
351        let prefix = if in_import { "" } else { "[export]" };
352
353        let module = format!(
354            "{prefix}{}",
355            interface
356                .as_ref()
357                .map(|name| resolve.name_world_key(name))
358                .unwrap_or_else(|| "$root".into())
359        );
360
361        let (payload_ty, kind, count) = match &resolve.types[ty].kind {
362            TypeDefKind::Future(ty) => (*ty, "future", ""),
363            TypeDefKind::Stream(ty) => (*ty, "stream", ", count uint32"),
364            _ => unreachable!(),
365        };
366
367        let upper_kind = kind.to_upper_camel_case();
368
369        let mut data = InterfaceData {
370            need_unsafe: true,
371            ..InterfaceData::default()
372        };
373        data.imports.insert("wit_types".into());
374
375        let (payload, snake) = if let Some(ty) = payload_ty {
376            (
377                self.type_name(resolve, ty, interface, imported_type, &mut data.imports),
378                self.mangle_name(resolve, ty, interface),
379            )
380        } else {
381            self.need_unit = true;
382            ("wit_types.Unit".into(), "unit".into())
383        };
384        let camel = snake.to_upper_camel_case();
385
386        let abi = self.sizes.record(payload_ty.as_ref());
387        let size = abi.size.format(POINTER_SIZE_EXPRESSION);
388        let align = abi.align.format(POINTER_SIZE_EXPRESSION);
389
390        // TODO: Skip lifting/lowering other types that can be used directly in
391        // their canonical form:
392        let (lift, lift_name, lower, lower_name) = match payload_ty {
393            None => (
394                format!(
395                    "func wasm_{kind}_lift_{snake}(src unsafe.Pointer) {payload} {{
396	return wit_types.Unit{{}}
397}}
398"
399                ),
400                format!("wasm_{kind}_lift_{snake}"),
401                String::new(),
402                "nil".to_string(),
403            ),
404            Some(Type::U8 | Type::S8) => (
405                String::new(),
406                "nil".to_string(),
407                String::new(),
408                "nil".to_string(),
409            ),
410            Some(ty) => {
411                data.need_runtime = true;
412
413                let mut generator = FunctionGenerator::new(
414                    self,
415                    None,
416                    None,
417                    interface,
418                    "INVALID",
419                    Vec::new(),
420                    false,
421                    imported_type,
422                );
423                generator.collect_lifters = true;
424
425                let lift_result =
426                    abi::lift_from_memory(resolve, &mut generator, "src".to_string(), &ty);
427                let lift = mem::take(&mut generator.src);
428
429                abi::lower_to_memory(
430                    resolve,
431                    &mut generator,
432                    "dst".to_string(),
433                    "value".to_string(),
434                    &ty,
435                );
436
437                let lifter_count = generator.lifter_count;
438                let (prefix, suffix) = if lifter_count > 0 {
439                    (
440                        format!("lifters := make([]func(), 0, {lifter_count})\n"),
441                        "\nreturn func() {
442        for _, lifter := range lifters {
443                lifter()
444        }
445}",
446                    )
447                } else {
448                    (String::new(), "\nreturn func() {}")
449                };
450
451                let lower = mem::take(&mut generator.src);
452                data.extend(InterfaceData::from_generator_and_code(
453                    generator,
454                    String::new(),
455                ));
456
457                (
458                    format!(
459                        "func wasm_{kind}_lift_{snake}(src unsafe.Pointer) {payload} {{
460        {lift}
461	return {lift_result}
462}}
463"
464                    ),
465                    format!("wasm_{kind}_lift_{snake}"),
466                    format!(
467                        "func wasm_{kind}_lower_{snake}(
468        pinner *runtime.Pinner,
469        value {payload},
470        dst unsafe.Pointer,
471) func() {{
472        {prefix}{lower}{suffix}
473}}
474"
475                    ),
476                    format!("wasm_{kind}_lower_{snake}"),
477                )
478            }
479        };
480
481        data.code = format!(
482            r#"
483//go:wasmimport {module} [{kind}-new-{index}]{func_name}
484func wasm_{kind}_new_{snake}() uint64
485
486//go:wasmimport {module} [async-lower][{kind}-read-{index}]{func_name}
487func wasm_{kind}_read_{snake}(handle int32, item unsafe.Pointer{count}) uint32
488
489//go:wasmimport {module} [async-lower][{kind}-write-{index}]{func_name}
490func wasm_{kind}_write_{snake}(handle int32, item unsafe.Pointer{count}) uint32
491
492//go:wasmimport {module} [{kind}-drop-readable-{index}]{func_name}
493func wasm_{kind}_drop_readable_{snake}(handle int32)
494
495//go:wasmimport {module} [{kind}-drop-writable-{index}]{func_name}
496func wasm_{kind}_drop_writable_{snake}(handle int32)
497
498{lift}
499
500{lower}
501
502var wasm_{kind}_vtable_{snake} = wit_types.{upper_kind}Vtable[{payload}]{{
503	{size},
504	{align},
505	wasm_{kind}_read_{snake},
506	wasm_{kind}_write_{snake},
507	nil,
508	nil,
509	wasm_{kind}_drop_readable_{snake},
510	wasm_{kind}_drop_writable_{snake},
511	{lift_name},
512	{lower_name},
513}}
514
515func Make{upper_kind}{camel}() (*wit_types.{upper_kind}Writer[{payload}], *wit_types.{upper_kind}Reader[{payload}]) {{
516	pair := wasm_{kind}_new_{snake}()
517	return wit_types.Make{upper_kind}Writer[{payload}](&wasm_{kind}_vtable_{snake}, int32(pair >> 32)),
518		wit_types.Make{upper_kind}Reader[{payload}](&wasm_{kind}_vtable_{snake}, int32(pair & 0xFFFFFFFF))
519}}
520
521func Lift{upper_kind}{camel}(handle int32) *wit_types.{upper_kind}Reader[{payload}] {{
522	return wit_types.Make{upper_kind}Reader[{payload}](&wasm_{kind}_vtable_{snake}, handle)
523}}
524"#
525        );
526
527        data
528    }
529
530    fn mangle_name(&self, resolve: &Resolve, ty: Type, local: Option<&WorldKey>) -> String {
531        // TODO: Ensure the returned name is always distinct for distinct types
532        // (e.g. by incorporating interface version numbers and/or additional
533        // mangling as needed).
534        match ty {
535            Type::Bool => "bool".into(),
536            Type::U8 => "u8".into(),
537            Type::U16 => "u16".into(),
538            Type::U32 => "u32".into(),
539            Type::U64 => "u64".into(),
540            Type::S8 => "s8".into(),
541            Type::S16 => "s16".into(),
542            Type::S32 => "s32".into(),
543            Type::S64 => "s64".into(),
544            Type::ErrorContext => "error_context".into(),
545            Type::F32 => "f32".into(),
546            Type::F64 => "f64".into(),
547            Type::Char => "char".into(),
548            Type::String => "string".into(),
549            Type::Id(id) => {
550                let ty = &resolve.types[id];
551                match &ty.kind {
552                    TypeDefKind::Record(_)
553                    | TypeDefKind::Variant(_)
554                    | TypeDefKind::Enum(_)
555                    | TypeDefKind::Flags(_)
556                    | TypeDefKind::Resource => {
557                        let package = match ty.owner {
558                            TypeOwner::Interface(interface) => {
559                                let key = self
560                                    .interface_names
561                                    .get(&interface)
562                                    .cloned()
563                                    .unwrap_or(WorldKey::Interface(interface));
564
565                                if local == Some(&key) {
566                                    String::new()
567                                } else {
568                                    format!(
569                                        "{}_",
570                                        interface_name(
571                                            resolve,
572                                            Some(
573                                                &self
574                                                    .interface_names
575                                                    .get(&interface)
576                                                    .cloned()
577                                                    .unwrap_or(WorldKey::Interface(interface))
578                                            )
579                                        )
580                                    )
581                                }
582                            }
583                            _ => String::new(),
584                        };
585
586                        let name = ty.name.as_ref().unwrap().to_snake_case();
587
588                        format!("{package}{name}")
589                    }
590                    TypeDefKind::Option(some) => {
591                        format!("option_{}", self.mangle_name(resolve, *some, local))
592                    }
593                    TypeDefKind::Result(result) => format!(
594                        "result_{}_{}",
595                        result
596                            .ok
597                            .map(|ty| self.mangle_name(resolve, ty, local))
598                            .unwrap_or_else(|| "unit".into()),
599                        result
600                            .err
601                            .map(|ty| self.mangle_name(resolve, ty, local))
602                            .unwrap_or_else(|| "unit".into())
603                    ),
604                    TypeDefKind::List(ty) => {
605                        format!("list_{}", self.mangle_name(resolve, *ty, local))
606                    }
607                    TypeDefKind::Tuple(tuple) => {
608                        let types = tuple
609                            .types
610                            .iter()
611                            .map(|ty| self.mangle_name(resolve, *ty, local))
612                            .collect::<Vec<_>>()
613                            .join("_");
614                        format!("tuple{}_{types}", tuple.types.len())
615                    }
616                    TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
617                        self.mangle_name(resolve, Type::Id(*ty), local)
618                    }
619                    TypeDefKind::Type(ty) => self.mangle_name(resolve, *ty, local),
620                    TypeDefKind::Stream(ty) => {
621                        format!(
622                            "stream_{}",
623                            ty.map(|ty| self.mangle_name(resolve, ty, local))
624                                .unwrap_or_else(|| "unit".into())
625                        )
626                    }
627                    TypeDefKind::Future(ty) => {
628                        format!(
629                            "future_{}",
630                            ty.map(|ty| self.mangle_name(resolve, ty, local))
631                                .unwrap_or_else(|| "unit".into())
632                        )
633                    }
634                    kind => todo!("{kind:?}"),
635                }
636            }
637        }
638    }
639}
640
641impl WorldGenerator for Go {
642    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
643        _ = world;
644        self.sizes.fill(resolve);
645        self.imports.insert("wit_runtime".into());
646    }
647
648    fn import_interface(
649        &mut self,
650        resolve: &Resolve,
651        name: &WorldKey,
652        id: InterfaceId,
653        _files: &mut Files,
654    ) -> Result<()> {
655        if let WorldKey::Name(_) = name {
656            self.interface_names.insert(id, name.clone());
657        }
658
659        let mut data = {
660            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), true);
661            for (name, ty) in resolve.interfaces[id].types.iter() {
662                if !generator.generator.types.contains(ty) {
663                    generator.generator.types.insert(*ty);
664                    generator.define_type(name, *ty);
665                }
666            }
667            InterfaceData::from(generator)
668        };
669
670        for (_, func) in &resolve.interfaces[id].functions {
671            data.extend(self.import(resolve, func, Some(name)));
672        }
673        self.interfaces
674            .entry(interface_name(resolve, Some(name)))
675            .or_default()
676            .extend(data);
677
678        Ok(())
679    }
680
681    fn import_funcs(
682        &mut self,
683        resolve: &Resolve,
684        _world: WorldId,
685        funcs: &[(&str, &Function)],
686        _files: &mut Files,
687    ) {
688        let mut data = InterfaceData::default();
689        for (_, func) in funcs {
690            data.extend(self.import(resolve, func, None));
691        }
692        self.interfaces
693            .entry(interface_name(resolve, None))
694            .or_default()
695            .extend(data);
696    }
697
698    fn export_interface(
699        &mut self,
700        resolve: &Resolve,
701        name: &WorldKey,
702        id: InterfaceId,
703        _files: &mut Files,
704    ) -> Result<()> {
705        if let WorldKey::Name(_) = name {
706            self.interface_names.insert(id, name.clone());
707        }
708
709        for (type_name, ty) in &resolve.interfaces[id].types {
710            let exported = matches!(resolve.types[*ty].kind, TypeDefKind::Resource)
711                || self.has_exported_resource(resolve, Type::Id(*ty));
712
713            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), false);
714
715            if exported || !generator.generator.types.contains(ty) {
716                generator.generator.types.insert(*ty);
717                generator.define_type(type_name, *ty);
718            }
719
720            let data = generator.into();
721
722            if exported {
723                &mut self.export_interfaces
724            } else {
725                &mut self.interfaces
726            }
727            .entry(interface_name(resolve, Some(name)))
728            .or_default()
729            .extend(data);
730        }
731
732        for (_, func) in &resolve.interfaces[id].functions {
733            let code = self.export(resolve, func, Some(name));
734            self.src.push_str(&code);
735        }
736
737        Ok(())
738    }
739
740    fn export_funcs(
741        &mut self,
742        resolve: &Resolve,
743        _world: WorldId,
744        funcs: &[(&str, &Function)],
745        _files: &mut Files,
746    ) -> Result<()> {
747        for (_, func) in funcs {
748            let code = self.export(resolve, func, None);
749            self.src.push_str(&code);
750        }
751        Ok(())
752    }
753
754    fn import_types(
755        &mut self,
756        resolve: &Resolve,
757        _world: WorldId,
758        types: &[(&str, TypeId)],
759        _files: &mut Files,
760    ) {
761        let mut generator = InterfaceGenerator::new(self, resolve, None, true);
762        for (name, ty) in types {
763            if !generator.generator.types.contains(ty) {
764                generator.generator.types.insert(*ty);
765                generator.define_type(name, *ty);
766            }
767        }
768        let data = generator.into();
769        self.interfaces
770            .entry(interface_name(resolve, None))
771            .or_default()
772            .extend(data);
773    }
774
775    fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
776        _ = (resolve, id);
777
778        let version = env!("CARGO_PKG_VERSION");
779        let header = &format!("// Generated by `wit-bindgen` {version}. DO NOT EDIT!");
780
781        let src = mem::take(&mut self.src);
782        let align = self.return_area_align.format(POINTER_SIZE_EXPRESSION);
783        let size = self.return_area_size.format(POINTER_SIZE_EXPRESSION);
784        let imports = self
785            .imports
786            .iter()
787            .map(|v| format!(r#""wit_component/{v}""#))
788            .chain(self.need_math.then(|| r#""math""#.into()))
789            .chain(self.need_unsafe.then(|| r#""unsafe""#.into()))
790            .collect::<Vec<_>>()
791            .join("\n");
792
793        files.push(
794            "wit_bindings.go",
795            &maybe_gofmt(
796                self.opts.format,
797                format!(
798                    r#"{header}
799package main
800
801import (
802        "runtime"
803        {imports}
804)
805
806var staticPinner = runtime.Pinner{{}}
807var {EXPORT_RETURN_AREA} = uintptr(wit_runtime.Allocate(&staticPinner, {size}, {align}))
808var {SYNC_EXPORT_PINNER} = runtime.Pinner{{}}
809
810{src}
811
812// Unused, but present to make the compiler happy
813func main() {{}}
814"#
815                )
816                .as_bytes(),
817            ),
818        );
819        files.push("go.mod", b"module wit_component\n\ngo 1.25");
820        files.push(
821            "wit_runtime/wit_runtime.go",
822            format!("{header}\n{}", include_str!("wit_runtime.go")).as_bytes(),
823        );
824
825        for (prefix, interfaces) in [("export_", &self.export_interfaces), ("", &self.interfaces)] {
826            for (name, data) in interfaces {
827                let imports = data.imports();
828                let code = &data.code;
829
830                files.push(
831                    &format!("{prefix}{name}/wit_bindings.go"),
832                    &maybe_gofmt(
833                        self.opts.format,
834                        format!(
835                            "{header}
836package {prefix}{name}
837
838import (
839        {imports}
840)
841
842{code}"
843                        )
844                        .as_bytes(),
845                    ),
846                );
847            }
848        }
849
850        if !self.tuples.is_empty() {
851            let tuples = self
852                .tuples
853                .iter()
854                .map(|&v| {
855                    let types = (0..v)
856                        .map(|index| format!("T{index} any"))
857                        .collect::<Vec<_>>()
858                        .join(", ");
859                    let fields = (0..v)
860                        .map(|index| format!("F{index} T{index}"))
861                        .collect::<Vec<_>>()
862                        .join("\n");
863                    format!(
864                        "type Tuple{v}[{types}] struct {{
865        {fields}
866}}"
867                    )
868                })
869                .collect::<Vec<_>>()
870                .join("\n");
871
872            files.push(
873                "wit_types/wit_tuples.go",
874                &maybe_gofmt(
875                    self.opts.format,
876                    format!(
877                        r#"{header}
878package wit_types
879
880{tuples}
881"#
882                    )
883                    .as_bytes(),
884                ),
885            );
886        }
887
888        if self.need_async {
889            files.push(
890                "wit_async/wit_async.go",
891                format!("{header}\n{}", include_str!("wit_async.go")).as_bytes(),
892            );
893        }
894
895        if self.need_option {
896            files.push(
897                "wit_types/wit_option.go",
898                format!("{header}\n{}", include_str!("wit_option.go")).as_bytes(),
899            );
900        }
901
902        if self.need_result {
903            files.push(
904                "wit_types/wit_result.go",
905                format!("{header}\n{}", include_str!("wit_result.go")).as_bytes(),
906            );
907        }
908
909        if self.need_unit {
910            files.push(
911                "wit_types/wit_unit.go",
912                format!("{header}\n{}", include_str!("wit_unit.go")).as_bytes(),
913            );
914        }
915
916        if self.need_future {
917            files.push(
918                "wit_types/wit_future.go",
919                format!("{header}\n{}", include_str!("wit_future.go")).as_bytes(),
920            );
921        }
922
923        if self.need_stream {
924            files.push(
925                "wit_types/wit_stream.go",
926                format!("{header}\n{}", include_str!("wit_stream.go")).as_bytes(),
927            );
928        }
929
930        Ok(())
931    }
932}
933
934impl Go {
935    fn import(
936        &mut self,
937        resolve: &Resolve,
938        func: &Function,
939        interface: Option<&WorldKey>,
940    ) -> InterfaceData {
941        self.visit_futures_and_streams(true, resolve, func, interface);
942
943        let async_ = self.opts.async_.is_async(resolve, interface, func, true);
944
945        let (variant, prefix) = if async_ {
946            (AbiVariant::GuestImportAsync, "[async-lower]")
947        } else {
948            (AbiVariant::GuestImport, "")
949        };
950
951        let sig = resolve.wasm_signature(variant, func);
952        let import_name = &func.name;
953        let name = func.name.to_snake_case().replace('.', "_");
954        let (camel, has_self) = func_declaration(resolve, func);
955
956        let module = match interface {
957            Some(name) => resolve.name_world_key(name),
958            None => "$root".to_string(),
959        };
960
961        let params = sig
962            .params
963            .iter()
964            .enumerate()
965            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
966            .collect::<Vec<_>>()
967            .join(", ");
968
969        let results = match &sig.results[..] {
970            [] => "",
971            [result] => wasm_type(*result),
972            _ => unreachable!(),
973        };
974
975        let mut imports = BTreeSet::new();
976        let go_params =
977            self.func_params(resolve, func, interface, true, &mut imports, has_self, "");
978        let go_results = self.func_results(resolve, func, interface, true, &mut imports);
979
980        let raw_name = format!("wasm_import_{name}");
981
982        let go_param_names = has_self
983            .then(|| "self".to_string())
984            .into_iter()
985            .chain(
986                func.params
987                    .iter()
988                    .skip(if has_self { 1 } else { 0 })
989                    .map(|(name, _)| name.to_lower_camel_case()),
990            )
991            .collect::<Vec<_>>();
992
993        let mut generator = FunctionGenerator::new(
994            self,
995            None,
996            interface,
997            interface,
998            &raw_name,
999            go_param_names.clone(),
1000            false,
1001            true,
1002        );
1003        generator.imports = imports;
1004
1005        let code = if async_ {
1006            generator.generator.need_async = true;
1007            generator.imports.insert("wit_async".into());
1008
1009            let (lower, wasm_params) = if sig.indirect_params {
1010                generator.imports.insert("wit_runtime".into());
1011
1012                let params_pointer = generator.locals.tmp("params");
1013                let abi = generator
1014                    .generator
1015                    .sizes
1016                    .record(func.params.iter().map(|(_, ty)| ty));
1017                let size = abi.size.format(POINTER_SIZE_EXPRESSION);
1018                let align = abi.align.format(POINTER_SIZE_EXPRESSION);
1019                let offsets = generator
1020                    .generator
1021                    .sizes
1022                    .field_offsets(func.params.iter().map(|(_, ty)| ty));
1023
1024                for (name, (offset, ty)) in go_param_names.iter().zip(offsets) {
1025                    let offset = offset.format(POINTER_SIZE_EXPRESSION);
1026                    abi::lower_to_memory(
1027                        resolve,
1028                        &mut generator,
1029                        format!("unsafe.Add(unsafe.Pointer({params_pointer}), {offset})"),
1030                        name.clone(),
1031                        ty,
1032                    );
1033                }
1034
1035                let code = mem::take(&mut generator.src);
1036                generator.need_pinner = true;
1037                (
1038                    format!(
1039                        "{params_pointer} := wit_runtime.Allocate({PINNER}, {size}, {align})\n{code}"
1040                    ),
1041                    vec![params_pointer],
1042                )
1043            } else {
1044                let wasm_params = go_param_names
1045                    .iter()
1046                    .zip(&func.params)
1047                    .flat_map(|(name, (_, ty))| {
1048                        abi::lower_flat(resolve, &mut generator, name.clone(), ty)
1049                    })
1050                    .collect();
1051                (mem::take(&mut generator.src), wasm_params)
1052            };
1053
1054            let wasm_params = wasm_params
1055                .iter()
1056                .map(|v| v.as_str())
1057                .chain(func.result.map(|_| IMPORT_RETURN_AREA))
1058                .collect::<Vec<_>>()
1059                .join(", ");
1060
1061            let lift = if let Some(ty) = func.result {
1062                let result = abi::lift_from_memory(
1063                    resolve,
1064                    &mut generator,
1065                    IMPORT_RETURN_AREA.to_string(),
1066                    &ty,
1067                );
1068                let code = mem::take(&mut generator.src);
1069                if let Type::Id(ty) = ty
1070                    && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1071                {
1072                    let count = tuple.types.len();
1073                    let tuple = generator.locals.tmp("tuple");
1074
1075                    let results = (0..count)
1076                        .map(|index| format!("{tuple}.F{index}"))
1077                        .collect::<Vec<_>>()
1078                        .join(", ");
1079
1080                    format!(
1081                        "{code}
1082{tuple} := {result}
1083return {results}"
1084                    )
1085                } else {
1086                    format!("{code}\nreturn {result}")
1087                }
1088            } else {
1089                String::new()
1090            };
1091
1092            format!(
1093                "{lower}
1094wit_async.SubtaskWait(uint32({raw_name}({wasm_params})))
1095{lift}
1096"
1097            )
1098        } else {
1099            abi::call(
1100                resolve,
1101                variant,
1102                LiftLower::LowerArgsLiftResults,
1103                func,
1104                &mut generator,
1105                false,
1106            );
1107            mem::take(&mut generator.src)
1108        };
1109
1110        let return_area = |generator: &mut FunctionGenerator<'_>,
1111                           size: ArchitectureSize,
1112                           align: Alignment| {
1113            generator.imports.insert("wit_runtime".into());
1114            generator.need_pinner = true;
1115            let size = size.format(POINTER_SIZE_EXPRESSION);
1116            let align = align.format(POINTER_SIZE_EXPRESSION);
1117            format!(
1118                "{IMPORT_RETURN_AREA} := uintptr(wit_runtime.Allocate({PINNER}, {size}, {align}))"
1119            )
1120        };
1121
1122        let return_area = if async_ && func.result.is_some() {
1123            let abi = generator.generator.sizes.record(func.result.as_ref());
1124            return_area(&mut generator, abi.size, abi.align)
1125        } else if !(async_ || generator.return_area_size.is_empty()) {
1126            let size = generator.return_area_size;
1127            let align = generator.return_area_align;
1128            return_area(&mut generator, size, align)
1129        } else {
1130            String::new()
1131        };
1132
1133        let pinner = if generator.need_pinner {
1134            format!(
1135                "{PINNER} := &runtime.Pinner{{}}
1136defer {PINNER}.Unpin()
1137"
1138            )
1139        } else {
1140            String::new()
1141        };
1142
1143        InterfaceData::from_generator_and_code(
1144            generator,
1145            format!(
1146                "
1147//go:wasmimport {module} {prefix}{import_name}
1148func {raw_name}({params}) {results}
1149
1150func {camel}({go_params}) {go_results} {{
1151        {pinner}
1152        {return_area}
1153        {code}
1154}}
1155"
1156            ),
1157        )
1158    }
1159
1160    fn export(
1161        &mut self,
1162        resolve: &Resolve,
1163        func: &Function,
1164        interface: Option<&WorldKey>,
1165    ) -> String {
1166        self.visit_futures_and_streams(false, resolve, func, interface);
1167
1168        let async_ = self.opts.async_.is_async(resolve, interface, func, false);
1169
1170        let (variant, prefix) = if async_ {
1171            (AbiVariant::GuestExportAsync, "[async-lift]")
1172        } else {
1173            (AbiVariant::GuestExport, "")
1174        };
1175
1176        let sig = resolve.wasm_signature(variant, func);
1177        let core_module_name = interface.map(|v| resolve.name_world_key(v));
1178        let export_name = func.legacy_core_export_name(core_module_name.as_deref());
1179        let name = func_name(resolve, interface, func);
1180
1181        let params = sig
1182            .params
1183            .iter()
1184            .enumerate()
1185            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
1186            .collect::<Vec<_>>()
1187            .join(", ");
1188
1189        let results = match &sig.results[..] {
1190            [] => "",
1191            [result] => wasm_type(*result),
1192            _ => unreachable!(),
1193        };
1194
1195        let unpin_params =
1196            sig.indirect_params || abi::guest_export_params_have_allocations(resolve, func);
1197
1198        let param_names = (0..sig.params.len()).map(|i| format!("arg{i}")).collect();
1199        let mut generator = FunctionGenerator::new(
1200            self,
1201            Some(&name),
1202            interface,
1203            None,
1204            "INVALID",
1205            param_names,
1206            unpin_params,
1207            false,
1208        );
1209        abi::call(
1210            resolve,
1211            variant,
1212            LiftLower::LiftArgsLowerResults,
1213            func,
1214            &mut generator,
1215            async_,
1216        );
1217        let code = generator.src;
1218        let imports = generator.imports;
1219        let need_unsafe = generator.need_unsafe;
1220        self.need_math |= generator.need_math;
1221        self.need_unsafe |= need_unsafe;
1222        self.imports.extend(imports);
1223
1224        let (pinner, other, start, end) = if async_ {
1225            self.need_async = true;
1226            self.imports.insert("wit_async".into());
1227
1228            let module = match interface {
1229                Some(name) => resolve.name_world_key(name),
1230                None => "$root".to_string(),
1231            };
1232
1233            let function = &func.name;
1234
1235            let task_return_params = func
1236                .result
1237                .map(|ty| {
1238                    let mut storage = vec![WasmType::I32; MAX_FLAT_PARAMS];
1239                    let mut flat = FlatTypes::new(&mut storage);
1240                    if resolve.push_flat(&ty, &mut flat) {
1241                        flat.to_vec()
1242                    } else {
1243                        vec![WasmType::I32]
1244                    }
1245                })
1246                .unwrap_or_default()
1247                .into_iter()
1248                .enumerate()
1249                .map(|(i, ty)| {
1250                    let ty = wasm_type(ty);
1251                    format!("arg{i} {ty}")
1252                })
1253                .collect::<Vec<_>>()
1254                .join(", ");
1255
1256            (
1257                if abi::guest_export_needs_post_return(resolve, func) {
1258                    format!("{PINNER} := &runtime.Pinner{{}}")
1259                } else {
1260                    String::new()
1261                },
1262                format!(
1263                    "
1264
1265//go:wasmexport [callback]{prefix}{export_name}
1266func wasm_export_callback_{name}(event0 uint32, event1 uint32, event2 uint32) uint32 {{
1267        return wit_async.Callback(event0, event1, event2)
1268}}
1269
1270//go:wasmimport [export]{module} [task-return]{function}
1271func wasm_export_task_return_{name}({task_return_params})
1272"
1273                ),
1274                "return int32(wit_async.Run(func() {",
1275                "}))",
1276            )
1277        } else if abi::guest_export_needs_post_return(resolve, func) {
1278            (
1279                format!("{PINNER} := &{SYNC_EXPORT_PINNER}"),
1280                format!(
1281                    "
1282
1283//go:wasmexport cabi_post_{export_name}
1284func wasm_export_post_return_{name}(result {results}) {{
1285        syncExportPinner.Unpin()
1286}}
1287"
1288                ),
1289                "",
1290                "",
1291            )
1292        } else {
1293            (String::new(), String::new(), "", "")
1294        };
1295
1296        if self.opts.generate_stubs {
1297            let (camel, has_self) = func_declaration(resolve, func);
1298
1299            let mut imports = BTreeSet::new();
1300            let params =
1301                self.func_params(resolve, func, interface, false, &mut imports, has_self, "_");
1302            let results = self.func_results(resolve, func, interface, false, &mut imports);
1303
1304            self.export_interfaces
1305                .entry(interface_name(resolve, interface))
1306                .or_default()
1307                .extend(InterfaceData {
1308                    code: format!(
1309                        r#"
1310func {camel}({params}) {results} {{
1311        panic("not implemented")
1312}}
1313"#
1314                    ),
1315                    imports,
1316                    ..InterfaceData::default()
1317                });
1318        }
1319
1320        format!(
1321            "
1322//go:wasmexport {prefix}{export_name}
1323func wasm_export_{name}({params}) {results} {{
1324        {start}
1325        {pinner}
1326        {code}
1327        {end}
1328}}{other}
1329"
1330        )
1331    }
1332
1333    #[expect(clippy::too_many_arguments)]
1334    fn func_params(
1335        &mut self,
1336        resolve: &Resolve,
1337        func: &Function,
1338        interface: Option<&WorldKey>,
1339        in_import: bool,
1340        imports: &mut BTreeSet<String>,
1341        has_self: bool,
1342        prefix: &str,
1343    ) -> String {
1344        func.params
1345            .iter()
1346            .skip(if has_self { 1 } else { 0 })
1347            .map(|(name, ty)| {
1348                let name = name.to_lower_camel_case();
1349                let ty = self.type_name(resolve, *ty, interface, in_import, imports);
1350                format!("{prefix}{name} {ty}")
1351            })
1352            .collect::<Vec<_>>()
1353            .join(", ")
1354    }
1355
1356    fn func_results(
1357        &mut self,
1358        resolve: &Resolve,
1359        func: &Function,
1360        interface: Option<&WorldKey>,
1361        in_import: bool,
1362        imports: &mut BTreeSet<String>,
1363    ) -> String {
1364        if let Some(ty) = &func.result {
1365            if let Type::Id(id) = ty
1366                && let TypeDefKind::Tuple(tuple) = &resolve.types[*id].kind
1367            {
1368                let types = tuple
1369                    .types
1370                    .iter()
1371                    .map(|ty| self.type_name(resolve, *ty, interface, in_import, imports))
1372                    .collect::<Vec<_>>()
1373                    .join(", ");
1374                format!("({types})")
1375            } else {
1376                self.type_name(resolve, *ty, interface, in_import, imports)
1377            }
1378        } else {
1379            String::new()
1380        }
1381    }
1382
1383    fn visit_futures_and_streams(
1384        &mut self,
1385        in_import: bool,
1386        resolve: &Resolve,
1387        func: &Function,
1388        interface: Option<&WorldKey>,
1389    ) {
1390        for (index, ty) in func
1391            .find_futures_and_streams(resolve)
1392            .into_iter()
1393            .enumerate()
1394        {
1395            self.need_async = true;
1396
1397            let payload_type = match &resolve.types[ty].kind {
1398                TypeDefKind::Future(ty) => {
1399                    self.need_future = true;
1400                    ty
1401                }
1402                TypeDefKind::Stream(ty) => {
1403                    self.need_stream = true;
1404                    ty
1405                }
1406                _ => unreachable!(),
1407            };
1408
1409            let exported = payload_type
1410                .map(|ty| self.has_exported_resource(resolve, ty))
1411                .unwrap_or(false);
1412
1413            if let hash_map::Entry::Vacant(e) = self.futures_and_streams.entry((ty, exported)) {
1414                e.insert(interface.cloned());
1415
1416                let data = self.future_or_stream(
1417                    resolve,
1418                    ty,
1419                    index,
1420                    in_import,
1421                    in_import || !exported,
1422                    interface,
1423                    &func.name,
1424                );
1425
1426                if in_import || !exported {
1427                    &mut self.interfaces
1428                } else {
1429                    &mut self.export_interfaces
1430                }
1431                .entry(interface_name(resolve, interface))
1432                .or_default()
1433                .extend(data);
1434            }
1435        }
1436    }
1437
1438    fn has_exported_resource(&self, resolve: &Resolve, ty: Type) -> bool {
1439        any(resolve, ty, &|ty| {
1440            if let Type::Id(id) = ty
1441                && let TypeDefKind::Resource = &resolve.types[id].kind
1442                && let Direction::Export = self.resources.get(&id).unwrap()
1443            {
1444                true
1445            } else {
1446                false
1447            }
1448        })
1449    }
1450}
1451
1452struct FunctionGenerator<'a> {
1453    generator: &'a mut Go,
1454    name: Option<&'a str>,
1455    interface: Option<&'a WorldKey>,
1456    interface_for_types: Option<&'a WorldKey>,
1457    function_to_call: &'a str,
1458    param_names: Vec<String>,
1459    unpin_params: bool,
1460    in_import: bool,
1461    locals: Ns,
1462    src: String,
1463    block_storage: Vec<String>,
1464    blocks: Vec<(String, Vec<String>)>,
1465    need_unsafe: bool,
1466    need_pinner: bool,
1467    need_math: bool,
1468    collect_lifters: bool,
1469    lifter_count: u32,
1470    return_area_size: ArchitectureSize,
1471    return_area_align: Alignment,
1472    imports: BTreeSet<String>,
1473}
1474
1475impl<'a> FunctionGenerator<'a> {
1476    #[expect(clippy::too_many_arguments)]
1477    fn new(
1478        generator: &'a mut Go,
1479        name: Option<&'a str>,
1480        interface: Option<&'a WorldKey>,
1481        interface_for_types: Option<&'a WorldKey>,
1482        function_to_call: &'a str,
1483        param_names: Vec<String>,
1484        unpin_params: bool,
1485        in_import: bool,
1486    ) -> Self {
1487        let mut locals = Ns::default();
1488        for name in &param_names {
1489            locals.insert(name).unwrap();
1490        }
1491
1492        Self {
1493            generator,
1494            name,
1495            interface,
1496            interface_for_types,
1497            function_to_call,
1498            param_names,
1499            unpin_params,
1500            in_import,
1501            locals,
1502            src: String::new(),
1503            block_storage: Vec::new(),
1504            blocks: Vec::new(),
1505            need_unsafe: false,
1506            need_pinner: false,
1507            need_math: false,
1508            collect_lifters: false,
1509            lifter_count: 0,
1510            return_area_size: ArchitectureSize::default(),
1511            return_area_align: Alignment::default(),
1512            imports: BTreeSet::new(),
1513        }
1514    }
1515
1516    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
1517        self.generator.type_name(
1518            resolve,
1519            ty,
1520            self.interface_for_types,
1521            self.in_import,
1522            &mut self.imports,
1523        )
1524    }
1525
1526    fn package_for_owner(
1527        &mut self,
1528        resolve: &Resolve,
1529        owner: Option<&WorldKey>,
1530        ty: TypeId,
1531    ) -> String {
1532        self.generator.package_for_owner(
1533            resolve,
1534            owner,
1535            ty,
1536            self.interface_for_types,
1537            self.in_import,
1538            &mut self.imports,
1539        )
1540    }
1541}
1542
1543impl Bindgen for FunctionGenerator<'_> {
1544    type Operand = String;
1545
1546    fn sizes(&self) -> &SizeAlign {
1547        &self.generator.sizes
1548    }
1549
1550    fn push_block(&mut self) {
1551        let prev = mem::take(&mut self.src);
1552        self.block_storage.push(prev);
1553    }
1554
1555    fn finish_block(&mut self, operands: &mut Vec<String>) {
1556        let to_restore = self.block_storage.pop().unwrap();
1557        let src = mem::replace(&mut self.src, to_restore);
1558        self.blocks.push((src, mem::take(operands)));
1559    }
1560
1561    fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
1562        if self.in_import {
1563            self.return_area_size = self.return_area_size.max(size);
1564            self.return_area_align = self.return_area_align.max(align);
1565
1566            if !self.return_area_size.is_empty() {
1567                self.need_pinner = true;
1568                self.imports.insert("wit_runtime".into());
1569            }
1570
1571            IMPORT_RETURN_AREA.into()
1572        } else {
1573            self.generator.return_area_size = self.generator.return_area_size.max(size);
1574            self.generator.return_area_align = self.generator.return_area_align.max(align);
1575            EXPORT_RETURN_AREA.into()
1576        }
1577    }
1578
1579    fn is_list_canonical(&self, _: &Resolve, ty: &Type) -> bool {
1580        matches!(
1581            ty,
1582            Type::U8
1583                | Type::S8
1584                | Type::U16
1585                | Type::S16
1586                | Type::U32
1587                | Type::S32
1588                | Type::U64
1589                | Type::S64
1590                | Type::F32
1591                | Type::F64
1592        )
1593    }
1594
1595    fn emit(
1596        &mut self,
1597        resolve: &Resolve,
1598        instruction: &Instruction<'_>,
1599        operands: &mut Vec<String>,
1600        results: &mut Vec<String>,
1601    ) {
1602        let store = |me: &mut Self, src, pointer, offset: &ArchitectureSize, ty| {
1603            me.need_unsafe = true;
1604            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1605            uwriteln!(
1606                me.src,
1607                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset})) = {src}"
1608            );
1609        };
1610        let load = |me: &mut Self,
1611                    results: &mut Vec<String>,
1612                    pointer,
1613                    offset: &ArchitectureSize,
1614                    ty,
1615                    cast: &dyn Fn(String) -> String| {
1616            me.need_unsafe = true;
1617            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1618            results.push(cast(format!(
1619                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset}))"
1620            )));
1621        };
1622
1623        match instruction {
1624            Instruction::GetArg { nth } => results.push(self.param_names[*nth].clone()),
1625            Instruction::StringLower { .. } => {
1626                self.need_pinner = true;
1627                self.need_unsafe = true;
1628                let string = &operands[0];
1629                let utf8 = self.locals.tmp("utf8");
1630                uwriteln!(
1631                    self.src,
1632                    "{utf8} := unsafe.Pointer(unsafe.StringData({string}))\n\
1633                     {PINNER}.Pin({utf8})"
1634                );
1635                results.push(format!("uintptr({utf8})"));
1636                results.push(format!("uint32(len({string}))"));
1637            }
1638            Instruction::StringLift { .. } => {
1639                self.need_unsafe = true;
1640                let pointer = &operands[0];
1641                let length = &operands[1];
1642                let value = self.locals.tmp("value");
1643                uwriteln!(
1644                    self.src,
1645                    "{value} := unsafe.String((*uint8)(unsafe.Pointer({pointer})), {length})"
1646                );
1647                results.push(value)
1648            }
1649            Instruction::ListCanonLower { .. } => {
1650                self.need_pinner = true;
1651                self.need_unsafe = true;
1652                let slice = &operands[0];
1653                let data = self.locals.tmp("data");
1654                uwriteln!(
1655                    self.src,
1656                    "{data} := unsafe.Pointer(unsafe.SliceData({slice}))\n\
1657                     {PINNER}.Pin({data})"
1658                );
1659                results.push(format!("uintptr({data})"));
1660                results.push(format!("uint32(len({slice}))"));
1661            }
1662            Instruction::ListCanonLift { element, .. } => {
1663                self.need_unsafe = true;
1664                let pointer = &operands[0];
1665                let length = &operands[1];
1666                let ty = self.type_name(resolve, **element);
1667                let value = self.locals.tmp("value");
1668                uwriteln!(
1669                    self.src,
1670                    "{value} := unsafe.Slice((*{ty})(unsafe.Pointer({pointer})), {length})"
1671                );
1672                results.push(value)
1673            }
1674            Instruction::ListLower { element, .. } => {
1675                self.need_unsafe = true;
1676                self.need_pinner = true;
1677                self.imports.insert("wit_runtime".into());
1678                let (body, _) = self.blocks.pop().unwrap();
1679                let value = &operands[0];
1680                let slice = self.locals.tmp("slice");
1681                let result = self.locals.tmp("result");
1682                let length = self.locals.tmp("length");
1683                let size = self
1684                    .generator
1685                    .sizes
1686                    .size(element)
1687                    .format(POINTER_SIZE_EXPRESSION);
1688                let align = self
1689                    .generator
1690                    .sizes
1691                    .align(element)
1692                    .format(POINTER_SIZE_EXPRESSION);
1693                uwriteln!(
1694                    self.src,
1695                    "{slice} := {value}
1696{length} := uint32(len({slice}))
1697{result} := wit_runtime.Allocate({PINNER}, uintptr({length} * {size}), {align})
1698for index, {ITER_ELEMENT} := range {slice} {{
1699        {ITER_BASE_POINTER} := unsafe.Add({result}, index * {size})
1700        {body}
1701}}
1702"
1703                );
1704                results.push(format!("uintptr({result})"));
1705                results.push(length);
1706            }
1707            Instruction::ListLift { element, .. } => {
1708                self.need_unsafe = true;
1709                let (body, body_results) = self.blocks.pop().unwrap();
1710                let value = &operands[0];
1711                let length = &operands[1];
1712                let result = self.locals.tmp("result");
1713                let size = self
1714                    .generator
1715                    .sizes
1716                    .size(element)
1717                    .format(POINTER_SIZE_EXPRESSION);
1718                let element_type = self.type_name(resolve, **element);
1719                let body_result = &body_results[0];
1720                uwriteln!(
1721                    self.src,
1722                    "{result} := make([]{element_type}, 0, {length})
1723for index := 0; index < int({length}); index++ {{
1724        {ITER_BASE_POINTER} := unsafe.Add(unsafe.Pointer({value}), index * {size})
1725        {body}
1726        {result} = append({result}, {body_result})        
1727}}
1728"
1729                );
1730                results.push(result);
1731            }
1732            Instruction::CallInterface { func, .. } => {
1733                if self.unpin_params {
1734                    self.imports.insert("wit_runtime".into());
1735                    uwriteln!(self.src, "wit_runtime.Unpin()");
1736                }
1737
1738                let name = func.item_name().to_upper_camel_case();
1739                let package = format!("export_{}", interface_name(resolve, self.interface));
1740
1741                let call = match &func.kind {
1742                    FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1743                        let args = operands.join(", ");
1744                        let call = format!("{package}.{name}({args})");
1745                        self.imports.insert(package);
1746                        call
1747                    }
1748                    FunctionKind::Constructor(ty) => {
1749                        let args = operands.join(", ");
1750                        let ty = resolve.types[*ty]
1751                            .name
1752                            .as_ref()
1753                            .unwrap()
1754                            .to_upper_camel_case();
1755                        let call = format!("{package}.Make{ty}({args})");
1756                        self.imports.insert(package);
1757                        call
1758                    }
1759                    FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
1760                        let target = &operands[0];
1761                        let args = operands[1..].join(", ");
1762                        format!("({target}).{name}({args})")
1763                    }
1764                    FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
1765                        let args = operands.join(", ");
1766                        let ty = self.type_name(resolve, Type::Id(*ty));
1767                        format!("{ty}{name}({args})")
1768                    }
1769                };
1770
1771                if let Some(ty) = func.result {
1772                    let result = self.locals.tmp("result");
1773                    if let Type::Id(ty) = ty
1774                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1775                    {
1776                        let count = tuple.types.len();
1777                        self.generator.tuples.insert(count);
1778                        self.imports.insert("wit_types".into());
1779
1780                        let results = (0..count)
1781                            .map(|_| self.locals.tmp("result"))
1782                            .collect::<Vec<_>>()
1783                            .join(", ");
1784
1785                        let types = tuple
1786                            .types
1787                            .iter()
1788                            .map(|&ty| self.type_name(resolve, ty))
1789                            .collect::<Vec<_>>()
1790                            .join(", ");
1791
1792                        uwriteln!(
1793                            self.src,
1794                            "{results} := {call}
1795{result} := wit_types.Tuple{count}[{types}]{{{results}}}"
1796                        );
1797                    } else {
1798                        uwriteln!(self.src, "{result} := {call}");
1799                    }
1800                    results.push(result);
1801                } else {
1802                    uwriteln!(self.src, "{call}");
1803                }
1804            }
1805            Instruction::Return { func, .. } => {
1806                if let Some(ty) = func.result {
1807                    let result = &operands[0];
1808                    if self.in_import
1809                        && let Type::Id(ty) = ty
1810                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1811                    {
1812                        let count = tuple.types.len();
1813                        let tuple = self.locals.tmp("tuple");
1814
1815                        let results = (0..count)
1816                            .map(|index| format!("{tuple}.F{index}"))
1817                            .collect::<Vec<_>>()
1818                            .join(", ");
1819
1820                        uwriteln!(
1821                            self.src,
1822                            "{tuple} := {result}
1823return {results}"
1824                        );
1825                    } else {
1826                        uwriteln!(self.src, "return {result}");
1827                    }
1828                }
1829            }
1830            Instruction::AsyncTaskReturn { .. } => {
1831                let name = self.name.unwrap();
1832                let args = operands.join(", ");
1833                uwriteln!(self.src, "wasm_export_task_return_{name}({args})");
1834            }
1835            Instruction::LengthStore { offset } => store(
1836                self,
1837                &format!("uint32({})", operands[0]),
1838                &operands[1],
1839                offset,
1840                "uint32",
1841            ),
1842            Instruction::PointerStore { offset } => store(
1843                self,
1844                &format!("uint32(uintptr({}))", operands[0]),
1845                &operands[1],
1846                offset,
1847                "uint32",
1848            ),
1849            Instruction::I32Store8 { offset } => store(
1850                self,
1851                &format!("int8({})", operands[0]),
1852                &operands[1],
1853                offset,
1854                "int8",
1855            ),
1856            Instruction::I32Store16 { offset } => store(
1857                self,
1858                &format!("int16({})", operands[0]),
1859                &operands[1],
1860                offset,
1861                "int16",
1862            ),
1863            Instruction::I32Store { offset } => {
1864                store(self, &operands[0], &operands[1], offset, "int32")
1865            }
1866            Instruction::I64Store { offset } => {
1867                store(self, &operands[0], &operands[1], offset, "int64")
1868            }
1869            Instruction::F32Store { offset } => {
1870                store(self, &operands[0], &operands[1], offset, "float32")
1871            }
1872            Instruction::F64Store { offset } => {
1873                store(self, &operands[0], &operands[1], offset, "float64")
1874            }
1875            Instruction::LengthLoad { offset } => {
1876                load(self, results, &operands[0], offset, "uint32", &|v| v)
1877            }
1878            Instruction::PointerLoad { offset } => {
1879                load(self, results, &operands[0], offset, "uint32", &|v| {
1880                    format!("uintptr({v})")
1881                })
1882            }
1883            Instruction::I32Load8U { offset } => {
1884                load(self, results, &operands[0], offset, "uint32", &|v| {
1885                    format!("uint8({v})")
1886                })
1887            }
1888            Instruction::I32Load8S { offset } => {
1889                load(self, results, &operands[0], offset, "uint32", &|v| {
1890                    format!("int8({v})")
1891                })
1892            }
1893            Instruction::I32Load16U { offset } => {
1894                load(self, results, &operands[0], offset, "uint32", &|v| {
1895                    format!("uint16({v})")
1896                })
1897            }
1898            Instruction::I32Load16S { offset } => {
1899                load(self, results, &operands[0], offset, "uint32", &|v| {
1900                    format!("int16({v})")
1901                })
1902            }
1903            Instruction::I32Load { offset } => {
1904                load(self, results, &operands[0], offset, "int32", &|v| v)
1905            }
1906            Instruction::I64Load { offset } => {
1907                load(self, results, &operands[0], offset, "int64", &|v| v)
1908            }
1909            Instruction::F32Load { offset } => {
1910                load(self, results, &operands[0], offset, "float32", &|v| v)
1911            }
1912            Instruction::F64Load { offset } => {
1913                load(self, results, &operands[0], offset, "float64", &|v| v)
1914            }
1915            Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
1916            Instruction::U8FromI32 => results.push(format!("uint8({})", operands[0])),
1917            Instruction::S8FromI32 => results.push(format!("int8({})", operands[0])),
1918            Instruction::U16FromI32 => results.push(format!("uint16({})", operands[0])),
1919            Instruction::S16FromI32 => results.push(format!("int16({})", operands[0])),
1920            Instruction::U32FromI32 => results.push(format!("uint32({})", operands[0])),
1921            Instruction::S32FromI32 | Instruction::S64FromI64 => {
1922                results.push(operands.pop().unwrap())
1923            }
1924            Instruction::U64FromI64 => results.push(format!("uint64({})", operands[0])),
1925            Instruction::I32FromBool => {
1926                let value = &operands[0];
1927                let result = self.locals.tmp("result");
1928                uwriteln!(
1929                    self.src,
1930                    "var {result} int32
1931if {value} {{
1932        {result} = 1
1933}} else {{
1934        {result} = 0
1935}}"
1936                );
1937                results.push(result);
1938            }
1939            Instruction::I32FromU8
1940            | Instruction::I32FromS8
1941            | Instruction::I32FromU16
1942            | Instruction::I32FromS16
1943            | Instruction::I32FromU32 => {
1944                results.push(format!("int32({})", operands[0]));
1945            }
1946            Instruction::I32FromS32 | Instruction::I64FromS64 => {
1947                results.push(operands.pop().unwrap())
1948            }
1949            Instruction::I64FromU64 => results.push(format!("int64({})", operands[0])),
1950            Instruction::CoreF32FromF32
1951            | Instruction::CoreF64FromF64
1952            | Instruction::F32FromCoreF32
1953            | Instruction::F64FromCoreF64 => results.push(operands.pop().unwrap()),
1954            Instruction::CharFromI32 => results.push(format!("rune({})", operands[0])),
1955            Instruction::I32FromChar => results.push(format!("int32({})", operands[0])),
1956            Instruction::TupleLower { tuple, .. } => {
1957                let op = &operands[0];
1958                for index in 0..tuple.types.len() {
1959                    results.push(format!("({op}).F{index}"));
1960                }
1961            }
1962            Instruction::TupleLift { tuple, .. } => {
1963                let count = tuple.types.len();
1964                self.generator.tuples.insert(count);
1965                let types = tuple
1966                    .types
1967                    .iter()
1968                    .map(|&ty| self.type_name(resolve, ty))
1969                    .collect::<Vec<_>>()
1970                    .join(", ");
1971                let fields = operands.join(", ");
1972                self.imports.insert("wit_types".into());
1973                results.push(format!("wit_types.Tuple{count}[{types}]{{{fields}}}"));
1974            }
1975            Instruction::FlagsLower { .. } => {
1976                let value = operands.pop().unwrap();
1977                results.push(format!("int32({value})"))
1978            }
1979            Instruction::FlagsLift { flags, .. } => {
1980                let value = operands.pop().unwrap();
1981                let repr = flags_repr(flags);
1982                results.push(format!("{repr}({value})"))
1983            }
1984            Instruction::RecordLower { record, .. } => {
1985                let op = &operands[0];
1986                for field in &record.fields {
1987                    let field = field.name.to_upper_camel_case();
1988                    results.push(format!("({op}).{field}"));
1989                }
1990            }
1991            Instruction::RecordLift { ty, .. } => {
1992                let name = self.type_name(resolve, Type::Id(*ty));
1993                let fields = operands.join(", ");
1994                results.push(format!("{name}{{{fields}}}"));
1995            }
1996            Instruction::OptionLower {
1997                results: result_types,
1998                ..
1999            } => {
2000                self.generator.need_option = true;
2001                self.imports.insert("wit_types".into());
2002                let (some, some_results) = self.blocks.pop().unwrap();
2003                let (none, none_results) = self.blocks.pop().unwrap();
2004                let value = &operands[0];
2005
2006                let result_names = (0..result_types.len())
2007                    .map(|_| self.locals.tmp("option"))
2008                    .collect::<Vec<_>>();
2009
2010                let declarations = result_types
2011                    .iter()
2012                    .zip(&result_names)
2013                    .map(|(ty, name)| {
2014                        let ty = wasm_type(*ty);
2015                        format!("var {name} {ty}")
2016                    })
2017                    .collect::<Vec<_>>()
2018                    .join("\n");
2019
2020                let some_result_assignments = some_results
2021                    .iter()
2022                    .zip(&result_names)
2023                    .map(|(result, name)| format!("{name} = {result}"))
2024                    .collect::<Vec<_>>()
2025                    .join("\n");
2026
2027                let none_result_assignments = none_results
2028                    .iter()
2029                    .zip(&result_names)
2030                    .map(|(result, name)| format!("{name} = {result}"))
2031                    .collect::<Vec<_>>()
2032                    .join("\n");
2033
2034                results.extend(result_names);
2035
2036                uwriteln!(
2037                    self.src,
2038                    r#"{declarations}
2039switch {value}.Tag() {{
2040case wit_types.OptionNone:
2041        {none}
2042        {none_result_assignments}
2043case wit_types.OptionSome:
2044        {VARIANT_PAYLOAD_NAME} := {value}.Some()
2045        {some}
2046        {some_result_assignments}
2047default:
2048        panic("unreachable")
2049}}"#
2050                );
2051            }
2052            Instruction::OptionLift { ty, payload } => {
2053                self.generator.need_option = true;
2054                self.imports.insert("wit_types".into());
2055                let (some, some_results) = self.blocks.pop().unwrap();
2056                let (none, none_results) = self.blocks.pop().unwrap();
2057                assert!(none_results.is_empty());
2058                assert!(some_results.len() == 1);
2059                let some_result = &some_results[0];
2060                let ty = self.type_name(resolve, Type::Id(*ty));
2061                let some_type = self.type_name(resolve, **payload);
2062                let result = self.locals.tmp("option");
2063                let tag = &operands[0];
2064                uwriteln!(
2065                    self.src,
2066                    r#"var {result} {ty}
2067switch {tag} {{
2068case 0:
2069        {none}
2070        {result} = wit_types.None[{some_type}]()
2071case 1:
2072        {some}
2073        {result} = wit_types.Some[{some_type}]({some_result})
2074default:
2075        panic("unreachable")
2076}}"#
2077                );
2078                results.push(result);
2079            }
2080            Instruction::ResultLower {
2081                result,
2082                results: result_types,
2083                ..
2084            } => {
2085                self.generator.need_result = true;
2086                self.imports.insert("wit_types".into());
2087                let (err, err_results) = self.blocks.pop().unwrap();
2088                let (ok, ok_results) = self.blocks.pop().unwrap();
2089                let value = &operands[0];
2090
2091                let result_names = (0..result_types.len())
2092                    .map(|_| self.locals.tmp("option"))
2093                    .collect::<Vec<_>>();
2094
2095                let declarations = result_types
2096                    .iter()
2097                    .zip(&result_names)
2098                    .map(|(ty, name)| {
2099                        let ty = wasm_type(*ty);
2100                        format!("var {name} {ty}")
2101                    })
2102                    .collect::<Vec<_>>()
2103                    .join("\n");
2104
2105                let ok_result_assignments = ok_results
2106                    .iter()
2107                    .zip(&result_names)
2108                    .map(|(result, name)| format!("{name} = {result}"))
2109                    .collect::<Vec<_>>()
2110                    .join("\n");
2111
2112                let err_result_assignments = err_results
2113                    .iter()
2114                    .zip(&result_names)
2115                    .map(|(result, name)| format!("{name} = {result}"))
2116                    .collect::<Vec<_>>()
2117                    .join("\n");
2118
2119                results.extend(result_names);
2120
2121                let ok_set_payload = if result.ok.is_some() {
2122                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Ok()")
2123                } else {
2124                    self.generator.need_unit = true;
2125                    String::new()
2126                };
2127
2128                let err_set_payload = if result.err.is_some() {
2129                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Err()")
2130                } else {
2131                    self.generator.need_unit = true;
2132                    String::new()
2133                };
2134
2135                uwriteln!(
2136                    self.src,
2137                    r#"{declarations}
2138switch {value}.Tag() {{
2139case wit_types.ResultOk:
2140        {ok_set_payload}
2141        {ok}
2142        {ok_result_assignments}
2143case wit_types.ResultErr:
2144        {err_set_payload}
2145        {err}
2146        {err_result_assignments}
2147default:
2148        panic("unreachable")
2149}}"#
2150                );
2151            }
2152            Instruction::ResultLift { ty, result, .. } => {
2153                self.generator.need_result = true;
2154                self.imports.insert("wit_types".into());
2155                let (err, err_results) = self.blocks.pop().unwrap();
2156                let (ok, ok_results) = self.blocks.pop().unwrap();
2157                assert_eq!(ok_results.is_empty(), result.ok.is_none());
2158                assert_eq!(err_results.is_empty(), result.err.is_none());
2159                let ok_result = if result.ok.is_some() {
2160                    &ok_results[0]
2161                } else {
2162                    self.generator.need_unit = true;
2163                    "wit_types.Unit{}"
2164                };
2165                let err_result = if result.err.is_some() {
2166                    &err_results[0]
2167                } else {
2168                    self.generator.need_unit = true;
2169                    "wit_types.Unit{}"
2170                };
2171                let ty = self.type_name(resolve, Type::Id(*ty));
2172                let ok_type = result
2173                    .ok
2174                    .map(|ty| self.type_name(resolve, ty))
2175                    .unwrap_or_else(|| {
2176                        self.generator.need_unit = true;
2177                        "wit_types.Unit".into()
2178                    });
2179                let err_type = result
2180                    .err
2181                    .map(|ty| self.type_name(resolve, ty))
2182                    .unwrap_or_else(|| {
2183                        self.generator.need_unit = true;
2184                        "wit_types.Unit".into()
2185                    });
2186                let result = self.locals.tmp("result");
2187                let tag = &operands[0];
2188                uwriteln!(
2189                    self.src,
2190                    r#"var {result} {ty}
2191switch {tag} {{
2192case 0:
2193        {ok}
2194        {result} = wit_types.Ok[{ok_type}, {err_type}]({ok_result})
2195case 1:
2196        {err}
2197        {result} = wit_types.Err[{ok_type}, {err_type}]({err_result})
2198default:
2199        panic("unreachable")
2200}}"#
2201                );
2202                results.push(result);
2203            }
2204            Instruction::EnumLower { .. } => results.push(format!("int32({})", operands[0])),
2205            Instruction::EnumLift { enum_, .. } => {
2206                results.push(format!("{}({})", int_repr(enum_.tag()), operands[0]))
2207            }
2208            Instruction::VariantLower {
2209                ty,
2210                variant,
2211                results: result_types,
2212                ..
2213            } => {
2214                let blocks = self
2215                    .blocks
2216                    .drain(self.blocks.len() - variant.cases.len()..)
2217                    .collect::<Vec<_>>();
2218
2219                let ty = self.type_name(resolve, Type::Id(*ty));
2220                let value = &operands[0];
2221
2222                let result_names = (0..result_types.len())
2223                    .map(|_| self.locals.tmp("variant"))
2224                    .collect::<Vec<_>>();
2225
2226                let declarations = result_types
2227                    .iter()
2228                    .zip(&result_names)
2229                    .map(|(ty, name)| {
2230                        let ty = wasm_type(*ty);
2231                        format!("var {name} {ty}")
2232                    })
2233                    .collect::<Vec<_>>()
2234                    .join("\n");
2235
2236                let cases = variant
2237                    .cases
2238                    .iter()
2239                    .zip(blocks)
2240                    .map(|(case, (block, block_results))| {
2241                        let assignments = result_names
2242                            .iter()
2243                            .zip(&block_results)
2244                            .map(|(name, result)| format!("{name} = {result}"))
2245                            .collect::<Vec<_>>()
2246                            .join("\n");
2247
2248                        let name = case.name.to_upper_camel_case();
2249
2250                        let set_payload = if case.ty.is_some() {
2251                            format!("{VARIANT_PAYLOAD_NAME} := {value}.{name}()")
2252                        } else {
2253                            String::new()
2254                        };
2255
2256                        format!(
2257                            "case {ty}{name}:
2258        {set_payload}
2259        {block}
2260        {assignments}
2261"
2262                        )
2263                    })
2264                    .collect::<Vec<_>>()
2265                    .join("\n");
2266
2267                results.extend(result_names);
2268
2269                uwriteln!(
2270                    self.src,
2271                    r#"{declarations}
2272switch {value}.Tag() {{
2273{cases}
2274default:
2275        panic("unreachable")
2276}}"#
2277                );
2278            }
2279            Instruction::VariantLift { ty, variant, .. } => {
2280                let blocks = self
2281                    .blocks
2282                    .drain(self.blocks.len() - variant.cases.len()..)
2283                    .collect::<Vec<_>>();
2284
2285                let ty = self.type_name(resolve, Type::Id(*ty));
2286                let result = self.locals.tmp("variant");
2287                let tag = &operands[0];
2288
2289                let (package, name) = if let Some(index) = ty.find('.') {
2290                    (&ty[..index + 1], &ty[index + 1..])
2291                } else {
2292                    ("", ty.as_str())
2293                };
2294
2295                let cases = variant
2296                    .cases
2297                    .iter()
2298                    .zip(blocks)
2299                    .enumerate()
2300                    .map(|(index, (case, (block, block_results)))| {
2301                        assert_eq!(block_results.is_empty(), case.ty.is_none());
2302                        let payload = if case.ty.is_some() {
2303                            &block_results[0]
2304                        } else {
2305                            ""
2306                        };
2307                        let case = case.name.to_upper_camel_case();
2308                        format!(
2309                            "case {index}:
2310        {block}
2311        {result} = {package}Make{name}{case}({payload})
2312"
2313                        )
2314                    })
2315                    .collect::<Vec<_>>()
2316                    .join("\n");
2317
2318                uwriteln!(
2319                    self.src,
2320                    r#"var {result} {ty}
2321switch {tag} {{
2322{cases}
2323default:
2324        panic("unreachable")
2325}}"#
2326                );
2327                results.push(result);
2328            }
2329            Instruction::VariantPayloadName => results.push(VARIANT_PAYLOAD_NAME.into()),
2330            Instruction::IterElem { .. } => results.push(ITER_ELEMENT.into()),
2331            Instruction::IterBasePointer => results.push(ITER_BASE_POINTER.into()),
2332            Instruction::I32Const { val } => results.push(format!("int32({val})")),
2333            Instruction::ConstZero { tys } => {
2334                results.extend(iter::repeat_with(|| "0".into()).take(tys.len()));
2335            }
2336            Instruction::Bitcasts { casts } => {
2337                results.extend(
2338                    casts
2339                        .iter()
2340                        .zip(operands)
2341                        .map(|(which, op)| cast(op, which, &mut self.need_math)),
2342                );
2343            }
2344            Instruction::FutureLower { .. }
2345            | Instruction::StreamLower { .. }
2346            | Instruction::HandleLower {
2347                handle: Handle::Own(_),
2348                ..
2349            } => {
2350                let op = &operands[0];
2351                if self.collect_lifters {
2352                    self.lifter_count += 1;
2353                    let resource = self.locals.tmp("resource");
2354                    let handle = self.locals.tmp("handle");
2355                    uwriteln!(
2356                        self.src,
2357                        "{resource} := {op}
2358{handle} := {resource}.TakeHandle()
2359lifters = append(lifters, func() {{
2360        {resource}.SetHandle({handle})
2361}})"
2362                    );
2363                    results.push(handle)
2364                } else {
2365                    results.push(format!("({op}).TakeHandle()"))
2366                }
2367            }
2368            Instruction::HandleLower {
2369                handle: Handle::Borrow(_),
2370                ..
2371            } => results.push(format!("({}).Handle()", operands[0])),
2372            Instruction::HandleLift { handle, .. } => {
2373                let (which, resource) = match handle {
2374                    Handle::Borrow(resource) => ("Borrow", resource),
2375                    Handle::Own(resource) => ("Own", resource),
2376                };
2377                let handle = &operands[0];
2378                let ty = self.type_name(resolve, Type::Id(*resource));
2379                results.push(format!("{ty}From{which}Handle(int32(uintptr({handle})))"))
2380            }
2381            Instruction::CallWasm { sig, .. } => {
2382                let assignment = match &sig.results[..] {
2383                    [] => String::new(),
2384                    [_] => {
2385                        let result = self.locals.tmp("result");
2386                        let assignment = format!("{result} := ");
2387                        results.push(result);
2388                        assignment
2389                    }
2390                    _ => unreachable!(),
2391                };
2392                let name = &self.function_to_call;
2393                let params = operands.join(", ");
2394                uwriteln!(self.src, "{assignment}{name}({params})")
2395            }
2396            Instruction::Flush { amt } => {
2397                for op in operands.iter().take(*amt) {
2398                    let result = self.locals.tmp("result");
2399                    uwriteln!(self.src, "{result} := {op};");
2400                    results.push(result);
2401                }
2402            }
2403            Instruction::FutureLift { ty, .. } => {
2404                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2405                let owner = self
2406                    .generator
2407                    .futures_and_streams
2408                    .get(&(*ty, exported))
2409                    .unwrap()
2410                    .clone();
2411                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2412                let TypeDefKind::Future(payload_ty) = &resolve.types[*ty].kind else {
2413                    unreachable!()
2414                };
2415                let camel = if let Some(ty) = payload_ty {
2416                    self.generator
2417                        .mangle_name(resolve, *ty, owner.as_ref())
2418                        .to_upper_camel_case()
2419                } else {
2420                    "Unit".into()
2421                };
2422                let handle = &operands[0];
2423                results.push(format!("{package}LiftFuture{camel}({handle})"));
2424            }
2425            Instruction::StreamLift { ty, .. } => {
2426                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2427                let owner = self
2428                    .generator
2429                    .futures_and_streams
2430                    .get(&(*ty, exported))
2431                    .unwrap()
2432                    .clone();
2433                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2434                let TypeDefKind::Stream(payload_ty) = &resolve.types[*ty].kind else {
2435                    unreachable!()
2436                };
2437                let camel = if let Some(ty) = payload_ty {
2438                    self.generator
2439                        .mangle_name(resolve, *ty, owner.as_ref())
2440                        .to_upper_camel_case()
2441                } else {
2442                    "Unit".into()
2443                };
2444                let handle = &operands[0];
2445                results.push(format!("{package}LiftStream{camel}({handle})"));
2446            }
2447            Instruction::GuestDeallocate { .. } => {
2448                // Nothing to do here; should be handled when calling `pinner.Unpin()`
2449            }
2450            _ => unimplemented!("{instruction:?}"),
2451        }
2452    }
2453}
2454
2455struct InterfaceGenerator<'a> {
2456    generator: &'a mut Go,
2457    resolve: &'a Resolve,
2458    interface: Option<(InterfaceId, &'a WorldKey)>,
2459    in_import: bool,
2460    src: String,
2461    imports: BTreeSet<String>,
2462    need_unsafe: bool,
2463    need_runtime: bool,
2464}
2465
2466impl<'a> InterfaceGenerator<'a> {
2467    fn new(
2468        generator: &'a mut Go,
2469        resolve: &'a Resolve,
2470        interface: Option<(InterfaceId, &'a WorldKey)>,
2471        in_import: bool,
2472    ) -> Self {
2473        Self {
2474            generator,
2475            resolve,
2476            interface,
2477            in_import,
2478            src: String::new(),
2479            imports: BTreeSet::new(),
2480            need_unsafe: false,
2481            need_runtime: false,
2482        }
2483    }
2484
2485    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
2486        self.generator.type_name(
2487            resolve,
2488            ty,
2489            self.interface.map(|(_, key)| key),
2490            self.in_import || !self.generator.has_exported_resource(resolve, ty),
2491            &mut self.imports,
2492        )
2493    }
2494}
2495
2496impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
2497    fn resolve(&self) -> &'a Resolve {
2498        self.resolve
2499    }
2500
2501    fn type_record(&mut self, _: TypeId, name: &str, record: &Record, docs: &Docs) {
2502        let name = name.to_upper_camel_case();
2503
2504        let fields = record
2505            .fields
2506            .iter()
2507            .map(|field| {
2508                let ty = self.type_name(self.resolve, field.ty);
2509                let docs = format_docs(&field.docs);
2510                let field = field.name.to_upper_camel_case();
2511                format!("{docs}{field} {ty}")
2512            })
2513            .collect::<Vec<_>>()
2514            .join("\n");
2515
2516        let docs = format_docs(docs);
2517
2518        uwriteln!(
2519            self.src,
2520            "
2521{docs}type {name} struct {{
2522        {fields} 
2523}}"
2524        )
2525    }
2526
2527    fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs) {
2528        self.generator.resources.insert(
2529            id,
2530            if self.in_import {
2531                Direction::Import
2532            } else {
2533                Direction::Export
2534            },
2535        );
2536
2537        let camel = name.to_upper_camel_case();
2538        let module = self
2539            .interface
2540            .map(|(_, key)| self.resolve.name_world_key(key))
2541            .unwrap_or_else(|| "$root".into());
2542
2543        if self.in_import {
2544            self.imports.insert("wit_runtime".into());
2545            self.need_runtime = true;
2546            let docs = format_docs(docs);
2547            uwriteln!(
2548                self.src,
2549                r#"
2550//go:wasmimport {module} [resource-drop]{name}
2551func resourceDrop{camel}(handle int32)
2552
2553{docs}type {camel} struct {{
2554        handle *wit_runtime.Handle
2555}}
2556
2557func (self *{camel}) TakeHandle() int32 {{
2558        return self.handle.Take()
2559}}
2560
2561func (self *{camel}) SetHandle(handle int32) {{
2562        self.handle.Set(handle)
2563}}
2564
2565func (self *{camel}) Handle() int32 {{
2566        return self.handle.Use()
2567}}
2568
2569func (self *{camel}) Drop() {{
2570	handle := self.handle.TakeOrNil()
2571	if handle != 0 {{
2572		resourceDrop{camel}(handle)
2573	}}
2574}}
2575
2576func {camel}FromOwnHandle(handleValue int32) *{camel} {{
2577        handle := wit_runtime.MakeHandle(handleValue)
2578        value := &{camel}{{handle}}
2579        runtime.AddCleanup(value, func(_ int) {{
2580                handleValue := handle.TakeOrNil()
2581                if handleValue != 0 {{
2582                        resourceDrop{camel}(handleValue)
2583                }}
2584        }}, 0)
2585        return value
2586}}
2587
2588func {camel}FromBorrowHandle(handleValue int32) *{camel} {{
2589	return {camel}FromOwnHandle(handleValue)
2590}}
2591"#
2592            );
2593        } else {
2594            self.need_unsafe = true;
2595            uwriteln!(
2596                self.src,
2597                r#"
2598//go:wasmimport [export]{module} [resource-new]{name}
2599func resourceNew{camel}(pointer unsafe.Pointer) int32
2600
2601//go:wasmimport [export]{module} [resource-rep]{name}
2602func resourceRep{camel}(handle int32) unsafe.Pointer
2603
2604//go:wasmimport [export]{module} [resource-drop]{name}
2605func resourceDrop{camel}(handle int32)
2606
2607//go:wasmexport {module}#[dtor]{name}
2608func resourceDtor{camel}(rep int32) {{
2609        val := (*{camel})(unsafe.Pointer(uintptr(rep)))
2610        val.handle = 0
2611        val.pinner.Unpin()
2612        val.OnDrop()
2613}}
2614
2615func (self *{camel}) TakeHandle() int32 {{
2616	self.pinner.Pin(self)
2617	self.handle = resourceNew{camel}(unsafe.Pointer(self))
2618	return self.handle
2619}}
2620
2621func (self *{camel}) SetHandle(handle int32) {{
2622        if self.handle != handle {{
2623                panic("invalid handle")
2624        }}
2625}}
2626
2627func (self *{camel}) Drop() {{
2628	handle := self.handle
2629	if self.handle != 0 {{
2630		self.handle = 0
2631		resourceDrop{camel}(handle)
2632		self.pinner.Unpin()
2633                self.OnDrop()
2634	}}
2635}}
2636
2637func {camel}FromOwnHandle(handle int32) *{camel} {{
2638	return (*{camel})(unsafe.Pointer(resourceRep{camel}(handle)))
2639}}
2640
2641func {camel}FromBorrowHandle(rep int32) *{camel} {{
2642	return (*{camel})(unsafe.Pointer(uintptr(rep)))
2643}}
2644"#
2645            );
2646
2647            if self.generator.opts.generate_stubs {
2648                self.need_runtime = true;
2649                uwriteln!(
2650                    self.src,
2651                    r#"
2652type {camel} struct {{
2653        pinner runtime.Pinner
2654        handle int32
2655}}
2656
2657func (self *{camel}) OnDrop() {{}}
2658"#
2659                );
2660            }
2661        }
2662    }
2663
2664    fn type_flags(&mut self, _: TypeId, name: &str, flags: &Flags, docs: &Docs) {
2665        let repr = flags_repr(flags);
2666
2667        let name = name.to_upper_camel_case();
2668
2669        let constants = flags
2670            .flags
2671            .iter()
2672            .enumerate()
2673            .map(|(i, flag)| {
2674                let docs = format_docs(&flag.docs);
2675                let flag = flag.name.to_upper_camel_case();
2676                format!("{docs}{name}{flag} {repr} = 1 << {i}")
2677            })
2678            .collect::<Vec<_>>()
2679            .join("\n");
2680
2681        let docs = format_docs(docs);
2682
2683        uwriteln!(
2684            self.src,
2685            "
2686const (
2687{constants}
2688)
2689
2690{docs}type {name} = {repr}"
2691        )
2692    }
2693
2694    fn type_tuple(&mut self, _: TypeId, name: &str, tuple: &Tuple, docs: &Docs) {
2695        self.imports.insert("wit_types".into());
2696        let count = tuple.types.len();
2697        self.generator.tuples.insert(count);
2698        let name = name.to_upper_camel_case();
2699        let docs = format_docs(docs);
2700        let types = tuple
2701            .types
2702            .iter()
2703            .map(|ty| self.type_name(self.resolve, *ty))
2704            .collect::<Vec<_>>()
2705            .join(", ");
2706
2707        uwriteln!(
2708            self.src,
2709            "{docs}type {name} = wit_types.Tuple{count}[{types}]"
2710        );
2711    }
2712
2713    fn type_variant(&mut self, _: TypeId, name: &str, variant: &Variant, docs: &Docs) {
2714        let repr = int_repr(variant.tag());
2715
2716        let name = name.to_upper_camel_case();
2717
2718        let constants = variant
2719            .cases
2720            .iter()
2721            .enumerate()
2722            .map(|(i, case)| {
2723                let docs = format_docs(&case.docs);
2724                let case = case.name.to_upper_camel_case();
2725                format!("{docs}{name}{case} {repr} = {i}")
2726            })
2727            .collect::<Vec<_>>()
2728            .join("\n");
2729
2730        let getters = variant
2731            .cases
2732            .iter()
2733            .filter_map(|case| {
2734                case.ty.map(|ty| {
2735                    let case = case.name.to_upper_camel_case();
2736                    let ty = self.type_name(self.resolve, ty);
2737                    format!(
2738                        r#"func (self {name}) {case}() {ty} {{
2739        if self.tag != {name}{case} {{
2740                panic("tag mismatch")
2741        }}
2742        return self.value.({ty})
2743}}
2744"#
2745                    )
2746                })
2747            })
2748            .collect::<Vec<_>>()
2749            .concat();
2750
2751        let constructors = variant
2752            .cases
2753            .iter()
2754            .map(|case| {
2755                let (param, value) = if let Some(ty) = case.ty {
2756                    let ty = self.type_name(self.resolve, ty);
2757                    (format!("value {ty}"), "value")
2758                } else {
2759                    (String::new(), "nil")
2760                };
2761                let case = case.name.to_upper_camel_case();
2762                format!(
2763                    r#"func Make{name}{case}({param}) {name} {{
2764        return {name}{{{name}{case}, {value}}}
2765}}
2766"#
2767                )
2768            })
2769            .collect::<Vec<_>>()
2770            .concat();
2771
2772        let docs = format_docs(docs);
2773
2774        uwriteln!(
2775            self.src,
2776            "
2777const (
2778{constants}
2779)
2780
2781{docs}type {name} struct {{
2782        tag {repr}
2783        value any
2784}}
2785
2786func (self {name}) Tag() {repr} {{
2787        return self.tag
2788}}
2789
2790{getters}
2791{constructors}
2792"
2793        )
2794    }
2795
2796    fn type_option(&mut self, _: TypeId, name: &str, payload: &Type, docs: &Docs) {
2797        self.generator.need_option = true;
2798        self.imports.insert("wit_types".into());
2799        let name = name.to_upper_camel_case();
2800        let ty = self.type_name(self.resolve, *payload);
2801        let docs = format_docs(docs);
2802        uwriteln!(self.src, "{docs}type {name} = wit_types.Option[{ty}]");
2803    }
2804
2805    fn type_result(&mut self, _: TypeId, name: &str, result: &Result_, docs: &Docs) {
2806        self.generator.need_result = true;
2807        self.imports.insert("wit_types".into());
2808        let name = name.to_upper_camel_case();
2809        let ok_type = result
2810            .ok
2811            .map(|ty| self.type_name(self.resolve, ty))
2812            .unwrap_or_else(|| {
2813                self.generator.need_unit = true;
2814                "wit_types.Unit".into()
2815            });
2816        let err_type = result
2817            .err
2818            .map(|ty| self.type_name(self.resolve, ty))
2819            .unwrap_or_else(|| {
2820                self.generator.need_unit = true;
2821                "wit_types.Unit".into()
2822            });
2823        let docs = format_docs(docs);
2824        uwriteln!(
2825            self.src,
2826            "{docs}type {name} = wit_types.Result[{ok_type}, {err_type}]"
2827        );
2828    }
2829
2830    fn type_enum(&mut self, _: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
2831        let repr = int_repr(enum_.tag());
2832
2833        let name = name.to_upper_camel_case();
2834
2835        let constants = enum_
2836            .cases
2837            .iter()
2838            .enumerate()
2839            .map(|(i, case)| {
2840                let docs = format_docs(&case.docs);
2841                let case = case.name.to_upper_camel_case();
2842                format!("{docs}{name}{case} {repr} = {i}")
2843            })
2844            .collect::<Vec<_>>()
2845            .join("\n");
2846
2847        let docs = format_docs(docs);
2848
2849        uwriteln!(
2850            self.src,
2851            "
2852const (
2853        {constants}
2854)
2855{docs}type {name} = {repr}"
2856        )
2857    }
2858
2859    fn type_alias(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2860        let name = name.to_upper_camel_case();
2861        let ty = self.type_name(self.resolve, *ty);
2862        let docs = format_docs(docs);
2863        uwriteln!(self.src, "{docs}type {name} = {ty}");
2864    }
2865
2866    fn type_list(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2867        let name = name.to_upper_camel_case();
2868        let ty = self.type_name(self.resolve, *ty);
2869        let docs = format_docs(docs);
2870        uwriteln!(self.src, "{docs}type {name} = []{ty}");
2871    }
2872
2873    fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
2874        _ = (id, name, ty, docs);
2875        todo!()
2876    }
2877
2878    fn type_future(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2879        let name = name.to_upper_camel_case();
2880        let ty = self.type_name(self.resolve, Type::Id(id));
2881        let docs = format_docs(docs);
2882        uwriteln!(self.src, "{docs}type {name} = {ty}");
2883    }
2884
2885    fn type_stream(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2886        let name = name.to_upper_camel_case();
2887        let ty = self.type_name(self.resolve, Type::Id(id));
2888        let docs = format_docs(docs);
2889        uwriteln!(self.src, "{docs}type {name} = {ty}");
2890    }
2891}
2892
2893fn interface_name(resolve: &Resolve, interface: Option<&WorldKey>) -> String {
2894    match interface {
2895        Some(WorldKey::Name(name)) => name.to_snake_case(),
2896        Some(WorldKey::Interface(id)) => {
2897            let interface = &resolve.interfaces[*id];
2898            let package = &resolve.packages[interface.package.unwrap()];
2899            let package_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
2900                p.name.namespace == package.name.namespace
2901                    && p.name.name == package.name.name
2902                    && p.name.version != package.name.version
2903            });
2904            let version = if package_has_multiple_versions {
2905                if let Some(version) = &package.name.version {
2906                    format!("{}_", version.to_string().replace(['.', '-', '+'], "_"))
2907                } else {
2908                    String::new()
2909                }
2910            } else {
2911                String::new()
2912            };
2913            let namespace = package.name.namespace.to_snake_case();
2914            let package = package.name.name.to_snake_case();
2915            let interface = interface.name.as_ref().unwrap().to_snake_case();
2916            format!("{namespace}_{package}_{version}{interface}")
2917        }
2918        None => "wit_world".into(),
2919    }
2920}
2921
2922fn func_name(resolve: &Resolve, interface: Option<&WorldKey>, func: &Function) -> String {
2923    let prefix = interface_name(resolve, interface);
2924    let name = func.name.to_snake_case().replace('.', "_");
2925
2926    format!("{prefix}_{name}")
2927}
2928
2929fn wasm_type(ty: WasmType) -> &'static str {
2930    match ty {
2931        WasmType::I32 => "int32",
2932        WasmType::I64 => "int64",
2933        WasmType::F32 => "float32",
2934        WasmType::F64 => "float64",
2935        WasmType::Pointer => "uintptr",
2936        WasmType::PointerOrI64 => "int64",
2937        WasmType::Length => "uint32",
2938    }
2939}
2940
2941fn format_docs(docs: &Docs) -> String {
2942    docs.contents
2943        .as_ref()
2944        .map(|v| {
2945            v.trim()
2946                .lines()
2947                .map(|line| format!("// {line}\n"))
2948                .collect::<Vec<_>>()
2949                .concat()
2950        })
2951        .unwrap_or_default()
2952}
2953
2954fn flags_repr(flags: &Flags) -> &'static str {
2955    match flags.repr() {
2956        FlagsRepr::U8 => "uint8",
2957        FlagsRepr::U16 => "uint16",
2958        FlagsRepr::U32(1) => "uint32",
2959        _ => unreachable!(),
2960    }
2961}
2962
2963fn int_repr(int: Int) -> &'static str {
2964    match int {
2965        Int::U8 => "uint8",
2966        Int::U16 => "uint16",
2967        Int::U32 => "uint32",
2968        Int::U64 => unreachable!(),
2969    }
2970}
2971
2972fn cast(op: &str, which: &Bitcast, need_math: &mut bool) -> String {
2973    match which {
2974        Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
2975            *need_math = true;
2976            format!("math.Float32frombits(uint32({op}))")
2977        }
2978        Bitcast::F32ToI32 => {
2979            *need_math = true;
2980            format!("int32(math.Float32bits({op}))")
2981        }
2982        Bitcast::F32ToI64 => {
2983            *need_math = true;
2984            format!("int64(math.Float32bits({op}))")
2985        }
2986        Bitcast::I64ToF64 => {
2987            *need_math = true;
2988            format!("math.Float64frombits(uint64({op}))")
2989        }
2990        Bitcast::F64ToI64 => {
2991            *need_math = true;
2992            format!("int64(math.Float64bits({op}))")
2993        }
2994        Bitcast::I32ToI64 | Bitcast::LToI64 => {
2995            format!("int64({op})")
2996        }
2997        Bitcast::PToP64 => {
2998            format!("int64({op})")
2999        }
3000        Bitcast::I64ToI32 | Bitcast::I64ToL | Bitcast::PToI32 => {
3001            format!("int32({op})")
3002        }
3003        Bitcast::I64ToP64 | Bitcast::P64ToI64 => op.into(),
3004        Bitcast::P64ToP | Bitcast::LToP | Bitcast::I32ToP => {
3005            format!("uintptr({op})")
3006        }
3007        Bitcast::PToL => {
3008            format!("uint32({op})")
3009        }
3010        Bitcast::I32ToL => {
3011            format!("uint32({op})")
3012        }
3013        Bitcast::LToI32 => {
3014            format!("uint32({op})")
3015        }
3016        Bitcast::None => op.to_string(),
3017        Bitcast::Sequence(sequence) => {
3018            let [first, second] = &**sequence;
3019            let inner = cast(op, first, need_math);
3020            cast(&inner, second, need_math)
3021        }
3022    }
3023}
3024
3025fn any(resolve: &Resolve, ty: Type, fun: &dyn Fn(Type) -> bool) -> bool {
3026    if fun(ty) {
3027        return true;
3028    }
3029
3030    match ty {
3031        Type::Bool
3032        | Type::U8
3033        | Type::S8
3034        | Type::U16
3035        | Type::S16
3036        | Type::U32
3037        | Type::S32
3038        | Type::U64
3039        | Type::S64
3040        | Type::F32
3041        | Type::F64
3042        | Type::Char
3043        | Type::String => false,
3044        Type::Id(id) => {
3045            let ty = &resolve.types[id];
3046            match &ty.kind {
3047                TypeDefKind::Flags(_) | TypeDefKind::Enum(_) | TypeDefKind::Resource => false,
3048                TypeDefKind::Handle(Handle::Own(resource) | Handle::Borrow(resource)) => {
3049                    any(resolve, Type::Id(*resource), fun)
3050                }
3051                TypeDefKind::Record(record) => record
3052                    .fields
3053                    .iter()
3054                    .any(|field| any(resolve, field.ty, fun)),
3055                TypeDefKind::Variant(variant) => variant
3056                    .cases
3057                    .iter()
3058                    .any(|case| case.ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)),
3059                TypeDefKind::Option(ty) | TypeDefKind::List(ty) | TypeDefKind::Type(ty) => {
3060                    any(resolve, *ty, fun)
3061                }
3062                TypeDefKind::Result(result) => result
3063                    .ok
3064                    .map(|ty| any(resolve, ty, fun))
3065                    .or_else(|| result.err.map(|ty| any(resolve, ty, fun)))
3066                    .unwrap_or(false),
3067                TypeDefKind::Tuple(tuple) => tuple.types.iter().any(|ty| any(resolve, *ty, fun)),
3068                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
3069                    ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)
3070                }
3071                _ => todo!("{:?}", ty.kind),
3072            }
3073        }
3074        _ => todo!("{ty:?}"),
3075    }
3076}
3077
3078fn func_declaration(resolve: &Resolve, func: &Function) -> (String, bool) {
3079    match &func.kind {
3080        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
3081            (func.item_name().to_upper_camel_case(), false)
3082        }
3083        FunctionKind::Constructor(ty) => {
3084            let ty = resolve.types[*ty]
3085                .name
3086                .as_ref()
3087                .unwrap()
3088                .to_upper_camel_case();
3089            (format!("Make{ty}"), false)
3090        }
3091        FunctionKind::Method(ty) | FunctionKind::AsyncMethod(ty) => {
3092            let ty = resolve.types[*ty]
3093                .name
3094                .as_ref()
3095                .unwrap()
3096                .to_upper_camel_case();
3097            let camel = func.item_name().to_upper_camel_case();
3098            (format!("(self *{ty}) {camel}"), true)
3099        }
3100        FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
3101            let ty = resolve.types[*ty]
3102                .name
3103                .as_ref()
3104                .unwrap()
3105                .to_upper_camel_case();
3106            let camel = func.item_name().to_upper_camel_case();
3107            (format!("{ty}{camel}"), false)
3108        }
3109    }
3110}
3111
3112fn maybe_gofmt<'a>(format: Format, code: &'a [u8]) -> Cow<'a, [u8]> {
3113    thread::scope(|s| {
3114        if let Format::True = format
3115            && let Ok((reader, mut writer)) = io::pipe()
3116        {
3117            s.spawn(move || {
3118                _ = writer.write_all(code);
3119            });
3120
3121            if let Ok(output) = Command::new("gofmt").stdin(reader).output()
3122                && output.status.success()
3123            {
3124                return Cow::Owned(output.stdout);
3125            }
3126        }
3127
3128        Cow::Borrowed(code)
3129    })
3130}