e0/bin/e0c.rs

95 lines
2.7 KiB
Rust

use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use std::process::ExitCode;
use anyhow::Result;
use clap::Parser;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use codespan_reporting::term::{self, Config as CodespanConfig};
use e0::ast::typeck_bidi::TypeChecker;
use e0::codegen::llvm_ir::LlvmIrCodegen;
use e0::codegen::CodegenBackend;
use e0::parser::ProgramParser;
use lalrpop_util::ParseError;
#[derive(Debug, Parser)]
struct Opt {
path: PathBuf,
/// Path to output the bitcode to.
#[clap(short = 'o', long = "out", name = "bitcode-out")]
out_path: PathBuf,
/// Path to output the AST to, if at all.
#[clap(long = "emit-ast", name = "ast-out")]
emit_ast: Option<PathBuf>,
}
fn main() -> Result<ExitCode> {
let opts = Opt::parse();
// Set up reporting
let mut files = SimpleFiles::new();
let writer = StandardStream::stderr(ColorChoice::Always);
let config = CodespanConfig::default();
let contents = fs::read_to_string(&opts.path)?;
let file_id = files.add(opts.path.display().to_string(), &contents);
let parser = ProgramParser::new();
let ast = match parser.parse(&contents) {
Ok(v) => v,
Err(err) => {
let loc = match err {
ParseError::InvalidToken { location }
| ParseError::UnrecognizedEOF { location, .. } => (location, location),
ParseError::UnrecognizedToken { ref token, .. }
| ParseError::ExtraToken { ref token } => (token.0, token.2),
_ => todo!(),
};
let diagnostic = Diagnostic::error()
.with_labels(vec![Label::primary(file_id, loc.0..loc.1)])
.with_message(err.to_string());
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
return Ok(ExitCode::FAILURE);
}
};
let type_checker = TypeChecker::default();
let typed_ast = match type_checker.convert(ast) {
Ok(v) => v,
Err(err) => {
let diagnostic = Diagnostic::error().with_message(err.to_string());
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
return Ok(ExitCode::FAILURE);
}
};
if let Some(path) = opts.emit_ast {
let mut file = File::create(&path)?;
file.write(format!("{:#?}", typed_ast).as_bytes())?;
}
{
let file = File::create(&opts.out_path)?;
let mut codegen = LlvmIrCodegen::new(file);
codegen.convert(typed_ast)?;
}
// let ctx = ast::cranelift::convert(
// opts.path.display().to_string(),
// typed_ast,
// )?;
// {
// let file = File::create(&opts.out_path)?;
// ctx.compile_and_emit();
// println!("Emitted.");
// }
Ok(ExitCode::SUCCESS)
}