use clap::parser::ValueSource;
use clap::{ArgMatches, Parser, Subcommand};
use runmat_config::runtime::{PlotBackend, PlotMode};
use runmat_server_client::auth::CredentialStoreMode;
use std::path::PathBuf;
use uuid::Uuid;
use crate::cli::parse::{parse_bool_env, parse_figure_size, parse_log_level_env};
use crate::cli::remote::{FsCommand, OrgCommand, ProjectCommand, RemoteCommand};
use crate::cli::value_types::{
CaptureFiguresMode, CompressionAlg, FigureSize, GcPreset, LogLevel, OptLevel,
};
#[derive(Parser, Clone)]
#[command(
name = "runmat",
version = env!("CARGO_PKG_VERSION"),
about = "High-performance MATLAB/Octave code runtime",
long_about = r#"
RunMat is a modern, high-performance runtime for MATLAB/Octave.
It is built in Rust, and features a V8-inspired tiered execution model with a
baseline interpreter feeding an optimizing JIT compiler built on Cranelift.
Key features:
• JIT compilation with Cranelift for optimal performance
• Generational garbage collection with configurable policies
• High-performance BLAS/LAPACK operations
• Fast startup with snapshotting capabilities
• World-class error messages and debugging
• Compatible with MATLAB/Octave syntax and semantics
Performance Features:
• Multi-tier execution: interpreter + JIT compiler
• Adaptive optimization based on hotspot profiling
• Generational GC with write barriers and concurrent collection
• SIMD-optimized mathematical operations
• Zero-copy memory management where possible
Examples:
runmat # Start interactive REPL with JIT
runmat --no-jit # Start REPL with interpreter only
runmat --gc-preset low-latency # Optimize GC for low latency
runmat script.m # Execute MATLAB/Octave script
runmat --emit-bytecode script.m # Emit bytecode disassembly
runmat version --detailed # Show detailed version information
"#,
after_help = r#"
Environment Variables:
RUNMAT_CONFIG=<path> Explicit path to runmat.toml/runmat.json
RUNMAT_API_KEY=<token> Remote API token (remote commands)
RUNMAT_SERVER_URL=<url> Remote server URL (remote commands)
RUNMAT_ORG_ID=<uuid> Remote org override (remote commands)
RUNMAT_PROJECT_ID=<uuid> Remote project override (remote commands)
For more information, visit: https://github.com/runmat-org/runmat
"#
)]
#[command(propagate_version = true)]
pub struct Cli {
#[arg(short, long, value_parser = parse_bool_env)]
pub debug: bool,
#[arg(long, value_enum, default_value = "warn", value_parser = parse_log_level_env)]
pub log_level: LogLevel,
#[arg(long, default_value = "200")]
pub callstack_limit: usize,
#[arg(long, value_name = "PATH", num_args = 0..=1, default_missing_value = "-")]
pub emit_bytecode: Option<PathBuf>,
#[arg(long)]
pub error_namespace: Option<String>,
#[arg(long, env = "RUNMAT_CONFIG")]
pub config: Option<PathBuf>,
#[arg(long, value_parser = parse_bool_env)]
pub no_jit: bool,
#[arg(long, default_value = "10")]
pub jit_threshold: u32,
#[arg(long, value_enum, default_value = "speed")]
pub jit_opt_level: OptLevel,
#[arg(long, value_enum)]
pub gc_preset: Option<GcPreset>,
#[arg(long)]
pub gc_young_size: Option<usize>,
#[arg(long)]
pub gc_threads: Option<usize>,
#[arg(long, value_parser = parse_bool_env)]
pub gc_stats: bool,
#[arg(short, long)]
pub verbose: bool,
#[arg(long)]
pub snapshot: Option<PathBuf>,
#[arg(long, value_enum)]
pub plot_mode: Option<PlotMode>,
#[arg(long, value_parser = parse_bool_env)]
pub plot_headless: bool,
#[arg(long, value_enum)]
pub plot_backend: Option<PlotBackend>,
#[arg(long)]
pub plot_scatter_target: Option<u32>,
#[arg(long)]
pub plot_surface_vertex_budget: Option<u64>,
#[arg(long)]
pub artifacts_dir: Option<PathBuf>,
#[arg(long)]
pub artifacts_manifest: Option<PathBuf>,
#[arg(long, value_enum, default_value = "auto")]
pub capture_figures: CaptureFiguresMode,
#[arg(long, default_value = "1280x720", value_parser = parse_figure_size)]
pub figure_size: FigureSize,
#[arg(long, default_value = "8")]
pub max_figures: usize,
#[arg(long)]
pub generate_config: bool,
#[command(subcommand)]
pub command: Option<Commands>,
pub script: Option<PathBuf>,
}
#[derive(Clone, Debug, Default)]
pub struct CliOverrideSources {
pub debug: bool,
pub log_level: bool,
pub callstack_limit: bool,
pub jit_threshold: bool,
pub jit_opt_level: bool,
pub gc_stats: bool,
pub verbose: bool,
}
impl CliOverrideSources {
pub fn from_matches(matches: &ArgMatches) -> Self {
Self {
debug: Self::was_provided(matches, "debug"),
log_level: Self::was_provided(matches, "log_level"),
callstack_limit: Self::was_provided(matches, "callstack_limit"),
jit_threshold: Self::was_provided(matches, "jit_threshold"),
jit_opt_level: Self::was_provided(matches, "jit_opt_level"),
gc_stats: Self::was_provided(matches, "gc_stats"),
verbose: Self::was_provided(matches, "verbose"),
}
}
fn was_provided(matches: &ArgMatches, id: &str) -> bool {
matches
.value_source(id)
.is_some_and(|source| source != ValueSource::DefaultValue)
}
}
#[derive(Subcommand, Clone)]
pub enum Commands {
Repl {
#[arg(short, long)]
verbose: bool,
},
Run {
file: PathBuf,
#[arg(last = true)]
args: Vec<String>,
},
Version {
#[arg(long)]
detailed: bool,
},
Info,
AccelInfo {
#[arg(long)]
json: bool,
#[arg(long)]
reset: bool,
},
#[cfg(feature = "wgpu")]
AccelCalibrate {
input: PathBuf,
#[arg(long)]
dry_run: bool,
#[arg(long)]
json: bool,
},
Gc {
#[command(subcommand)]
gc_command: GcCommand,
},
Benchmark {
file: PathBuf,
#[arg(short, long, default_value = "10")]
iterations: u32,
#[arg(long)]
jit: bool,
},
Snapshot {
#[command(subcommand)]
snapshot_command: SnapshotCommand,
},
Config {
#[command(subcommand)]
config_command: ConfigCommand,
},
Remote {
#[command(subcommand)]
remote_command: RemoteCommand,
},
Login {
#[arg(long)]
server: Option<String>,
#[arg(long)]
api_key: Option<String>,
#[arg(long)]
email: Option<String>,
#[arg(long, default_value = "file")]
credential_store: CredentialStoreMode,
#[arg(long)]
org: Option<Uuid>,
#[arg(long)]
project: Option<Uuid>,
},
Org {
#[command(subcommand)]
org_command: OrgCommand,
},
Project {
#[command(subcommand)]
project_command: ProjectCommand,
},
Fs {
#[command(subcommand)]
fs_command: FsCommand,
},
}
#[derive(Subcommand, Clone)]
pub enum GcCommand {
Stats,
Minor,
Major,
Config,
Stress {
#[arg(short, long, default_value = "10000")]
allocations: usize,
},
}
#[derive(Subcommand, Clone)]
pub enum SnapshotCommand {
Create {
#[arg(short, long)]
output: PathBuf,
#[arg(short = 'O', long, value_enum, default_value = "speed")]
optimization: OptLevel,
#[arg(short, long, value_enum)]
compression: Option<CompressionAlg>,
},
Info {
snapshot: PathBuf,
},
Presets,
Validate {
snapshot: PathBuf,
},
}
#[derive(Subcommand, Clone)]
pub enum ConfigCommand {
Show {
#[arg(long, value_enum, default_value = "toml")]
format: ConfigFormat,
},
Generate {
#[arg(short, long, default_value = "runmat.toml")]
output: PathBuf,
#[arg(long, value_enum)]
format: Option<ConfigFormat>,
},
Validate {
config_file: PathBuf,
},
Paths,
}
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
pub enum ConfigFormat {
Toml,
Json,
}