refactor: split project into multiple crates
This commit is contained in:
parent
486af67fc2
commit
857f747524
27 changed files with 308 additions and 222 deletions
157
lila-cli/src/main.rs
Normal file
157
lila-cli/src/main.rs
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
use std::default::Default;
|
||||
use std::io::Write as _;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser as ClapParser, Subcommand};
|
||||
|
||||
use lila::report::ToReport;
|
||||
use lila::source::SourceCache;
|
||||
use lila_ast::Module;
|
||||
use lila_checking::TypeCheckModule;
|
||||
use lila_jit as jit;
|
||||
use lila_parsing::{DefaultParser as LilaParser, Parser as _};
|
||||
|
||||
/// Experimental compiler for lila
|
||||
#[derive(ClapParser, Debug)]
|
||||
#[command(author = "Romain P. <rpqt@rpqt.fr>")]
|
||||
#[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<String>,
|
||||
|
||||
/// Dump the AST to stdout
|
||||
#[arg(long)]
|
||||
dump_ast: bool,
|
||||
},
|
||||
Check {
|
||||
/// Paths to the source files
|
||||
files: Vec<String>,
|
||||
|
||||
/// Dump the AST to stdout
|
||||
#[arg(long)]
|
||||
dump_ast: bool,
|
||||
},
|
||||
Compile {
|
||||
/// Paths to the source files
|
||||
files: Vec<String>,
|
||||
|
||||
/// Dump the CLIR to stdout
|
||||
#[arg(long)]
|
||||
dump_clir: bool,
|
||||
},
|
||||
Run {
|
||||
/// Paths to the source files
|
||||
files: Vec<String>,
|
||||
|
||||
#[arg(long)]
|
||||
dump_clir: bool,
|
||||
},
|
||||
}
|
||||
|
||||
fn parse(files: &[String]) -> Vec<Module> {
|
||||
let mut parser = LilaParser::default();
|
||||
let paths = files.iter().map(std::path::Path::new);
|
||||
paths
|
||||
.enumerate()
|
||||
.map(|(i, path)| match parser.parse_file(path, i as u32) {
|
||||
Ok(module) => module,
|
||||
Err(e) => panic!("Parsing error: {e:#?}"),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn check(modules: &mut Vec<Module>, source_cache: &mut SourceCache) -> usize {
|
||||
let mut failed_count = 0;
|
||||
|
||||
for module in modules {
|
||||
if let Err(errors) = module.type_check() {
|
||||
failed_count += 1;
|
||||
for error in errors {
|
||||
error
|
||||
.to_report(module)
|
||||
.eprint(&mut *source_cache)
|
||||
.expect("cannot write error to stderr");
|
||||
std::io::stderr().write_all("\n".as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
failed_count
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
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");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Commands::Check { files, dump_ast } => {
|
||||
let mut source_cache = SourceCache {
|
||||
paths: files.iter().map(PathBuf::from).collect(),
|
||||
file_cache: ariadne::FileCache::default(),
|
||||
};
|
||||
let mut modules = parse(files);
|
||||
let failed_count = check(&mut modules, &mut source_cache);
|
||||
if *dump_ast {
|
||||
for module in &modules {
|
||||
println!("{:#?}", &module);
|
||||
}
|
||||
}
|
||||
|
||||
if failed_count > 0 {
|
||||
anyhow::bail!("{}/{} files failed to compile", failed_count, files.len());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Commands::Compile { files, dump_clir } | Commands::Run { files, dump_clir } => {
|
||||
if files.is_empty() {
|
||||
println!("No input files");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut source_cache = SourceCache {
|
||||
paths: files.iter().map(PathBuf::from).collect(),
|
||||
file_cache: ariadne::FileCache::default(),
|
||||
};
|
||||
|
||||
let mut jit = jit::JIT::default();
|
||||
jit.dump_clir = *dump_clir;
|
||||
|
||||
for (id, file) in files.iter().enumerate() {
|
||||
println!("Compiling {file}");
|
||||
match jit.compile_file(file, id as u32, &mut source_cache) {
|
||||
Err(e) => eprintln!("{e}"),
|
||||
Ok(code) => {
|
||||
if let Commands::Run { .. } = cli.command {
|
||||
let ret = unsafe {
|
||||
let code_fn: unsafe extern "sysv64" fn() -> i32 =
|
||||
std::mem::transmute(code);
|
||||
code_fn()
|
||||
};
|
||||
println!("Main returned {ret}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue