cardinal_codegen/
instruction.rs

1//! Information about possible Cardinal instructions.
2
3use crate::entities::{Block, Value, ValueInfo};
4use crate::instbuilder::InstBuilder;
5
6#[derive(Clone, Copy)]
7pub enum Opcode {
8
9    Add,
10    Sub,
11    Mul,
12    Div,
13    Mod,
14    BitAnd,
15    BitOr,
16    BitXor,
17    BitLeft,
18    BitRight,
19    BitNot,
20    TestEq,
21    TestNeq,
22    TestGt,
23    TestGtEq,
24    TestLt,
25    TestLtEq,
26    Not,
27    Or,
28    And,
29    Jmp,
30    Set,
31    Call,
32    Ret,
33
34}
35
36/// Information about an instruction or operation.
37#[derive(Clone)]
38pub struct InstructionInfo {
39
40    /// The opcode of the instruction.
41    pub opcode: Opcode,
42
43    /// The arguments provided with the instruction.
44    pub arguments: Vec<Value>,
45
46}
47
48/// A block type for creating different kinds of blocks.
49#[derive(Clone, Copy)]
50pub enum BlockType {
51
52    /// A basic IF type that uses a value as an expression.
53    If(Value),
54
55    /// A basic block with no conditions.
56    Basic,
57
58}
59
60/// A block for instruction building.
61#[derive(Clone)]
62pub struct InstBlock {
63
64    /// The type of the block.
65    pub block_type: BlockType,
66
67    /// A list of elseif statements for the block, if any.
68    pub elses: Vec<InstBlock>,
69
70    /// An else_block for If blocks.
71    pub else_block: Option<Box<InstBlock>>,
72
73    /// A list of values defined in the block.
74    pub values: Vec<ValueInfo>,
75
76    /// A list of instructions in the block.
77    pub insts: Vec<InstructionInfo>,
78
79    /// A list of imports in the block.
80    pub imports: Vec<String>,
81
82    /// A list of nested blocks in the block.
83    pub blocks: Vec<InstBlock>,
84
85}
86
87impl InstBuilder for InstBlock {
88
89    fn require_import(&mut self, name: String) {
90        if !self.imports.contains(&name) {
91            self.imports.push(name);
92        }
93    }
94
95    fn create_value(&mut self, value: ValueInfo) -> Value {
96        let val = Value(self.values.len() as u32);
97        self.values.push(value);
98
99        val
100    }
101
102    fn create_block(&mut self, block: InstBlock) -> Block {
103        let val = Block(self.blocks.len() as u32);
104        self.blocks.push(block);
105
106        val
107    }
108
109    fn create_inst(&mut self, inst: InstructionInfo) {
110        self.insts.push(inst);
111    }
112
113    fn use_block(&mut self, block: Block) -> &mut InstBlock {
114        self.blocks.get_mut(block.0 as usize).unwrap()
115    }
116
117}