1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

refactor: more simpler instructions

This commit is contained in:
Natapat Samutpong 2022-01-26 08:31:11 +07:00
parent 65e7ca560f
commit 9699e4a270
3 changed files with 116 additions and 97 deletions

View file

@ -1 +1 @@
(print "Hello, World!") (print "Hello, World")

View file

@ -2,150 +2,170 @@ use std::fmt::Display;
use crate::parser::Sexpr::{self, *}; use crate::parser::Sexpr::{self, *};
#[derive(Clone, Debug, Copy)] /// Literal types for the assembler.
pub struct Register { value: i64 }
impl Display for Register {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
/// Literal types for the bytecode.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Type { pub enum Type {
Int(i64), Int(i64),
Float(f64), Float(f64),
Bool(bool), Boolean(bool),
String(String), String(String),
} }
impl Display for Type { impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
Type::Int(i) => write!(f, "{}", i), Type::Int(i) => write!(f, "${}", i),
Type::Float(fl) => write!(f, "{}", fl), Type::Float(fl) => write!(f, "${}", fl),
Type::Bool(b) => write!(f, "{}", b), Type::Boolean(b) => write!(f, "${}", b),
Type::String(s) => write!(f, "{}", s), Type::String(s) => write!(f, "$\"{}\"", s),
} }
} }
} }
/// Instructions for the bytecode. #[derive(Clone, Copy, Debug)]
pub struct Register { pub value: usize }
impl Display for Register {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "r{}", self.value)
}
}
/// Instructions for the assembler.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Instr { pub enum Instr {
/// Call(Function Index, Arguments) // Load a literal value onto the stack;
Call(usize, [Register; 6]), Load { address: Register },
// Store a literal value into a register.
/// Stack manipulators Store { address: Register, value: Type, },
Push(usize, Type), Pop(usize, Register), // Call intrinsic function.
Call { address: Register, args: Register },
JumpIfFalse(usize, Register, usize), // Stack arithmetic.
Add, Sub, Mul, Div,
// Immediate arithmetic.
IAdd { lhs: Register, rhs: Register, to: Register, },
ISub { lhs: Register, rhs: Register, to: Register, },
IMul { lhs: Register, rhs: Register, to: Register, },
IDiv { lhs: Register, rhs: Register, to: Register, },
} }
impl Display for Instr { impl Display for Instr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
Instr::Call(idx, args) => write!(f, "{} call {} {} {} {} {} {}", idx, args[0], args[1], args[2], args[3], args[4], args[5]), Instr::Load { address } => write!(f, "load {}", address),
Instr::Push(idx, t) => write!(f, "{} push {}", idx, t), Instr::Store { address, value } => write!(f, "store {} {}", address, value),
Instr::Pop(idx, r) => write!(f, "{} pop {}", idx, r), Instr::Call { address, args } => write!(f, "call {} {}", address, args),
Instr::JumpIfFalse(idx, r, to) => write!(f, "{} jmpf {} {}", idx, r, to), Instr::Add => write!(f, "add"),
Instr::Sub => write!(f, "sub"),
Instr::Mul => write!(f, "mul"),
Instr::Div => write!(f, "div"),
Instr::IAdd { lhs, rhs, to } => write!(f, "iadd {} {} {}", lhs, rhs, to),
Instr::ISub { lhs, rhs, to } => write!(f, "isub {} {} {}", lhs, rhs, to),
Instr::IMul { lhs, rhs, to } => write!(f, "imul {} {} {}", lhs, rhs, to),
Instr::IDiv { lhs, rhs, to } => write!(f, "idiv {} {} {}", lhs, rhs, to),
} }
} }
} }
pub struct Compiler { pub struct Compiler {
/// The bytecode. pub instructions: Vec<Instr>,
pub bytecode: Vec<Instr>, pub register_pointer: usize,
/// The stack.
pub stack: Vec<Type>,
/// The current register index.
pub register: Register,
/// The current label index.
pub label: usize,
} }
impl Compiler { impl Compiler {
pub fn new() -> Compiler { pub fn new() -> Compiler {
Compiler { Compiler {
bytecode: Vec::new(), instructions: Vec::new(),
stack: Vec::new(), register_pointer: 1,
register: Register { value: 1 },
label: 0,
} }
} }
fn next_register(&mut self) -> Register { fn next_register(&mut self) -> Register {
let r = self.register; let r = Register { value: self.register_pointer };
self.register.value += 1; self.register_pointer += 1;
r r
} }
fn next_label(&mut self) -> usize { fn current_pointer(&self) -> Register {
let l = self.label; Register { value: self.register_pointer - 1 }
self.label += 1;
l
} }
pub fn compile_sexpr(&mut self, ast: Sexpr) -> Vec<Instr> { pub fn compile(&mut self, ast: Sexpr) -> Result<Vec<Instr>, String> {
let mut result: Vec<Instr> = Vec::new(); let mut result = Vec::new();
match ast { match ast {
Cons(car, cdr) => { Cons(car, cdr) => {
match *car { match *car {
Symbol(f) => { Symbol(ref s) => {
match f.as_str() { match s.as_str() {
"do" => { "do" => {
for c in cdr { for c in cdr {
result.append(&mut self.compile_sexpr(c)); result.append(&mut self.compile(c)?);
} }
}, }
"print" => { "print" => {
let function_register = self.next_register(); let mut arg = self.compile_atom(&cdr[0])?;
result.push(Instr::Push(self.next_label(), Type::Int(1))); result.append(&mut arg);
result.push(Instr::Pop(self.next_label(), function_register)); let arg_pointer = self.current_pointer();
let arg = &cdr[0]; let call_register = self.next_register();
let instrs = &mut self.compile_ast(arg); result.push(Instr::Store {
result.append(&mut instrs.clone()); address: call_register,
value: Type::Int(1),
});
let arg_register = match instrs.last().unwrap() { result.push(Instr::Call {
Instr::Pop(_, r) => *r, address: call_register,
_ => panic!("Expected mov instruction in `print`"), args: arg_pointer,
}; });
result.push(
Instr::Call(self.next_label(), [
function_register,
arg_register,
Register { value: 0 },
Register { value: 0 },
Register { value: 0 },
Register { value: 0 }
])
);
}, },
_ => todo!(), _ => return Err(format!("Unknown symbol: {}", s)),
} }
}, }
_ => todo!(), _ => return Err(format!("Expected symbol, got {:?}", car)),
} }
}, }
_ => todo!() _ => { dbg!(ast); unimplemented!() }
} }
result Ok(result)
} }
fn compile_ast(&mut self, ast: &Sexpr) -> Vec<Instr> { fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new(); let mut result = Vec::new();
match ast {
match atom {
Int(i) => {
let r = self.next_register();
result.push(Instr::Store {
address: r,
value: Type::Int(*i),
});
}
Float(f) => {
let r = self.next_register();
result.push(Instr::Store {
address: r,
value: Type::Float(*f),
});
}
Boolean(b) => {
let r = self.next_register();
result.push(Instr::Store {
address: r,
value: Type::Boolean(*b),
});
}
Str(s) => { Str(s) => {
result.push(Instr::Push(self.next_label(), Type::String(format!("\"{}\"", s)))); let r = self.next_register();
result.push(Instr::Pop(self.next_label(), self.next_register())); result.push(Instr::Store {
}, address: r,
_ => todo!() value: Type::String(s.to_string()),
});
}
_ => return Err(format!("Expected atom, got {:?}", atom)),
} }
result
Ok(result)
} }
} }

View file

@ -26,12 +26,11 @@ fn main() {
match args.verbose { match args.verbose {
0 => { 0 => {
let mut compiler = Compiler::new();
let instrs = compiler.compile_sexpr(result.unwrap());
let mut file = File::create(format!("{}.bbb", file_name)).unwrap(); let mut file = File::create(format!("{}.bbb", file_name)).unwrap();
for instr in instrs {
file.write_all(format!("{}\n", instr).as_bytes()).unwrap(); let mut compiler = Compiler::new();
for instr in compiler.compile(result.unwrap()).unwrap() {
write!(file, "{}\n", instr).unwrap();
} }
}, },
1 => println!("{:?}", result), 1 => println!("{:?}", result),