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}