This commit is contained in:
2025-05-29 18:47:21 +02:00
parent 47412dda11
commit 4d066acda3
2 changed files with 80 additions and 2 deletions

71
src/codegen.rs Normal file
View 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(())
}
}

View File

@@ -1,3 +1,4 @@
mod codegen;
mod parser;
mod tokenizer;
@@ -9,9 +10,15 @@ fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
// TODO: basename
let tokenizer = tokenizer::Tokenizer::new(path, source);
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(())
}