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 Nop,
73 Push(Value),
75 Drop,
77 Clone,
79 Call(usize),
81 SetMp(isize),
83 RelToAddr(isize),
85 Ret,
87 Exit,
89 Jmp(usize),
91 JmpFalse(usize),
93 SetVarImm(Pointer),
96 SetVar,
100 GetVar,
103 Cast(Type),
105
106 Neg,
108 Not,
109
110 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}