94 lines
2.7 KiB
Rust
94 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)
|
|
}
|