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