wit_bindgen_teavm_java/
lib.rs

1use anyhow::Result;
2use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
3use std::{
4    collections::{HashMap, HashSet},
5    fmt::Write,
6    iter, mem,
7    ops::Deref,
8};
9use wit_bindgen_core::{
10    abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType},
11    uwrite, uwriteln,
12    wit_parser::{
13        Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Int, InterfaceId, Record, Resolve,
14        Result_, SizeAlign, Tuple, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, Variant, WorldId,
15        WorldKey,
16    },
17    Direction, Files, InterfaceGenerator as _, Ns, Source, WorldGenerator,
18};
19
20const IMPORTS: &str = "\
21import java.nio.charset.StandardCharsets;
22import java.util.ArrayList;
23
24import org.teavm.interop.Memory;
25import org.teavm.interop.Address;
26import org.teavm.interop.Import;
27import org.teavm.interop.Export;\
28";
29
30#[derive(Default, Debug, Clone)]
31#[cfg_attr(feature = "clap", derive(clap::Args))]
32pub struct Opts {
33    /// Whether or not to generate a stub class for exported functions
34    #[cfg_attr(feature = "clap", arg(long))]
35    pub generate_stub: bool,
36}
37
38impl Opts {
39    pub fn build(&self) -> Box<dyn WorldGenerator> {
40        Box::new(TeaVmJava {
41            opts: self.clone(),
42            ..TeaVmJava::default()
43        })
44    }
45}
46
47struct InterfaceFragment {
48    src: String,
49    stub: String,
50}
51
52#[derive(Default)]
53pub struct TeaVmJava {
54    opts: Opts,
55    name: String,
56    return_area_size: usize,
57    return_area_align: usize,
58    tuple_counts: HashSet<usize>,
59    needs_cleanup: bool,
60    needs_result: bool,
61    interface_fragments: HashMap<String, Vec<InterfaceFragment>>,
62    world_fragments: Vec<InterfaceFragment>,
63    sizes: SizeAlign,
64    interface_names: HashMap<InterfaceId, String>,
65}
66
67impl TeaVmJava {
68    fn qualifier(&self) -> String {
69        format!("{}.", self.name)
70    }
71
72    fn interface<'a>(&'a mut self, resolve: &'a Resolve, name: &'a str) -> InterfaceGenerator<'a> {
73        InterfaceGenerator {
74            src: String::new(),
75            stub: String::new(),
76            gen: self,
77            resolve,
78            name,
79        }
80    }
81}
82
83impl WorldGenerator for TeaVmJava {
84    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
85        self.name = world_name(resolve, world);
86        self.sizes.fill(resolve);
87    }
88
89    fn import_interface(
90        &mut self,
91        resolve: &Resolve,
92        key: &WorldKey,
93        id: InterfaceId,
94        _files: &mut Files,
95    ) -> Result<()> {
96        let name = interface_name(resolve, key, Direction::Import);
97        self.interface_names.insert(id, name.clone());
98        let mut gen = self.interface(resolve, &name);
99        gen.types(id);
100
101        for (_, func) in resolve.interfaces[id].functions.iter() {
102            gen.import(&resolve.name_world_key(key), func);
103        }
104
105        gen.add_interface_fragment();
106
107        Ok(())
108    }
109
110    fn import_funcs(
111        &mut self,
112        resolve: &Resolve,
113        world: WorldId,
114        funcs: &[(&str, &Function)],
115        _files: &mut Files,
116    ) {
117        let name = world_name(resolve, world);
118        let mut gen = self.interface(resolve, &name);
119
120        for (_, func) in funcs {
121            gen.import("$root", func);
122        }
123
124        gen.add_world_fragment();
125    }
126
127    fn export_interface(
128        &mut self,
129        resolve: &Resolve,
130        key: &WorldKey,
131        id: InterfaceId,
132        _files: &mut Files,
133    ) -> Result<()> {
134        let name = interface_name(resolve, key, Direction::Export);
135        self.interface_names.insert(id, name.clone());
136        let mut gen = self.interface(resolve, &name);
137        gen.types(id);
138
139        for (_, func) in resolve.interfaces[id].functions.iter() {
140            gen.export(Some(&resolve.name_world_key(key)), func);
141        }
142
143        gen.add_interface_fragment();
144        Ok(())
145    }
146
147    fn export_funcs(
148        &mut self,
149        resolve: &Resolve,
150        world: WorldId,
151        funcs: &[(&str, &Function)],
152        _files: &mut Files,
153    ) -> Result<()> {
154        let name = world_name(resolve, world);
155        let mut gen = self.interface(resolve, &name);
156
157        for (_, func) in funcs {
158            gen.export(None, func);
159        }
160
161        gen.add_world_fragment();
162        Ok(())
163    }
164
165    fn import_types(
166        &mut self,
167        resolve: &Resolve,
168        world: WorldId,
169        types: &[(&str, TypeId)],
170        _files: &mut Files,
171    ) {
172        let name = world_name(resolve, world);
173        let mut gen = self.interface(resolve, &name);
174
175        for (ty_name, ty) in types {
176            gen.define_type(ty_name, *ty);
177        }
178
179        gen.add_world_fragment();
180    }
181
182    fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
183        let name = world_name(resolve, id);
184        let (package, name) = split_qualified_name(&name);
185
186        let mut src = Source::default();
187        let version = env!("CARGO_PKG_VERSION");
188        wit_bindgen_core::generated_preamble(&mut src, version);
189
190        uwrite!(
191            src,
192            "package {package};
193
194             {IMPORTS}
195             import org.teavm.interop.CustomSection;
196
197             public final class {name} {{
198                private {name}() {{}}
199            "
200        );
201
202        src.push_str(
203            &self
204                .world_fragments
205                .iter()
206                .map(|f| f.src.deref())
207                .collect::<Vec<_>>()
208                .join("\n"),
209        );
210
211        let mut producers = wasm_metadata::Producers::empty();
212        producers.add(
213            "processed-by",
214            env!("CARGO_PKG_NAME"),
215            env!("CARGO_PKG_VERSION"),
216        );
217
218        let component_type = wit_component::metadata::encode(
219            resolve,
220            id,
221            wit_component::StringEncoding::UTF8,
222            Some(&producers),
223        )
224        .unwrap();
225
226        let component_type = component_type
227            .into_iter()
228            .map(|byte| format!("{byte:02x}"))
229            .collect::<Vec<_>>()
230            .concat();
231
232        uwriteln!(
233            src,
234            r#"
235            @CustomSection(name = "component-type:{name}")
236            private static final String __WIT_BINDGEN_COMPONENT_TYPE = "{component_type}";
237            "#
238        );
239
240        for &count in &self.tuple_counts {
241            let (type_params, instance) = if count == 0 {
242                (
243                    String::new(),
244                    "public static final Tuple0 INSTANCE = new Tuple0();",
245                )
246            } else {
247                (
248                    format!(
249                        "<{}>",
250                        (0..count)
251                            .map(|index| format!("T{index}"))
252                            .collect::<Vec<_>>()
253                            .join(", ")
254                    ),
255                    "",
256                )
257            };
258            let value_params = (0..count)
259                .map(|index| format!("T{index} f{index}"))
260                .collect::<Vec<_>>()
261                .join(", ");
262            let fields = (0..count)
263                .map(|index| format!("public final T{index} f{index};"))
264                .collect::<Vec<_>>()
265                .join("\n");
266            let inits = (0..count)
267                .map(|index| format!("this.f{index} = f{index};"))
268                .collect::<Vec<_>>()
269                .join("\n");
270
271            uwrite!(
272                src,
273                "
274                public static final class Tuple{count}{type_params} {{
275                    {fields}
276
277                    public Tuple{count}({value_params}) {{
278                        {inits}
279                    }}
280
281                    {instance}
282                }}
283                "
284            )
285        }
286
287        if self.needs_result {
288            src.push_str(
289                r#"
290                public static final class Result<Ok, Err> {
291                    public final byte tag;
292                    private final Object value;
293
294                    private Result(byte tag, Object value) {
295                        this.tag = tag;
296                        this.value = value;
297                    }
298
299                    public static <Ok, Err> Result<Ok, Err> ok(Ok ok) {
300                        return new Result<>(OK, ok);
301                    }
302
303                    public static <Ok, Err> Result<Ok, Err> err(Err err) {
304                        return new Result<>(ERR, err);
305                    }
306
307                    public Ok getOk() {
308                        if (this.tag == OK) {
309                            return (Ok) this.value;
310                        } else {
311                            throw new RuntimeException("expected OK, got " + this.tag);
312                        }
313                    }
314
315                    public Err getErr() {
316                        if (this.tag == ERR) {
317                            return (Err) this.value;
318                        } else {
319                            throw new RuntimeException("expected ERR, got " + this.tag);
320                        }
321                    }
322
323                    public static final byte OK = 0;
324                    public static final byte ERR = 1;
325                }
326                "#,
327            )
328        }
329
330        if self.needs_cleanup {
331            src.push_str(
332                "
333                public static final class Cleanup {
334                    public final int address;
335                    public final int size;
336                    public final int align;
337
338                    public Cleanup(int address, int size, int align) {
339                        this.address = address;
340                        this.size = size;
341                        this.align = align;
342                    }
343                }
344                ",
345            );
346        }
347
348        if self.return_area_align > 0 {
349            let size = self.return_area_size;
350            let align = self.return_area_align;
351
352            uwriteln!(
353                src,
354                "public static final int RETURN_AREA = Memory.malloc({size}, {align}).toInt();",
355            );
356        }
357
358        src.push_str("}\n");
359
360        let directory = package.replace('.', "/");
361        files.push(&format!("{directory}/{name}.java"), indent(&src).as_bytes());
362
363        let generate_stub =
364            |package: &str, name, fragments: &[InterfaceFragment], files: &mut Files| {
365                let b = fragments
366                    .iter()
367                    .map(|f| f.stub.deref())
368                    .collect::<Vec<_>>()
369                    .join("\n");
370
371                let mut body = Source::default();
372                wit_bindgen_core::generated_preamble(&mut body, version);
373                uwriteln!(
374                    &mut body,
375                    "package {package};
376
377                 {IMPORTS}
378
379                 public class {name} {{
380                     {b}
381                 }}
382                "
383                );
384
385                let directory = package.replace('.', "/");
386                files.push(
387                    &format!("{directory}/{name}.java"),
388                    indent(&body).as_bytes(),
389                );
390            };
391
392        if self.opts.generate_stub {
393            generate_stub(
394                &package,
395                format!("{name}Impl"),
396                &self.world_fragments,
397                files,
398            );
399        }
400
401        for (name, fragments) in &self.interface_fragments {
402            let (package, name) = split_qualified_name(name);
403
404            let b = fragments
405                .iter()
406                .map(|f| f.src.deref())
407                .collect::<Vec<_>>()
408                .join("\n");
409
410            let mut body = Source::default();
411            wit_bindgen_core::generated_preamble(&mut body, version);
412            uwriteln!(
413                &mut body,
414                "package {package};
415
416                 {IMPORTS}
417
418                 public final class {name} {{
419                     private {name}() {{}}
420
421                     {b}
422                 }}
423                "
424            );
425
426            let directory = package.replace('.', "/");
427            files.push(
428                &format!("{directory}/{name}.java"),
429                indent(&body).as_bytes(),
430            );
431
432            if self.opts.generate_stub {
433                generate_stub(&package, format!("{name}Impl"), fragments, files);
434            }
435        }
436
437        Ok(())
438    }
439}
440
441struct InterfaceGenerator<'a> {
442    src: String,
443    stub: String,
444    gen: &'a mut TeaVmJava,
445    resolve: &'a Resolve,
446    name: &'a str,
447}
448
449impl InterfaceGenerator<'_> {
450    fn qualifier(&self, when: bool, ty: &TypeDef) -> String {
451        if let TypeOwner::Interface(id) = &ty.owner {
452            if let Some(name) = self.gen.interface_names.get(id) {
453                if name != self.name {
454                    return format!("{name}.");
455                }
456            }
457        }
458
459        if when {
460            format!("{}.", self.name)
461        } else {
462            String::new()
463        }
464    }
465
466    fn add_interface_fragment(self) {
467        self.gen
468            .interface_fragments
469            .entry(self.name.to_owned())
470            .or_default()
471            .push(InterfaceFragment {
472                src: self.src,
473                stub: self.stub,
474            });
475    }
476
477    fn add_world_fragment(self) {
478        self.gen.world_fragments.push(InterfaceFragment {
479            src: self.src,
480            stub: self.stub,
481        });
482    }
483
484    fn import(&mut self, module: &str, func: &Function) {
485        if func.kind != FunctionKind::Freestanding {
486            todo!("resources");
487        }
488
489        let mut bindgen = FunctionBindgen::new(
490            self,
491            &func.name,
492            func.params
493                .iter()
494                .map(|(name, _)| name.to_java_ident())
495                .collect(),
496        );
497
498        abi::call(
499            bindgen.gen.resolve,
500            AbiVariant::GuestImport,
501            LiftLower::LowerArgsLiftResults,
502            func,
503            &mut bindgen,
504            false,
505        );
506
507        let src = bindgen.src;
508
509        let cleanup_list = if bindgen.needs_cleanup_list {
510            self.gen.needs_cleanup = true;
511
512            format!(
513                "ArrayList<{}Cleanup> cleanupList = new ArrayList<>();\n",
514                self.gen.qualifier()
515            )
516        } else {
517            String::new()
518        };
519
520        let name = &func.name;
521
522        let sig = self.resolve.wasm_signature(AbiVariant::GuestImport, func);
523
524        let result_type = match &sig.results[..] {
525            [] => "void",
526            [result] => wasm_type(*result),
527            _ => unreachable!(),
528        };
529
530        let camel_name = func.name.to_upper_camel_case();
531
532        let params = sig
533            .params
534            .iter()
535            .enumerate()
536            .map(|(i, param)| {
537                let ty = wasm_type(*param);
538                format!("{ty} p{i}")
539            })
540            .collect::<Vec<_>>()
541            .join(", ");
542
543        let sig = self.sig_string(func, false);
544
545        uwrite!(
546            self.src,
547            r#"@Import(name = "{name}", module = "{module}")
548               private static native {result_type} wasmImport{camel_name}({params});
549
550               {sig} {{
551                   {cleanup_list} {src}
552               }}
553            "#
554        );
555    }
556
557    fn export(&mut self, interface_name: Option<&str>, func: &Function) {
558        let sig = self.resolve.wasm_signature(AbiVariant::GuestExport, func);
559
560        let export_name = func.legacy_core_export_name(interface_name);
561
562        let mut bindgen = FunctionBindgen::new(
563            self,
564            &func.name,
565            (0..sig.params.len()).map(|i| format!("p{i}")).collect(),
566        );
567
568        abi::call(
569            bindgen.gen.resolve,
570            AbiVariant::GuestExport,
571            LiftLower::LiftArgsLowerResults,
572            func,
573            &mut bindgen,
574            false,
575        );
576
577        assert!(!bindgen.needs_cleanup_list);
578
579        let src = bindgen.src;
580
581        let result_type = match &sig.results[..] {
582            [] => "void",
583            [result] => wasm_type(*result),
584            _ => unreachable!(),
585        };
586
587        let camel_name = func.name.to_upper_camel_case();
588
589        let params = sig
590            .params
591            .iter()
592            .enumerate()
593            .map(|(i, param)| {
594                let ty = wasm_type(*param);
595                format!("{ty} p{i}")
596            })
597            .collect::<Vec<_>>()
598            .join(", ");
599
600        uwrite!(
601            self.src,
602            r#"
603            @Export(name = "{export_name}")
604            private static {result_type} wasmExport{camel_name}({params}) {{
605                {src}
606            }}
607            "#
608        );
609
610        if abi::guest_export_needs_post_return(self.resolve, func) {
611            let params = sig
612                .results
613                .iter()
614                .enumerate()
615                .map(|(i, param)| {
616                    let ty = wasm_type(*param);
617                    format!("{ty} p{i}")
618                })
619                .collect::<Vec<_>>()
620                .join(", ");
621
622            let mut bindgen = FunctionBindgen::new(
623                self,
624                "INVALID",
625                (0..sig.results.len()).map(|i| format!("p{i}")).collect(),
626            );
627
628            abi::post_return(bindgen.gen.resolve, func, &mut bindgen, false);
629
630            let src = bindgen.src;
631
632            uwrite!(
633                self.src,
634                r#"
635                @Export(name = "cabi_post_{export_name}")
636                private static void wasmExport{camel_name}PostReturn({params}) {{
637                    {src}
638                }}
639                "#
640            );
641        }
642
643        if self.gen.opts.generate_stub {
644            let sig = self.sig_string(func, true);
645
646            uwrite!(
647                self.stub,
648                r#"
649                {sig} {{
650                    throw new RuntimeException("todo");
651                }}
652                "#
653            );
654        }
655    }
656
657    fn type_name(&mut self, ty: &Type) -> String {
658        self.type_name_with_qualifier(ty, false)
659    }
660
661    fn type_name_with_qualifier(&mut self, ty: &Type, qualifier: bool) -> String {
662        match ty {
663            Type::Bool => "boolean".into(),
664            Type::U8 | Type::S8 => "byte".into(),
665            Type::U16 | Type::S16 => "short".into(),
666            Type::U32 | Type::S32 | Type::Char => "int".into(),
667            Type::U64 | Type::S64 => "long".into(),
668            Type::F32 => "float".into(),
669            Type::F64 => "double".into(),
670            Type::String => "String".into(),
671            Type::ErrorContext => todo!("error context type name"),
672            Type::Id(id) => {
673                let ty = &self.resolve.types[*id];
674                match &ty.kind {
675                    TypeDefKind::Type(ty) => self.type_name_with_qualifier(ty, qualifier),
676                    TypeDefKind::List(ty) => {
677                        if is_primitive(ty) {
678                            format!("{}[]", self.type_name(ty))
679                        } else {
680                            format!("ArrayList<{}>", self.type_name_boxed(ty, qualifier))
681                        }
682                    }
683                    TypeDefKind::Tuple(tuple) => {
684                        let count = tuple.types.len();
685                        self.gen.tuple_counts.insert(count);
686
687                        let params = if count == 0 {
688                            String::new()
689                        } else {
690                            format!(
691                                "<{}>",
692                                tuple
693                                    .types
694                                    .iter()
695                                    .map(|ty| self.type_name_boxed(ty, qualifier))
696                                    .collect::<Vec<_>>()
697                                    .join(", ")
698                            )
699                        };
700
701                        format!("{}Tuple{count}{params}", self.gen.qualifier())
702                    }
703                    TypeDefKind::Option(ty) => self.type_name_boxed(ty, qualifier),
704                    TypeDefKind::Result(result) => {
705                        self.gen.needs_result = true;
706                        let mut name = |ty: &Option<Type>| {
707                            ty.as_ref()
708                                .map(|ty| self.type_name_boxed(ty, qualifier))
709                                .unwrap_or_else(|| {
710                                    self.gen.tuple_counts.insert(0);
711
712                                    format!("{}Tuple0", self.gen.qualifier())
713                                })
714                        };
715                        let ok = name(&result.ok);
716                        let err = name(&result.err);
717
718                        format!("{}Result<{ok}, {err}>", self.gen.qualifier())
719                    }
720                    _ => {
721                        if let Some(name) = &ty.name {
722                            format!(
723                                "{}{}",
724                                self.qualifier(qualifier, ty),
725                                name.to_upper_camel_case()
726                            )
727                        } else {
728                            unreachable!()
729                        }
730                    }
731                }
732            }
733        }
734    }
735
736    fn type_name_boxed(&mut self, ty: &Type, qualifier: bool) -> String {
737        match ty {
738            Type::Bool => "Boolean".into(),
739            Type::U8 | Type::S8 => "Byte".into(),
740            Type::U16 | Type::S16 => "Short".into(),
741            Type::U32 | Type::S32 | Type::Char => "Integer".into(),
742            Type::U64 | Type::S64 => "Long".into(),
743            Type::F32 => "Float".into(),
744            Type::F64 => "Double".into(),
745            Type::Id(id) => {
746                let def = &self.resolve.types[*id];
747                match &def.kind {
748                    TypeDefKind::Type(ty) => self.type_name_boxed(ty, qualifier),
749                    _ => self.type_name_with_qualifier(ty, qualifier),
750                }
751            }
752            _ => self.type_name_with_qualifier(ty, qualifier),
753        }
754    }
755
756    fn print_docs(&mut self, docs: &Docs) {
757        if let Some(docs) = &docs.contents {
758            let lines = docs
759                .trim()
760                .lines()
761                .map(|line| format!("* {line}"))
762                .collect::<Vec<_>>()
763                .join("\n");
764
765            uwrite!(
766                self.src,
767                "
768                /**
769                 {lines}
770                 */
771                "
772            )
773        }
774    }
775
776    fn non_empty_type<'a>(&self, ty: Option<&'a Type>) -> Option<&'a Type> {
777        if let Some(ty) = ty {
778            let id = match ty {
779                Type::Id(id) => *id,
780                _ => return Some(ty),
781            };
782            match &self.resolve.types[id].kind {
783                TypeDefKind::Type(t) => self.non_empty_type(Some(t)).map(|_| ty),
784                TypeDefKind::Record(r) => (!r.fields.is_empty()).then_some(ty),
785                TypeDefKind::Tuple(t) => (!t.types.is_empty()).then_some(ty),
786                _ => Some(ty),
787            }
788        } else {
789            None
790        }
791    }
792
793    fn sig_string(&mut self, func: &Function, qualifier: bool) -> String {
794        let name = func.name.to_java_ident();
795
796        let result_type = match &func.result {
797            None => "void".into(),
798            Some(ty) => self.type_name_with_qualifier(ty, qualifier),
799        };
800
801        let params = func
802            .params
803            .iter()
804            .map(|(name, ty)| {
805                let ty = self.type_name_with_qualifier(ty, qualifier);
806                let name = name.to_java_ident();
807                format!("{ty} {name}")
808            })
809            .collect::<Vec<_>>()
810            .join(", ");
811
812        format!("public static {result_type} {name}({params})")
813    }
814}
815
816impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
817    fn resolve(&self) -> &'a Resolve {
818        self.resolve
819    }
820
821    fn type_record(&mut self, _id: TypeId, name: &str, record: &Record, docs: &Docs) {
822        self.print_docs(docs);
823
824        let name = name.to_upper_camel_case();
825
826        let parameters = record
827            .fields
828            .iter()
829            .map(|field| {
830                format!(
831                    "{} {}",
832                    self.type_name(&field.ty),
833                    field.name.to_java_ident()
834                )
835            })
836            .collect::<Vec<_>>()
837            .join(", ");
838
839        let assignments = record
840            .fields
841            .iter()
842            .map(|field| {
843                let name = field.name.to_java_ident();
844                format!("this.{name} = {name};")
845            })
846            .collect::<Vec<_>>()
847            .join("\n");
848
849        let fields = if record.fields.is_empty() {
850            format!("public static final {name} INSTANCE = new {name}();")
851        } else {
852            record
853                .fields
854                .iter()
855                .map(|field| {
856                    format!(
857                        "public final {} {};",
858                        self.type_name(&field.ty),
859                        field.name.to_java_ident()
860                    )
861                })
862                .collect::<Vec<_>>()
863                .join("\n")
864        };
865
866        uwrite!(
867            self.src,
868            "
869            public static final class {name} {{
870                {fields}
871
872                public {name}({parameters}) {{
873                    {assignments}
874                }}
875            }}
876            "
877        );
878    }
879
880    fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs) {
881        _ = (id, name, docs);
882        todo!()
883    }
884
885    fn type_flags(&mut self, _id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
886        self.print_docs(docs);
887
888        let name = name.to_upper_camel_case();
889
890        let ty = match flags.repr() {
891            FlagsRepr::U8 => "byte",
892            FlagsRepr::U16 => "short",
893            FlagsRepr::U32(1) => "int",
894            FlagsRepr::U32(2) => "long",
895            repr => todo!("flags {repr:?}"),
896        };
897
898        let flags = flags
899            .flags
900            .iter()
901            .enumerate()
902            .map(|(i, flag)| {
903                let flag_name = flag.name.to_shouty_snake_case();
904                let suffix = if matches!(flags.repr(), FlagsRepr::U32(2)) {
905                    "L"
906                } else {
907                    ""
908                };
909                format!(
910                    "public static final {name} {flag_name} = new {name}(({ty}) (1{suffix} << {i}));"
911                )
912            })
913            .collect::<Vec<_>>()
914            .join("\n");
915
916        uwrite!(
917            self.src,
918            "
919            public static final class {name} {{
920                public final {ty} value;
921
922                public {name}({ty} value) {{
923                    this.value = value;
924                }}
925
926                {flags}
927            }}
928            "
929        );
930    }
931
932    fn type_tuple(&mut self, id: TypeId, _name: &str, _tuple: &Tuple, _docs: &Docs) {
933        self.type_name(&Type::Id(id));
934    }
935
936    fn type_variant(&mut self, _id: TypeId, name: &str, variant: &Variant, docs: &Docs) {
937        self.print_docs(docs);
938
939        let name = name.to_upper_camel_case();
940        let tag_type = int_type(variant.tag());
941
942        let constructors = variant
943            .cases
944            .iter()
945            .map(|case| {
946                let case_name = case.name.to_java_ident();
947                let tag = case.name.to_shouty_snake_case();
948                let (parameter, argument) = if let Some(ty) = self.non_empty_type(case.ty.as_ref())
949                {
950                    (
951                        format!("{} {case_name}", self.type_name(ty)),
952                        case_name.deref(),
953                    )
954                } else {
955                    (String::new(), "null")
956                };
957
958                format!(
959                    "public static {name} {case_name}({parameter}) {{
960                         return new {name}({tag}, {argument});
961                     }}
962                    "
963                )
964            })
965            .collect::<Vec<_>>()
966            .join("\n");
967
968        let accessors = variant
969            .cases
970            .iter()
971            .filter_map(|case| {
972                self.non_empty_type(case.ty.as_ref()).map(|ty| {
973                    let case_name = case.name.to_upper_camel_case();
974                    let tag = case.name.to_shouty_snake_case();
975                    let ty = self.type_name(ty);
976                    format!(
977                        r#"public {ty} get{case_name}() {{
978                               if (this.tag == {tag}) {{
979                                   return ({ty}) this.value;
980                               }} else {{
981                                   throw new RuntimeException("expected {tag}, got " + this.tag);
982                               }}
983                           }}
984                        "#
985                    )
986                })
987            })
988            .collect::<Vec<_>>()
989            .join("\n");
990
991        let tags = variant
992            .cases
993            .iter()
994            .enumerate()
995            .map(|(i, case)| {
996                let tag = case.name.to_shouty_snake_case();
997                format!("public static final {tag_type} {tag} = {i};")
998            })
999            .collect::<Vec<_>>()
1000            .join("\n");
1001
1002        uwrite!(
1003            self.src,
1004            "
1005            public static final class {name} {{
1006                public final {tag_type} tag;
1007                private final Object value;
1008
1009                private {name}({tag_type} tag, Object value) {{
1010                    this.tag = tag;
1011                    this.value = value;
1012                }}
1013
1014                {constructors}
1015                {accessors}
1016                {tags}
1017            }}
1018            "
1019        );
1020    }
1021
1022    fn type_option(&mut self, id: TypeId, _name: &str, _payload: &Type, _docs: &Docs) {
1023        self.type_name(&Type::Id(id));
1024    }
1025
1026    fn type_result(&mut self, id: TypeId, _name: &str, _result: &Result_, _docs: &Docs) {
1027        self.type_name(&Type::Id(id));
1028    }
1029
1030    fn type_enum(&mut self, _id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1031        self.print_docs(docs);
1032
1033        let name = name.to_upper_camel_case();
1034
1035        let cases = enum_
1036            .cases
1037            .iter()
1038            .map(|case| case.name.to_shouty_snake_case())
1039            .collect::<Vec<_>>()
1040            .join(", ");
1041
1042        uwrite!(
1043            self.src,
1044            "
1045            public static enum {name} {{
1046                {cases}
1047            }}
1048            "
1049        );
1050    }
1051
1052    fn type_alias(&mut self, id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1053        self.type_name(&Type::Id(id));
1054    }
1055
1056    fn type_list(&mut self, id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1057        self.type_name(&Type::Id(id));
1058    }
1059
1060    fn type_future(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1061        _ = (id, name, ty, docs);
1062        todo!()
1063    }
1064
1065    fn type_stream(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1066        _ = (id, name, ty, docs);
1067        todo!()
1068    }
1069
1070    fn type_builtin(&mut self, _id: TypeId, _name: &str, _ty: &Type, _docs: &Docs) {
1071        unimplemented!();
1072    }
1073}
1074
1075struct Block {
1076    body: String,
1077    results: Vec<String>,
1078    element: String,
1079    base: String,
1080}
1081
1082struct Cleanup {
1083    address: String,
1084    size: String,
1085    align: usize,
1086}
1087
1088struct BlockStorage {
1089    body: String,
1090    element: String,
1091    base: String,
1092    cleanup: Vec<Cleanup>,
1093}
1094
1095struct FunctionBindgen<'a, 'b> {
1096    gen: &'b mut InterfaceGenerator<'a>,
1097    func_name: &'b str,
1098    params: Box<[String]>,
1099    src: String,
1100    locals: Ns,
1101    block_storage: Vec<BlockStorage>,
1102    blocks: Vec<Block>,
1103    payloads: Vec<String>,
1104    cleanup: Vec<Cleanup>,
1105    needs_cleanup_list: bool,
1106}
1107
1108impl<'a, 'b> FunctionBindgen<'a, 'b> {
1109    fn new(
1110        gen: &'b mut InterfaceGenerator<'a>,
1111        func_name: &'b str,
1112        params: Box<[String]>,
1113    ) -> FunctionBindgen<'a, 'b> {
1114        Self {
1115            gen,
1116            func_name,
1117            params,
1118            src: String::new(),
1119            locals: Ns::default(),
1120            block_storage: Vec::new(),
1121            blocks: Vec::new(),
1122            payloads: Vec::new(),
1123            cleanup: Vec::new(),
1124            needs_cleanup_list: false,
1125        }
1126    }
1127
1128    fn lower_variant(
1129        &mut self,
1130        cases: &[(&str, Option<Type>)],
1131        lowered_types: &[WasmType],
1132        op: &str,
1133        results: &mut Vec<String>,
1134    ) {
1135        let blocks = self
1136            .blocks
1137            .drain(self.blocks.len() - cases.len()..)
1138            .collect::<Vec<_>>();
1139
1140        let payloads = self
1141            .payloads
1142            .drain(self.payloads.len() - cases.len()..)
1143            .collect::<Vec<_>>();
1144
1145        let lowered = lowered_types
1146            .iter()
1147            .map(|_| self.locals.tmp("lowered"))
1148            .collect::<Vec<_>>();
1149
1150        results.extend(lowered.iter().cloned());
1151
1152        let declarations = lowered
1153            .iter()
1154            .zip(lowered_types)
1155            .map(|(lowered, ty)| format!("{} {lowered};", wasm_type(*ty)))
1156            .collect::<Vec<_>>()
1157            .join("\n");
1158
1159        let cases = cases
1160            .iter()
1161            .zip(blocks)
1162            .zip(payloads)
1163            .enumerate()
1164            .map(
1165                |(i, (((name, ty), Block { body, results, .. }), payload))| {
1166                    let payload = if let Some(ty) = self.gen.non_empty_type(ty.as_ref()) {
1167                        let ty = self.gen.type_name(ty);
1168                        let name = name.to_upper_camel_case();
1169
1170                        format!("{ty} {payload} = ({op}).get{name}();")
1171                    } else {
1172                        String::new()
1173                    };
1174
1175                    let assignments = lowered
1176                        .iter()
1177                        .zip(&results)
1178                        .map(|(lowered, result)| format!("{lowered} = {result};\n"))
1179                        .collect::<Vec<_>>()
1180                        .concat();
1181
1182                    format!(
1183                        "case {i}: {{
1184                         {payload}
1185                         {body}
1186                         {assignments}
1187                         break;
1188                     }}"
1189                    )
1190                },
1191            )
1192            .collect::<Vec<_>>()
1193            .join("\n");
1194
1195        uwrite!(
1196            self.src,
1197            r#"
1198            {declarations}
1199
1200            switch (({op}).tag) {{
1201                {cases}
1202
1203                default: throw new AssertionError("invalid discriminant: " + ({op}).tag);
1204            }}
1205            "#
1206        );
1207    }
1208
1209    fn lift_variant(
1210        &mut self,
1211        ty: &Type,
1212        cases: &[(&str, Option<Type>)],
1213        op: &str,
1214        results: &mut Vec<String>,
1215    ) {
1216        let blocks = self
1217            .blocks
1218            .drain(self.blocks.len() - cases.len()..)
1219            .collect::<Vec<_>>();
1220
1221        let ty = self.gen.type_name(ty);
1222        let generics_position = ty.find('<');
1223        let lifted = self.locals.tmp("lifted");
1224
1225        let cases = cases
1226            .iter()
1227            .zip(blocks)
1228            .enumerate()
1229            .map(|(i, ((case_name, case_ty), Block { body, results, .. }))| {
1230                let payload = if self.gen.non_empty_type(case_ty.as_ref()).is_some() {
1231                    results.into_iter().next().unwrap()
1232                } else if generics_position.is_some() {
1233                    if let Some(ty) = case_ty.as_ref() {
1234                        format!("{}.INSTANCE", self.gen.type_name(ty))
1235                    } else {
1236                        format!("{}Tuple0.INSTANCE", self.gen.gen.qualifier())
1237                    }
1238                } else {
1239                    String::new()
1240                };
1241
1242                let method = case_name.to_java_ident();
1243
1244                let call = if let Some(position) = generics_position {
1245                    let (ty, generics) = ty.split_at(position);
1246                    format!("{ty}.{generics}{method}")
1247                } else {
1248                    format!("{ty}.{method}")
1249                };
1250
1251                format!(
1252                    "case {i}: {{
1253                         {body}
1254                         {lifted} = {call}({payload});
1255                         break;
1256                     }}"
1257                )
1258            })
1259            .collect::<Vec<_>>()
1260            .join("\n");
1261
1262        uwrite!(
1263            self.src,
1264            r#"
1265            {ty} {lifted};
1266
1267            switch ({op}) {{
1268                {cases}
1269
1270                default: throw new AssertionError("invalid discriminant: " + ({op}));
1271            }}
1272            "#
1273        );
1274
1275        results.push(lifted);
1276    }
1277}
1278
1279impl Bindgen for FunctionBindgen<'_, '_> {
1280    type Operand = String;
1281
1282    fn emit(
1283        &mut self,
1284        _resolve: &Resolve,
1285        inst: &Instruction<'_>,
1286        operands: &mut Vec<String>,
1287        results: &mut Vec<String>,
1288    ) {
1289        match inst {
1290            Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
1291            Instruction::I32Const { val } => results.push(val.to_string()),
1292            Instruction::ConstZero { tys } => results.extend(tys.iter().map(|ty| {
1293                match ty {
1294                    WasmType::I32 => "0",
1295                    WasmType::I64 => "0L",
1296                    WasmType::F32 => "0.0F",
1297                    WasmType::F64 => "0.0D",
1298                    WasmType::Pointer => "0",
1299                    WasmType::PointerOrI64 => "0L",
1300                    WasmType::Length => "0",
1301                }
1302                .to_owned()
1303            })),
1304
1305            // TODO: checked
1306            Instruction::U8FromI32 => results.push(format!("(byte) ({})", operands[0])),
1307            Instruction::S8FromI32 => results.push(format!("(byte) ({})", operands[0])),
1308            Instruction::U16FromI32 => results.push(format!("(short) ({})", operands[0])),
1309            Instruction::S16FromI32 => results.push(format!("(short) ({})", operands[0])),
1310
1311            Instruction::I32FromU8 => results.push(format!("((int) ({})) & 0xFF", operands[0])),
1312            Instruction::I32FromU16 => results.push(format!("((int) ({})) & 0xFFFF", operands[0])),
1313
1314            Instruction::I32FromS8 | Instruction::I32FromS16 => {
1315                results.push(format!("(int) ({})", operands[0]))
1316            }
1317
1318            Instruction::CharFromI32
1319            | Instruction::I32FromChar
1320            | Instruction::U32FromI32
1321            | Instruction::S32FromI32
1322            | Instruction::S64FromI64
1323            | Instruction::U64FromI64
1324            | Instruction::I32FromU32
1325            | Instruction::I32FromS32
1326            | Instruction::I64FromS64
1327            | Instruction::I64FromU64
1328            | Instruction::CoreF32FromF32
1329            | Instruction::CoreF64FromF64
1330            | Instruction::F32FromCoreF32
1331            | Instruction::F64FromCoreF64 => results.push(operands[0].clone()),
1332
1333            Instruction::Bitcasts { casts } => results.extend(
1334                casts
1335                    .iter()
1336                    .zip(operands)
1337                    .map(|(cast, op)| perform_cast(op, cast)),
1338            ),
1339
1340            Instruction::I32FromBool => {
1341                results.push(format!("({} ? 1 : 0)", operands[0]));
1342            }
1343            Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
1344
1345            // TODO: checked
1346            Instruction::FlagsLower { flags, .. } => match flags_repr(flags) {
1347                Int::U8 | Int::U16 | Int::U32 => {
1348                    results.push(format!("({}).value", operands[0]));
1349                }
1350                Int::U64 => {
1351                    let op = &operands[0];
1352                    results.push(format!("(int) (({op}).value & 0xffffffffL)"));
1353                    results.push(format!("(int) ((({op}).value >>> 32) & 0xffffffffL)"));
1354                }
1355            },
1356
1357            Instruction::FlagsLift { flags, ty, .. } => match flags_repr(flags) {
1358                Int::U8 | Int::U16 | Int::U32 => {
1359                    results.push(format!(
1360                        "new {}(({}) {})",
1361                        self.gen.type_name(&Type::Id(*ty)),
1362                        int_type(flags_repr(flags)),
1363                        operands[0]
1364                    ));
1365                }
1366                Int::U64 => {
1367                    results.push(format!(
1368                        "new {}(((long) ({})) | (((long) ({})) << 32))",
1369                        self.gen.type_name(&Type::Id(*ty)),
1370                        operands[0],
1371                        operands[1]
1372                    ));
1373                }
1374            },
1375
1376            Instruction::HandleLower { .. } | Instruction::HandleLift { .. } => todo!(),
1377
1378            Instruction::RecordLower { record, .. } => {
1379                let op = &operands[0];
1380                for field in record.fields.iter() {
1381                    results.push(format!("({op}).{}", field.name.to_java_ident()));
1382                }
1383            }
1384            Instruction::RecordLift { ty, .. } | Instruction::TupleLift { ty, .. } => {
1385                let ops = operands
1386                    .iter()
1387                    .map(|op| op.to_string())
1388                    .collect::<Vec<_>>()
1389                    .join(", ");
1390
1391                results.push(format!("new {}({ops})", self.gen.type_name(&Type::Id(*ty))));
1392            }
1393
1394            Instruction::TupleLower { tuple, .. } => {
1395                let op = &operands[0];
1396                for i in 0..tuple.types.len() {
1397                    results.push(format!("({op}).f{i}"));
1398                }
1399            }
1400
1401            Instruction::VariantPayloadName => {
1402                let payload = self.locals.tmp("payload");
1403                results.push(payload.clone());
1404                self.payloads.push(payload);
1405            }
1406
1407            Instruction::VariantLower {
1408                variant,
1409                results: lowered_types,
1410                ..
1411            } => self.lower_variant(
1412                &variant
1413                    .cases
1414                    .iter()
1415                    .map(|case| (case.name.deref(), case.ty))
1416                    .collect::<Vec<_>>(),
1417                lowered_types,
1418                &operands[0],
1419                results,
1420            ),
1421
1422            Instruction::VariantLift { variant, ty, .. } => self.lift_variant(
1423                &Type::Id(*ty),
1424                &variant
1425                    .cases
1426                    .iter()
1427                    .map(|case| (case.name.deref(), case.ty))
1428                    .collect::<Vec<_>>(),
1429                &operands[0],
1430                results,
1431            ),
1432
1433            Instruction::OptionLower {
1434                results: lowered_types,
1435                payload,
1436                ..
1437            } => {
1438                let some = self.blocks.pop().unwrap();
1439                let none = self.blocks.pop().unwrap();
1440                let some_payload = self.payloads.pop().unwrap();
1441                let none_payload = self.payloads.pop().unwrap();
1442
1443                let lowered = lowered_types
1444                    .iter()
1445                    .map(|_| self.locals.tmp("lowered"))
1446                    .collect::<Vec<_>>();
1447
1448                results.extend(lowered.iter().cloned());
1449
1450                let declarations = lowered
1451                    .iter()
1452                    .zip(lowered_types.iter())
1453                    .map(|(lowered, ty)| format!("{} {lowered};", wasm_type(*ty)))
1454                    .collect::<Vec<_>>()
1455                    .join("\n");
1456
1457                let op = &operands[0];
1458
1459                let mut block = |ty: Option<&Type>, Block { body, results, .. }, payload| {
1460                    let payload = if let Some(ty) = self.gen.non_empty_type(ty) {
1461                        let ty = self.gen.type_name(ty);
1462
1463                        format!("{ty} {payload} = ({ty}) ({op});")
1464                    } else {
1465                        String::new()
1466                    };
1467
1468                    let assignments = lowered
1469                        .iter()
1470                        .zip(&results)
1471                        .map(|(lowered, result)| format!("{lowered} = {result};\n"))
1472                        .collect::<Vec<_>>()
1473                        .concat();
1474
1475                    format!(
1476                        "{payload}
1477                         {body}
1478                         {assignments}"
1479                    )
1480                };
1481
1482                let none = block(None, none, none_payload);
1483                let some = block(Some(payload), some, some_payload);
1484
1485                uwrite!(
1486                    self.src,
1487                    r#"
1488                    {declarations}
1489
1490                    if (({op}) == null) {{
1491                        {none}
1492                    }} else {{
1493                        {some}
1494                    }}
1495                    "#
1496                );
1497            }
1498
1499            Instruction::OptionLift { payload, ty } => {
1500                let some = self.blocks.pop().unwrap();
1501                let _none = self.blocks.pop().unwrap();
1502
1503                let ty = self.gen.type_name(&Type::Id(*ty));
1504                let lifted = self.locals.tmp("lifted");
1505                let op = &operands[0];
1506
1507                let payload = if self.gen.non_empty_type(Some(*payload)).is_some() {
1508                    some.results.into_iter().next().unwrap()
1509                } else {
1510                    "null".into()
1511                };
1512
1513                let some = some.body;
1514
1515                uwrite!(
1516                    self.src,
1517                    r#"
1518                    {ty} {lifted};
1519
1520                    switch ({op}) {{
1521                        case 0: {{
1522                            {lifted} = null;
1523                            break;
1524                        }}
1525
1526                        case 1: {{
1527                            {some}
1528                            {lifted} = {payload};
1529                            break;
1530                        }}
1531
1532                        default: throw new AssertionError("invalid discriminant: " + ({op}));
1533                    }}
1534                    "#
1535                );
1536
1537                results.push(lifted);
1538            }
1539
1540            Instruction::ResultLower {
1541                results: lowered_types,
1542                result,
1543                ..
1544            } => self.lower_variant(
1545                &[("ok", result.ok), ("err", result.err)],
1546                lowered_types,
1547                &operands[0],
1548                results,
1549            ),
1550
1551            Instruction::ResultLift { result, ty } => self.lift_variant(
1552                &Type::Id(*ty),
1553                &[("ok", result.ok), ("err", result.err)],
1554                &operands[0],
1555                results,
1556            ),
1557
1558            Instruction::EnumLower { .. } => results.push(format!("{}.ordinal()", operands[0])),
1559
1560            Instruction::EnumLift { ty, .. } => results.push(format!(
1561                "{}.values()[{}]",
1562                self.gen.type_name(&Type::Id(*ty)),
1563                operands[0]
1564            )),
1565
1566            Instruction::ListCanonLower { element, realloc } => {
1567                let op = &operands[0];
1568                let (size, ty) = list_element_info(element);
1569
1570                // Note that we can only reliably use `Address.ofData` for elements with alignment <= 4 because as
1571                // of this writing TeaVM does not guarantee 64 bit items are aligned on 8 byte boundaries.
1572                if realloc.is_none() && size <= 4 {
1573                    results.push(format!("org.teavm.interop.Address.ofData({op}).toInt()"));
1574                } else {
1575                    let address = self.locals.tmp("address");
1576                    let ty = ty.to_upper_camel_case();
1577
1578                    uwrite!(
1579                        self.src,
1580                        "
1581                        org.teavm.interop.Address {address} = Memory.malloc({size} * ({op}).length, {size});
1582                        Memory.put{ty}s({address}, {op}, 0, ({op}).length);
1583                        "
1584                    );
1585
1586                    if realloc.is_none() {
1587                        self.cleanup.push(Cleanup {
1588                            address: format!("{address}.toInt()"),
1589                            size: format!("{size} * ({op}).length"),
1590                            align: size,
1591                        });
1592                    }
1593
1594                    results.push(format!("{address}.toInt()"));
1595                }
1596                results.push(format!("({op}).length"));
1597            }
1598
1599            Instruction::ListCanonLift { element, .. } => {
1600                let (_, ty) = list_element_info(element);
1601                let ty_upper = ty.to_upper_camel_case();
1602                let array = self.locals.tmp("array");
1603                let address = &operands[0];
1604                let length = &operands[1];
1605
1606                uwrite!(
1607                    self.src,
1608                    "
1609                    {ty}[] {array} = new {ty}[{length}];
1610                    Memory.get{ty_upper}s(org.teavm.interop.Address.fromInt({address}), {array}, 0, ({array}).length);
1611                    "
1612                );
1613
1614                results.push(array);
1615            }
1616
1617            Instruction::StringLower { realloc } => {
1618                let op = &operands[0];
1619                let bytes = self.locals.tmp("bytes");
1620                uwriteln!(
1621                    self.src,
1622                    "byte[] {bytes} = ({op}).getBytes(StandardCharsets.UTF_8);"
1623                );
1624
1625                if realloc.is_none() {
1626                    results.push(format!("org.teavm.interop.Address.ofData({bytes}).toInt()"));
1627                } else {
1628                    let address = self.locals.tmp("address");
1629
1630                    uwrite!(
1631                        self.src,
1632                        "
1633                        org.teavm.interop.Address {address} = Memory.malloc({bytes}.length, 1);
1634                        Memory.putBytes({address}, {bytes}, 0, {bytes}.length);
1635                        "
1636                    );
1637
1638                    results.push(format!("{address}.toInt()"));
1639                }
1640                results.push(format!("{bytes}.length"));
1641            }
1642
1643            Instruction::StringLift { .. } => {
1644                let bytes = self.locals.tmp("bytes");
1645                let address = &operands[0];
1646                let length = &operands[1];
1647
1648                uwrite!(
1649                    self.src,
1650                    "
1651                    byte[] {bytes} = new byte[{length}];
1652                    Memory.getBytes(org.teavm.interop.Address.fromInt({address}), {bytes}, 0, {length});
1653                    "
1654                );
1655
1656                results.push(format!("new String({bytes}, StandardCharsets.UTF_8)"));
1657            }
1658
1659            Instruction::ListLower { element, realloc } => {
1660                let Block {
1661                    body,
1662                    results: block_results,
1663                    element: block_element,
1664                    base,
1665                } = self.blocks.pop().unwrap();
1666                assert!(block_results.is_empty());
1667
1668                let op = &operands[0];
1669                let size = self.gen.gen.sizes.size(element).size_wasm32();
1670                let align = self.gen.gen.sizes.align(element).align_wasm32();
1671                let address = self.locals.tmp("address");
1672                let ty = self.gen.type_name(element);
1673                let index = self.locals.tmp("index");
1674
1675                uwrite!(
1676                    self.src,
1677                    "
1678                    int {address} = Memory.malloc(({op}).size() * {size}, {align}).toInt();
1679                    for (int {index} = 0; {index} < ({op}).size(); ++{index}) {{
1680                        {ty} {block_element} = ({op}).get({index});
1681                        int {base} = {address} + ({index} * {size});
1682                        {body}
1683                    }}
1684                    "
1685                );
1686
1687                if realloc.is_none() {
1688                    self.cleanup.push(Cleanup {
1689                        address: address.clone(),
1690                        size: format!("({op}).size() * {size}"),
1691                        align,
1692                    });
1693                }
1694
1695                results.push(address);
1696                results.push(format!("({op}).size()"));
1697            }
1698
1699            Instruction::ListLift { element, .. } => {
1700                let Block {
1701                    body,
1702                    results: block_results,
1703                    base,
1704                    ..
1705                } = self.blocks.pop().unwrap();
1706                let address = &operands[0];
1707                let length = &operands[1];
1708                let array = self.locals.tmp("array");
1709                let ty = self.gen.type_name(element);
1710                let size = self.gen.gen.sizes.size(element).size_wasm32();
1711                let align = self.gen.gen.sizes.align(element).align_wasm32();
1712                let index = self.locals.tmp("index");
1713
1714                let result = match &block_results[..] {
1715                    [result] => result,
1716                    _ => todo!("result count == {}", results.len()),
1717                };
1718
1719                uwrite!(
1720                    self.src,
1721                    "
1722                    ArrayList<{ty}> {array} = new ArrayList<>({length});
1723                    for (int {index} = 0; {index} < ({length}); ++{index}) {{
1724                        int {base} = ({address}) + ({index} * {size});
1725                        {body}
1726                        {array}.add({result});
1727                    }}
1728                    Memory.free(org.teavm.interop.Address.fromInt({address}), ({length}) * {size}, {align});
1729                    "
1730                );
1731
1732                results.push(array);
1733            }
1734
1735            Instruction::IterElem { .. } => {
1736                results.push(self.block_storage.last().unwrap().element.clone())
1737            }
1738
1739            Instruction::IterBasePointer => {
1740                results.push(self.block_storage.last().unwrap().base.clone())
1741            }
1742
1743            Instruction::CallWasm { sig, .. } => {
1744                let assignment = match &sig.results[..] {
1745                    [result] => {
1746                        let ty = wasm_type(*result);
1747                        let result = self.locals.tmp("result");
1748                        let assignment = format!("{ty} {result} = ");
1749                        results.push(result);
1750                        assignment
1751                    }
1752
1753                    [] => String::new(),
1754
1755                    _ => unreachable!(),
1756                };
1757
1758                let func_name = self.func_name.to_upper_camel_case();
1759
1760                let operands = operands.join(", ");
1761
1762                uwriteln!(self.src, "{assignment} wasmImport{func_name}({operands});");
1763            }
1764
1765            Instruction::CallInterface { func, .. } => {
1766                let (assignment, destructure) = match &func.result {
1767                    None => (String::new(), String::new()),
1768                    Some(ty) => {
1769                        let ty = self.gen.type_name(ty);
1770                        let result = self.locals.tmp("result");
1771                        let assignment = format!("{ty} {result} = ");
1772                        results.push(result);
1773                        (assignment, String::new())
1774                    }
1775                };
1776
1777                let module = self.gen.name;
1778                let name = func.name.to_java_ident();
1779
1780                let args = operands.join(", ");
1781
1782                uwrite!(
1783                    self.src,
1784                    "
1785                    {assignment}{module}Impl.{name}({args});
1786                    {destructure}
1787                    "
1788                );
1789            }
1790
1791            Instruction::Return { amt, .. } => {
1792                for Cleanup {
1793                    address,
1794                    size,
1795                    align,
1796                } in &self.cleanup
1797                {
1798                    uwriteln!(
1799                        self.src,
1800                        "Memory.free(org.teavm.interop.Address.fromInt({address}), {size}, {align});"
1801                    );
1802                }
1803
1804                if self.needs_cleanup_list {
1805                    uwrite!(
1806                        self.src,
1807                        "
1808                        for ({}Cleanup cleanup : cleanupList) {{
1809                            Memory.free(org.teavm.interop.Address.fromInt(cleanup.address), cleanup.size, cleanup.align);
1810                        }}
1811                        ",
1812                        self.gen.gen.qualifier()
1813                    );
1814                }
1815
1816                match *amt {
1817                    0 => (),
1818                    1 => uwriteln!(self.src, "return {};", operands[0]),
1819                    count => {
1820                        let results = operands.join(", ");
1821                        uwriteln!(
1822                            self.src,
1823                            "return new {}Tuple{count}<>({results});",
1824                            self.gen.gen.qualifier()
1825                        )
1826                    }
1827                }
1828            }
1829
1830            Instruction::I32Load { offset }
1831            | Instruction::PointerLoad { offset }
1832            | Instruction::LengthLoad { offset } => results.push(format!(
1833                "org.teavm.interop.Address.fromInt(({}) + {offset}).getInt()",
1834                operands[0]
1835            )),
1836
1837            Instruction::I32Load8U { offset } => results.push(format!(
1838                "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte()) & 0xFF)",
1839                operands[0]
1840            )),
1841
1842            Instruction::I32Load8S { offset } => results.push(format!(
1843                "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getByte())",
1844                operands[0]
1845            )),
1846
1847            Instruction::I32Load16U { offset } => results.push(format!(
1848                "(((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort()) & 0xFFFF)",
1849                operands[0]
1850            )),
1851
1852            Instruction::I32Load16S { offset } => results.push(format!(
1853                "((int) org.teavm.interop.Address.fromInt(({}) + {offset}).getShort())",
1854                operands[0]
1855            )),
1856
1857            Instruction::I64Load { offset } => results.push(format!(
1858                "org.teavm.interop.Address.fromInt(({}) + {offset}).getLong()",
1859                operands[0]
1860            )),
1861
1862            Instruction::F32Load { offset } => results.push(format!(
1863                "org.teavm.interop.Address.fromInt(({}) + {offset}).getFloat()",
1864                operands[0]
1865            )),
1866
1867            Instruction::F64Load { offset } => results.push(format!(
1868                "org.teavm.interop.Address.fromInt(({}) + {offset}).getDouble()",
1869                operands[0]
1870            )),
1871
1872            Instruction::I32Store { offset }
1873            | Instruction::PointerStore { offset }
1874            | Instruction::LengthStore { offset } => uwriteln!(
1875                self.src,
1876                "org.teavm.interop.Address.fromInt(({}) + {offset}).putInt({});",
1877                operands[1],
1878                operands[0]
1879            ),
1880
1881            Instruction::I32Store8 { offset } => uwriteln!(
1882                self.src,
1883                "org.teavm.interop.Address.fromInt(({}) + {offset}).putByte((byte) ({}));",
1884                operands[1],
1885                operands[0]
1886            ),
1887
1888            Instruction::I32Store16 { offset } => uwriteln!(
1889                self.src,
1890                "org.teavm.interop.Address.fromInt(({}) + {offset}).putShort((short) ({}));",
1891                operands[1],
1892                operands[0]
1893            ),
1894
1895            Instruction::I64Store { offset } => uwriteln!(
1896                self.src,
1897                "org.teavm.interop.Address.fromInt(({}) + {offset}).putLong({});",
1898                operands[1],
1899                operands[0]
1900            ),
1901
1902            Instruction::F32Store { offset } => uwriteln!(
1903                self.src,
1904                "org.teavm.interop.Address.fromInt(({}) + {offset}).putFloat({});",
1905                operands[1],
1906                operands[0]
1907            ),
1908
1909            Instruction::F64Store { offset } => uwriteln!(
1910                self.src,
1911                "org.teavm.interop.Address.fromInt(({}) + {offset}).putDouble({});",
1912                operands[1],
1913                operands[0]
1914            ),
1915
1916            Instruction::Malloc { .. } => unimplemented!(),
1917
1918            Instruction::GuestDeallocate { size, align } => {
1919                uwriteln!(
1920                    self.src,
1921                    "Memory.free(org.teavm.interop.Address.fromInt({}), {size}, {align});",
1922                    operands[0]
1923                )
1924            }
1925
1926            Instruction::GuestDeallocateString => uwriteln!(
1927                self.src,
1928                "Memory.free(org.teavm.interop.Address.fromInt({}), {}, 1);",
1929                operands[0],
1930                operands[1]
1931            ),
1932
1933            Instruction::GuestDeallocateVariant { blocks } => {
1934                let cases = self
1935                    .blocks
1936                    .drain(self.blocks.len() - blocks..)
1937                    .enumerate()
1938                    .map(|(i, Block { body, results, .. })| {
1939                        assert!(results.is_empty());
1940
1941                        format!(
1942                            "case {i}: {{
1943                                 {body}
1944                                 break;
1945                             }}"
1946                        )
1947                    })
1948                    .collect::<Vec<_>>()
1949                    .join("\n");
1950
1951                let op = &operands[0];
1952
1953                uwrite!(
1954                    self.src,
1955                    "
1956                    switch ({op}) {{
1957                        {cases}
1958                    }}
1959                    "
1960                );
1961            }
1962
1963            Instruction::GuestDeallocateList { element } => {
1964                let Block {
1965                    body,
1966                    results,
1967                    base,
1968                    ..
1969                } = self.blocks.pop().unwrap();
1970                assert!(results.is_empty());
1971
1972                let address = &operands[0];
1973                let length = &operands[1];
1974
1975                let size = self.gen.gen.sizes.size(element).size_wasm32();
1976                let align = self.gen.gen.sizes.align(element).align_wasm32();
1977
1978                if !body.trim().is_empty() {
1979                    let index = self.locals.tmp("index");
1980
1981                    uwrite!(
1982                        self.src,
1983                        "
1984                        for (int {index} = 0; {index} < ({length}); ++{index}) {{
1985                            int {base} = ({address}) + ({index} * {size});
1986                            {body}
1987                        }}
1988                        "
1989                    );
1990                }
1991
1992                uwriteln!(
1993                    self.src,
1994                    "Memory.free(org.teavm.interop.Address.fromInt({address}), ({length}) * {size}, {align});"
1995                );
1996            }
1997
1998            Instruction::Flush { amt } => {
1999                results.extend(operands.iter().take(*amt).map(|v| v.clone()));
2000            }
2001
2002            Instruction::AsyncMalloc { .. }
2003            | Instruction::AsyncPostCallInterface { .. }
2004            | Instruction::AsyncCallReturn { .. }
2005            | Instruction::FutureLower { .. }
2006            | Instruction::FutureLift { .. }
2007            | Instruction::StreamLower { .. }
2008            | Instruction::StreamLift { .. }
2009            | Instruction::ErrorContextLower { .. }
2010            | Instruction::ErrorContextLift { .. }
2011            | Instruction::AsyncCallWasm { .. } => todo!(),
2012        }
2013    }
2014
2015    fn return_pointer(&mut self, size: usize, align: usize) -> String {
2016        self.gen.gen.return_area_size = self.gen.gen.return_area_size.max(size);
2017        self.gen.gen.return_area_align = self.gen.gen.return_area_align.max(align);
2018        format!("{}RETURN_AREA", self.gen.gen.qualifier())
2019    }
2020
2021    fn push_block(&mut self) {
2022        self.block_storage.push(BlockStorage {
2023            body: mem::take(&mut self.src),
2024            element: self.locals.tmp("element"),
2025            base: self.locals.tmp("base"),
2026            cleanup: mem::take(&mut self.cleanup),
2027        });
2028    }
2029
2030    fn finish_block(&mut self, operands: &mut Vec<String>) {
2031        let BlockStorage {
2032            body,
2033            element,
2034            base,
2035            cleanup,
2036        } = self.block_storage.pop().unwrap();
2037
2038        if !self.cleanup.is_empty() {
2039            self.needs_cleanup_list = true;
2040
2041            for Cleanup {
2042                address,
2043                size,
2044                align,
2045            } in &self.cleanup
2046            {
2047                uwriteln!(
2048                    self.src,
2049                    "cleanupList.add(new {}Cleanup({address}, {size}, {align}));",
2050                    self.gen.gen.qualifier()
2051                );
2052            }
2053        }
2054
2055        self.cleanup = cleanup;
2056
2057        self.blocks.push(Block {
2058            body: mem::replace(&mut self.src, body),
2059            results: mem::take(operands),
2060            element,
2061            base,
2062        });
2063    }
2064
2065    fn sizes(&self) -> &SizeAlign {
2066        &self.gen.gen.sizes
2067    }
2068
2069    fn is_list_canonical(&self, _resolve: &Resolve, element: &Type) -> bool {
2070        is_primitive(element)
2071    }
2072}
2073
2074fn perform_cast(op: &str, cast: &Bitcast) -> String {
2075    match cast {
2076        Bitcast::I32ToF32 => {
2077            format!("Float.intBitsToFloat({op})")
2078        }
2079        Bitcast::I64ToF32 => format!("Float.intBitsToFloat((int) ({op}))"),
2080        Bitcast::F32ToI32 => {
2081            format!("Float.floatToIntBits({op})")
2082        }
2083        Bitcast::F32ToI64 => format!("(long) Float.floatToIntBits({op})"),
2084        Bitcast::I64ToF64 => {
2085            format!("Double.longBitsToDouble({op})")
2086        }
2087        Bitcast::F64ToI64 => {
2088            format!("Double.doubleToLongBits({op})")
2089        }
2090        Bitcast::I32ToI64 => format!("(long) ({op})"),
2091        Bitcast::I64ToI32 => format!("(int) ({op})"),
2092        Bitcast::I64ToP64 => format!("{op}"),
2093        Bitcast::P64ToI64 => format!("{op}"),
2094        Bitcast::LToI64 | Bitcast::PToP64 => format!("(long) ({op})"),
2095        Bitcast::I64ToL | Bitcast::P64ToP => format!("(int) ({op})"),
2096        Bitcast::I32ToP
2097        | Bitcast::PToI32
2098        | Bitcast::I32ToL
2099        | Bitcast::LToI32
2100        | Bitcast::LToP
2101        | Bitcast::PToL
2102        | Bitcast::None => op.to_owned(),
2103
2104        Bitcast::Sequence(sequence) => {
2105            let [first, second] = &**sequence;
2106            perform_cast(&perform_cast(op, first), second)
2107        }
2108    }
2109}
2110
2111fn int_type(int: Int) -> &'static str {
2112    match int {
2113        Int::U8 => "byte",
2114        Int::U16 => "short",
2115        Int::U32 => "int",
2116        Int::U64 => "long",
2117    }
2118}
2119
2120fn wasm_type(ty: WasmType) -> &'static str {
2121    match ty {
2122        WasmType::I32 => "int",
2123        WasmType::I64 => "long",
2124        WasmType::F32 => "float",
2125        WasmType::F64 => "double",
2126        WasmType::Pointer => "int",
2127        WasmType::PointerOrI64 => "long",
2128        WasmType::Length => "int",
2129    }
2130}
2131
2132fn flags_repr(flags: &Flags) -> Int {
2133    match flags.repr() {
2134        FlagsRepr::U8 => Int::U8,
2135        FlagsRepr::U16 => Int::U16,
2136        FlagsRepr::U32(1) => Int::U32,
2137        FlagsRepr::U32(2) => Int::U64,
2138        repr => panic!("unimplemented flags {repr:?}"),
2139    }
2140}
2141
2142fn list_element_info(ty: &Type) -> (usize, &'static str) {
2143    match ty {
2144        Type::U8 | Type::S8 => (1, "byte"),
2145        Type::U16 | Type::S16 => (2, "short"),
2146        Type::U32 | Type::S32 => (4, "int"),
2147        Type::U64 | Type::S64 => (8, "long"),
2148        Type::F32 => (4, "float"),
2149        Type::F64 => (8, "double"),
2150        _ => unreachable!(),
2151    }
2152}
2153
2154fn indent(code: &str) -> String {
2155    let mut indented = String::with_capacity(code.len());
2156    let mut indent = 0;
2157    let mut was_empty = false;
2158    for line in code.lines() {
2159        let trimmed = line.trim();
2160        if trimmed.is_empty() {
2161            if was_empty {
2162                continue;
2163            }
2164            was_empty = true;
2165        } else {
2166            was_empty = false;
2167        }
2168
2169        if trimmed.starts_with('}') {
2170            indent -= 1;
2171        }
2172        indented.extend(iter::repeat(' ').take(indent * 4));
2173        indented.push_str(trimmed);
2174        if trimmed.ends_with('{') {
2175            indent += 1;
2176        }
2177        indented.push('\n');
2178    }
2179    indented
2180}
2181
2182fn is_primitive(ty: &Type) -> bool {
2183    matches!(
2184        ty,
2185        Type::U8
2186            | Type::S8
2187            | Type::U16
2188            | Type::S16
2189            | Type::U32
2190            | Type::S32
2191            | Type::U64
2192            | Type::S64
2193            | Type::F32
2194            | Type::F64
2195    )
2196}
2197
2198fn world_name(resolve: &Resolve, world: WorldId) -> String {
2199    format!(
2200        "wit.worlds.{}",
2201        resolve.worlds[world].name.to_upper_camel_case()
2202    )
2203}
2204
2205fn interface_name(resolve: &Resolve, name: &WorldKey, direction: Direction) -> String {
2206    let pkg = match name {
2207        WorldKey::Name(_) => None,
2208        WorldKey::Interface(id) => {
2209            let pkg = resolve.interfaces[*id].package.unwrap();
2210            Some(resolve.packages[pkg].name.clone())
2211        }
2212    };
2213
2214    let name = match name {
2215        WorldKey::Name(name) => name,
2216        WorldKey::Interface(id) => resolve.interfaces[*id].name.as_ref().unwrap(),
2217    }
2218    .to_upper_camel_case();
2219
2220    format!(
2221        "wit.{}.{}{name}",
2222        match direction {
2223            Direction::Import => "imports",
2224            Direction::Export => "exports",
2225        },
2226        if let Some(name) = &pkg {
2227            format!(
2228                "{}.{}.",
2229                name.namespace.to_java_ident(),
2230                name.name.to_java_ident()
2231            )
2232        } else {
2233            String::new()
2234        }
2235    )
2236}
2237
2238fn split_qualified_name(name: &str) -> (String, &str) {
2239    let tokens = name.split('.').collect::<Vec<_>>();
2240
2241    let package = tokens
2242        .iter()
2243        .copied()
2244        .take(tokens.len() - 1)
2245        .collect::<Vec<_>>()
2246        .join(".");
2247
2248    let name = tokens.last().unwrap();
2249
2250    (package, name)
2251}
2252
2253trait ToJavaIdent: ToOwned {
2254    fn to_java_ident(&self) -> Self::Owned;
2255}
2256
2257impl ToJavaIdent for str {
2258    fn to_java_ident(&self) -> String {
2259        // Escape Java keywords
2260        // Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
2261        match self {
2262            "abstract" | "continue" | "for" | "new" | "switch" | "assert" | "default" | "goto"
2263            | "package" | "synchronized" | "boolean" | "do" | "if" | "private" | "this"
2264            | "break" | "double" | "implements" | "protected" | "throw" | "byte" | "else"
2265            | "import" | "public" | "throws" | "case" | "enum" | "instanceof" | "return"
2266            | "transient" | "catch" | "extends" | "int" | "short" | "try" | "char" | "final"
2267            | "interface" | "static" | "void" | "class" | "finally" | "long" | "strictfp"
2268            | "volatile" | "const" | "float" | "native" | "super" | "while" => format!("{self}_"),
2269            _ => self.to_lower_camel_case(),
2270        }
2271    }
2272}