1use std::collections::HashMap;
2use std::fmt;
3
4pub type InstructionPointerType = u64;
5
6#[derive(Debug, Clone)]
7pub enum Instruction {
8 Store(Location, Arg),
9 StoreStructure(Location, HashMap<String, Arg>),
10 StoreArray1(Location, Vec<Arg>),
11 StoreArray2(Location, Arg, u64),
12
13 AddI(Location, Arg, Arg),
14 SubI(Location, Arg, Arg),
15 MulI(Location, Arg, Arg),
16 DivI(Location, Arg, Arg),
17 ModI(Location, Arg, Arg),
18
19 AddF(Location, Arg, Arg),
20 SubF(Location, Arg, Arg),
21 MulF(Location, Arg, Arg),
22 DivF(Location, Arg, Arg),
23 ModF(Location, Arg, Arg),
24
25 And(Location, Arg, Arg),
26 Or(Location, Arg, Arg),
27
28 GEqI(Location, Arg, Arg),
29 LEqI(Location, Arg, Arg),
30 GEI(Location, Arg, Arg),
31 LEI(Location, Arg, Arg),
32
33 GEqF(Location, Arg, Arg),
34 LEqF(Location, Arg, Arg),
35 GEF(Location, Arg, Arg),
36 LEF(Location, Arg, Arg),
37
38 Eq(Location, Arg, Arg),
39 InEq(Location, Arg, Arg),
40
41 Negate(Location, Arg),
42 Invert(Location, Arg),
43
44 FnCall(Location, Vec<Arg>), Return(Option<Arg>),
46 TakeReturn(Location), Jump(JumpTarget),
49 JumpCondition(JumpTarget, Arg), JumpNegateCondition(JumpTarget, Arg), RelJump(RelJumpTarget),
53 RelJumpCondition(RelJumpTarget, Arg), RelJumpNegateCondition(RelJumpTarget, Arg), }
56
57impl fmt::Display for Instruction {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 use super::Instruction::*;
60
61 match *self {
62 Store(ref location, ref arg) => {
63 write!(f, "store {}, {}", location, arg)
64 }
65
66 StoreStructure(ref location, ref map) => {
67 write!(f, "store_struct {}", location)?;
68
69 for (key, arg) in map.iter() {
70 write!(f, ", ({}, {})", key, arg)?;
71 }
72
73 Ok(())
74 }
75
76 StoreArray1(ref location, ref args) => {
77 write!(f, "store_array1 size={}, {} ", args.len(), location)?;
78
79 for arg in args.iter() {
80 write!(f, ", {}", arg)?;
81 }
82
83 Ok(())
84 }
85
86 StoreArray2(ref location, ref element, ref size) => write!(
87 f,
88 "store_array2 size={}, {}, {}",
89 size, location, element
90 ),
91
92 AddI(ref location, ref arg1, ref arg2) => {
93 write!(f, "addi {}, {}, {}", location, arg1, arg2)
94 }
95
96 SubI(ref location, ref arg1, ref arg2) => {
97 write!(f, "subi {}, {}, {}", location, arg1, arg2)
98 }
99
100 MulI(ref location, ref arg1, ref arg2) => {
101 write!(f, "muli {}, {}, {}", location, arg1, arg2)
102 }
103
104 DivI(ref location, ref arg1, ref arg2) => {
105 write!(f, "divi {}, {}, {}", location, arg1, arg2)
106 }
107
108 ModI(ref location, ref arg1, ref arg2) => {
109 write!(f, "modi {}, {}, {}", location, arg1, arg2)
110 }
111
112 AddF(ref location, ref arg1, ref arg2) => {
113 write!(f, "addf {}, {}, {}", location, arg1, arg2)
114 }
115
116 SubF(ref location, ref arg1, ref arg2) => {
117 write!(f, "subf {}, {}, {}", location, arg1, arg2)
118 }
119
120 MulF(ref location, ref arg1, ref arg2) => {
121 write!(f, "mulf {}, {}, {}", location, arg1, arg2)
122 }
123
124 DivF(ref location, ref arg1, ref arg2) => {
125 write!(f, "divf {}, {}, {}", location, arg1, arg2)
126 }
127
128 ModF(ref location, ref arg1, ref arg2) => {
129 write!(f, "modf {}, {}, {}", location, arg1, arg2)
130 }
131
132 And(ref location, ref arg1, ref arg2) => {
133 write!(f, "and {}, {}, {}", location, arg1, arg2)
134 }
135
136 Or(ref location, ref arg1, ref arg2) => {
137 write!(f, "or {}, {}, {}", location, arg1, arg2)
138 }
139
140 GEqI(ref location, ref arg1, ref arg2) => {
141 write!(f, "geqi {}, {}, {}", location, arg1, arg2)
142 }
143
144 LEqI(ref location, ref arg1, ref arg2) => {
145 write!(f, "leqi {}, {}, {}", location, arg1, arg2)
146 }
147
148 GEI(ref location, ref arg1, ref arg2) => {
149 write!(f, "gei {}, {}, {}", location, arg1, arg2)
150 }
151
152 LEI(ref location, ref arg1, ref arg2) => {
153 write!(f, "lei {}, {}, {}", location, arg1, arg2)
154 }
155
156 GEqF(ref location, ref arg1, ref arg2) => {
157 write!(f, "geqf {}, {}, {}", location, arg1, arg2)
158 }
159
160 LEqF(ref location, ref arg1, ref arg2) => {
161 write!(f, "leqf {}, {}, {}", location, arg1, arg2)
162 }
163
164 GEF(ref location, ref arg1, ref arg2) => {
165 write!(f, "gef {}, {}, {}", location, arg1, arg2)
166 }
167
168 LEF(ref location, ref arg1, ref arg2) => {
169 write!(f, "lef {}, {}, {}", location, arg1, arg2)
170 }
171
172 Eq(ref location, ref arg1, ref arg2) => {
173 write!(f, "eq {}, {}, {}", location, arg1, arg2)
174 }
175
176 InEq(ref location, ref arg1, ref arg2) => {
177 write!(f, "neq {}, {}, {}", location, arg1, arg2)
178 }
179
180 Negate(ref location, ref arg) => {
181 write!(f, "negate {}, {}", location, arg)
182 }
183
184 Invert(ref location, ref arg) => {
185 write!(f, "negate {}, {}", location, arg)
186 }
187
188 FnCall(ref location, ref args) => {
189 write!(f, "call size={}, {} ", args.len(), location)?;
190
191 for arg in args.iter() {
192 write!(f, ", {}", arg)?;
193 }
194
195 Ok(())
196 }
197
198 Return(ref arg) => match *arg {
199 Some(ref to_return) => write!(f, "return {}", to_return),
200
201 None => write!(f, "return <none>"),
202 },
203
204 TakeReturn(ref location) => write!(f, "take {}", location),
205
206 Jump(ref target) => write!(f, "jump {}", target),
207
208 JumpCondition(ref target, ref arg) => {
209 write!(f, "jump {}, condition={}", target, arg)
210 }
211
212 JumpNegateCondition(ref target, ref arg) => {
213 write!(f, "jump {}, invert-condition={}", target, arg)
214 }
215
216 RelJump(ref target) => write!(f, "rel_jump {}", target),
217
218 RelJumpCondition(ref target, ref arg) => {
219 write!(f, "rel_jump {}, condition={}", target, arg)
220 }
221
222 RelJumpNegateCondition(ref target, ref arg) => {
223 write!(f, "rel_jump {}, invert-condition={}", target, arg)
224 }
225 }
226 }
227}
228
229#[derive(Debug, Clone, Copy, Display)]
230#[display(fmt = "{}", _0)]
231pub struct JumpTarget(InstructionPointerType);
232
233impl JumpTarget {
234 pub fn new(t: InstructionPointerType) -> JumpTarget {
235 JumpTarget(t)
236 }
237
238 pub fn absolute_target(&self) -> InstructionPointerType {
239 self.0
240 }
241}
242
243#[derive(Debug, Clone, Copy, Display)]
244#[display(fmt = "{}", _0)]
245pub struct RelJumpTarget(i64);
246
247impl RelJumpTarget {
248 pub fn new(t: i64) -> RelJumpTarget {
249 RelJumpTarget(t)
250 }
251
252 pub fn relative_target(&self) -> i64 {
253 self.0
254 }
255}
256
257#[derive(Debug, Clone)]
258pub enum Location {
259 Compound {
260 root: String,
261 root_index: Option<String>,
262 path: Vec<FieldAccess>,
263 },
264 Namespace(String),
265 Tmp(String),
266}
267
268impl fmt::Display for Location {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 match *self {
271 Location::Compound {
272 ref root,
273 ref root_index,
274 ref path,
275 } => {
276 write!(f, "{}", root)?;
277
278 if let Some(ref root_index) = *root_index {
279 write!(f, "[{}]", root_index)?;
280 }
281
282 for field_access in path.iter() {
283 write!(f, "{}", field_access)?;
284 }
285
286 Ok(())
287 }
288
289 Location::Namespace(ref n) | Location::Tmp(ref n) => {
290 write!(f, "{}", n)
291 }
292 }
293 }
294}
295
296#[derive(Debug, Clone, Display)]
297pub enum FieldAccess {
298 #[display(fmt = ".{}", _0)]
299 Field(String),
300
301 #[display(fmt = ".{}[{}]", field, index_tmp)]
302 FieldIndex { field: String, index_tmp: String },
303}
304
305#[derive(Debug, Clone, Display)]
306pub enum Arg {
307 #[display(fmt = "{}", _0)]
308 Location(Location),
309
310 #[display(fmt = "{}", _0)]
311 Int(i64),
312
313 #[display(fmt = "{}", _0)]
314 Float(f64),
315
316 #[display(fmt = "{}", _0)]
317 Bool(bool),
318
319 #[display(fmt = "\"{}\"", _0)]
320 String(String),
321}