feat: expose JIT compiler via CLI command
Add `lux compile <file>` command that compiles and runs Lux code using the Cranelift JIT compiler. Includes --benchmark flag for timing. - Add compile_file() function in main.rs - Add jit_test.lux example with fib(30) + factorial(10) - Update VISION.md status Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
135
src/main.rs
135
src/main.rs
@@ -139,6 +139,15 @@ fn main() {
|
||||
// Package manager
|
||||
handle_pkg_command(&args[2..]);
|
||||
}
|
||||
"compile" => {
|
||||
// Compile and run with JIT
|
||||
if args.len() < 3 {
|
||||
eprintln!("Usage: lux compile <file.lux> [--benchmark]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let benchmark = args.iter().any(|a| a == "--benchmark");
|
||||
compile_file(&args[2], benchmark);
|
||||
}
|
||||
path => {
|
||||
// Run a file
|
||||
run_file(path);
|
||||
@@ -154,18 +163,19 @@ fn print_help() {
|
||||
println!("Lux {} - A functional language with first-class effects", VERSION);
|
||||
println!();
|
||||
println!("Usage:");
|
||||
println!(" lux Start the REPL");
|
||||
println!(" lux <file.lux> Run a file");
|
||||
println!(" lux fmt <file.lux> Format a file (--check to verify only)");
|
||||
println!(" lux check <file.lux> Type check without running");
|
||||
println!(" lux test [pattern] Run tests (optional pattern filter)");
|
||||
println!(" lux watch <file.lux> Watch and re-run on changes");
|
||||
println!(" lux debug <file.lux> Start interactive debugger");
|
||||
println!(" lux init [name] Initialize a new project");
|
||||
println!(" lux pkg <command> Package manager (install, add, remove, list, update)");
|
||||
println!(" lux --lsp Start LSP server (for IDE integration)");
|
||||
println!(" lux --help Show this help");
|
||||
println!(" lux --version Show version");
|
||||
println!(" lux Start the REPL");
|
||||
println!(" lux <file.lux> Run a file (interpreter)");
|
||||
println!(" lux compile <file.lux> Compile and run with JIT (--benchmark for timing)");
|
||||
println!(" lux fmt <file.lux> Format a file (--check to verify only)");
|
||||
println!(" lux check <file.lux> Type check without running");
|
||||
println!(" lux test [pattern] Run tests (optional pattern filter)");
|
||||
println!(" lux watch <file.lux> Watch and re-run on changes");
|
||||
println!(" lux debug <file.lux> Start interactive debugger");
|
||||
println!(" lux init [name] Initialize a new project");
|
||||
println!(" lux pkg <command> Package manager (install, add, remove, list, update)");
|
||||
println!(" lux --lsp Start LSP server (for IDE integration)");
|
||||
println!(" lux --help Show this help");
|
||||
println!(" lux --version Show version");
|
||||
}
|
||||
|
||||
fn format_file(path: &str, check_only: bool) {
|
||||
@@ -246,6 +256,107 @@ fn check_file(path: &str) {
|
||||
println!("{}: OK", path);
|
||||
}
|
||||
|
||||
fn compile_file(path: &str, benchmark: bool) {
|
||||
use compiler::JitCompiler;
|
||||
use modules::ModuleLoader;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
let file_path = Path::new(path);
|
||||
let source = match std::fs::read_to_string(file_path) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
eprintln!("Error reading file '{}': {}", path, e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse
|
||||
let parse_start = Instant::now();
|
||||
let mut loader = ModuleLoader::new();
|
||||
if let Some(parent) = file_path.parent() {
|
||||
loader.add_search_path(parent.to_path_buf());
|
||||
}
|
||||
|
||||
let program = match loader.load_source(&source, Some(file_path)) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
eprintln!("Module error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let parse_time = parse_start.elapsed();
|
||||
|
||||
// Type check
|
||||
let check_start = Instant::now();
|
||||
let mut checker = TypeChecker::new();
|
||||
if let Err(errors) = checker.check_program_with_modules(&program, &loader) {
|
||||
for error in errors {
|
||||
let diagnostic = error.to_diagnostic();
|
||||
eprint!("{}", render(&diagnostic, &source, Some(path)));
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
let check_time = check_start.elapsed();
|
||||
|
||||
// Compile with JIT
|
||||
let compile_start = Instant::now();
|
||||
let mut jit = match JitCompiler::new() {
|
||||
Ok(j) => j,
|
||||
Err(e) => {
|
||||
eprintln!("JIT initialization error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = jit.compile_program(&program) {
|
||||
eprintln!("Compilation error: {}", e);
|
||||
eprintln!();
|
||||
eprintln!("Note: The JIT compiler currently only supports:");
|
||||
eprintln!(" - Integer arithmetic and comparisons");
|
||||
eprintln!(" - Conditionals (if/then/else)");
|
||||
eprintln!(" - Let bindings and blocks");
|
||||
eprintln!(" - Function calls (including recursion)");
|
||||
eprintln!();
|
||||
eprintln!("Not yet supported: strings, floats, lists, records,");
|
||||
eprintln!("pattern matching, effects, ADTs.");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let compile_time = compile_start.elapsed();
|
||||
|
||||
// Find main function or last expression
|
||||
let exec_start = Instant::now();
|
||||
let result = if jit.get_function("main").is_some() {
|
||||
unsafe { jit.call_function("main", &[]) }
|
||||
} else {
|
||||
// Try to find any function to call
|
||||
eprintln!("No 'main' function found.");
|
||||
eprintln!("Define a function like: fn main(): Int = ...");
|
||||
std::process::exit(1);
|
||||
};
|
||||
let exec_time = exec_start.elapsed();
|
||||
|
||||
match result {
|
||||
Ok(value) => {
|
||||
println!("{}", value);
|
||||
|
||||
if benchmark {
|
||||
println!();
|
||||
println!("=== JIT Benchmark ===");
|
||||
println!("Parse time: {:?}", parse_time);
|
||||
println!("Check time: {:?}", check_time);
|
||||
println!("Compile time: {:?}", compile_time);
|
||||
println!("Execute time: {:?}", exec_time);
|
||||
println!("Total time: {:?}", parse_time + check_time + compile_time + exec_time);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Execution error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_tests(args: &[String]) {
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
|
||||
Reference in New Issue
Block a user