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(result: (Value, String)) { println!("{}", result.1); println!("RESULT: {}", result.0); } fn jit(ir: ngr::ir::Program) -> Result { 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(), } }