Added src/codegen/holeybytes.rs.
This commit is contained in:
parent
e3cdfec0d9
commit
137d9f5884
274
src/codegen/holeybytes.rs
Normal file
274
src/codegen/holeybytes.rs
Normal file
|
@ -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<String, u32>,
|
||||
globals: HashMap<String, u64>,
|
||||
}
|
||||
|
||||
impl HbCodegen {
|
||||
pub fn new() -> Self {
|
||||
HbCodegen {
|
||||
pc: 0,
|
||||
functions: HashMap::new(),
|
||||
globals: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hb_codegen(&mut self, exprs: &Vec<Expr>) -> &[u8] {
|
||||
let mut gen: Vec<u8> = 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::<u32, [u8; 4]>(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::<u32, [u8; 4]>(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::<u32, [u8; 4]>(self.pc.wrapping_sub(action)) });
|
||||
}
|
||||
}
|
||||
},
|
||||
Expr::Number(n) => {
|
||||
ins!([0x4b, 1]; unsafe { ::core::mem::transmute::<u64, [u8; 8]>(*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::<f64>();
|
||||
::std::ptr::write(ptr, 124010240120401240.12410240124120401240);
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
&gen
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue