wip compiler
This commit is contained in:
parent
61d0adb25b
commit
4249d67308
6 changed files with 172 additions and 43 deletions
1
src/arch.rs
Normal file
1
src/arch.rs
Normal file
|
@ -0,0 +1 @@
|
|||
mod aarch64;
|
5
src/arch/aarch64.rs
Normal file
5
src/arch/aarch64.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use crate::ir::{IrBlock, IrProgram};
|
||||
|
||||
pub enum ISA {}
|
||||
|
||||
pub fn compile_program(program: IrProgram<ISA>) {}
|
|
@ -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
11
src/ir.rs
Normal 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),
|
||||
}
|
56
src/main.rs
56
src/main.rs
|
@ -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
59
src/parser.rs
Normal 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)
|
||||
}
|
Loading…
Reference in a new issue