wasm_printer/wast/
mod.rs

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}