adding simple cli
This commit is contained in:
parent
c3cbd054f7
commit
5c38115119
|
@ -3,6 +3,10 @@ name = "hblang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "hbc"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -307,8 +307,9 @@ impl<'a> std::fmt::Display for TypeDisplay<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
path: &'a std::path::Path,
|
path: &'a str,
|
||||||
input: &'a [u8],
|
input: &'a [u8],
|
||||||
ret: Type,
|
ret: Type,
|
||||||
gpa: RegAlloc,
|
gpa: RegAlloc,
|
||||||
|
@ -325,31 +326,7 @@ pub struct Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
impl<'a> Codegen<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn file(&mut self, path: &'a str, input: &'a [u8], exprs: &'a [parser::Expr<'a>]) {
|
||||||
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 {
|
|
||||||
self.path = path;
|
self.path = path;
|
||||||
self.input = input;
|
self.input = input;
|
||||||
|
|
||||||
|
@ -442,7 +419,6 @@ impl<'a> Codegen<'a> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_of(&self, ty: Type) -> u64 {
|
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) -> ! {
|
fn report(&self, pos: parser::Pos, msg: impl std::fmt::Display) -> ! {
|
||||||
let (line, col) = lexer::line_col(self.input, pos);
|
let (line, col) = lexer::line_col(self.input, pos);
|
||||||
println!("{}:{}:{}: {}", self.path.display(), line, col, msg);
|
println!("{}:{}:{}: {}", self.path, line, col, msg);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1276,12 +1252,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate(input: &'static str, output: &mut String) {
|
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 arena = crate::parser::Arena::default();
|
||||||
let mut parser = super::parser::Parser::new(input, path, &arena);
|
let mut parser = super::parser::Parser::new(input, path, &arena);
|
||||||
let exprs = parser.file();
|
let exprs = parser.file();
|
||||||
let mut codegen = super::Codegen::new();
|
let mut codegen = super::Codegen::default();
|
||||||
codegen.file(path, input.as_bytes(), &exprs).unwrap();
|
codegen.file(path, input.as_bytes(), &exprs);
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
codegen.dump(&mut out).unwrap();
|
codegen.dump(&mut out).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ macro_rules! run_tests {
|
||||||
)*};
|
)*};
|
||||||
}
|
}
|
||||||
|
|
||||||
mod codegen;
|
pub mod codegen;
|
||||||
mod ident;
|
mod ident;
|
||||||
mod instrs;
|
mod instrs;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod log;
|
mod log;
|
||||||
mod parser;
|
pub mod parser;
|
||||||
mod tests;
|
mod tests;
|
||||||
mod typechk;
|
mod typechk;
|
||||||
|
|
||||||
|
|
25
hblang/src/main.rs
Normal file
25
hblang/src/main.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use hblang::{codegen, parser};
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
if std::env::args().len() == 1 {
|
||||||
|
eprintln!("Usage: hblang <file1> <file2> ...");
|
||||||
|
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::<io::Result<Vec<_>>>()?;
|
||||||
|
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())
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ struct ScopeIdent<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Parser<'a, 'b> {
|
pub struct Parser<'a, 'b> {
|
||||||
path: &'a std::path::Path,
|
path: &'a str,
|
||||||
lexer: Lexer<'a>,
|
lexer: Lexer<'a>,
|
||||||
arena: &'b Arena<'a>,
|
arena: &'b Arena<'a>,
|
||||||
token: Token,
|
token: Token,
|
||||||
|
@ -23,7 +23,7 @@ pub struct Parser<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> 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 mut lexer = Lexer::new(input);
|
||||||
let token = lexer.next();
|
let token = lexer.next();
|
||||||
Self {
|
Self {
|
||||||
|
@ -43,7 +43,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let (line, col) = self.lexer.line_col(ident::pos(id.ident));
|
let (line, col) = self.lexer.line_col(ident::pos(id.ident));
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{}:{}:{} => undeclared identifier: {}",
|
"{}:{}:{} => undeclared identifier: {}",
|
||||||
self.path.display(),
|
self.path,
|
||||||
line,
|
line,
|
||||||
col,
|
col,
|
||||||
self.lexer.slice(ident::range(id.ident))
|
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) -> ! {
|
fn report(&self, msg: impl std::fmt::Display) -> ! {
|
||||||
let (line, col) = self.lexer.line_col(self.token.start);
|
let (line, col) = self.lexer.line_col(self.token.start);
|
||||||
eprintln!("{}:{}:{} => {}", self.path.display(), line, col, msg);
|
eprintln!("{}:{}:{} => {}", self.path, line, col, msg);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,7 +717,7 @@ mod tests {
|
||||||
fn parse(input: &'static str, output: &mut String) {
|
fn parse(input: &'static str, output: &mut String) {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut arena = super::Arena::default();
|
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() {
|
for expr in parser.file() {
|
||||||
writeln!(output, "{}", expr).unwrap();
|
writeln!(output, "{}", expr).unwrap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue