codegen
This commit is contained in:
71
src/codegen.rs
Normal file
71
src/codegen.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use std::{error::Error, fmt::Write};
|
||||||
|
|
||||||
|
use crate::{parser::Expr, tokenizer::TokenType};
|
||||||
|
|
||||||
|
pub struct Codegen {
|
||||||
|
output: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Codegen {
|
||||||
|
pub fn new() -> Codegen {
|
||||||
|
Codegen {
|
||||||
|
output: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
writeln!(&mut self.output, "section .data")?;
|
||||||
|
writeln!(&mut self.output, "format db \"%d\", 10, 0")?;
|
||||||
|
writeln!(&mut self.output, "section .text")?;
|
||||||
|
writeln!(&mut self.output, "global main")?;
|
||||||
|
writeln!(&mut self.output, "main:")?;
|
||||||
|
writeln!(&mut self.output, " extern printf")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
writeln!(&mut self.output, " mov rdi, format")?;
|
||||||
|
writeln!(&mut self.output, " mov rsi, rax")?;
|
||||||
|
writeln!(&mut self.output, " xor rax, rax")?;
|
||||||
|
writeln!(&mut self.output, " call printf")?;
|
||||||
|
writeln!(&mut self.output, " mov rax, 0")?;
|
||||||
|
writeln!(&mut self.output, " ret")?;
|
||||||
|
writeln!(&mut self.output, "section .note.GNU-stack")?;
|
||||||
|
writeln!(&mut self.output, " db 0")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_output(self) -> String {
|
||||||
|
self.output
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_expr(&mut self, expr: Expr) -> Result<(), Box<dyn Error>> {
|
||||||
|
match expr {
|
||||||
|
Expr::Binary { left, op, right } => {
|
||||||
|
self.compile_expr(*left)?;
|
||||||
|
writeln!(&mut self.output, " push rax")?;
|
||||||
|
self.compile_expr(*right)?;
|
||||||
|
writeln!(&mut self.output, " mov rbx, rax")?;
|
||||||
|
writeln!(&mut self.output, " pop rax")?;
|
||||||
|
|
||||||
|
match op.token_type {
|
||||||
|
TokenType::Plus => writeln!(&mut self.output, " add rax, rbx")?,
|
||||||
|
TokenType::Minus => writeln!(&mut self.output, " sub rax, rbx")?,
|
||||||
|
TokenType::Star => writeln!(&mut self.output, " imul rax, rbx")?,
|
||||||
|
TokenType::Slash => {
|
||||||
|
writeln!(&mut self.output, " cqo")?;
|
||||||
|
writeln!(&mut self.output, " idiv rbx")?;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Grouping(expr) => self.compile_expr(*expr)?,
|
||||||
|
Expr::Literal(token) => match token.token_type {
|
||||||
|
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?,
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
Expr::Unary { op, right } => todo!(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main.rs
11
src/main.rs
@@ -1,3 +1,4 @@
|
|||||||
|
mod codegen;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
|
|
||||||
@@ -9,9 +10,15 @@ fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
|||||||
// TODO: basename
|
// TODO: basename
|
||||||
let tokenizer = tokenizer::Tokenizer::new(path, source);
|
let tokenizer = tokenizer::Tokenizer::new(path, source);
|
||||||
let tokens = tokenizer.tokenize()?;
|
let tokens = tokenizer.tokenize()?;
|
||||||
let parser = parser::Parser::new(tokens);
|
|
||||||
|
|
||||||
println!("{:#?}", parser.parse());
|
let parser = parser::Parser::new(tokens);
|
||||||
|
let expr = parser.parse()?;
|
||||||
|
|
||||||
|
let mut codegen = codegen::Codegen::new();
|
||||||
|
codegen.emit_prologue()?;
|
||||||
|
codegen.compile_expr(expr)?;
|
||||||
|
codegen.emit_epilogue()?;
|
||||||
|
println!("{}", codegen.get_output());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user