Files
ngr/src/bin/ngrun.rs

112 lines
3.0 KiB
Rust

use clap::Parser;
use codespan_reporting::files::SimpleFiles;
use ngr::backend::Backend;
use ngr::eval::Value;
use ngr::syntax;
use ngr::type_infer::TypeInferenceResult;
use pretty::termcolor::StandardStream;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct CommandLineArguments {
/// Which interpreter to use: syntax, ir, or jit
#[arg(value_enum)]
interpreter: Interpreter,
/// The file to parse
file: String,
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
enum Interpreter {
/// Run the syntax-level interpreter
Syntax,
/// Run the IR-level interpreter
IR,
/// Run the JIT backend
JIT,
}
fn print_result<E>(result: (Value<E>, String)) {
println!("{}", result.1);
println!("RESULT: {}", result.0);
}
fn jit(ir: ngr::ir::Program<ngr::ir::Type>) -> Result<fn(), ngr::backend::BackendError> {
let mut backend = Backend::jit(None)?;
let function_id = backend.compile_program("gogogo", ir)?;
backend.module.finalize_definitions()?;
let compiled_bytes = backend.bytes(function_id);
Ok(unsafe { std::mem::transmute::<_, fn() -> ()>(compiled_bytes) })
}
fn main() {
let cli = CommandLineArguments::parse();
let mut file_database = SimpleFiles::new();
let mut console = StandardStream::stdout(pretty::termcolor::ColorChoice::Auto);
let console_options = codespan_reporting::term::Config::default();
let syntax = syntax::Program::parse_file(&mut file_database, cli.file.as_ref());
let mut emit = |x| {
let _ = codespan_reporting::term::emit(&mut console, &console_options, &file_database, &x);
};
let syntax = match syntax {
Ok(x) => x,
Err(e) => {
emit((&e).into());
return;
}
};
let (errors, warnings) = syntax.validate();
let stop = !errors.is_empty();
for error in errors {
emit(error.into());
}
for warning in warnings {
emit(warning.into());
}
if stop {
return;
}
if cli.interpreter == Interpreter::Syntax {
match syntax.eval() {
Err(e) => println!("Evaluation error: {}", e),
Ok(v) => print_result(v),
}
return;
}
let ir = match syntax.type_infer() {
TypeInferenceResult::Success { result, warnings } => {
for warning in warnings {
emit(warning.into());
}
result
}
TypeInferenceResult::Failure { errors, warnings } => {
for warning in warnings {
emit(warning.into());
}
for error in errors {
emit(error.into());
}
return;
}
};
if cli.interpreter == Interpreter::IR {
match ir.eval() {
Err(e) => println!("Evaluation error: {}", e),
Ok(v) => print_result(v),
}
return;
}
match jit(ir) {
Err(e) => emit(e.into()),
Ok(compiled_function) => compiled_function(),
}
}