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