1use colored::Colorize;
2pub mod coredump;
3use core_wasm_ast as ast;
4use log::warn;
5use std::fmt::Write;
6
7type BoxError = Box<dyn std::error::Error>;
8
9pub struct WastPrinter<'a, W> {
10 pub module: &'a ast::traverse::WasmModule,
11 pub out: &'a mut W,
12}
13
14impl<'a, W: Write> WastPrinter<'a, W> {
15 pub fn print_global(&mut self, node: &ast::Global) -> Result<(), BoxError> {
16 write!(self.out, "({} ", "global".bright_red())?;
17 self.print_globaltype(&node.global_type)?;
18 write!(self.out, " ")?;
19 self.print_expr(&node.expr)?;
20 write!(self.out, ")")?;
21 Ok(())
22 }
23
24 pub fn print_globaltype(&mut self, node: &ast::GlobalType) -> Result<(), BoxError> {
25 if node.mutable {
26 write!(self.out, "({} ", "mut".bright_red())?;
27 self.print_valuetype(&node.valtype)?;
28 write!(self.out, ")")?;
29 } else {
30 self.print_valuetype(&node.valtype)?;
31 }
32 Ok(())
33 }
34
35 pub fn print_valuetype(&mut self, node: &ast::ValueType) -> Result<(), BoxError> {
36 let t = match node {
37 ast::ValueType::NumType(ast::NumType::F32) => "f32",
38 ast::ValueType::NumType(ast::NumType::F64) => "f64",
39 ast::ValueType::NumType(ast::NumType::I32) => "i32",
40 ast::ValueType::NumType(ast::NumType::I64) => "i64",
41 };
42 write!(self.out, "{}", t.bright_red())?;
43 Ok(())
44 }
45
46 pub fn print_expr(&mut self, node: &ast::Expr) -> Result<(), BoxError> {
47 write!(self.out, "(")?;
48 for instr in &node.value {
49 self.print_instr(&instr.value)?;
50 }
51 write!(self.out, ")")?;
52 Ok(())
53 }
54
55 pub fn print_instr(&mut self, node: &ast::Instr) -> Result<(), BoxError> {
56 use ast::Instr::*;
57
58 let expr = match node {
59 end => format!(""),
60 i32_const(v) => format!("i32.const {}", v.to_string().blue()),
61 e => {
62 warn!("unsupported expr: {:?}", e);
63 "unknown".to_owned()
64 }
65 };
66 write!(self.out, "{}", expr)?;
67 Ok(())
68 }
69
70 pub fn print_import(&mut self, node: &ast::Import) -> Result<(), BoxError> {
71 write!(self.out, "({} ", "import".bright_red())?;
72 self.print_name(&node.module)?;
73 write!(self.out, " ")?;
74 self.print_name(&node.name)?;
75 write!(self.out, " ")?;
76
77 match &node.import_type {
78 ast::ImportType::Func(typeidx) => {
79 if let Some(t) = self.module.get_type(*typeidx) {
80 self.print_type(&t)?;
81 } else {
82 write!(self.out, "(type {})", typeidx)?;
83 }
84 }
85
86 ast::ImportType::Table(_tabletype) => {
87 write!(self.out, "(table)")?;
88 }
89
90 ast::ImportType::Memory(_globaltype) => {
91 write!(self.out, "(memory)")?;
92 }
93
94 ast::ImportType::Global(_globaltype) => {
95 write!(self.out, "(global)")?;
96 }
97 }
98
99 write!(self.out, ")")?;
100 Ok(())
101 }
102
103 pub fn print_name(&mut self, node: &str) -> Result<(), BoxError> {
104 write!(self.out, "{}", format!("\"{}\"", node).blue())?;
105 Ok(())
106 }
107
108 pub fn print_type(&mut self, node: &ast::Type) -> Result<(), BoxError> {
109 write!(self.out, "(")?;
110 write!(self.out, "{}", "func".bright_red())?;
111 let mut i = 0;
112 while i < node.params.len() - 1 {
113 write!(self.out, " ({} ", "param".bright_red())?;
114 loop {
115 self.print_valuetype(&node.params[i])?;
116 if let Some(next) = node.params.get(i + 1) {
117 if node.params[i] != *next {
118 break;
119 }
120 } else {
121 break;
122 }
123 write!(self.out, " ")?;
124 i += 1
125 }
126 write!(self.out, ")")?;
127 }
128 for result in &node.results {
129 write!(self.out, " ({} ", "result".bright_red())?;
130 self.print_valuetype(result)?;
131 write!(self.out, ")")?;
132 }
133 write!(self.out, ")")?;
134 Ok(())
135 }
136}