nyar_wasm/operations/
mod.rs

1use crate::{
2    encoder::WastEncoder,
3    helpers::{EmitConstant, EmitDefault, ToWasiType},
4    operations::branch::EnumerationTable,
5    Identifier, JumpBranch, JumpTable, WasiType, WasiValue,
6};
7use std::fmt::Write;
8
9pub mod branch;
10
11pub(crate) trait Emit {
12    fn emit<W: Write>(&self, w: &mut WastEncoder<W>) -> std::fmt::Result;
13}
14
15pub(crate) trait EmitValue {
16    fn emit_default<W: Write>(&self, w: &mut WastEncoder<W>) -> std::fmt::Result;
17    fn emit_constant<W: Write>(&self, w: &mut WastEncoder<W>) -> std::fmt::Result;
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub enum WasiInstruction {
22    /// Create the default value for a given type
23    Default(WasiType),
24    /// Create a constant value
25    Constant(WasiValue),
26    /// Convert stack value to WASI type
27    Convert {
28        /// The target type after convert
29        into: WasiType,
30    },
31    /// Transmute stack value to WASI type
32    Transmute {
33        /// The target type after transmute
34        into: WasiType,
35    },
36    GetField,
37    SetField,
38    CallFunction {
39        symbol: Identifier,
40    },
41    NativeSum {
42        terms: Vec<WasiInstruction>,
43    },
44    NativeProduct {
45        terms: Vec<WasiInstruction>,
46    },
47    /// `if cond { } else { }`
48    JumpBranch(JumpBranch),
49    /// `if c1 { } else if c2 { } else { }`
50    JumpTable(JumpTable),
51    /// `case 0: ... else: ...`
52    JumpEnumeration(EnumerationTable),
53    Goto {},
54    Return {},
55    Drop {
56        objects: usize,
57    },
58}
59
60impl WasiInstruction {
61    /// Create a const type
62    pub fn constant<T>(value: T) -> Self
63    where
64        T: Into<WasiValue>,
65    {
66        Self::Constant(value.into())
67    }
68}
69
70impl<'a, W: Write> WastEncoder<'a, W> {
71    pub fn emit_instructions(&mut self, instruction: &[WasiInstruction]) -> std::fmt::Result {
72        for i in instruction {
73            i.emit(self)?;
74        }
75        Ok(())
76    }
77}
78
79impl Emit for WasiInstruction {
80    fn emit<W: Write>(&self, w: &mut WastEncoder<W>) -> std::fmt::Result {
81        match self {
82            Self::Default(v) => {
83                w.newline()?;
84                v.emit_default(w)?;
85                w.stack.push(v.clone())
86            }
87            Self::Constant(v) => {
88                w.newline()?;
89                v.emit_constant(w)?;
90                w.stack.push(v.to_wasi_type())
91            }
92            Self::Convert { into } => {
93                let last = w.stack.pop();
94                match last {
95                    Some(last) => {
96                        w.newline()?;
97                        last.emit_convert(into, w)?;
98                        w.stack.push(into.clone())
99                    }
100                    None => {
101                        panic!("no item on stack!")
102                    }
103                }
104            }
105            Self::Transmute { into } => {
106                let last = w.stack.pop();
107                match last {
108                    Some(last) => {
109                        last.emit_transmute(into, w)?;
110                        w.stack.push(into.clone())
111                    }
112                    None => {
113                        panic!("no item on stack!")
114                    }
115                }
116            }
117            Self::GetField => {
118                todo!()
119            }
120            Self::SetField => {
121                todo!()
122            }
123            Self::CallFunction { symbol } => match w.source.get_function(symbol) {
124                Some(s) => {
125                    write!(w, "call {}", symbol.wasi_id())?;
126                    for input in s.inputs.iter() {
127                        match w.stack.pop() {
128                            Some(s) => {
129                                if s.ne(&input.r#type) {
130                                    panic!("Mismatch type")
131                                }
132                            }
133                            None => {
134                                panic!("Missing parameter")
135                            }
136                        }
137                    }
138                    for output in s.output.clone() {
139                        w.stack.push(output.r#type)
140                    }
141                }
142                None => {
143                    panic!("Missing function")
144                }
145            },
146            // (drop drop ...)
147            Self::Drop { objects } => write!(w, "({})", "drop ".repeat(*objects).trim_end())?,
148            Self::Goto { .. } => {
149                todo!()
150            }
151            Self::Return { .. } => {
152                todo!()
153            }
154            Self::NativeSum { .. } => {
155                todo!()
156            }
157            Self::NativeProduct { .. } => {
158                todo!()
159            }
160            Self::JumpBranch(v) => v.emit(w)?,
161            Self::JumpTable(_) => {
162                todo!()
163            }
164            Self::JumpEnumeration(_) => {
165                todo!()
166            }
167        }
168        Ok(())
169    }
170}
171
172#[derive(Copy, Clone, Debug)]
173pub enum VariableKind {
174    Global,
175    Local,
176    Table,
177}