use clap::{Args, Parser};
use forc_pkg::source::IPFSNode;
use sway_core::{BuildTarget, PrintAsm, PrintIr};
use sway_ir::PassManager;
#[derive(Debug, Default, Parser)]
pub struct Build {
#[clap(flatten)]
pub pkg: Pkg,
#[clap(flatten)]
pub print: Print,
#[clap(flatten)]
pub minify: Minify,
#[clap(flatten)]
pub output: BuildOutput,
#[clap(flatten)]
pub profile: BuildProfile,
#[clap(long, value_enum, default_value_t = BuildTarget::default(), alias="target")]
pub build_target: BuildTarget,
}
#[derive(Args, Debug, Default)]
pub struct BuildOutput {
#[clap(long = "output-bin", short = 'o')]
pub bin_file: Option<String>,
#[clap(long = "output-debug", short = 'g')]
pub debug_file: Option<String>,
}
#[derive(Args, Debug, Default)]
pub struct BuildProfile {
#[clap(long, conflicts_with = "release", default_value = forc_pkg::BuildProfile::DEBUG)]
pub build_profile: String,
#[clap(long)]
pub release: bool,
#[clap(long)]
pub error_on_warnings: bool,
}
#[derive(Args, Debug, Default)]
pub struct Print {
#[clap(long)]
pub ast: bool,
#[clap(long)]
pub dca_graph: Option<String>,
#[clap(long, verbatim_doc_comment)]
pub dca_graph_url_format: Option<String>,
#[arg(long, verbatim_doc_comment, num_args(1..=5), value_parser = clap::builder::PossibleValuesParser::new(&PrintAsmCliOpt::CLI_OPTIONS))]
pub asm: Option<Vec<String>>,
#[clap(long)]
pub bytecode: bool,
#[arg(long, verbatim_doc_comment, num_args(1..=18), value_parser = clap::builder::PossibleValuesParser::new(PrintIrCliOpt::cli_options()))]
pub ir: Option<Vec<String>>,
#[clap(long)]
pub time_phases: bool,
#[clap(long)]
pub reverse_order: bool,
#[clap(long)]
pub metrics_outfile: Option<String>,
}
impl Print {
pub fn asm(&self) -> PrintAsm {
self.asm
.as_ref()
.map_or(PrintAsm::default(), |opts| PrintAsmCliOpt::from(opts).0)
}
pub fn ir(&self) -> PrintIr {
self.ir
.as_ref()
.map_or(PrintIr::default(), |opts| PrintIrCliOpt::from(opts).0)
}
}
#[derive(Args, Debug, Default)]
pub struct Pkg {
#[clap(short, long)]
pub path: Option<String>,
#[clap(long)]
pub offline: bool,
#[clap(long, short = 't')]
pub terse: bool,
#[clap(long)]
pub output_directory: Option<String>,
#[clap(long)]
pub locked: bool,
#[clap(long)]
pub ipfs_node: Option<IPFSNode>,
}
#[derive(Args, Debug, Default)]
pub struct Minify {
#[clap(long)]
pub json_abi: bool,
#[clap(long)]
pub json_storage_slots: bool,
}
pub struct PrintAsmCliOpt(pub PrintAsm);
impl PrintAsmCliOpt {
const VIRTUAL: &'static str = "virtual";
const ALLOCATED: &'static str = "allocated";
const ABSTRACT: &'static str = "abstract";
const FINAL: &'static str = "final";
const ALL: &'static str = "all";
pub const CLI_OPTIONS: [&'static str; 5] = [
Self::VIRTUAL,
Self::ALLOCATED,
Self::ABSTRACT,
Self::FINAL,
Self::ALL,
];
}
impl From<&Vec<String>> for PrintAsmCliOpt {
fn from(value: &Vec<String>) -> Self {
let contains_opt = |opt: &str| value.iter().any(|val| *val == opt);
let print_asm = if contains_opt(Self::ALL) {
PrintAsm::all()
} else {
PrintAsm {
virtual_abstract: contains_opt(Self::ABSTRACT) || contains_opt(Self::VIRTUAL),
allocated_abstract: contains_opt(Self::ABSTRACT) || contains_opt(Self::ALLOCATED),
r#final: contains_opt(Self::FINAL),
}
};
Self(print_asm)
}
}
pub struct PrintIrCliOpt(pub PrintIr);
impl PrintIrCliOpt {
const INITIAL: &'static str = "initial";
const FINAL: &'static str = "final";
const ALL: &'static str = "all";
const MODIFIED: &'static str = "modified";
pub const CLI_OPTIONS: [&'static str; 4] =
[Self::INITIAL, Self::FINAL, Self::ALL, Self::MODIFIED];
pub fn cli_options() -> Vec<&'static str> {
Self::CLI_OPTIONS
.iter()
.chain(PassManager::OPTIMIZATION_PASSES.iter())
.cloned()
.collect()
}
}
impl From<&Vec<String>> for PrintIrCliOpt {
fn from(value: &Vec<String>) -> Self {
let contains_opt = |opt: &str| value.iter().any(|val| *val == opt);
let print_ir = if contains_opt(Self::ALL) {
PrintIr::all(contains_opt(Self::MODIFIED))
} else {
PrintIr {
initial: contains_opt(Self::INITIAL),
r#final: contains_opt(Self::FINAL),
modified_only: contains_opt(Self::MODIFIED),
passes: value
.iter()
.filter(|val| !Self::CLI_OPTIONS.contains(&val.as_str()))
.cloned()
.collect(),
}
};
Self(print_ir)
}
}