witx_codegen/assemblyscript/
function.rs

1use std::io::Write;
2
3use super::*;
4
5impl AssemblyScriptGenerator {
6    pub fn define_func<T: Write>(
7        w: &mut PrettyWriter<T>,
8        module_name: &str,
9        func_witx: &witx::Function,
10    ) -> Result<(), Error> {
11        assert_eq!(func_witx.abi, witx::Abi::Preview1);
12        let name = func_witx.name.as_str().to_string();
13        let params_witx = &func_witx.params;
14        let mut params = vec![];
15        for param_witx in params_witx {
16            let param_name = param_witx.name.as_str();
17            let param_type = ASType::from(&param_witx.tref);
18            params.push((param_name.to_string(), param_type));
19        }
20
21        let results_witx = &func_witx.results;
22        assert_eq!(results_witx.len(), 1);
23        let result_witx = &results_witx[0];
24        let result = ASType::from(&result_witx.tref);
25        let result = match result {
26            ASType::Result(result) => result,
27            _ => unreachable!(),
28        };
29
30        let ok_type = result.ok_type.clone();
31
32        let docs = &func_witx.docs;
33        if !docs.is_empty() {
34            Self::write_docs(w, docs)?;
35        }
36
37        let mut params_decomposed = vec![];
38
39        for param in &params {
40            let mut decomposed = param.1.decompose(&param.0, false);
41            params_decomposed.append(&mut decomposed);
42        }
43
44        let mut results = vec![];
45        // A tuple in a result is expanded into additional parameters, transformed to
46        // pointers
47        if let ASType::Tuple(tuple_members) = ok_type.as_ref().leaf() {
48            for (i, tuple_member) in tuple_members.iter().enumerate() {
49                let name = format!("result{}_ptr", i);
50                results.push((name, tuple_member.type_.clone()));
51            }
52        } else {
53            let name = "result_ptr";
54            results.push((name.to_string(), ok_type));
55        }
56        for result in &results {
57            let mut decomposed = result.1.decompose(&result.0, true);
58            params_decomposed.append(&mut decomposed);
59        }
60
61        w.write_line("// @ts-ignore: decorator")?
62            .write_line("@unsafe")?
63            .write_line("// @ts-ignore: decorator")?
64            .write_line(format!("@external(\"{}\", \"{}\")", module_name, name))?
65            .indent()?
66            .write(format!("export declare function {}(", name.as_fn()))?;
67
68        if !params_decomposed.is_empty() || !results.is_empty() {
69            w.eol()?;
70        }
71        for (i, param) in params_decomposed.iter().enumerate() {
72            let eol = if i + 1 == params_decomposed.len() {
73                ""
74            } else {
75                ","
76            };
77            w.write_line_continued(format!(
78                "{}: {}{}",
79                param.name.as_var(),
80                param.type_.as_lang(),
81                eol
82            ))?;
83        }
84
85        w.write_line(format!("): {};", result.error_type.as_lang()))?;
86        w.eob()?;
87
88        let signature_witx = func_witx.wasm_signature(witx::CallMode::DefinedImport);
89        let params_count_witx = signature_witx.params.len() + signature_witx.results.len();
90        assert_eq!(params_count_witx, params_decomposed.len() + 1);
91
92        Ok(())
93    }
94}