nyar_wasm/operations/
mod.rs1use 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 Default(WasiType),
24 Constant(WasiValue),
26 Convert {
28 into: WasiType,
30 },
31 Transmute {
33 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 JumpBranch(JumpBranch),
49 JumpTable(JumpTable),
51 JumpEnumeration(EnumerationTable),
53 Goto {},
54 Return {},
55 Drop {
56 objects: usize,
57 },
58}
59
60impl WasiInstruction {
61 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 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}