Skip to main content

falsec_cli/
lib.rs

1use clap::builder::Styles;
2use clap::{Parser, Subcommand, ValueEnum, ValueHint};
3use std::path::PathBuf;
4
5#[derive(Debug, Parser)]
6#[command(name = "falsec", version, about, long_about = None, styles=styles())]
7pub struct Cli {
8    pub name: Option<String>,
9
10    /// The path to the configuration file
11    #[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath)]
12    pub config: Option<PathBuf>,
13
14    /// Enable debug output
15    #[arg(short, long, action = clap::ArgAction::Count)]
16    pub debug: u8,
17
18    #[command(subcommand)]
19    pub command: Commands,
20}
21
22#[derive(Debug, Subcommand)]
23pub enum Commands {
24    Run(Run),
25    Compile(Compile),
26}
27
28#[derive(ValueEnum, Copy, Clone, PartialEq, Eq, Debug)]
29pub enum TypeSafety {
30    /// No type safety checks are performed.
31    None,
32    /// When trying to execute a lambda, make sure that the popped value is a lambda.
33    Lambda,
34    /// Include all checks from [TypeSafety::Lambda], and make sure that when storing or loading
35    /// a variable, the popped value is a variable name.
36    LambdaAndVar,
37    /// Include all checks from [TypeSafety::LambdaAndVar], and ensure that only integers can be
38    /// used for arithmetic operations.
39    Full,
40}
41
42mod run {
43    use crate::TypeSafety;
44    use clap::{Args, ValueHint};
45    use std::ffi::OsString;
46
47    /// Execute a FALSE program
48    #[derive(Debug, Args)]
49    #[command(version, about, long_about = None)]
50    pub struct Run {
51        #[arg(long, require_equals = true, value_name = "TYPE", value_enum)]
52        pub type_safety: Option<TypeSafety>,
53
54        /// The path to the FALSE program to execute
55        #[arg(value_name = "FILE", value_hint = ValueHint::FilePath)]
56        pub program: OsString,
57
58        /// Print backtrace on error
59        #[arg(short = 'b', long)]
60        pub print_backtrace: bool,
61    }
62}
63
64pub use run::Run;
65
66mod compile {
67    use crate::TypeSafety;
68    use clap::{Args, ValueHint};
69    use std::ffi::OsString;
70
71    /// Compile a FALSE program
72    #[derive(Debug, Args)]
73    #[command(version, about, long_about = None)]
74    pub struct Compile {
75        #[arg(long, require_equals = true, value_name = "TYPE", value_enum)]
76        pub type_safety: Option<TypeSafety>,
77
78        /// The path to the intermediary assembly
79        #[arg(long, value_name = "FILE", value_hint = ValueHint::FilePath)]
80        pub dump_asm: Option<OsString>,
81
82        /// The path to the compiled FALSE program
83        #[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath)]
84        pub out: Option<OsString>,
85
86        /// The path to the FALSE program to execute
87        #[arg(value_name = "FILE", value_hint = ValueHint::FilePath)]
88        pub program: OsString,
89    }
90}
91
92pub use compile::Compile;
93
94fn styles() -> Styles {
95    Styles::styled()
96        .usage(
97            anstyle::Style::new()
98                .bold()
99                .underline()
100                .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Yellow))),
101        )
102        .header(
103            anstyle::Style::new()
104                .bold()
105                .underline()
106                .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Yellow))),
107        )
108        .literal(
109            anstyle::Style::new().fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Green))),
110        )
111        .invalid(
112            anstyle::Style::new()
113                .bold()
114                .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red))),
115        )
116        .error(
117            anstyle::Style::new()
118                .bold()
119                .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red))),
120        )
121        .valid(
122            anstyle::Style::new()
123                .bold()
124                .underline()
125                .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Green))),
126        )
127        .placeholder(
128            anstyle::Style::new().fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::White))),
129        )
130}