#[cfg(feature = "binary")]
use anyhow::Result;
#[cfg(feature = "binary")]
use clap::{Parser, Subcommand};
#[cfg(feature = "binary")]
use oxur_cli::common::output;
#[cfg(feature = "binary")]
use oxur_cli::config::ReplConfig;
#[cfg(feature = "binary")]
use oxur_cli::ReplArgs;
#[cfg(feature = "binary")]
use std::path::PathBuf;
#[cfg(feature = "binary")]
#[derive(Parser)]
#[command(name = "oxur")]
#[command(about = "Oxur - A Lisp that compiles to Rust", long_about = None)]
#[command(version)]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
}
#[cfg(feature = "binary")]
#[derive(Subcommand)]
enum Commands {
Compile {
input: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
},
Run {
input: PathBuf,
args: Vec<String>,
},
Repl(ReplArgs),
New {
name: String,
},
Build {
#[arg(long)]
release: bool,
},
Test,
}
#[cfg(feature = "binary")]
fn main() -> Result<()> {
let cli = Cli::parse();
let command = cli.command.unwrap_or(Commands::Repl(ReplArgs::default()));
match command {
Commands::Compile { input, output } => {
output::info(&format!("Compiling: {}", input.display()));
let source = std::fs::read_to_string(&input)?;
let mut parser = oxur_lang::Parser::new(source);
let surface_forms = parser.parse()?;
let mut expander = oxur_lang::Expander::new();
let core_forms = expander.expand(surface_forms)?;
let source_map = expander.source_map().clone();
let output = output.unwrap_or_else(|| input.with_extension(""));
let build_dir = PathBuf::from(".oxur-build");
let mut compiler = oxur_comp::Compiler::new(build_dir);
compiler.compile(core_forms, source_map, &output)?;
output::success(&format!("Compiled successfully: {}", output.display()));
}
Commands::Run { input, args } => {
output::info(&format!("Running: {}", input.display()));
if !args.is_empty() {
output::info(&format!("With args: {:?}", args));
}
output::warning("Not yet implemented");
}
Commands::Repl(args) => {
handle_repl(args)?;
}
Commands::New { name } => {
output::info(&format!("Creating new project: {}", name));
let project_dir = PathBuf::from(&name);
std::fs::create_dir_all(&project_dir)?;
output::success(&format!("Created project directory: {}", project_dir.display()));
output::warning("Not yet fully implemented");
}
Commands::Build { release } => {
output::info("Building project...");
if release {
output::info("Release mode enabled");
}
output::warning("Not yet implemented");
}
Commands::Test => {
output::info("Running tests...");
output::warning("Not yet implemented");
}
}
Ok(())
}
#[cfg(feature = "binary")]
fn handle_repl(args: ReplArgs) -> Result<()> {
let config = ReplConfig::load(args.no_color)?;
if let Some(addr) = args.serve {
run_server_mode(&addr, args.ack)
} else if let Some(addr) = args.connect {
let addr = addr.unwrap_or_else(|| "127.0.0.1:5099".to_string());
run_connect_mode(&addr, config)
} else {
run_interactive_mode(config)
}
}
#[cfg(feature = "binary")]
fn run_interactive_mode(config: ReplConfig) -> Result<()> {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(oxur_cli::repl::interactive::run(config))
}
#[cfg(feature = "binary")]
fn run_server_mode(addr: &str, ack_port: Option<u16>) -> Result<()> {
output::info(&format!("Starting REPL server on {}...", addr));
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(oxur_cli::repl::server::run(addr, ack_port))
}
#[cfg(feature = "binary")]
fn run_connect_mode(addr: &str, config: ReplConfig) -> Result<()> {
output::info(&format!("Connecting to REPL server at {}...", addr));
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(oxur_cli::repl::connect::run(addr, config))
}
#[cfg(not(feature = "binary"))]
fn main() {
eprintln!("Error: The oxur binary must be built with the 'binary' feature enabled");
eprintln!("Use: cargo build --bin oxur --features binary");
std::process::exit(1);
}