Skip to main content

vermilion_codegen/
ir.rs

1//! A module for generating Vermilion IR.
2
3use crate::entities::{Block, GlobalData, Symbol, Value};
4use crate::instruction::{ InstructionData, Opcode };
5use std::collections::HashMap;
6
7/// A module wrapper for initializing Vermilion IR.
8pub struct Module {
9
10    /// A list of symbols declared in the module.
11    pub symbols: HashMap<String, Symbol>,
12
13    /// A list of Module data.
14    pub data: HashMap<String, GlobalData>
15
16}
17
18/// An enum that allows the different types of data.
19#[derive(Clone)]
20pub enum FunctionValue {
21
22    /// A standard boolean.
23    Boolean(bool),
24
25    /// A standard integer.
26    Byte(u8),
27
28    /// A standard 64-bit integer.
29    Integer(i64),
30
31    /// A standard 64-bit float.
32    Float(f64),
33
34    /// A block pointer.
35    Block(Block),
36
37    /// An instruction call.
38    Instruction(InstructionData),
39
40    /// A reference to a symbol.
41    Symbol(String),
42
43}
44
45/// A function for generating Vermilion IR.
46#[derive(Clone)]
47pub struct Function {
48
49    /// A list of blocks in the function.
50    pub blocks: Vec<FunctionBlock>,
51
52    /// A list of values used by the function.
53    pub values: Vec<FunctionValue>,
54
55    /// A pointer to the current block.
56    pub current_block: u32,
57
58}
59
60/// A block that contains Vermilion IR.
61#[derive(Clone)]
62pub struct FunctionBlock {
63
64    /// A list of instructions in the block.
65    pub instructions: Vec<InstructionData>,
66
67}
68
69impl Module {
70
71    /// Creates a new empty module.
72    pub fn new() -> Self {
73        Self {
74            symbols: HashMap::new(),
75            data: HashMap::new(),
76        }
77    }
78
79    /// Declare an external function
80    pub fn declare_function(&mut self, name: String) {
81        self.symbols.insert(name, Symbol::External);
82    }
83
84    /// Defines a function.
85    pub fn define_function(&mut self, name: String, f: Function) {
86        self.symbols.insert(name, Symbol::Local(f));
87    }
88
89}
90
91/// The functionality behind the Function struct.
92impl Function {
93
94    /// Creates a new empty function.
95    pub fn new() -> Self {
96        Function {
97            blocks: vec![],
98            values: vec![],
99            current_block: 0,
100        }
101    }
102
103    /// Creates a new code block.  To use this code block, you
104    /// must first switch to it.
105    pub fn create_block(&mut self) -> Block {
106        let b = FunctionBlock {
107            instructions: vec![]
108        };
109        let block = Block(self.blocks.len() as u32);
110        self.blocks.push(b);
111
112        block
113    }
114
115    /// Switches the current block to the selected block.
116    pub fn switch_to_block(&mut self, block: Block) {
117        self.current_block = block.0;
118    }
119
120    /// Creates a new SSA boolean.  Uses the `Boolean` instruction
121    /// behind the scenes.
122    pub fn iconst_boolean(&mut self, val: bool) -> Value {
123        let id = self.values.len();
124        let v = Value(id as u32);
125
126        self.values.push(FunctionValue::Boolean(val));
127
128        v
129    }
130
131    /// Creates a new SSA integer.  Uses the `Byte` instruction
132    /// behind the scenes.
133    pub fn iconst_integer(&mut self, val: i64) -> Value {
134        let id = self.values.len();
135        let v = Value(id as u32);
136
137        self.values.push(FunctionValue::Integer(val));
138
139        v
140    }
141
142    /// Creates a new SSA float.  Uses the `Float` instruction
143    /// behind the scenes.
144    pub fn iconst_float(&mut self, val: f64) -> Value {
145        let id = self.values.len();
146        let v = Value(id as u32);
147
148        self.values.push(FunctionValue::Float(val));
149
150        v
151    }
152
153    /// Yields the topmost stack item and removes it from the stack.
154    pub fn ipop(&mut self) -> Value {
155        let id = self.values.len();
156        let v = Value(id as u32);
157
158        self.values.push(FunctionValue::Instruction(InstructionData {
159            opcode: Opcode::Pop,
160            args: vec![],
161        }));
162
163        v
164    }
165
166    /// Removes the topmost stack item.
167    pub fn pop(&mut self) {
168        self.blocks
169            .get_mut(self.current_block as usize).unwrap()
170            .instructions.push(InstructionData {
171            opcode: Opcode::Pop,
172            args: vec![],
173        });
174    }
175
176    /// Clones the current topmost stack item and yields it.
177    pub fn iclone(&mut self) -> Value {
178        let id = self.values.len();
179        let v = Value(id as u32);
180
181        self.values.push(FunctionValue::Instruction(InstructionData {
182            opcode: Opcode::Pop,
183            args: vec![],
184        }));
185
186        v
187    }
188
189    /// Clones the topmost stack item and pushes it to the stack.
190    pub fn clone(&mut self) {
191        self.blocks
192            .get_mut(self.current_block as usize).unwrap()
193            .instructions.push(InstructionData {
194            opcode: Opcode::Clone,
195            args: vec![],
196        });
197    }
198
199    /// Clears the stack, so it has no items.
200    pub fn clear(&mut self) {
201        self.blocks
202            .get_mut(self.current_block as usize).unwrap()
203            .instructions.push(InstructionData {
204            opcode: Opcode::Clear,
205            args: vec![],
206        });
207    }
208
209    /// Adds two booleans together and yields the sum.
210    /// 
211    /// # Arguments
212    /// - `l`: The left side of the operation.
213    /// - `r`: The right side of the operation.
214    pub fn iboolean_add(&mut self, l: Value, r: Value) -> Value {
215        let id = self.values.len();
216        let v = Value(id as u32);
217
218        self.values.push(FunctionValue::Instruction(InstructionData {
219            opcode: Opcode::BooleanAdd,
220            args: vec![l, r],
221        }));
222
223        v
224    }
225
226    /// Adds two booleans together and pushes the sum to the stack.
227    /// 
228    /// # Arguments
229    /// - `l`: The left side of the operation.
230    /// - `r`: The right side of the operation.
231    pub fn boolean_add(&mut self, l: Value, r: Value) {
232        self.blocks
233            .get_mut(self.current_block as usize).unwrap()
234            .instructions.push(InstructionData {
235            opcode: Opcode::BooleanAdd,
236            args: vec![l, r],
237        });
238    }
239
240    /// Subtracts two booleans together and yields the sum.
241    /// 
242    /// # Arguments
243    /// - `l`: The left side of the operation.
244    /// - `r`: The right side of the operation.
245    pub fn iboolean_sub(&mut self, l: Value, r: Value) -> Value {
246        let id = self.values.len();
247        let v = Value(id as u32);
248
249        self.values.push(FunctionValue::Instruction(InstructionData {
250            opcode: Opcode::BooleanSubtract,
251            args: vec![l, r],
252        }));
253
254        v
255    }
256
257    /// Subtracts two booleans together and pushes the sum to the stack.
258    /// 
259    /// # Arguments
260    /// - `l`: The left side of the operation.
261    /// - `r`: The right side of the operation.
262    pub fn boolean_sub(&mut self, l: Value, r: Value) {
263        self.blocks
264            .get_mut(self.current_block as usize).unwrap()
265            .instructions.push(InstructionData {
266            opcode: Opcode::BooleanSubtract,
267            args: vec![l, r],
268        });
269    }
270
271    /// Adds two bytes together and yields the sum.
272    /// 
273    /// # Arguments
274    /// - `l`: The left side of the operation.
275    /// - `r`: The right side of the operation.
276    pub fn ibyte_add(&mut self, l: Value, r: Value) -> Value {
277        let id = self.values.len();
278        let v = Value(id as u32);
279
280        self.values.push(FunctionValue::Instruction(InstructionData {
281            opcode: Opcode::ByteAdd,
282            args: vec![l, r],
283        }));
284
285        v
286    }
287
288    /// Adds two bytes together and pushes the sum to the stack.
289    /// 
290    /// # Arguments
291    /// - `l`: The left side of the operation.
292    /// - `r`: The right side of the operation.
293    pub fn byte_add(&mut self, l: Value, r: Value) {
294        self.blocks
295            .get_mut(self.current_block as usize).unwrap()
296            .instructions.push(InstructionData {
297            opcode: Opcode::ByteAdd,
298            args: vec![l, r],
299        });
300    }
301
302    /// Subtracts two bytes together and yields the sum.
303    /// 
304    /// # Arguments
305    /// - `l`: The left side of the operation.
306    /// - `r`: The right side of the operation.
307    pub fn ibyte_sub(&mut self, l: Value, r: Value) -> Value {
308        let id = self.values.len();
309        let v = Value(id as u32);
310
311        self.values.push(FunctionValue::Instruction(InstructionData {
312            opcode: Opcode::ByteSubtract,
313            args: vec![l, r],
314        }));
315
316        v
317    }
318
319    /// Subtracts two bytes together and pushes the sum to the stack.
320    /// 
321    /// # Arguments
322    /// - `l`: The left side of the operation.
323    /// - `r`: The right side of the operation.
324    pub fn byte_sub(&mut self, l: Value, r: Value) {
325        self.blocks
326            .get_mut(self.current_block as usize).unwrap()
327            .instructions.push(InstructionData {
328            opcode: Opcode::ByteSubtract,
329            args: vec![l, r],
330        });
331    }
332
333    /// Multiplies two bytes together and yields the sum.
334    /// 
335    /// # Arguments
336    /// - `l`: The left side of the operation.
337    /// - `r`: The right side of the operation.
338    pub fn ibyte_mul(&mut self, l: Value, r: Value) -> Value {
339        let id = self.values.len();
340        let v = Value(id as u32);
341
342        self.values.push(FunctionValue::Instruction(InstructionData {
343            opcode: Opcode::ByteMultiply,
344            args: vec![l, r],
345        }));
346
347        v
348    }
349
350    /// Multiplies two bytes together and pushes the sum to the stack.
351    /// 
352    /// # Arguments
353    /// - `l`: The left side of the operation.
354    /// - `r`: The right side of the operation.
355    pub fn byte_mul(&mut self, l: Value, r: Value) {
356        self.blocks
357            .get_mut(self.current_block as usize).unwrap()
358            .instructions.push(InstructionData {
359            opcode: Opcode::ByteMultiply,
360            args: vec![l, r],
361        });
362    }
363
364    /// Divides two bytes together and yields the sum.
365    /// 
366    /// # Arguments
367    /// - `l`: The left side of the operation.
368    /// - `r`: The right side of the operation.
369    pub fn ibyte_div(&mut self, l: Value, r: Value) -> Value {
370        let id = self.values.len();
371        let v = Value(id as u32);
372
373        self.values.push(FunctionValue::Instruction(InstructionData {
374            opcode: Opcode::ByteDivide,
375            args: vec![l, r],
376        }));
377
378        v
379    }
380
381    /// Divides two bytes together and pushes the sum to the stack.
382    /// 
383    /// # Arguments
384    /// - `l`: The left side of the operation.
385    /// - `r`: The right side of the operation.
386    pub fn byte_div(&mut self, l: Value, r: Value) {
387        self.blocks
388            .get_mut(self.current_block as usize).unwrap()
389            .instructions.push(InstructionData {
390            opcode: Opcode::ByteDivide,
391            args: vec![l, r],
392        });
393    }
394
395    /// Divides two bytes together and yields the remainder.
396    /// 
397    /// # Arguments
398    /// - `l`: The left side of the operation.
399    /// - `r`: The right side of the operation.
400    pub fn ibyte_mod(&mut self, l: Value, r: Value) -> Value {
401        let id = self.values.len();
402        let v = Value(id as u32);
403
404        self.values.push(FunctionValue::Instruction(InstructionData {
405            opcode: Opcode::ByteRemainder,
406            args: vec![l, r],
407        }));
408
409        v
410    }
411
412    /// Divides two integers together and pushes the remainder to the stack.
413    /// 
414    /// # Arguments
415    /// - `l`: The left side of the operation.
416    /// - `r`: The right side of the operation.
417    pub fn integer_mod(&mut self, l: Value, r: Value) {
418        self.blocks
419            .get_mut(self.current_block as usize).unwrap()
420            .instructions.push(InstructionData {
421            opcode: Opcode::ByteRemainder,
422            args: vec![l, r],
423        });
424    }
425
426    /// Adds two integers together and yields the sum.
427    /// 
428    /// # Arguments
429    /// - `l`: The left side of the operation.
430    /// - `r`: The right side of the operation.
431    pub fn iint_add(&mut self, l: Value, r: Value) -> Value {
432        let id = self.values.len();
433        let v = Value(id as u32);
434
435        self.values.push(FunctionValue::Instruction(InstructionData {
436            opcode: Opcode::IntegerAdd,
437            args: vec![l, r],
438        }));
439
440        v
441    }
442
443    /// Adds two integers together and pushes the sum to the stack.
444    /// 
445    /// # Arguments
446    /// - `l`: The left side of the operation.
447    /// - `r`: The right side of the operation.
448    pub fn int_add(&mut self, l: Value, r: Value) {
449        self.blocks
450            .get_mut(self.current_block as usize).unwrap()
451            .instructions.push(InstructionData {
452            opcode: Opcode::IntegerAdd,
453            args: vec![l, r],
454        });
455    }
456
457    /// Subtracts two integers together and yields the sum.
458    /// 
459    /// # Arguments
460    /// - `l`: The left side of the operation.
461    /// - `r`: The right side of the operation.
462    pub fn iint_sub(&mut self, l: Value, r: Value) -> Value {
463        let id = self.values.len();
464        let v = Value(id as u32);
465
466        self.values.push(FunctionValue::Instruction(InstructionData {
467            opcode: Opcode::IntegerSubtract,
468            args: vec![l, r],
469        }));
470
471        v
472    }
473
474    /// Subtracts two integers together and pushes the sum to the stack.
475    /// 
476    /// # Arguments
477    /// - `l`: The left side of the operation.
478    /// - `r`: The right side of the operation.
479    pub fn int_sub(&mut self, l: Value, r: Value) {
480        self.blocks
481            .get_mut(self.current_block as usize).unwrap()
482            .instructions.push(InstructionData {
483            opcode: Opcode::IntegerSubtract,
484            args: vec![l, r],
485        });
486    }
487
488    /// Multiplies two integers together and yields the sum.
489    /// 
490    /// # Arguments
491    /// - `l`: The left side of the operation.
492    /// - `r`: The right side of the operation.
493    pub fn iint_mul(&mut self, l: Value, r: Value) -> Value {
494        let id = self.values.len();
495        let v = Value(id as u32);
496
497        self.values.push(FunctionValue::Instruction(InstructionData {
498            opcode: Opcode::IntegerMultiply,
499            args: vec![l, r],
500        }));
501
502        v
503    }
504
505    /// Multiplies two integers together and pushes the sum to the stack.
506    /// 
507    /// # Arguments
508    /// - `l`: The left side of the operation.
509    /// - `r`: The right side of the operation.
510    pub fn int_mul(&mut self, l: Value, r: Value) {
511        self.blocks
512            .get_mut(self.current_block as usize).unwrap()
513            .instructions.push(InstructionData {
514            opcode: Opcode::IntegerMultiply,
515            args: vec![l, r],
516        });
517    }
518
519    /// Divides two integers together and yields the sum.
520    /// 
521    /// # Arguments
522    /// - `l`: The left side of the operation.
523    /// - `r`: The right side of the operation.
524    pub fn iint_div(&mut self, l: Value, r: Value) -> Value {
525        let id = self.values.len();
526        let v = Value(id as u32);
527
528        self.values.push(FunctionValue::Instruction(InstructionData {
529            opcode: Opcode::IntegerDivide,
530            args: vec![l, r],
531        }));
532
533        v
534    }
535
536    /// Divides two integers together and pushes the sum to the stack.
537    /// 
538    /// # Arguments
539    /// - `l`: The left side of the operation.
540    /// - `r`: The right side of the operation.
541    pub fn int_div(&mut self, l: Value, r: Value) {
542        self.blocks
543            .get_mut(self.current_block as usize).unwrap()
544            .instructions.push(InstructionData {
545            opcode: Opcode::IntegerDivide,
546            args: vec![l, r],
547        });
548    }
549
550    /// Divides two integers together and yields the remainder.
551    /// 
552    /// # Arguments
553    /// - `l`: The left side of the operation.
554    /// - `r`: The right side of the operation.
555    pub fn iint_mod(&mut self, l: Value, r: Value) -> Value {
556        let id = self.values.len();
557        let v = Value(id as u32);
558
559        self.values.push(FunctionValue::Instruction(InstructionData {
560            opcode: Opcode::IntegerRemainder,
561            args: vec![l, r],
562        }));
563
564        v
565    }
566
567    /// Divides two integers together and pushes the remainder to the stack.
568    /// 
569    /// # Arguments
570    /// - `l`: The left side of the operation.
571    /// - `r`: The right side of the operation.
572    pub fn int_mod(&mut self, l: Value, r: Value) {
573        self.blocks
574            .get_mut(self.current_block as usize).unwrap()
575            .instructions.push(InstructionData {
576            opcode: Opcode::IntegerRemainder,
577            args: vec![l, r],
578        });
579    }
580
581    /// Adds two floats together and yields the sum.
582    /// 
583    /// # Arguments
584    /// - `l`: The left side of the operation.
585    /// - `r`: The right side of the operation.
586    pub fn ifloat_add(&mut self, l: Value, r: Value) -> Value {
587        let id = self.values.len();
588        let v = Value(id as u32);
589
590        self.values.push(FunctionValue::Instruction(InstructionData {
591            opcode: Opcode::FloatAdd,
592            args: vec![l, r],
593        }));
594
595        v
596    }
597
598    /// Adds two floats together and pushes the sum to the stack.
599    /// 
600    /// # Arguments
601    /// - `l`: The left side of the operation.
602    /// - `r`: The right side of the operation.
603    pub fn float_add(&mut self, l: Value, r: Value) {
604        self.blocks
605            .get_mut(self.current_block as usize).unwrap()
606            .instructions.push(InstructionData {
607            opcode: Opcode::FloatAdd,
608            args: vec![l, r],
609        });
610    }
611
612    /// Subtracts two integers together and yields the sum.
613    /// 
614    /// # Arguments
615    /// - `l`: The left side of the operation.
616    /// - `r`: The right side of the operation.
617    pub fn ifloat_sub(&mut self, l: Value, r: Value) -> Value {
618        let id = self.values.len();
619        let v = Value(id as u32);
620
621        self.values.push(FunctionValue::Instruction(InstructionData {
622            opcode: Opcode::FloatSubtract,
623            args: vec![l, r],
624        }));
625
626        v
627    }
628
629    /// Subtracts two floats together and pushes the sum to the stack.
630    /// 
631    /// # Arguments
632    /// - `l`: The left side of the operation.
633    /// - `r`: The right side of the operation.
634    pub fn float_sub(&mut self, l: Value, r: Value) {
635        self.blocks
636            .get_mut(self.current_block as usize).unwrap()
637            .instructions.push(InstructionData {
638            opcode: Opcode::FloatSubtract,
639            args: vec![l, r],
640        });
641    }
642
643    /// Multiplies two floats together and yields the sum.
644    /// 
645    /// # Arguments
646    /// - `l`: The left side of the operation.
647    /// - `r`: The right side of the operation.
648    pub fn ifloat_mul(&mut self, l: Value, r: Value) -> Value {
649        let id = self.values.len();
650        let v = Value(id as u32);
651
652        self.values.push(FunctionValue::Instruction(InstructionData {
653            opcode: Opcode::FloatMultiply,
654            args: vec![l, r],
655        }));
656
657        v
658    }
659
660    /// Multiplies two floats together and pushes the sum to the stack.
661    /// 
662    /// # Arguments
663    /// - `l`: The left side of the operation.
664    /// - `r`: The right side of the operation.
665    pub fn float_mul(&mut self, l: Value, r: Value) {
666        self.blocks
667            .get_mut(self.current_block as usize).unwrap()
668            .instructions.push(InstructionData {
669            opcode: Opcode::FloatMultiply,
670            args: vec![l, r],
671        });
672    }
673
674    /// Divides two floats together and yields the sum.
675    /// 
676    /// # Arguments
677    /// - `l`: The left side of the operation.
678    /// - `r`: The right side of the operation.
679    pub fn ifloat_div(&mut self, l: Value, r: Value) -> Value {
680        let id = self.values.len();
681        let v = Value(id as u32);
682
683        self.values.push(FunctionValue::Instruction(InstructionData {
684            opcode: Opcode::FloatDivide,
685            args: vec![l, r],
686        }));
687
688        v
689    }
690
691    /// Divides two floats together and pushes the sum to the stack.
692    /// 
693    /// # Arguments
694    /// - `l`: The left side of the operation.
695    /// - `r`: The right side of the operation.
696    pub fn float_div(&mut self, l: Value, r: Value) {
697        self.blocks
698            .get_mut(self.current_block as usize).unwrap()
699            .instructions.push(InstructionData {
700            opcode: Opcode::FloatDivide,
701            args: vec![l, r],
702        });
703    }
704
705    /// Divides two floats together and yields the remainder.
706    /// 
707    /// # Arguments
708    /// - `l`: The left side of the operation.
709    /// - `r`: The right side of the operation.
710    pub fn ifloat_mod(&mut self, l: Value, r: Value) -> Value {
711        let id = self.values.len();
712        let v = Value(id as u32);
713
714        self.values.push(FunctionValue::Instruction(InstructionData {
715            opcode: Opcode::FloatRemainder,
716            args: vec![l, r],
717        }));
718
719        v
720    }
721
722    /// Divides two floats together and pushes the remainder to the stack.
723    /// 
724    /// # Arguments
725    /// - `l`: The left side of the operation.
726    /// - `r`: The right side of the operation.
727    pub fn float_mod(&mut self, l: Value, r: Value) {
728        self.blocks
729            .get_mut(self.current_block as usize).unwrap()
730            .instructions.push(InstructionData {
731            opcode: Opcode::FloatRemainder,
732            args: vec![l, r],
733        });
734    }
735
736    /// Converts a value into a boolean and yields it.
737    /// 
738    /// # Arguments
739    /// - `l`: The value to convert.
740    pub fn icast_boolean(&mut self, l: Value) -> Value {
741        let id = self.values.len();
742        let v = Value(id as u32);
743
744        self.values.push(FunctionValue::Instruction(InstructionData {
745            opcode: Opcode::CastBoolean,
746            args: vec![l],
747        }));
748
749        v
750    }
751
752    /// Converts a value into a boolean and pushes it to the stack.
753    /// 
754    /// # Arguments
755    /// - `l`: The value to convert.
756    pub fn cast_boolean(&mut self, l: Value) {
757        self.blocks
758            .get_mut(self.current_block as usize).unwrap()
759            .instructions.push(InstructionData {
760            opcode: Opcode::CastBoolean,
761            args: vec![l],
762        });
763    }
764
765    /// Converts a value into a byte and yields it.
766    /// 
767    /// # Arguments
768    /// - `l`: The value to convert.
769    pub fn icast_byte(&mut self, l: Value) -> Value {
770        let id = self.values.len();
771        let v = Value(id as u32);
772
773        self.values.push(FunctionValue::Instruction(InstructionData {
774            opcode: Opcode::CastByte,
775            args: vec![l],
776        }));
777
778        v
779    }
780
781    /// Converts a value into a byte and pushes it to the stack.
782    /// 
783    /// # Arguments
784    /// - `l`: The value to convert.
785    pub fn cast_byte(&mut self, l: Value) {
786        self.blocks
787            .get_mut(self.current_block as usize).unwrap()
788            .instructions.push(InstructionData {
789            opcode: Opcode::CastByte,
790            args: vec![l],
791        });
792    }
793
794    /// Converts a value into an integer and yields it.
795    /// 
796    /// # Arguments
797    /// - `l`: The value to convert.
798    pub fn icast_int(&mut self, l: Value) -> Value {
799        let id = self.values.len();
800        let v = Value(id as u32);
801
802        self.values.push(FunctionValue::Instruction(InstructionData {
803            opcode: Opcode::CastInteger,
804            args: vec![l],
805        }));
806
807        v
808    }
809
810    /// Converts a value into an integer and pushes it to the stack.
811    /// 
812    /// # Arguments
813    /// - `l`: The value to convert.
814    pub fn cast_int(&mut self, l: Value) {
815        self.blocks
816            .get_mut(self.current_block as usize).unwrap()
817            .instructions.push(InstructionData {
818            opcode: Opcode::CastInteger,
819            args: vec![l],
820        });
821    }
822
823    /// Converts a value into an float and yields it.
824    /// 
825    /// # Arguments
826    /// - `l`: The value to convert.
827    pub fn icast_float(&mut self, l: Value) -> Value {
828        let id = self.values.len();
829        let v = Value(id as u32);
830
831        self.values.push(FunctionValue::Instruction(InstructionData {
832            opcode: Opcode::CastFloat,
833            args: vec![l],
834        }));
835
836        v
837    }
838
839    /// Converts a value into an float and pushes it to the stack.
840    /// 
841    /// # Arguments
842    /// - `l`: The value to convert.
843    pub fn cast_float(&mut self, l: Value) {
844        self.blocks
845            .get_mut(self.current_block as usize).unwrap()
846            .instructions.push(InstructionData {
847            opcode: Opcode::CastFloat,
848            args: vec![l],
849        });
850    }
851
852    /// Negates a boolean and yields it.
853    /// 
854    /// # Arguments
855    /// - `l`: The value to convert.
856    pub fn ineg_boolean(&mut self, l: Value) -> Value {
857        let id = self.values.len();
858        let v = Value(id as u32);
859
860        self.values.push(FunctionValue::Instruction(InstructionData {
861            opcode: Opcode::NegateBoolean,
862            args: vec![l],
863        }));
864
865        v
866    }
867
868    /// Negates a boolean and pushes it to the stack.
869    /// 
870    /// # Arguments
871    /// - `l`: The value to convert.
872    pub fn neg_boolean(&mut self, l: Value) {
873        self.blocks
874            .get_mut(self.current_block as usize).unwrap()
875            .instructions.push(InstructionData {
876            opcode: Opcode::NegateBoolean,
877            args: vec![l],
878        });
879    }
880
881    /// Negates an integer and yields it.
882    /// 
883    /// # Arguments
884    /// - `l`: The value to convert.
885    pub fn ineg_int(&mut self, l: Value) -> Value {
886        let id = self.values.len();
887        let v = Value(id as u32);
888
889        self.values.push(FunctionValue::Instruction(InstructionData {
890            opcode: Opcode::NegateInteger,
891            args: vec![l],
892        }));
893
894        v
895    }
896
897    /// Negates an integer and pushes it to the stack.
898    /// 
899    /// # Arguments
900    /// - `l`: The value to convert.
901    pub fn neg_byte(&mut self, l: Value) {
902        self.blocks
903            .get_mut(self.current_block as usize).unwrap()
904            .instructions.push(InstructionData {
905            opcode: Opcode::NegateInteger,
906            args: vec![l],
907        });
908    }
909
910    /// Negates a float and yields it.
911    /// 
912    /// # Arguments
913    /// - `l`: The value to convert.
914    pub fn ineg_float(&mut self, l: Value) -> Value {
915        let id = self.values.len();
916        let v = Value(id as u32);
917
918        self.values.push(FunctionValue::Instruction(InstructionData {
919            opcode: Opcode::NegateFloat,
920            args: vec![l],
921        }));
922
923        v
924    }
925
926    /// Negates a float and pushes it to the stack.
927    /// 
928    /// # Arguments
929    /// - `l`: The value to convert.
930    pub fn neg_float(&mut self, l: Value) {
931        self.blocks
932            .get_mut(self.current_block as usize).unwrap()
933            .instructions.push(InstructionData {
934            opcode: Opcode::NegateFloat,
935            args: vec![l],
936        });
937    }
938
939    /// Loads a byte from memory and yields it.  For efficiency, if
940    /// the offset is 0, the offset calculation is not compiled
941    /// 
942    /// # Arguments
943    /// - `l`: The address to load.
944    /// - `offset`: The offset to load it from.
945    pub fn iload(&mut self, l: Value, offset: i64) -> Value {
946        if offset > 0 {
947            let off = self.iconst_integer(offset);
948            let addr = self.iint_add(l, off);
949
950            let v = self.values.len();
951            let val = Value(v as u32);
952
953            self.values.push(FunctionValue::Instruction(InstructionData {
954                opcode: Opcode::Load,
955                args: vec![addr],
956            }));
957
958            val
959        } else if offset < 0 {
960            let off = self.iconst_integer(offset);
961            let addr = self.iint_sub(l, off);
962
963            let v = self.values.len();
964            let val = Value(v as u32);
965
966            self.values.push(FunctionValue::Instruction(InstructionData {
967                opcode: Opcode::Load,
968                args: vec![addr],
969            }));
970
971            val
972        } else {
973            let v = self.values.len();
974            let val = Value(v as u32);
975
976            self.values.push(FunctionValue::Instruction(InstructionData {
977                opcode: Opcode::Load,
978                args: vec![l],
979            }));
980
981            val
982        }
983    }
984
985    /// Loads a byte from memory and pushes it to the stack. 
986    /// For efficiency, if the offset is 0, the offset
987    /// calculation is not compiled.
988    /// 
989    /// # Arguments
990    /// - `l`: The address to load.
991    /// - `offset`: The offset to load it from.
992    pub fn load(&mut self, l: Value, offset: i64) {
993        if offset > 0 {
994            let off = self.iconst_integer(offset);
995            let addr = self.iint_add(l, off);
996
997            self.blocks
998                .get_mut(self.current_block as usize).unwrap()
999                .instructions.push(InstructionData {
1000                opcode: Opcode::Load,
1001                args: vec![addr],
1002            });
1003        } else if offset < 0 {
1004            let off = self.iconst_integer(offset);
1005            let addr = self.iint_sub(l, off);
1006
1007            self.blocks
1008                .get_mut(self.current_block as usize).unwrap()
1009                .instructions.push(InstructionData {
1010                opcode: Opcode::Load,
1011                args: vec![addr],
1012            });
1013        } else {
1014            self.blocks
1015                .get_mut(self.current_block as usize).unwrap()
1016                .instructions.push(InstructionData {
1017                opcode: Opcode::Load,
1018                args: vec![l],
1019            });
1020        }
1021    }
1022
1023    /// Stores a byte in memory. For efficiency, if the offset
1024    /// is 0, the offset calculation is not compiled.
1025    /// 
1026    /// # Arguments
1027    /// - `l`: The address to write to.
1028    /// - `r`: The byte to write.
1029    /// - `offset`: The offset to load it from.
1030    pub fn store(&mut self, l: Value, r: Value, offset: i64) {
1031        if offset > 0 {
1032            let off = self.iconst_integer(offset);
1033            let addr = self.iint_add(l, off);
1034
1035            self.blocks
1036                .get_mut(self.current_block as usize).unwrap()
1037                .instructions.push(InstructionData {
1038                opcode: Opcode::Store,
1039                args: vec![addr, r],
1040            });
1041        } else if offset < 0 {
1042            let off = self.iconst_integer(offset);
1043            let addr = self.iint_sub(l, off);
1044
1045            self.blocks
1046                .get_mut(self.current_block as usize).unwrap()
1047                .instructions.push(InstructionData {
1048                opcode: Opcode::Store,
1049                args: vec![addr, r],
1050            });
1051        } else {
1052            self.blocks
1053                .get_mut(self.current_block as usize).unwrap()
1054                .instructions.push(InstructionData {
1055                opcode: Opcode::Store,
1056                args: vec![l, r],
1057            });
1058        }
1059    }
1060
1061    /// Reallocates the heap to the specified size.
1062    /// 
1063    /// # Arguments
1064    /// - `l`: The new size.
1065    pub fn realloc(&mut self, l: Value) {
1066        self.blocks
1067            .get_mut(self.current_block as usize).unwrap()
1068            .instructions.push(InstructionData {
1069            opcode: Opcode::Realloc,
1070            args: vec![l],
1071        });
1072    }
1073
1074    /// Yields the amount of allocated heap memory as an integer.
1075    pub fn iheap_size(&mut self) -> Value {
1076        let id = self.values.len();
1077        let v = Value(id as u32);
1078
1079        self.values.push(FunctionValue::Instruction(InstructionData {
1080            opcode: Opcode::HeapSize,
1081            args: vec![],
1082        }));
1083
1084        v
1085    }
1086
1087    /// Pushes the amount of allocated heap memory to the stack.
1088    pub fn heap_size(&mut self) {
1089        self.blocks
1090            .get_mut(self.current_block as usize).unwrap()
1091            .instructions.push(InstructionData {
1092            opcode: Opcode::HeapSize,
1093            args: vec![],
1094        });
1095    }
1096
1097    /// Allocates a section of memory with the specified ID.
1098    /// 
1099    /// # Arguments
1100    /// - `l`: The ID of the new section. (int)
1101    pub fn alloc(&mut self, l: Value) {
1102        self.blocks
1103            .get_mut(self.current_block as usize).unwrap()
1104            .instructions.push(InstructionData {
1105            opcode: Opcode::Alloc,
1106            args: vec![l],
1107        });
1108    }
1109
1110    /// Reallocates a section of memory with the specified ID.
1111    /// 
1112    /// # Arguments
1113    /// - `l`: The ID of the new section. (int)
1114    /// - `r`: The new size of the section. (int)
1115    pub fn realloc_section(&mut self, l: Value, r: Value) {
1116        self.blocks
1117            .get_mut(self.current_block as usize).unwrap()
1118            .instructions.push(InstructionData {
1119            opcode: Opcode::ReallocSection,
1120            args: vec![l, r],
1121        });
1122    }
1123
1124    /// Yields the start address of the specified section.
1125    /// 
1126    /// # Arguments
1127    /// - `l`: The section ID to get (int)
1128    pub fn isection_addr(&mut self, l: Value) -> Value {
1129        let id = self.values.len();
1130        let v = Value(id as u32);
1131
1132        self.values.push(FunctionValue::Instruction(InstructionData {
1133            opcode: Opcode::SectionAddr,
1134            args: vec![l],
1135        }));
1136
1137        v
1138    }
1139
1140    /// Pushes the start address of a section to the stack.
1141    /// 
1142    /// # Arguments
1143    /// - `l`: The section ID to get (int)
1144    pub fn section_addr(&mut self, l: Value) {
1145        self.blocks
1146            .get_mut(self.current_block as usize).unwrap()
1147            .instructions.push(InstructionData {
1148            opcode: Opcode::SectionAddr,
1149            args: vec![l],
1150        });
1151    }
1152
1153    /// Shifts a section to the left.
1154    /// 
1155    /// # Arguments
1156    /// - `l`: The section ID to shift. (int)
1157    /// - `r`: The amount of bytes to shift the section by (int)
1158    pub fn section_shift_left(&mut self, l: Value, r: Value) {
1159        self.blocks
1160            .get_mut(self.current_block as usize).unwrap()
1161            .instructions.push(InstructionData {
1162            opcode: Opcode::SectionShiftLeft,
1163            args: vec![l, r],
1164        });
1165    }
1166
1167    /// Shifts a section to the right.
1168    /// 
1169    /// # Arguments
1170    /// - `l`: The section ID to shift. (int)
1171    /// - `r`: The amount of bytes to shift the section by (int)
1172    pub fn section_shift_right(&mut self, l: Value, r: Value) {
1173        self.blocks
1174            .get_mut(self.current_block as usize).unwrap()
1175            .instructions.push(InstructionData {
1176            opcode: Opcode::SectionShiftRight,
1177            args: vec![l, r],
1178        });
1179    }
1180
1181    /// Frees a section and fills it with bytes.
1182    /// 
1183    /// # Arguments
1184    /// - `l`: The section ID to free. (int)
1185    pub fn free(&mut self, l: Value) {
1186        self.blocks
1187            .get_mut(self.current_block as usize).unwrap()
1188            .instructions.push(InstructionData {
1189            opcode: Opcode::Free,
1190            args: vec![l],
1191        });
1192    }
1193
1194    /// Frees a section and fills it with bytes, then shifts
1195    /// all of the following sections to fill the free space.
1196    /// 
1197    /// # Arguments
1198    /// - `l`: The section ID to free. (int)
1199    pub fn free_and_shift(&mut self, l: Value) {
1200        self.blocks
1201            .get_mut(self.current_block as usize).unwrap()
1202            .instructions.push(InstructionData {
1203            opcode: Opcode::FreeAndShift,
1204            args: vec![l],
1205        });
1206    }
1207
1208    /// Branches to the specified block.
1209    /// 
1210    /// # Arguments
1211    /// - `l`: The block to branch to.
1212    pub fn branch(&mut self, l: Block) {
1213        let id = self.values.len();
1214        let v = Value(id as u32);
1215
1216        self.values.push(FunctionValue::Block(l));
1217
1218        self.blocks
1219            .get_mut(self.current_block as usize).unwrap()
1220            .instructions.push(InstructionData {
1221            opcode: Opcode::Branch,
1222            args: vec![v],
1223        });
1224    }
1225
1226    /// Branches if the specified boolean is zero.
1227    /// 
1228    /// # Arguments
1229    /// - `l`: The boolean to test
1230    pub fn brz(&mut self, l: Value) {
1231        self.blocks
1232            .get_mut(self.current_block as usize).unwrap()
1233            .instructions.push(InstructionData {
1234            opcode: Opcode::BranchIfZero,
1235            args: vec![l],
1236        });
1237    }
1238
1239    /// Branches if the specified boolean is not zero.
1240    /// 
1241    /// # Arguments
1242    /// - `l`: The boolean to test
1243    pub fn brnz(&mut self, l: Value) {
1244        self.blocks
1245            .get_mut(self.current_block as usize).unwrap()
1246            .instructions.push(InstructionData {
1247            opcode: Opcode::BranchIfNotZero,
1248            args: vec![l],
1249        });
1250    }
1251
1252    /// Tests if the two operands are exactly equal.
1253    /// 
1254    /// # Arguments
1255    /// - `l`: Left side of the operation.
1256    /// - `r`: Right side of the operation.
1257    pub fn iequal(&mut self, l: Value, r: Value) -> Value {
1258        let id = self.values.len();
1259        let v = Value(id as u32);
1260
1261        self.values.push(FunctionValue::Instruction(InstructionData {
1262            opcode: Opcode::Equal,
1263            args: vec![l, r],
1264        }));
1265
1266        v
1267    }
1268
1269    /// Branches if the specified boolean is not zero.  Pushes
1270    /// the result to the stack.
1271    /// 
1272    /// # Arguments
1273    /// - `l`: Left side of the operation.
1274    /// - `r`: Right side of the operation.
1275    pub fn equal(&mut self, l: Value, r: Value) {
1276        self.blocks
1277            .get_mut(self.current_block as usize).unwrap()
1278            .instructions.push(InstructionData {
1279            opcode: Opcode::Equal,
1280            args: vec![l, r],
1281        });
1282    }
1283
1284    /// Tests if the first operand is greater than the second.
1285    /// 
1286    /// # Arguments
1287    /// - `l`: Left side of the operation.
1288    /// - `r`: Right side of the operation.
1289    pub fn igreater(&mut self, l: Value, r: Value) -> Value {
1290        let id = self.values.len();
1291        let v = Value(id as u32);
1292
1293        self.values.push(FunctionValue::Instruction(InstructionData {
1294            opcode: Opcode::GreaterThan,
1295            args: vec![l, r],
1296        }));
1297
1298        v
1299    }
1300
1301    /// Tests if the first operand is greater than the second.
1302    /// Pushes the result to the stack.
1303    /// 
1304    /// # Arguments
1305    /// - `l`: Left side of the operation.
1306    /// - `r`: Right side of the operation.
1307    pub fn greater(&mut self, l: Value, r: Value) {
1308        self.blocks
1309            .get_mut(self.current_block as usize).unwrap()
1310            .instructions.push(InstructionData {
1311            opcode: Opcode::GreaterThan,
1312            args: vec![l, r],
1313        });
1314    }
1315
1316    /// Tests if the first operand is greater than the second.
1317    /// 
1318    /// # Arguments
1319    /// - `l`: Left side of the operation.
1320    /// - `r`: Right side of the operation.
1321    pub fn iless(&mut self, l: Value, r: Value) -> Value {
1322        let id = self.values.len();
1323        let v = Value(id as u32);
1324
1325        self.values.push(FunctionValue::Instruction(InstructionData {
1326            opcode: Opcode::LessThan,
1327            args: vec![l, r],
1328        }));
1329
1330        v
1331    }
1332
1333    /// Tests if the first operand is greater than the second.
1334    /// Pushes the result to the stack.
1335    /// 
1336    /// # Arguments
1337    /// - `l`: Left side of the operation.
1338    /// - `r`: Right side of the operation.
1339    pub fn less(&mut self, l: Value, r: Value) {
1340        self.blocks
1341            .get_mut(self.current_block as usize).unwrap()
1342            .instructions.push(InstructionData {
1343            opcode: Opcode::LessThan,
1344            args: vec![l, r],
1345        });
1346    }
1347
1348    /// Tests if the first operand is greater or equal to the second.
1349    /// 
1350    /// # Arguments
1351    /// - `l`: Left side of the operation.
1352    /// - `r`: Right side of the operation.
1353    pub fn igreater_or_equal(&mut self, l: Value, r: Value) -> Value {
1354        let id = self.values.len();
1355        let v = Value(id as u32);
1356
1357        self.values.push(FunctionValue::Instruction(InstructionData {
1358            opcode: Opcode::GreaterThanOrEqual,
1359            args: vec![l, r],
1360        }));
1361
1362        v
1363    }
1364
1365    /// Tests if the first operand is greater or equal to the second.
1366    /// Pushes the result to the stack.
1367    /// 
1368    /// # Arguments
1369    /// - `l`: Left side of the operation.
1370    /// - `r`: Right side of the operation.
1371    pub fn greater_or_eqal(&mut self, l: Value, r: Value) {
1372        self.blocks
1373            .get_mut(self.current_block as usize).unwrap()
1374            .instructions.push(InstructionData {
1375            opcode: Opcode::GreaterThanOrEqual,
1376            args: vec![l, r],
1377        });
1378    }
1379
1380    /// Tests if the first operand is less or equal to the second.
1381    /// 
1382    /// # Arguments
1383    /// - `l`: Left side of the operation.
1384    /// - `r`: Right side of the operation.
1385    pub fn iless_or_equal(&mut self, l: Value, r: Value) -> Value {
1386        let id = self.values.len();
1387        let v = Value(id as u32);
1388
1389        self.values.push(FunctionValue::Instruction(InstructionData {
1390            opcode: Opcode::LessThanOrEqual,
1391            args: vec![l, r],
1392        }));
1393
1394        v
1395    }
1396
1397    /// Tests if the first operand is less or equal to the second.
1398    /// Pushes the result to the stack.
1399    /// 
1400    /// # Arguments
1401    /// - `l`: Left side of the operation.
1402    /// - `r`: Right side of the operation.
1403    pub fn less_or_equal(&mut self, l: Value, r: Value) {
1404        self.blocks
1405            .get_mut(self.current_block as usize).unwrap()
1406            .instructions.push(InstructionData {
1407            opcode: Opcode::LessThanOrEqual,
1408            args: vec![l, r],
1409        });
1410    }
1411    
1412    /// Calls a function.
1413    /// 
1414    /// # Arguments
1415    /// - `name`: Name of the function to call.
1416    /// - `args`: The arguments of the function call.
1417    pub fn call(&mut self, name: String, args: &[Value]) {
1418        let id = self.values.len();
1419        let v = Value(id as u32);
1420
1421        let sym = FunctionValue::Symbol(name);
1422        self.values.push(sym);
1423        
1424        let mut a = args.to_vec();
1425        a.push(v);
1426    
1427        self.blocks
1428            .get_mut(self.current_block as usize).unwrap()
1429            .instructions.push(InstructionData {
1430            opcode: Opcode::Call,
1431            args: a,
1432        });
1433    }
1434
1435    /// Returns from a function call.
1436    /// 
1437    /// # Arguments
1438    /// - `args`: The arguments to return.
1439    pub fn return_(&mut self, args: &[Value]) {
1440        self.blocks
1441            .get_mut(self.current_block as usize).unwrap()
1442            .instructions.push(InstructionData {
1443            opcode: Opcode::Return,
1444            args: args.to_vec(),
1445        });
1446    }
1447
1448}