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

refactor: better file structure

This commit is contained in:
Natapat Samutpong 2022-01-26 08:45:59 +07:00
parent 9699e4a270
commit 3d02755095
5 changed files with 189 additions and 173 deletions

View file

@ -1,171 +0,0 @@
use std::fmt::Display;
use crate::parser::Sexpr::{self, *};
/// Literal types for the assembler.
#[derive(Clone, Debug)]
pub enum Type {
Int(i64),
Float(f64),
Boolean(bool),
String(String),
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::Int(i) => write!(f, "${}", i),
Type::Float(fl) => write!(f, "${}", fl),
Type::Boolean(b) => write!(f, "${}", b),
Type::String(s) => write!(f, "$\"{}\"", s),
}
}
}
#[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)]
pub enum Instr {
// Load a literal value onto the stack;
Load { address: Register },
// Store a literal value into a register.
Store { address: Register, value: Type, },
// Call intrinsic function.
Call { address: Register, args: Register },
// 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 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Instr::Load { address } => write!(f, "load {}", address),
Instr::Store { address, value } => write!(f, "store {} {}", address, value),
Instr::Call { address, args } => write!(f, "call {} {}", address, args),
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 instructions: Vec<Instr>,
pub register_pointer: usize,
}
impl Compiler {
pub fn new() -> Compiler {
Compiler {
instructions: Vec::new(),
register_pointer: 1,
}
}
fn next_register(&mut self) -> Register {
let r = Register { value: self.register_pointer };
self.register_pointer += 1;
r
}
fn current_pointer(&self) -> Register {
Register { value: self.register_pointer - 1 }
}
pub fn compile(&mut self, ast: Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
match ast {
Cons(car, cdr) => {
match *car {
Symbol(ref s) => {
match s.as_str() {
"do" => {
for c in cdr {
result.append(&mut self.compile(c)?);
}
}
"print" => {
let mut arg = self.compile_atom(&cdr[0])?;
result.append(&mut arg);
let arg_pointer = self.current_pointer();
let call_register = self.next_register();
result.push(Instr::Store {
address: call_register,
value: Type::Int(1),
});
result.push(Instr::Call {
address: call_register,
args: arg_pointer,
});
},
_ => return Err(format!("Unknown symbol: {}", s)),
}
}
_ => return Err(format!("Expected symbol, got {:?}", car)),
}
}
_ => { dbg!(ast); unimplemented!() }
}
Ok(result)
}
fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
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) => {
let r = self.next_register();
result.push(Instr::Store {
address: r,
value: Type::String(s.to_string()),
});
}
_ => return Err(format!("Expected atom, got {:?}", atom)),
}
Ok(result)
}
}

119
src/compiler/compile.rs Normal file
View file

@ -0,0 +1,119 @@
use crate::{
compiler::lib::{Type, Register, Instr},
parser::Sexpr::{self, *},
};
pub struct Compiler {
pub instructions: Vec<Instr>,
pub register_pointer: usize,
}
impl Compiler {
pub fn new() -> Compiler {
Compiler {
instructions: Vec::new(),
register_pointer: 1,
}
}
fn next_register(&mut self) -> Register {
let r = Register { value: self.register_pointer };
self.register_pointer += 1;
r
}
fn current_pointer(&self) -> Register {
Register { value: self.register_pointer - 1 }
}
pub fn compile(&mut self, ast: Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
match ast {
Cons(car, cdr) => {
match *car {
Symbol(ref s) => {
match s.as_str() {
"do" => {
for c in cdr {
result.append(&mut self.compile(c)?);
}
}
_ => {
result.append(&mut self.compile_intrinsic(s, &cdr)?);
}
}
}
_ => return Err(format!("Expected symbol, got {:?}", car)),
}
}
_ => { dbg!(ast); unimplemented!() }
}
Ok(result)
}
fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
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) => {
let r = self.next_register();
result.push(Instr::Store {
address: r,
value: Type::String(s.to_string()),
});
}
_ => return Err(format!("Expected atom, got {:?}", atom)),
}
Ok(result)
}
fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
match intrinsic.as_str() {
"print" => {
let mut arg = self.compile_atom(&args[0])?;
result.append(&mut arg);
let arg_pointer = self.current_pointer();
let call_register = self.next_register();
result.push(Instr::Store {
address: call_register,
value: Type::Int(1),
});
result.push(Instr::Call {
address: call_register,
args: arg_pointer,
});
}
_ => return Err(format!("Unknown intrinsic: {}", intrinsic)),
}
Ok(result)
}
}

66
src/compiler/lib.rs Normal file
View file

@ -0,0 +1,66 @@
use std::fmt::Display;
/// Literal types for the assembler.
#[derive(Clone, Debug)]
pub enum Type {
Int(i64),
Float(f64),
Boolean(bool),
String(String),
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::Int(i) => write!(f, "${}", i),
Type::Float(fl) => write!(f, "${}", fl),
Type::Boolean(b) => write!(f, "${}", b),
Type::String(s) => write!(f, "$\"{}\"", s),
}
}
}
#[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)]
pub enum Instr {
// Load a literal value onto the stack.
Load { address: Register },
// Store a literal value into a register.
Store { address: Register, value: Type, },
// Call intrinsic function.
Call { address: Register, args: Register },
// 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 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Instr::Load { address } => write!(f, "LOAD {}", address),
Instr::Store { address, value } => write!(f, "STORE {} {}", address, value),
Instr::Call { address, args } => write!(f, "CALL {} {}", address, args),
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),
}
}
}

2
src/compiler/mod.rs Normal file
View file

@ -0,0 +1,2 @@
pub mod lib;
pub mod compile;

View file

@ -11,8 +11,8 @@ use util::cover_paren;
mod parser; mod parser;
use parser::{tokenize, Parser}; use parser::{tokenize, Parser};
mod compile; mod compiler;
use compile::Compiler; use compiler::compile::Compiler;
fn main() { fn main() {
let args = Args::from_args(); let args = Args::from_args();