diff --git a/hblang/Cargo.toml b/hblang/Cargo.toml index 3cd9233..d2d7742 100644 --- a/hblang/Cargo.toml +++ b/hblang/Cargo.toml @@ -3,6 +3,10 @@ name = "hblang" version = "0.1.0" edition = "2021" +[[bin]] +name = "hbc" +path = "src/main.rs" + [dependencies] [dev-dependencies] diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index 435f880..854ce97 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -307,8 +307,9 @@ impl<'a> std::fmt::Display for TypeDisplay<'a> { } } +#[derive(Default)] pub struct Codegen<'a> { - path: &'a std::path::Path, + path: &'a str, input: &'a [u8], ret: Type, gpa: RegAlloc, @@ -325,31 +326,7 @@ pub struct Codegen<'a> { } impl<'a> Codegen<'a> { - pub fn new() -> Self { - Self { - path: std::path::Path::new(""), - input: &[], - ret: bt::VOID, - gpa: Default::default(), - code: Default::default(), - temp: Default::default(), - labels: Default::default(), - stack_size: 0, - vars: Default::default(), - ret_relocs: Default::default(), - loops: Default::default(), - records: Default::default(), - pointers: Default::default(), - main: None, - } - } - - pub fn file( - &mut self, - path: &'a std::path::Path, - input: &'a [u8], - exprs: &'a [parser::Expr<'a>], - ) -> std::fmt::Result { + pub fn file(&mut self, path: &'a str, input: &'a [u8], exprs: &'a [parser::Expr<'a>]) { self.path = path; self.input = input; @@ -442,7 +419,6 @@ impl<'a> Codegen<'a> { _ => unreachable!(), } } - Ok(()) } fn align_of(&self, ty: Type) -> u64 { @@ -1168,7 +1144,7 @@ impl<'a> Codegen<'a> { fn report(&self, pos: parser::Pos, msg: impl std::fmt::Display) -> ! { let (line, col) = lexer::line_col(self.input, pos); - println!("{}:{}:{}: {}", self.path.display(), line, col, msg); + println!("{}:{}:{}: {}", self.path, line, col, msg); unreachable!(); } } @@ -1276,12 +1252,12 @@ mod tests { } fn generate(input: &'static str, output: &mut String) { - let path = std::path::Path::new("test"); + let path = "test"; let arena = crate::parser::Arena::default(); let mut parser = super::parser::Parser::new(input, path, &arena); let exprs = parser.file(); - let mut codegen = super::Codegen::new(); - codegen.file(path, input.as_bytes(), &exprs).unwrap(); + let mut codegen = super::Codegen::default(); + codegen.file(path, input.as_bytes(), &exprs); let mut out = Vec::new(); codegen.dump(&mut out).unwrap(); diff --git a/hblang/src/lib.rs b/hblang/src/lib.rs index 909fd2c..f41aa95 100644 --- a/hblang/src/lib.rs +++ b/hblang/src/lib.rs @@ -15,12 +15,12 @@ macro_rules! run_tests { )*}; } -mod codegen; +pub mod codegen; mod ident; mod instrs; mod lexer; mod log; -mod parser; +pub mod parser; mod tests; mod typechk; diff --git a/hblang/src/main.rs b/hblang/src/main.rs new file mode 100644 index 0000000..2e9fd70 --- /dev/null +++ b/hblang/src/main.rs @@ -0,0 +1,25 @@ +use std::io; + +use hblang::{codegen, parser}; + +fn main() -> io::Result<()> { + if std::env::args().len() == 1 { + eprintln!("Usage: hblang ..."); + eprintln!(" 1. compiled binary will be printed to stdout"); + eprintln!(" 2. order of files matters"); + std::process::exit(1); + } + + let files = std::env::args() + .skip(1) + .map(|path| std::fs::read_to_string(&path).map(|src| (path, src))) + .collect::>>()?; + let mut arena = parser::Arena::default(); + let mut codegen = codegen::Codegen::default(); + for (path, content) in files.iter() { + let file = parser::Parser::new(content, path, &arena).file(); + codegen.file(path, content.as_bytes(), file); + arena.clear(); + } + codegen.dump(&mut std::io::stdout()) +} diff --git a/hblang/src/parser.rs b/hblang/src/parser.rs index ce51d95..a12b11c 100644 --- a/hblang/src/parser.rs +++ b/hblang/src/parser.rs @@ -15,7 +15,7 @@ struct ScopeIdent<'a> { } pub struct Parser<'a, 'b> { - path: &'a std::path::Path, + path: &'a str, lexer: Lexer<'a>, arena: &'b Arena<'a>, token: Token, @@ -23,7 +23,7 @@ pub struct Parser<'a, 'b> { } impl<'a, 'b> Parser<'a, 'b> { - pub fn new(input: &'a str, path: &'a std::path::Path, arena: &'b Arena<'a>) -> Self { + pub fn new(input: &'a str, path: &'a str, arena: &'b Arena<'a>) -> Self { let mut lexer = Lexer::new(input); let token = lexer.next(); Self { @@ -43,7 +43,7 @@ impl<'a, 'b> Parser<'a, 'b> { let (line, col) = self.lexer.line_col(ident::pos(id.ident)); eprintln!( "{}:{}:{} => undeclared identifier: {}", - self.path.display(), + self.path, line, col, self.lexer.slice(ident::range(id.ident)) @@ -327,7 +327,7 @@ impl<'a, 'b> Parser<'a, 'b> { fn report(&self, msg: impl std::fmt::Display) -> ! { let (line, col) = self.lexer.line_col(self.token.start); - eprintln!("{}:{}:{} => {}", self.path.display(), line, col, msg); + eprintln!("{}:{}:{} => {}", self.path, line, col, msg); unreachable!(); } } @@ -717,7 +717,7 @@ mod tests { fn parse(input: &'static str, output: &mut String) { use std::fmt::Write; let mut arena = super::Arena::default(); - let mut parser = super::Parser::new(input, std::path::Path::new("test"), &arena); + let mut parser = super::Parser::new(input, "test", &arena); for expr in parser.file() { writeln!(output, "{}", expr).unwrap(); }