Skip to content

Commit

Permalink
Make compiler return Assembly instead of String
Browse files Browse the repository at this point in the history
  • Loading branch information
veera-sivarajan committed Feb 11, 2024
1 parent af64de1 commit e8e7f15
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 47 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]

resolver = "2"
members = [
"driver", # cli binary
"compiler", # compiler library
Expand Down
12 changes: 6 additions & 6 deletions compiler/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ pub struct Assembly {
pub global: String, // function names
}

impl Assembly {
fn build(&self) -> String {
format!("{}{}{}{}", self.global, self.header, self.code, self.data)
impl fmt::Display for Assembly {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}{}{}", self.global, self.header, self.code, self.data)
}
}

Expand Down Expand Up @@ -193,16 +193,16 @@ impl CodeGen {
}
}

pub fn compile(&mut self, ast: &[LLStmt]) -> String {
pub fn compile(&mut self, ast: &[LLStmt]) -> Assembly {
for ele in ast {
self.codegen(ele);
}
self.build_assembly()
}

fn build_assembly(&mut self) -> String {
fn build_assembly(&mut self) -> Assembly {
self.build_globals();
self.assembly.build()
self.assembly.clone()
}

fn build_globals(&mut self) {
Expand Down
7 changes: 3 additions & 4 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod codegen;
pub mod codegen;
mod error;
mod expr;
mod lexer;
Expand All @@ -8,8 +8,7 @@ mod typecheck;

use crate::error::BobaError;
use crate::parser::Parser;

type Assembly = String;
use crate::codegen::Assembly;

fn compile_helper(source: &str, print_ast: bool) -> Result<Assembly, BobaError> {
let mut lexer = lexer::Lexer::new(source);
Expand All @@ -29,7 +28,7 @@ fn compile_helper(source: &str, print_ast: bool) -> Result<Assembly, BobaError>
}
}

pub fn compile(source: &str, print_ast: bool) -> Result<String, BobaError> {
pub fn compile(source: &str, print_ast: bool) -> Result<Assembly, BobaError> {
if !source.is_empty() {
compile_helper(source, print_ast)
} else {
Expand Down
74 changes: 38 additions & 36 deletions driver/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,52 @@
use clap::Parser;
use std::fs::{read_to_string, write};
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[clap(version, about, long_about = None)]
struct Args {
/// Name of the file to be compiled
filename: String,
/// Print the parsed AST
#[arg(short, long)]
print_ast: bool,
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::process::{Command, Stdio};
use compiler::codegen::Assembly;

fn assemble(assembly: Assembly) -> std::io::Result<()> {
let mut assembly_file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open("/home/veera/projects/boba/misc/input.s")?;
assembly_file.write_all(assembly.to_string().as_bytes())?;
Command::new("gcc")
.arg("/home/veera/projects/boba/misc/input.s")
.arg("-o")
.arg("/home/veera/projects/boba/misc/input")
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.expect("Failed to invoke gcc.");
println!("========Program Output===========");
Command::new("/home/veera/projects/boba/misc/input")
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.expect("Failed to run the executable.");
Ok(())
}

fn run(args: Args) -> std::io::Result<()> {
let source = read_to_string(&args.filename)?;
let mut file = PathBuf::from(args.filename);
file.set_extension("s");
let mut output = std::env::current_dir()?;
output.push(file.file_name().unwrap());
match compiler::compile(source.trim_end(), args.print_ast) {
Ok(assembly) => {
write(output, assembly)?;
fn main() -> std::io::Result<()> {
let source = include_str!("/home/veera/projects/boba/misc/input.rs");
match compiler::compile(source.trim_end(), false) {
Ok(assembly) => assemble(assembly),
Err(err) => {
eprint!("{err}");
Ok(())
}
Err(error) => {
eprint!("{error}");
std::process::exit(1);
}
}
}

fn main() -> std::io::Result<()> {
run(Args::parse())
}

#[cfg(test)]
mod tests {
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use super::*;

fn assemble(assembly: &str, source_name: &str) -> String {
fn assemble(code: Assembly, source_name: &str) -> String {
let source_path = format!("../test/output/bin/{source_name}");
let mut assembly_file = PathBuf::from(&source_path);
assembly_file.set_extension("s");
Expand All @@ -56,7 +61,7 @@ mod tests {
.open(&assembly_file)
.unwrap();

file.write_all(assembly.as_bytes()).unwrap();
file.write_all(code.to_string().as_bytes()).unwrap();

// compile assembly to executable
Command::new("gcc")
Expand All @@ -80,7 +85,7 @@ mod tests {
let source = std::fs::read_to_string(input);
if let Ok(source) = source {
match compiler::compile(source.trim_end(), false) {
Ok(code) => assemble(&code, source_name),
Ok(code) => assemble(code, source_name),
Err(message) => message.to_string(),
}
} else {
Expand All @@ -96,10 +101,7 @@ mod tests {
let result = execute(input, source_name);
let expected = std::fs::read_to_string(output_handle)
.unwrap_or("Cannot read output file.".into());
(
result.trim().to_string(),
expected.trim().to_string(),
)
(result.trim().to_string(), expected.trim().to_string())
}

#[test]
Expand Down

0 comments on commit e8e7f15

Please sign in to comment.