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, } fn main() -> Result { 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) }