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

133 lines
4.6 KiB
Rust
Raw Normal View History

2022-03-12 08:01:20 -06:00
use std::{fs, io::Write, process::Command, path::PathBuf};
use clap::Parser as ArgParser;
2022-03-07 02:15:43 -06:00
use lexer::lex;
use parser::parse;
2022-03-11 17:35:14 -06:00
use diagnostic::Diagnostics;
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};
2022-03-11 18:14:01 -06:00
pub mod config;
pub mod util;
use crate::util::log;
fn main() {
2022-03-11 20:52:24 -06:00
let config_file = fs::read_to_string("./hazure.toml");
2022-03-11 18:14:01 -06:00
let config: config::Config;
match config_file {
Ok(content) => {
let parsed = config::parse_config(&content);
match parsed {
Ok(c) => config = c,
Err(e) => {
log(2, format!("{}", e));
config = config::default_config();
}
}
}
Err(e) => {
log(1, format!("Error reading config file: {}, using default config", e));
config = config::default_config();
}
}
let args = Args::parse();
match args.options {
Options::Compile {
input: file_name,
2022-03-12 16:00:42 -06:00
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-11 17:35:14 -06:00
let mut diagnostics = Diagnostics::new();
for err in lex_error { diagnostics.add_lex_error(err); }
for err in parse_error { diagnostics.add_parse_error(err); }
2022-03-11 18:35:16 -06:00
// Report syntax errors if any
2022-03-11 17:35:14 -06:00
if diagnostics.has_error() {
diagnostics.display(src);
logif!(0, "Epic parsing fail");
std::process::exit(1);
} else {
logif!(0, format!("Parsing took {}ms", start.elapsed().as_millis()));
}
2022-03-06 09:50:23 -06:00
2022-03-12 16:00:42 -06:00
if print_ast { log(0, format!("{:#?}", ast)); }
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-11 17:35:14 -06:00
let (ir, lowering_error) = ast_to_ir(ast);
for err in lowering_error { diagnostics.add_lowering_error(err); }
2022-03-11 18:35:16 -06:00
2022-03-12 16:00:42 -06:00
if print_ast { log(0, format!("{:#?}", ir)); }
2022-03-11 18:35:16 -06:00
// Report lowering errors if any
2022-03-11 17:35:14 -06:00
if diagnostics.has_error() {
diagnostics.display(src);
logif!(0, "Epic Lowering(HIR) fail");
std::process::exit(1);
} else {
logif!(0, format!("Lowering took {}ms", start.elapsed().as_millis()));
}
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-12 08:01:20 -06:00
let output_path: PathBuf = file_name.with_extension("cpp").file_name().unwrap().to_os_string().into();
2022-03-07 03:48:36 -06:00
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");
2022-03-11 18:35:16 -06:00
// Compile the generate code
2022-03-11 18:14:01 -06:00
let compiler = &config.compiler.compiler;
Command::new(compiler)
.arg(&output_path)
2022-03-12 08:01:20 -06:00
.arg(format!("-o{}", match output {
Some(o) => o.display().to_string(),
None => file_name
.with_extension("out")
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string(),
}))
2022-03-11 18:14:01 -06:00
.spawn()
.expect("Failed to run compiler");
2022-03-11 18:35:16 -06:00
// End timer
let duration = start.elapsed().as_millis();
logif!(0, format!("Compilation took {}ms", duration));
logif!(0, format!("Wrote output to `{}`", output_path.display()));
2022-03-06 09:50:23 -06:00
},
2022-03-11 18:14:01 -06:00
None => { unreachable!(); }
}
}
}
}