1use alloc::{fmt, str::FromStr, string::String, sync::Arc, vec, vec::Vec};
2use std::path::{Path, PathBuf};
3
4use crate::{
5 diagnostics::{DiagnosticsConfig, Emitter},
6 ColorChoice, CompileFlags, LinkLibrary, OutputTypes, ProjectType, TargetEnv,
7};
8
9#[derive(Debug)]
11pub struct Options {
12 pub name: Option<String>,
14 pub project_type: ProjectType,
16 pub entrypoint: Option<String>,
18 pub target: TargetEnv,
20 pub optimize: OptLevel,
22 pub debug: DebugInfo,
24 pub output_types: OutputTypes,
26 pub search_paths: Vec<PathBuf>,
28 pub link_libraries: Vec<LinkLibrary>,
30 pub sysroot: Option<PathBuf>,
32 pub color: ColorChoice,
34 pub diagnostics: DiagnosticsConfig,
36 pub current_dir: PathBuf,
38 pub parse_only: bool,
40 pub analyze_only: bool,
42 pub link_only: bool,
44 pub no_link: bool,
46 pub print_cfg_after_all: bool,
48 pub print_cfg_after_pass: Vec<String>,
50 pub print_ir_after_all: bool,
52 pub print_ir_after_pass: Vec<String>,
54 pub save_temps: bool,
56 pub flags: CompileFlags,
59}
60
61impl Default for Options {
62 fn default() -> Self {
63 let current_dir = std::env::current_dir().expect("could not get working directory");
64 let target = TargetEnv::default();
65 let project_type = ProjectType::default_for_target(target);
66 Self::new(None, target, project_type, current_dir, None)
67 }
68}
69
70impl Options {
71 pub fn new(
72 name: Option<String>,
73 target: TargetEnv,
74 project_type: ProjectType,
75 current_dir: PathBuf,
76 sysroot: Option<PathBuf>,
77 ) -> Self {
78 let sysroot = sysroot.or_else(|| {
79 std::env::var("HOME").ok().map(|home| {
80 Path::new(&home)
81 .join(".miden")
82 .join("toolchains")
83 .join(crate::MIDENC_BUILD_VERSION)
84 })
85 });
86
87 Self {
88 name,
89 target,
90 project_type,
91 entrypoint: None,
92 optimize: OptLevel::None,
93 debug: DebugInfo::None,
94 output_types: Default::default(),
95 search_paths: vec![],
96 link_libraries: vec![],
97 sysroot,
98 color: Default::default(),
99 diagnostics: Default::default(),
100 current_dir,
101 parse_only: false,
102 analyze_only: false,
103 link_only: false,
104 no_link: false,
105 save_temps: false,
106 print_cfg_after_all: false,
107 print_cfg_after_pass: vec![],
108 print_ir_after_all: false,
109 print_ir_after_pass: vec![],
110 flags: CompileFlags::default(),
111 }
112 }
113
114 #[inline(always)]
115 pub fn with_color(mut self, color: ColorChoice) -> Self {
116 self.color = color;
117 self
118 }
119
120 #[inline(always)]
121 pub fn with_verbosity(mut self, verbosity: Verbosity) -> Self {
122 self.diagnostics.verbosity = verbosity;
123 self
124 }
125
126 #[inline(always)]
127 pub fn with_debug_info(mut self, debug: DebugInfo) -> Self {
128 self.debug = debug;
129 self
130 }
131
132 #[inline(always)]
133 pub fn with_optimization(mut self, level: OptLevel) -> Self {
134 self.optimize = level;
135 self
136 }
137
138 pub fn with_warnings(mut self, warnings: Warnings) -> Self {
139 self.diagnostics.warnings = warnings;
140 self
141 }
142
143 #[inline(always)]
144 pub fn with_output_types(mut self, output_types: OutputTypes) -> Self {
145 self.output_types = output_types;
146 self
147 }
148
149 #[doc(hidden)]
150 pub fn with_extra_flags(mut self, flags: CompileFlags) -> Self {
151 self.flags = flags;
152 self
153 }
154
155 #[doc(hidden)]
156 pub fn set_extra_flags(&mut self, flags: CompileFlags) {
157 self.flags = flags;
158 }
159
160 pub fn default_emitter(&self) -> Arc<dyn Emitter> {
162 use crate::diagnostics::{DefaultEmitter, NullEmitter};
163
164 match self.diagnostics.verbosity {
165 Verbosity::Silent => Arc::new(NullEmitter::new(self.color)),
166 _ => Arc::new(DefaultEmitter::new(self.color)),
167 }
168 }
169
170 #[inline(always)]
172 pub fn emit_source_locations(&self) -> bool {
173 matches!(self.debug, DebugInfo::Line | DebugInfo::Full)
174 }
175
176 #[inline(always)]
178 pub fn emit_debug_decorators(&self) -> bool {
179 matches!(self.debug, DebugInfo::Full)
180 }
181
182 #[inline(always)]
184 pub fn emit_debug_assertions(&self) -> bool {
185 self.debug != DebugInfo::None && matches!(self.optimize, OptLevel::None | OptLevel::Basic)
186 }
187}
188
189#[derive(Debug, Copy, Clone, Default)]
191#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
192pub enum OptLevel {
193 None,
195 Basic,
197 #[default]
199 Balanced,
200 Max,
202 Size,
204 SizeMin,
206}
207
208#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
210#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
211pub enum DebugInfo {
212 None,
214 #[default]
216 Line,
217 Full,
219}
220
221#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
223#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
224pub enum Warnings {
225 None,
227 #[default]
229 All,
230 Error,
232}
233impl fmt::Display for Warnings {
234 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
235 match self {
236 Self::None => f.write_str("none"),
237 Self::All => f.write_str("auto"),
238 Self::Error => f.write_str("error"),
239 }
240 }
241}
242impl FromStr for Warnings {
243 type Err = ();
244
245 fn from_str(s: &str) -> Result<Self, Self::Err> {
246 match s {
247 "none" => Ok(Self::None),
248 "all" => Ok(Self::All),
249 "error" => Ok(Self::Error),
250 _ => Err(()),
251 }
252 }
253}
254
255#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
257#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
258pub enum Verbosity {
259 Debug,
261 #[default]
263 Info,
264 Warning,
266 Error,
268 Silent,
270}