#![forbid(unsafe_code)] #![warn(clippy::all)] mod args; #[cfg(feature = "compiler")] mod compiler; mod errors; mod file_io; #[cfg(feature = "compiler")] mod parser; mod vm; use file_io::open_bytecode; #[cfg(feature = "compiler")] use file_io::{into_bytecode, open_source, write_bytecode}; #[cfg(feature = "compiler")] use std::env; use std::path::Path; #[cfg(feature = "compiler")] use std::path::PathBuf; use args::*; #[cfg(feature = "compiler")] use compiler::Compiler; #[cfg(feature = "compiler")] use errors::GenericError; #[cfg(feature = "compiler")] use parser::Parser; #[cfg(feature = "compiler")] use vm::FunctionSignature; use vm::{BuiltinFunctionDef, BuiltinFunctions, CompiledReid, Value, VariableType, VirtualMachine}; fn main() { let print = BuiltinFunctionDef::new( "print", vec![VariableType::TypeString], Box::new(move |args| { if let Value::StringVal(string) = &args[0] { println!("{}", string); } }), ); let builtin_functions = BuiltinFunctions(vec![print]); let opt: MainOpt = argh::from_env(); #[cfg(feature = "compiler")] if let Some(run_path) = opt.run_path { run_bytecode(&run_path, builtin_functions); } else if let Some(subcommand) = opt.subcommand { match subcommand { Subcommand::Compile(opt) => { let source = Path::new(&opt.source); let output = if let Some(output) = opt.output { PathBuf::from(output) } else { source.with_extension("reidc") }; let compiled = compile(source, builtin_functions.signatures()); match compiled { Ok(compiled) => { let bytecode = into_bytecode(&compiled); if let Err(err) = write_bytecode(bytecode, &output) { eprintln!("{}", err); std::process::exit(1); } } Err(error) => { eprintln!("{}", error); std::process::exit(1); } } } Subcommand::Run(opt) => { let path = Path::new(&opt.source); let compiled = compile(path, builtin_functions.signatures()); match compiled { Ok(compiled) => run(compiled, builtin_functions), Err(error) => { eprintln!("{}", error); std::process::exit(1); } } } } } else { let command = env::args().collect::>().join(" "); eprintln!("Please try running instead:"); eprintln!(" {} ", command); eprintln!(" {} help", command); } #[cfg(not(feature = "compiler"))] run_bytecode(&opt.run_path, builtin_functions); } fn run_bytecode(run_path: &Path, builtin_functions: BuiltinFunctions) { let compiled = open_bytecode(run_path); dbg!(&compiled); match compiled { Ok(compiled) => run(compiled, builtin_functions), Err(error) => { eprintln!("{}", error); std::process::exit(1); } } } #[cfg(feature = "compiler")] fn compile(path: &Path, builtin: Vec) -> Result { let parsed = Parser::from(open_source(&path)?).parse()?; //dbg!(&parsed); let compiled = Compiler::from(parsed) .with_builtin_functions(builtin) .compile()?; //dbg!(&compiled); Ok(compiled) } fn run(reid: CompiledReid, builtin: BuiltinFunctions) { let mut vm = VirtualMachine::from(reid); vm.add_builtin_functions(builtin); if let Err(error) = vm.run() { eprintln!("Runtime panic: {:#?}", error); std::process::exit(1); } }