wip compiler

This commit is contained in:
Michael Zhang 2024-12-02 04:29:18 -06:00
parent 61d0adb25b
commit 4249d67308
6 changed files with 172 additions and 43 deletions

1
src/arch.rs Normal file
View file

@ -0,0 +1 @@
mod aarch64;

5
src/arch/aarch64.rs Normal file
View file

@ -0,0 +1,5 @@
use crate::ir::{IrBlock, IrProgram};
pub enum ISA {}
pub fn compile_program(program: IrProgram<ISA>) {}

View file

@ -1 +1,84 @@
use std::{
env::consts::{ARCH, OS},
fs,
path::PathBuf,
};
use anyhow::{bail, Result};
use crate::parser::parse;
#[derive(Debug)]
pub struct TargetTriple {
arch: Arch,
vendor: Vendor,
os: Os,
}
impl TargetTriple {
pub fn detect_build_machine() -> Result<Self> {
Ok(Self {
arch: Arch::detect_build_machine()?,
vendor: Vendor::detect_build_machine()?,
os: Os::detect_build_machine()?,
})
}
}
#[derive(Debug)]
pub enum Arch {
Aarch64,
X86_64,
}
impl Arch {
pub fn detect_build_machine() -> Result<Self> {
Ok(match ARCH {
"x86_64" => Arch::X86_64,
"aarch64" => Arch::Aarch64,
_ => bail!("could not determine arch from {ARCH} or not supported"),
})
}
}
#[derive(Debug)]
pub enum Vendor {
Apple,
Pc,
Unknown,
}
impl Vendor {
pub fn detect_build_machine() -> Result<Self> {
Ok(match OS {
"apple" | "macos" => Vendor::Apple,
"linux" => Vendor::Unknown,
_ => bail!("could not determine vendor from {OS} or not supported"),
})
}
}
#[derive(Debug)]
pub enum Os {
LinuxGnu,
WindowsGnu,
WindowsMsvc,
Darwin,
}
impl Os {
pub fn detect_build_machine() -> Result<Self> {
Ok(match OS {
"apple" | "macos" => Os::Darwin,
"linux" => Os::LinuxGnu,
_ => bail!("could not determine os from {OS} or not supported"),
})
}
}
pub fn compile(path: PathBuf, target: TargetTriple) -> Result<()> {
let source = fs::read_to_string(&path)?;
let tree = parse(&path, &source)?;
Ok(())
}

11
src/ir.rs Normal file
View file

@ -0,0 +1,11 @@
pub struct IrProgram<ISA> {
blocks: IrBlock<ISA>,
}
pub struct IrBlock<ISA> {
instructions: Vec<IrInstruction<ISA>>,
}
pub enum IrInstruction<ISA> {
Raw(ISA),
}

View file

@ -1,6 +1,9 @@
mod arch;
mod ast;
mod compiler;
mod interpreter;
mod ir;
mod parser;
use std::{fs, path::PathBuf, process::exit};
@ -14,8 +17,11 @@ use codespan_reporting::{
termcolor::{ColorChoice, StandardStream},
},
};
use interpreter::run;
use compiler::{compile, TargetTriple};
use lalrpop_util::{lalrpop_mod, ParseError};
use parser::parse;
use crate::interpreter::run;
lalrpop_mod!(grammar);
@ -41,50 +47,14 @@ fn main() -> Result<()> {
let opt = Opt::parse();
match opt.command {
Command::Compile { path } => todo!(),
Command::Compile { path } => {
let target_triple = TargetTriple::detect_build_machine()?;
println!("Target triple: {target_triple:?}");
compile(path, target_triple)?;
}
Command::Run { path } => {
let source = fs::read_to_string(&path)?;
let parser = grammar::ProgramParser::new();
let tree = match parser.parse(&source) {
Ok(v) => v,
Err(e) => {
let mut files = SimpleFiles::new();
let file_id = files.add(path.display().to_string(), &source);
let diagnostic = match e {
ParseError::InvalidToken { location } => Diagnostic::error()
.with_message("invalid token")
.with_labels(vec![Label::primary(file_id, location..location)]),
ParseError::UnrecognizedEof { location, expected } => {
Diagnostic::error()
.with_message(format!(
"unrecognized eof, expected [{}]",
expected.join(", ")
))
.with_labels(vec![Label::primary(file_id, location..location)])
}
ParseError::UnrecognizedToken { token, expected } => {
Diagnostic::error()
.with_message(format!(
"unrecognized token {}, expecting [{}]",
token.1,
expected.join(", ")
))
.with_labels(vec![Label::primary(file_id, token.0..token.2)])
}
ParseError::ExtraToken { token } => Diagnostic::error()
.with_message(format!("extra token {}", token.1))
.with_labels(vec![Label::primary(file_id, token.0..token.2)]),
ParseError::User { error } => {
Diagnostic::error().with_message(error)
}
};
let writer = StandardStream::stderr(ColorChoice::Always);
let config = codespan_reporting::term::Config::default();
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
exit(1);
}
};
let tree = parse(&path, &source)?;
run(path, tree)?;
}

59
src/parser.rs Normal file
View file

@ -0,0 +1,59 @@
use std::{path::Path, process::exit};
use anyhow::Result;
use codespan_reporting::{
diagnostic::{Diagnostic, Label},
files::SimpleFiles,
term::{
self,
termcolor::{ColorChoice, StandardStream},
},
};
use lalrpop_util::ParseError;
use crate::{ast::Stmt, grammar::ProgramParser};
pub fn parse(path: impl AsRef<Path>, source: &str) -> Result<Vec<Stmt>> {
let parser = ProgramParser::new();
let tree = match parser.parse(source) {
Ok(v) => v,
Err(e) => {
let mut files = SimpleFiles::new();
let file_id = files.add(path.as_ref().display().to_string(), &source);
let diagnostic = match e {
ParseError::InvalidToken { location } => Diagnostic::error()
.with_message("invalid token")
.with_labels(vec![Label::primary(file_id, location..location)]),
ParseError::UnrecognizedEof { location, expected } => {
Diagnostic::error()
.with_message(format!(
"unrecognized eof, expected [{}]",
expected.join(", ")
))
.with_labels(vec![Label::primary(file_id, location..location)])
}
ParseError::UnrecognizedToken { token, expected } => {
Diagnostic::error()
.with_message(format!(
"unrecognized token {}, expecting [{}]",
token.1,
expected.join(", ")
))
.with_labels(vec![Label::primary(file_id, token.0..token.2)])
}
ParseError::ExtraToken { token } => Diagnostic::error()
.with_message(format!("extra token {}", token.1))
.with_labels(vec![Label::primary(file_id, token.0..token.2)]),
ParseError::User { error } => Diagnostic::error().with_message(error),
};
let writer = StandardStream::stderr(ColorChoice::Always);
let config = codespan_reporting::term::Config::default();
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
// TODO: Report the error up
exit(1);
}
};
Ok(tree)
}