112 lines
3.0 KiB
Rust
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(),
|
|
}
|
|
}
|