pub mod ast; pub mod jit; pub mod parsing; pub mod typing; use clap::{Parser, Subcommand}; use crate::ast::Module; /// Experimental compiler for lila #[derive(Parser, Debug)] #[command(author = "Romain P. ")] #[command(version, about, long_about = None)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Subcommand, Debug)] enum Commands { Parse { /// Paths to the source files files: Vec, /// Dump the AST to stdout #[arg(long)] dump_ast: bool, }, TypeCheck { /// Paths to the source files files: Vec, /// Dump the AST to stdout #[arg(long)] dump_ast: bool, }, Compile { /// Paths to the source files files: Vec, /// Dump the CLIR to stdout #[arg(long)] dump_clir: bool, }, } fn parse(files: &Vec) -> Vec { let paths = files.iter().map(std::path::Path::new); paths .map(|path| match parsing::parse_file(&path) { Ok(module) => module, Err(e) => panic!("Parsing error: {:#?}", e), }) .collect() } fn check(modules: &mut Vec) { for module in modules { if let Err(e) = module.type_check() { eprintln!("{}", e); return; } } } fn main() { let cli = Cli::parse(); match &cli.command { Commands::Parse { files, dump_ast } => { let modules = parse(files); if *dump_ast { for module in &modules { println!("{:#?}", &module); } } println!("Parsing OK"); } Commands::TypeCheck { files, dump_ast } => { let mut modules = parse(files); check(&mut modules); if *dump_ast { for module in &modules { println!("{:#?}", &module); } } } Commands::Compile { files, dump_clir } => { let mut jit = jit::JIT::default(); for file in files { match jit.compile(std::fs::read_to_string(file).unwrap().as_str(), *dump_clir) { Err(e) => eprintln!("{}", e), Ok(_code) => println!("Compiled {}", file), } } } } }