wat_ast/
type_use.rs

1use wast::parser::{self, Parse, Parser};
2
3use crate::{Atom, Expr, Index, Param, Result, SExpr};
4
5/// https://webassembly.github.io/spec/core/text/modules.html#text-typeuse
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct TypeUse {
8    type_def: Option<Type>,
9    params:   Vec<Param>,
10    results:  Vec<Result>,
11}
12
13impl TypeUse {
14    pub fn new(
15        type_def: Option<Type>,
16        params: Vec<Param>,
17        results: Vec<Result>,
18    ) -> Self {
19        Self {
20            type_def,
21            params,
22            results,
23        }
24    }
25
26    pub(crate) fn exprs(&self) -> Vec<Expr> {
27        let mut v = Vec::new();
28
29        if let Some(ref type_def) = self.type_def {
30            v.push(Expr::SExpr(Box::new(type_def.clone())));
31        }
32
33        v.append(
34            &mut self
35                .params
36                .iter()
37                .map(|p| Expr::SExpr(Box::new(p.clone())))
38                .collect(),
39        );
40        v.append(
41            &mut self
42                .results
43                .iter()
44                .map(|r| Expr::SExpr(Box::new(r.clone())))
45                .collect(),
46        );
47
48        v
49    }
50}
51
52impl Parse<'_> for TypeUse {
53    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
54        let mut type_def = None;
55
56        if parser.peek2::<wast::kw::r#type>() {
57            type_def = Some(parser.parens(Type::parse)?);
58        }
59
60        let mut params = Vec::new();
61        let mut results = Vec::new();
62
63        while !parser.is_empty() {
64            if parser.peek2::<wast::kw::param>() {
65                params.push(parser.parens(Param::parse)?)
66            } else {
67                break;
68            }
69        }
70
71        while !parser.is_empty() {
72            if parser.peek2::<wast::kw::result>() {
73                results.push(parser.parens(Result::parse)?)
74            } else {
75                break;
76            }
77        }
78
79        Ok(Self {
80            type_def,
81            params,
82            results,
83        })
84    }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct Type {
89    pub idx: Index,
90}
91
92impl SExpr for Type {
93    fn car(&self) -> String {
94        "type".to_owned()
95    }
96
97    fn cdr(&self) -> Vec<Expr> {
98        vec![Expr::Atom(Atom::new(self.idx.to_string()))]
99    }
100}
101
102impl Parse<'_> for Type {
103    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
104        parser.parse::<wast::kw::r#type>()?;
105
106        let idx = parser.parse::<Index>()?;
107
108        Ok(Self { idx })
109    }
110}