1use crate::{CodegenBackend, MirProgram};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6#[repr(u8)]
7pub enum Op {
8 Nop = 0,
9 Push = 1,
10 Pop = 2,
11 Add = 3, Sub = 4, Mul = 5, Div = 6, Rem = 7,
12 Eq = 8, Ne = 9, Lt = 10, Le = 11, Gt = 12, Ge = 13,
13 And = 14, Or = 15, Not = 16,
14 Load = 17, Store = 18,
15 Call = 19, Ret = 20,
16 Jump = 21, JumpIf = 22,
17 Halt = 0xFF,
18}
19
20#[derive(Debug, Default)]
21pub struct Chunk {
22 pub code: Vec<u8>,
23 pub constants: Vec<f64>,
24}
25
26impl Chunk {
27 pub fn emit(&mut self, op: Op) { self.code.push(op as u8); }
28 pub fn emit_u16(&mut self, v: u16) { self.code.extend_from_slice(&v.to_le_bytes()); }
29 pub fn push_const(&mut self, v: f64) -> u16 {
30 let idx = self.constants.len() as u16;
31 self.constants.push(v);
32 idx
33 }
34}
35
36pub struct BytecodeBackend;
37
38impl CodegenBackend for BytecodeBackend {
39 fn emit(&mut self, mir: &MirProgram, out: &std::path::Path) -> anyhow::Result<()> {
40 let chunk = Chunk::default();
41 let bytes = chunk.code;
42 std::fs::write(out.with_extension("lingbc"), bytes)?;
43 Ok(())
44 }
45}