wat_ast/
lib.rs

1pub use document::Document;
2pub use export::{Export, InlineExport};
3pub use expression::{
4    fold, global_get, i32_const, i64_const, local_get, AsAtoms, Block, Br,
5    BrIf, BrTable, Call, Drop, Else, Expression, GlobalGet, GlobalSet, I32Add,
6    I32Const, I32Eq, I32Eqz, I32GtU, I32Load, I32LtS, I32LtU, I32Mul, I32Ne,
7    I32RemU, I32ShrU, I32Sub, I64Const, If, Instruction, Local, LocalGet,
8    LocalSet, LocalTee, Loop, MemoryGrow, Return, Then,
9};
10pub use import_desc::{ImportDesc, ImportDescFunc};
11pub use index::{symbolic, Index, Indexes, NumericIndex, SymbolicIndex};
12pub use integer::{Integer, Sign};
13pub use module::Module;
14pub use named_value_type::NamedValueType;
15pub use param::Param;
16pub use result::Result;
17pub use section::{
18    DataSection, DataSectionEntry, DataString, FunctionSection,
19    FunctionSectionEntry, GlobalSection, GlobalSectionEntry, ImportSection,
20    ImportSectionEntry, MemorySection, MemorySectionEntry, Offset, Section,
21    TypeSection, TypeSectionEntry,
22};
23pub use type_use::TypeUse;
24pub use types::{
25    FuncType, GlobalType, GlobalTypeMut, Limits, MemType, ValueType,
26};
27
28mod document;
29mod export;
30mod expression;
31mod import_desc;
32mod index;
33mod integer;
34mod module;
35mod named_value_type;
36mod param;
37mod result;
38mod section;
39mod type_use;
40mod types;
41
42use std::{fmt, io};
43
44pub(crate) use expression::ExpressionParser;
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47struct ToWatParams {
48    indent_size:  usize,
49    indent_level: usize,
50}
51
52impl ToWatParams {
53    fn indent(&self) -> usize {
54        self.indent_size * self.indent_level
55    }
56}
57
58trait ToWat {
59    fn write_wat<W: io::Write>(
60        &self,
61        w: &mut W,
62        p: &ToWatParams,
63    ) -> io::Result<()>;
64
65    fn to_wat(&self, p: &ToWatParams) -> String {
66        let mut buf = Vec::new();
67
68        self.write_wat(&mut buf, p).unwrap();
69
70        String::from_utf8_lossy(&buf).to_string()
71    }
72}
73
74pub enum Expr {
75    Atom(Atom),
76    SExpr(Box<dyn SExpr>),
77}
78
79impl ToWat for Expr {
80    fn write_wat<W: io::Write>(
81        &self,
82        w: &mut W,
83        p: &ToWatParams,
84    ) -> io::Result<()> {
85        match self {
86            Self::Atom(a) => {
87                write!(w, "{}{}", " ".repeat(p.indent()), a.to_string())
88            },
89            Self::SExpr(se) => {
90                let open = format!("{}({}", " ".repeat(p.indent()), se.car());
91
92                if se.cdr().len() == 0 {
93                    return write!(w, "{})", &open);
94                }
95
96                let cdr = se
97                    .cdr()
98                    .iter()
99                    .map(|expr| {
100                        expr.to_wat(&ToWatParams {
101                            indent_size:  2,
102                            indent_level: 0,
103                        })
104                    })
105                    .collect::<Vec<String>>()
106                    .join(" ");
107
108                if format!("{} {})", open, cdr).len() <= 80 {
109                    return write!(w, "{} {})", open, cdr);
110                }
111
112                writeln!(w, "{}", open)?;
113
114                for expr in se.cdr() {
115                    expr.write_wat(
116                        w,
117                        &ToWatParams {
118                            indent_size:  p.indent_size,
119                            indent_level: p.indent_level + 1,
120                        },
121                    )?;
122                    write!(w, "\n")?;
123                }
124
125                write!(w, "{})", " ".repeat(p.indent()))
126            },
127        }
128    }
129}
130
131#[derive(Clone, Debug, PartialEq, Eq)]
132pub struct Atom(String);
133
134impl Atom {
135    pub fn new(s: String) -> Atom {
136        Self(s)
137    }
138}
139
140impl fmt::Display for Atom {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        write!(f, "{}", self.0)
143    }
144}
145
146pub trait SExpr {
147    fn car(&self) -> String;
148
149    fn cdr(&self) -> Vec<Expr>;
150}