Skip to main content

smpl/code_gen/byte_gen/
byte_code.rs

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>), // Function to call, args
45    Return(Option<Arg>),
46    TakeReturn(Location), // Where to store return value
47
48    Jump(JumpTarget),
49    JumpCondition(JumpTarget, Arg), // Jump when Arg is true
50    JumpNegateCondition(JumpTarget, Arg), // Jump when Arg is false
51
52    RelJump(RelJumpTarget),
53    RelJumpCondition(RelJumpTarget, Arg), // Jump when Arg is true
54    RelJumpNegateCondition(RelJumpTarget, Arg), // Jump when Arg is false
55}
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}