1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00
bobbylisp/crates/main/src/main.rs

146 lines
5.9 KiB
Rust
Raw Normal View History

2022-03-07 02:15:43 -06:00
use std::{fs, io::Write};
use clap::Parser as ArgParser;
2022-03-06 09:50:23 -06:00
use ariadne::{Report, ReportKind, Label, Source, Color, Fmt};
2022-03-07 02:15:43 -06:00
use lexer::lex;
use parser::parse;
2022-03-06 14:45:09 -06:00
use hir::ast_to_ir;
2022-03-07 02:15:43 -06:00
use codegen::cpp;
pub mod args;
use args::{Args, Options};
pub mod util;
use crate::util::log;
fn main() {
let args = Args::parse();
match args.options {
Options::Compile {
input: file_name,
ast: _print_ast,
2022-03-07 03:48:36 -06:00
log: should_log,
output,
} => {
2022-03-07 03:48:36 -06:00
// Macro to only log if `should_log` is true
macro_rules! logif {
($level:expr, $msg:expr) => { if should_log { log($level, $msg); } };
}
2022-03-07 02:15:43 -06:00
// Start timer
let start = std::time::Instant::now();
// Get file contents
2022-03-07 03:48:36 -06:00
logif!(0, format!("Reading {}", &file_name.display()));
let src = fs::read_to_string(&file_name).expect("Failed to read file");
2022-03-07 02:15:43 -06:00
// Lex the file
let (tokens, lex_error) = lex(src.clone());
2022-03-06 09:50:23 -06:00
let (ast, parse_error) = parse(tokens.unwrap(), src.chars().count());
2022-03-07 02:15:43 -06:00
// Report errors
2022-03-06 09:50:23 -06:00
lex_error.into_iter()
.map(|e| e.map(|e| e.to_string()))
.chain(parse_error.into_iter().map(|e| e.map(|tok| tok.to_string())))
.for_each(|e| {
let report = Report::build(ReportKind::Error, (), e.span().start);
2022-03-06 09:50:23 -06:00
let report = match e.reason() {
chumsky::error::SimpleReason::Unclosed { span, delimiter } => report
.with_message(format!(
"Unclosed delimiter {}",
delimiter.fg(Color::Yellow)
))
.with_label(
Label::new(span.clone())
.with_message(format!(
"Expected closing delimiter {}",
delimiter.fg(Color::Yellow)
))
.with_color(Color::Yellow)
)
.with_label(
Label::new(e.span())
.with_message(format!(
"Must be closed before this {}",
e.found()
.unwrap_or(&"end of file".to_string())
.fg(Color::Red)
))
.with_color(Color::Red)
),
2022-03-07 02:15:43 -06:00
2022-03-06 09:50:23 -06:00
chumsky::error::SimpleReason::Unexpected => report
.with_message(format!(
"{}, expected {}",
2022-03-06 11:20:18 -06:00
if e.found().is_some() { "Unexpected token in input" }
2022-03-06 09:50:23 -06:00
else { "Unexpected end of input" },
if e.expected().len() == 0 { "something else".to_string().fg(Color::Green) }
else {
e.expected()
.map(|expected| match expected {
Some(expected) => expected.to_string(),
None => "end of input".to_string()
})
.collect::<Vec<_>>()
.join(", ")
.fg(Color::Green)
}
))
.with_label(
Label::new(e.span())
.with_message(format!(
"Unexpected token {}",
e.found()
.unwrap_or(&"EOF".to_string())
.fg(Color::Red)
))
.with_color(Color::Red)
),
_ => {
println!("{:?}", e);
todo!();
}
};
report.finish().print(Source::from(&src)).unwrap();
2022-03-07 02:15:43 -06:00
}
); // End errors reporting
2022-03-07 03:48:36 -06:00
logif!(0, format!("Parsing took {}ms", start.elapsed().as_millis()));
2022-03-06 09:50:23 -06:00
match ast {
Some(ast) => {
2022-03-07 02:15:43 -06:00
// Convert the AST to HIR
2022-03-06 14:45:09 -06:00
let ir = ast_to_ir(ast);
2022-03-07 03:48:36 -06:00
logif!(0, "Generated HIR.");
2022-03-07 02:15:43 -06:00
// Generate code
let mut codegen = cpp::Codegen::new();
codegen.gen(ir);
2022-03-07 03:48:36 -06:00
logif!(0, "Successfully generated code.");
2022-03-07 02:15:43 -06:00
// Write code to file
2022-03-07 03:48:36 -06:00
let output_path = match output {
Some(output) => output,
None => file_name.with_extension("cpp").file_name().unwrap().to_os_string().into(),
};
let mut file = fs::File::create(&output_path).expect("Failed to create file");
2022-03-07 02:15:43 -06:00
file.write_all(codegen.emitted.as_bytes()).expect("Failed to write to file");
// End timer
let duration = start.elapsed().as_millis();
2022-03-06 14:45:09 -06:00
2022-03-07 03:48:36 -06:00
logif!(0, format!("Compilation took {}ms", duration));
logif!(0, format!("Wrote output to `{}`. All done.", output_path.display()));
2022-03-06 09:50:23 -06:00
},
None => {
2022-03-07 03:48:36 -06:00
logif!(2, "Failed to parse.");
}
}
}
}
}