witx_codegen/zig/
function.rs

1use std::io::Write;
2
3use super::*;
4
5impl ZigGenerator {
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        let mut results_decomposed = vec![];
57        for result in &results {
58            let mut decomposed = result.1.decompose(&result.0, true);
59            results_decomposed.append(&mut decomposed);
60        }
61
62        Self::define_func_raw(
63            w,
64            module_name,
65            &name,
66            &params_decomposed,
67            &results_decomposed,
68            &result,
69        )?;
70
71        let signature_witx = func_witx.wasm_signature(witx::CallMode::DefinedImport);
72        let params_count_witx = signature_witx.params.len() + signature_witx.results.len();
73        assert_eq!(
74            params_count_witx,
75            params_decomposed.len() + results_decomposed.len() + 1
76        );
77
78        Ok(())
79    }
80
81    fn define_func_raw<T: Write>(
82        w: &mut PrettyWriter<T>,
83        module_name: &str,
84        name: &str,
85        params_decomposed: &[ASTypeDecomposed],
86        results_decomposed: &[ASTypeDecomposed],
87        result: &ASResult,
88    ) -> Result<(), Error> {
89        w.indent()?
90            .write(format!("pub extern \"{}\" fn {}(", module_name, name))?;
91        if !params_decomposed.is_empty() || !results_decomposed.is_empty() {
92            w.eol()?;
93        }
94        for param in params_decomposed.iter().chain(results_decomposed.iter()) {
95            w.write_line_continued(format!(
96                "{}: {},",
97                param.name.as_var(),
98                param.type_.as_lang(),
99            ))?;
100        }
101        w.write_line(format!(") callconv(.c) {};", result.error_type.as_lang()))?;
102        w.eob()?;
103        Ok(())
104    }
105}