1use crate::{
2 Value,
3 nodes::{ComparisonOperator, EqualityOperator, FactorOperator, TermOperator, UnaryOperator},
4};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
7#[repr(u8)]
8pub enum OpCode {
9 Constant,
10 Constant16,
11 Return,
12 Negate,
13 Add,
14 Subtract,
15 Multiply,
16 Divide,
17 Nil,
18 True,
19 False,
20 Not,
21 Equal,
22 Greater,
23 Less,
24 GreaterEqual,
25 LessEqual,
26 Modulo,
27 Pop,
28 DefineGlobal,
29 GetGlobal,
30 SetGlobal,
31 DefineGlobal16,
32 GetGlobal16,
33 SetGlobal16,
34 GetLocal,
35 SetLocal,
36 JumpIfFalse,
37 Jump,
38 Loop,
39 Call,
40 Closure,
41 Closure16,
42 GetUpvalue,
43 SetUpvalue,
44 CloseUpvalue,
45 Class,
46 Class16,
47 GetProperty,
48 SetProperty,
49 Method,
50 GetProperty16,
51 SetProperty16,
52 Method16,
53 Invoke,
54 Invoke16,
55 Inherit,
56 GetSuper,
57 SuperInvoke,
58 GetSuper16,
59 SuperInvoke16,
60 InitField,
61 InitField16,
62 ArrayLiteral,
63 GetArrayIndex,
64 SetArrayIndex,
65 ObjectLiteral,
66 Is,
67 GetOptionalProperty,
68 GetOptionalProperty16,
69 JumpIfNil,
70 TailCall,
71 Module,
72 Module16,
73 ModuleReturn,
74}
75
76impl From<u8> for OpCode {
77 fn from(byte: u8) -> Self {
78 match byte {
79 0 => OpCode::Constant,
80 1 => OpCode::Constant16,
81 2 => OpCode::Return,
82 3 => OpCode::Negate,
83 4 => OpCode::Add,
84 5 => OpCode::Subtract,
85 6 => OpCode::Multiply,
86 7 => OpCode::Divide,
87 8 => OpCode::Nil,
88 9 => OpCode::True,
89 10 => OpCode::False,
90 11 => OpCode::Not,
91 12 => OpCode::Equal,
92 13 => OpCode::Greater,
93 14 => OpCode::Less,
94 15 => OpCode::GreaterEqual,
95 16 => OpCode::LessEqual,
96 17 => OpCode::Modulo,
97 18 => OpCode::Pop,
98 19 => OpCode::DefineGlobal,
99 20 => OpCode::GetGlobal,
100 21 => OpCode::SetGlobal,
101 22 => OpCode::DefineGlobal16,
102 23 => OpCode::GetGlobal16,
103 24 => OpCode::SetGlobal16,
104 25 => OpCode::GetLocal,
105 26 => OpCode::SetLocal,
106 27 => OpCode::JumpIfFalse,
107 28 => OpCode::Jump,
108 29 => OpCode::Loop,
109 30 => OpCode::Call,
110 31 => OpCode::Closure,
111 32 => OpCode::Closure16,
112 33 => OpCode::GetUpvalue,
113 34 => OpCode::SetUpvalue,
114 35 => OpCode::CloseUpvalue,
115 36 => OpCode::Class,
116 37 => OpCode::Class16,
117 38 => OpCode::GetProperty,
118 39 => OpCode::SetProperty,
119 40 => OpCode::Method,
120 41 => OpCode::GetProperty16,
121 42 => OpCode::SetProperty16,
122 43 => OpCode::Method16,
123 44 => OpCode::Invoke,
124 45 => OpCode::Invoke16,
125 46 => OpCode::Inherit,
126 47 => OpCode::GetSuper,
127 48 => OpCode::SuperInvoke,
128 49 => OpCode::GetSuper16,
129 50 => OpCode::SuperInvoke16,
130 51 => OpCode::InitField,
131 52 => OpCode::InitField16,
132 53 => OpCode::ArrayLiteral,
133 54 => OpCode::GetArrayIndex,
134 55 => OpCode::SetArrayIndex,
135 56 => OpCode::ObjectLiteral,
136 57 => OpCode::Is,
137 58 => OpCode::GetOptionalProperty,
138 59 => OpCode::GetOptionalProperty16,
139 60 => OpCode::JumpIfNil,
140 61 => OpCode::TailCall,
141 62 => OpCode::Module,
142 63 => OpCode::Module16,
143 64 => OpCode::ModuleReturn,
144 _ => panic!("Unknown opcode: {}", byte),
145 }
146 }
147}
148
149impl From<bool> for OpCode {
150 fn from(boolean: bool) -> Self {
151 if boolean { OpCode::True } else { OpCode::False }
152 }
153}
154
155impl From<ComparisonOperator> for OpCode {
156 fn from(value: ComparisonOperator) -> Self {
157 match value {
158 ComparisonOperator::Greater => OpCode::Greater,
159 ComparisonOperator::Less => OpCode::Less,
160 ComparisonOperator::GreaterEqual => OpCode::GreaterEqual,
161 ComparisonOperator::LessEqual => OpCode::LessEqual,
162 }
163 }
164}
165
166impl From<TermOperator> for OpCode {
167 fn from(value: TermOperator) -> Self {
168 match value {
169 TermOperator::Add => OpCode::Add,
170 TermOperator::Subtract => OpCode::Subtract,
171 }
172 }
173}
174
175impl From<FactorOperator> for OpCode {
176 fn from(value: FactorOperator) -> Self {
177 match value {
178 FactorOperator::Divide => OpCode::Divide,
179 FactorOperator::Multiply => OpCode::Multiply,
180 FactorOperator::Modulo => OpCode::Modulo,
181 }
182 }
183}
184
185impl From<UnaryOperator> for OpCode {
186 fn from(value: UnaryOperator) -> Self {
187 match value {
188 UnaryOperator::Minus => OpCode::Negate,
189 UnaryOperator::Not => OpCode::Not,
190 }
191 }
192}
193
194impl From<EqualityOperator> for OpCode {
195 fn from(value: EqualityOperator) -> Self {
196 match value {
197 EqualityOperator::Is => OpCode::Is,
198 _ => OpCode::Equal,
199 }
200 }
201}
202
203impl From<OpCode> for u8 {
204 fn from(op: OpCode) -> Self {
205 op as u8
206 }
207}
208
209#[derive(Debug, Clone, PartialEq, Default, Copy)]
210pub struct SourceLocation {
211 pub line: u32,
212 pub col: u32,
213}
214
215impl SourceLocation {
216 pub fn new(line: u32, col: u32) -> Self {
217 Self { line, col }
218 }
219}
220
221#[derive(Debug, Clone, PartialEq, Default)]
222pub struct Chunk {
223 pub code: Vec<u8>,
224 pub locs: Vec<SourceLocation>,
225 pub constants: Vec<Value>,
226}
227
228impl Chunk {
229 pub fn new() -> Self {
230 Self {
231 code: Vec::new(),
232 locs: Vec::new(),
233 constants: Vec::new(),
234 }
235 }
236
237 pub fn write(&mut self, byte: u8, loc: SourceLocation) {
238 self.code.push(byte);
239 self.locs.push(loc);
240 }
241
242 pub fn write_opcode(&mut self, opcode: OpCode, loc: SourceLocation) {
243 self.write(opcode as u8, loc);
244 }
245
246 pub fn add_constant(&mut self, value: Value) -> usize {
247 for (i, existing) in self.constants.iter().enumerate() {
249 if *existing == value {
250 return i;
251 }
252 }
253
254 self.constants.push(value);
256 self.constants.len() - 1
257 }
258}