diff --git a/src/codegen/holeybytes.rs b/src/codegen/holeybytes.rs new file mode 100644 index 0000000..0e5ec21 --- /dev/null +++ b/src/codegen/holeybytes.rs @@ -0,0 +1,274 @@ +use crate::parse::ast::*; +use skylang::temp; +use std::rc::Rc; +use std::collections::HashMap; + +#[derive(Debug)] +pub struct HbCodegen { + pc: u32, + functions: HashMap, + globals: HashMap, +} + +impl HbCodegen { + pub fn new() -> Self { + HbCodegen { + pc: 0, + functions: HashMap::new(), + globals: HashMap::new() + } + } + + pub fn hb_codegen(&mut self, exprs: &Vec) -> &[u8] { + let mut gen: Vec = Vec::new(); + + macro_rules! unwrap { + ($item:expr) => { + ins!({ self.hb_codegen(&vec![Rc::unwrap_or_clone($item)]) }); + }; + + (norc $item:expr) => { + ins!(*{ self.hb_codegen(&vec![$item]) }); + } + } + + macro_rules! ins { + ($ins:expr) => { + let ins = $ins; + let new_pc = self.pc.wrapping_add(ins.len() as u32); + gen.extend_from_slice(&ins); + self.pc = new_pc; + }; + + ($($ins:expr);+) => { + $( + let ins = { $ins }; + let new_pc = self.pc.wrapping_add(ins.len() as u32); + gen.extend_from_slice(&ins); + self.pc = new_pc; + )+ + } + + } + + // Iterate over expressions. + for expr in exprs.iter() { + // Use patern matching on `expr`. + match expr { + // If the expression is a math expression. + Expr::MathExpr(e) => { + unwrap!(e.right); + // st r1, r254, 0, 8; addi64 r254, r254, 8; + ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]); + unwrap!(e.left); + // st r1, r254, 0, 8; addi64 r254, r254, 8; + ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]); + match e.operator { + // If the operator is addition. + MathOperator::OP_ADD => { + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]); + + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]); + + // add64 r1, r32, r33 + ins!([0x06, 1, 32, 33]); + }, + // If the operator is multiplication. + MathOperator::OP_MULT => { + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]); + + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]); + + // mul64 r1, r33, r34 + ins!([0x0e, 1, 33, 34]); + }, + // If the operator is division. + MathOperator::OP_DIV => { + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]); + + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]); + + // fdiv64 r1, r33, r34 + ins!([0x65, 1, 33, 34]); + }, + // If the operators is subtraction. + MathOperator::OP_SUB => { + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]); + + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]); + + // sub64 r1, r33, r34 + ins!([0x0a, 1, 33, 34]); + }, + // If the operator is modulo. + MathOperator::OP_MOD => { + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r33, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 33, 254, 0, 8]); + + // addi64 r254, r254, -8 (two's complement 0b11111000); ld r34, r254, 0, 8; + ins!([0x40, 254, 254, 0b11111000, 0x4d, 34, 254, 0, 8]); + + // dirs64 r2, r1, r33, r34 + } + } + }, + + // If the expression is a function call. + Expr::FunCall(e) => { + for (i, p) in e.params.iter().enumerate() { + match i { + 0 => { + unwrap!(*p); + + // cp r2, r1 + ins!([0x46, 2, 1]); + }, + + 1 => { + unwrap!(*p); + + // cp r3, r1 + ins!([0x46, 3, 1]); + }, + + 2 => { + unwrap!(*p); + + // cp r4, r1 + ins!([0x46, 4, 1]); + }, + + 3 => { + unwrap!(*p); + // cp r5, r1 + ins!([0x46, 5, 1]); + + }, + + 4 => { + unwrap!(*p); + // cp r6, r1 + ins!([0x46, 6, 1]); + }, + + 5 => { + unwrap!(*p); + // cp r7, r1 + ins!([0x46, 7, 1]); + }, + + 6 => { + unwrap!(*p); + // cp r8, r1 + ins!([0x46, 8, 1]); + }, + + 7 => { + unwrap!(*p); + // cp r9, r1 + ins!([0x46, 9, 1]); + }, + + 8 => { + unwrap!(*p); + // cp r10, r1 + ins!([0x46, 10, 1]); + }, + + 9 => { + unwrap!(*p); + // cp r11, r1 + ins!([0x46, 11, 1]); + }, + + _ => { + println!("More than ten parameters are currently not supported."); + std::process::exit(1); + } + } + } + + ins!([0x53]; unsafe { std::mem::transmute::(self.pc.wrapping_sub(self.functions[e.name])) }); + }, + + // Define a global variable. + Expr::GlobalDefinition(e) => { + // Define a 64-bit global variable. + + println!("Global variables are currently unsupported."); + std::process::exit(1); + }, + + // Breakpoint. + Expr::Breakpoint => { + // Write the interrupt for a debugger breakpoint. + ins!([0]); + }, + + // Return something from a function. + Expr::Return(e) => { + // Do the operation that should later be returned. + + println!("Returns are currently not supported, (i was too lazy to implement)"); + std::process::exit(1); + }, + + // A function defenition. + Expr::FunDefinition(e) => { + self.functions.insert(e.name.to_owned(), self.pc); + + ins!(&self.hb_codegen(&e.contents).to_vec()); + }, + + Expr::If(e) => { + // Increment the temporary variable/function counter. + // Compare the left and right value. + unwrap!(e.left); + // st r1, r254, 0, 8; addi64 r254, r254, 8; + ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]); + unwrap!(e.right); + // st r1, r254, 0, 8; addi64 r254, r254, 8; + ins!([0x4e, 1, 254, 0, 8, 0x30, 254, 254, 8]); + + let action = self.pc; + ins!(&self.hb_codegen(&e.action).to_vec()); + // Check what the condition is. + match e.cond { + COND_OP::EQ => { + // If the compared values are equal to each other jump to the temporary function. + ins!([0x56]; unsafe { std::mem::transmute::(self.pc.wrapping_sub(action)) }); + + }, + + COND_OP::NE => { + // If the compared values are not equal to eachother jump to the temporary function. + ins!([0x57]; unsafe { std::mem::transmute::(self.pc.wrapping_sub(action)) }); + } + } + }, + Expr::Number(n) => { + ins!([0x4b, 1]; unsafe { ::core::mem::transmute::(*n) }); + }, + no => unsafe { + // Write some data I randomly typed to your memory because don't going around playing with something that I haven't implemented yet. + println!("{:?} is not. implemented. prepare to be destroyed >:-(", no); + let ptr = std::ptr::null_mut::(); + ::std::ptr::write(ptr, 124010240120401240.12410240124120401240); + }, + } + + } + + + &gen + } + +}