mod printing;
use alloc::{fmt, str::FromStr, string::String, sync::Arc, vec, vec::Vec};
pub use self::printing::IrFilter;
#[cfg(feature = "std")]
use crate::Path;
use crate::{
ColorChoice, CompileFlags, LinkLibrary, OutputTypes, PathBuf, ProjectType, TargetEnv,
diagnostics::{DiagnosticsConfig, Emitter},
};
#[derive(Debug)]
pub struct Options {
pub name: Option<String>,
pub project_type: ProjectType,
pub entrypoint: Option<String>,
pub target: TargetEnv,
pub optimize: OptLevel,
pub debug: DebugInfo,
pub output_types: OutputTypes,
pub search_paths: Vec<PathBuf>,
pub link_libraries: Vec<LinkLibrary>,
pub sysroot: Option<PathBuf>,
pub color: ColorChoice,
pub diagnostics: DiagnosticsConfig,
pub current_dir: PathBuf,
pub trim_path_prefixes: Vec<PathBuf>,
pub print_hir_source_locations: bool,
pub parse_only: bool,
pub analyze_only: bool,
pub link_only: bool,
pub no_link: bool,
pub print_cfg_after_all: bool,
pub print_cfg_after_pass: Vec<String>,
pub print_ir_before_stage: Vec<String>,
pub print_ir_after_all: bool,
pub print_ir_after_pass: Vec<String>,
pub print_ir_after_modified: bool,
pub print_ir_filters: Vec<IrFilter>,
pub save_temps: bool,
pub flags: CompileFlags,
}
impl Default for Options {
fn default() -> Self {
let current_dir = current_dir();
let target = TargetEnv::default();
let project_type = ProjectType::default_for_target(target);
Self::new(None, target, project_type, current_dir, None)
}
}
#[cfg(feature = "std")]
fn current_dir() -> PathBuf {
std::env::current_dir().expect("could not get working directory")
}
#[cfg(not(feature = "std"))]
fn current_dir() -> PathBuf {
PathBuf::from(".")
}
#[cfg(feature = "std")]
fn current_sysroot() -> Option<PathBuf> {
std::env::var("HOME").ok().map(|home| {
Path::new(&home)
.join(".miden")
.join("toolchains")
.join(crate::MIDENC_BUILD_VERSION)
})
}
#[cfg(not(feature = "std"))]
fn current_sysroot() -> Option<PathBuf> {
None
}
impl Options {
pub fn new(
name: Option<String>,
target: TargetEnv,
project_type: ProjectType,
current_dir: PathBuf,
sysroot: Option<PathBuf>,
) -> Self {
let sysroot = sysroot.or_else(current_sysroot);
Self {
name,
target,
project_type,
entrypoint: None,
optimize: OptLevel::None,
debug: DebugInfo::None,
output_types: Default::default(),
search_paths: vec![],
link_libraries: vec![],
sysroot,
color: Default::default(),
diagnostics: Default::default(),
current_dir,
trim_path_prefixes: vec![],
print_hir_source_locations: false,
parse_only: false,
analyze_only: false,
link_only: false,
no_link: false,
save_temps: false,
print_cfg_after_all: false,
print_cfg_after_pass: vec![],
print_ir_before_stage: vec![],
print_ir_after_all: false,
print_ir_after_pass: vec![],
print_ir_after_modified: false,
print_ir_filters: vec![],
flags: CompileFlags::default(),
}
}
#[inline(always)]
pub fn with_color(mut self, color: ColorChoice) -> Self {
self.color = color;
self
}
#[inline(always)]
pub fn with_verbosity(mut self, verbosity: Verbosity) -> Self {
self.diagnostics.verbosity = verbosity;
self
}
#[inline(always)]
pub fn with_debug_info(mut self, debug: DebugInfo) -> Self {
self.debug = debug;
self
}
#[inline(always)]
pub fn with_optimization(mut self, level: OptLevel) -> Self {
self.optimize = level;
self
}
pub fn with_warnings(mut self, warnings: Warnings) -> Self {
self.diagnostics.warnings = warnings;
self
}
#[inline(always)]
pub fn with_output_types(mut self, output_types: OutputTypes) -> Self {
self.output_types = output_types;
self
}
#[doc(hidden)]
pub fn with_extra_flags(mut self, flags: CompileFlags) -> Self {
self.flags = flags;
self
}
#[doc(hidden)]
pub fn set_extra_flags(&mut self, flags: CompileFlags) {
self.flags = flags;
}
pub fn default_emitter(&self) -> Arc<dyn Emitter> {
use crate::diagnostics::{DefaultEmitter, NullEmitter};
match self.diagnostics.verbosity {
Verbosity::Silent => Arc::new(NullEmitter::new(self.color)),
_ => Arc::new(DefaultEmitter::new(self.color)),
}
}
#[inline(always)]
pub fn emit_source_locations(&self) -> bool {
matches!(self.debug, DebugInfo::Line | DebugInfo::Full)
}
#[inline(always)]
pub fn emit_debug_decorators(&self) -> bool {
matches!(self.debug, DebugInfo::Full)
}
#[inline(always)]
pub fn emit_debug_assertions(&self) -> bool {
self.debug != DebugInfo::None && matches!(self.optimize, OptLevel::None | OptLevel::Basic)
}
}
#[derive(Debug, Copy, Clone, Default)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
pub enum OptLevel {
None,
Basic,
#[default]
Balanced,
Max,
Size,
SizeMin,
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
pub enum DebugInfo {
None,
#[default]
Line,
Full,
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
pub enum Warnings {
None,
#[default]
All,
Error,
}
impl fmt::Display for Warnings {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::None => f.write_str("none"),
Self::All => f.write_str("auto"),
Self::Error => f.write_str("error"),
}
}
}
impl FromStr for Warnings {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"none" => Ok(Self::None),
"all" => Ok(Self::All),
"error" => Ok(Self::Error),
_ => Err(()),
}
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
pub enum Verbosity {
Debug,
#[default]
Info,
Warning,
Error,
Silent,
}