rush_interpreter_vm/
instruction.rs

1use std::fmt::{self, Display, Formatter};
2
3use rush_analyzer::{AssignOp, InfixOp, PrefixOp, Type as AnalyzerType};
4
5use crate::{value::Pointer, Value};
6
7pub struct Program(pub(crate) Vec<Vec<Instruction>>);
8
9impl Display for Program {
10    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
11        let out = self
12            .0
13            .iter()
14            .enumerate()
15            .map(|(idx, func)| {
16                let label = match idx {
17                    0 => "prelude".to_string(),
18                    1 => "main".to_string(),
19                    idx => idx.to_string(),
20                };
21                format!(
22                    "{label}: {}\n",
23                    func.iter()
24                        .enumerate()
25                        .map(|(idx, i)| format!("\n [{idx:02}]    {i}"))
26                        .collect::<String>()
27                )
28            })
29            .collect::<String>();
30        write!(f, "{out}")
31    }
32}
33
34#[derive(Debug, Clone, Copy)]
35pub enum Type {
36    Int,
37    Bool,
38    Char,
39    Float,
40}
41
42impl From<AnalyzerType> for Type {
43    fn from(src: AnalyzerType) -> Self {
44        match src {
45            AnalyzerType::Int(0) => Self::Int,
46            AnalyzerType::Float(0) => Self::Float,
47            AnalyzerType::Bool(0) => Self::Bool,
48            AnalyzerType::Char(0) => Self::Char,
49            _ => unreachable!("this function is never called on pointers"),
50        }
51    }
52}
53
54impl Display for Type {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        write!(
57            f,
58            "{}",
59            match self {
60                Type::Int => "int",
61                Type::Bool => "bool",
62                Type::Char => "char",
63                Type::Float => "float",
64            }
65        )
66    }
67}
68
69#[derive(Debug)]
70pub enum Instruction {
71    /// Does nothing.
72    Nop,
73    /// Adds a new constant to stack.
74    Push(Value),
75    /// Pops the top-most value off the stack and discards the value.
76    Drop,
77    /// Clones the top value on the stack: [..., top] -> [..., top, top].
78    Clone,
79    /// Calls a function (specified by index).
80    Call(usize),
81    /// Adjusts the memory pointer by the given offset.
82    SetMp(isize),
83    /// Pushes a pointer which points to the absolute address of the given relative offset.
84    RelToAddr(isize),
85    /// Returns from the current function call.
86    Ret,
87    /// Special instruction for exit calls.
88    Exit,
89    /// Jumps to the specified index.
90    Jmp(usize),
91    /// Jumps to the specified index if the value on the stack is `false`.
92    JmpFalse(usize),
93    /// Pops the top of the stack in order to use it as the variable's value.
94    /// Saves this value at the specified memory location.
95    SetVarImm(Pointer),
96    /// Pops the top value from the stack in order to use it as the variable's value.
97    /// Then pops the second value from the stack which is a pointer.
98    /// Saves this value at the memory location specified by the pointer.
99    SetVar,
100    /// Pops the top value from the stack because it is a pointer specifying the target memory
101    /// address. The value saved at this address is then loaded and pushed onto the stack.
102    GetVar,
103    /// Cast the current item on the stack to the specified type.
104    Cast(Type),
105
106    // Prefix operators
107    Neg,
108    Not,
109
110    // Infix operators
111    Add,
112    Sub,
113    Mul,
114    Pow,
115    Div,
116    Rem,
117    Eq,
118    Ne,
119    Lt,
120    Gt,
121    Le,
122    Ge,
123    Shl,
124    Shr,
125    BitOr,
126    BitAnd,
127    BitXor,
128}
129
130impl From<InfixOp> for Instruction {
131    fn from(src: InfixOp) -> Self {
132        match src {
133            InfixOp::Plus => Self::Add,
134            InfixOp::Minus => Self::Sub,
135            InfixOp::Mul => Self::Mul,
136            InfixOp::Div => Self::Div,
137            InfixOp::Rem => Self::Rem,
138            InfixOp::Pow => Self::Pow,
139            InfixOp::Eq => Self::Eq,
140            InfixOp::Neq => Self::Ne,
141            InfixOp::Lt => Self::Lt,
142            InfixOp::Gt => Self::Gt,
143            InfixOp::Lte => Self::Le,
144            InfixOp::Gte => Self::Ge,
145            InfixOp::Shl => Self::Shl,
146            InfixOp::Shr => Self::Shr,
147            InfixOp::BitOr => Self::BitOr,
148            InfixOp::BitAnd => Self::BitAnd,
149            InfixOp::BitXor => Self::BitXor,
150            _ => unreachable!("logical operators are handled separately"),
151        }
152    }
153}
154
155impl TryFrom<AssignOp> for Instruction {
156    type Error = ();
157
158    fn try_from(src: AssignOp) -> Result<Self, Self::Error> {
159        match src {
160            AssignOp::Basic => Err(()),
161            AssignOp::Plus => Ok(Self::Add),
162            AssignOp::Minus => Ok(Self::Sub),
163            AssignOp::Mul => Ok(Self::Mul),
164            AssignOp::Div => Ok(Self::Div),
165            AssignOp::Rem => Ok(Self::Rem),
166            AssignOp::Pow => Ok(Self::Pow),
167            AssignOp::Shl => Ok(Self::Shl),
168            AssignOp::Shr => Ok(Self::Shr),
169            AssignOp::BitOr => Ok(Self::BitOr),
170            AssignOp::BitAnd => Ok(Self::BitAnd),
171            AssignOp::BitXor => Ok(Self::BitXor),
172        }
173    }
174}
175
176impl TryFrom<PrefixOp> for Instruction {
177    type Error = ();
178
179    fn try_from(src: PrefixOp) -> Result<Self, Self::Error> {
180        match src {
181            PrefixOp::Not => Ok(Self::Not),
182            PrefixOp::Neg => Ok(Self::Neg),
183            _ => Err(()),
184        }
185    }
186}
187
188impl Display for Instruction {
189    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
190        match self {
191            Instruction::Nop => write!(f, "nop"),
192            Instruction::Push(val) => write!(f, "push {val}"),
193            Instruction::Drop => write!(f, "pop"),
194            Instruction::Clone => write!(f, "clone"),
195            Instruction::Jmp(idx) => write!(f, "jmp {idx}"),
196            Instruction::JmpFalse(idx) => write!(f, "jmpfalse {idx}"),
197            Instruction::SetVarImm(ptr) => write!(f, "svari {ptr}"),
198            Instruction::SetVar => write!(f, "svar"),
199            Instruction::GetVar => write!(f, "gvar"),
200            Instruction::Call(idx) => write!(f, "call {idx}"),
201            Instruction::SetMp(idx) => write!(f, "setmp {idx}"),
202            Instruction::RelToAddr(offset) => write!(f, "reltoaddr {offset}"),
203            Instruction::Cast(to) => write!(f, "cast {to}"),
204            Instruction::Ret => write!(f, "ret"),
205            Instruction::Exit => write!(f, "exit"),
206            Instruction::Not => write!(f, "not"),
207            Instruction::Neg => write!(f, "neg"),
208            Instruction::Add => write!(f, "add"),
209            Instruction::Sub => write!(f, "sub"),
210            Instruction::Mul => write!(f, "mul"),
211            Instruction::Pow => write!(f, "pow"),
212            Instruction::Div => write!(f, "div"),
213            Instruction::Rem => write!(f, "rem"),
214            Instruction::Eq => write!(f, "eq"),
215            Instruction::Ne => write!(f, "ne"),
216            Instruction::Lt => write!(f, "lt"),
217            Instruction::Gt => write!(f, "gt"),
218            Instruction::Le => write!(f, "le"),
219            Instruction::Ge => write!(f, "ge"),
220            Instruction::Shl => write!(f, "shl"),
221            Instruction::Shr => write!(f, "shr"),
222            Instruction::BitOr => write!(f, "bitor"),
223            Instruction::BitAnd => write!(f, "bitand"),
224            Instruction::BitXor => write!(f, "bitxor"),
225        }
226    }
227}