Skip to main content

qanglang_core/backend/
chunk.rs

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        // Check if constant already exists
248        for (i, existing) in self.constants.iter().enumerate() {
249            if *existing == value {
250                return i;
251            }
252        }
253
254        // Add new constant
255        self.constants.push(value);
256        self.constants.len() - 1
257    }
258}