1use alloc::{fmt, str::FromStr, string::String, sync::Arc, vec, vec::Vec};
2
3#[cfg(feature = "std")]
4use crate::Path;
5use crate::{
6 ColorChoice, CompileFlags, LinkLibrary, OutputTypes, PathBuf, ProjectType, TargetEnv,
7 diagnostics::{DiagnosticsConfig, Emitter},
8};
9
10#[derive(Debug)]
12pub struct Options {
13 pub name: Option<String>,
15 pub project_type: ProjectType,
17 pub entrypoint: Option<String>,
19 pub target: TargetEnv,
21 pub optimize: OptLevel,
23 pub debug: DebugInfo,
25 pub output_types: OutputTypes,
27 pub search_paths: Vec<PathBuf>,
29 pub link_libraries: Vec<LinkLibrary>,
31 pub sysroot: Option<PathBuf>,
33 pub color: ColorChoice,
35 pub diagnostics: DiagnosticsConfig,
37 pub current_dir: PathBuf,
39 pub trim_path_prefixes: Vec<PathBuf>,
41 pub print_hir_source_locations: bool,
43 pub parse_only: bool,
45 pub analyze_only: bool,
47 pub link_only: bool,
49 pub no_link: bool,
51 pub print_cfg_after_all: bool,
53 pub print_cfg_after_pass: Vec<String>,
55 pub print_ir_after_all: bool,
57 pub print_ir_after_pass: Vec<String>,
59 pub print_ir_after_modified: bool,
61 pub save_temps: bool,
63 pub flags: CompileFlags,
66}
67
68impl Default for Options {
69 fn default() -> Self {
70 let current_dir = current_dir();
71 let target = TargetEnv::default();
72 let project_type = ProjectType::default_for_target(target);
73 Self::new(None, target, project_type, current_dir, None)
74 }
75}
76
77#[cfg(feature = "std")]
78fn current_dir() -> PathBuf {
79 std::env::current_dir().expect("could not get working directory")
80}
81
82#[cfg(not(feature = "std"))]
83fn current_dir() -> PathBuf {
84 PathBuf::from(".")
85}
86
87#[cfg(feature = "std")]
88fn current_sysroot() -> Option<PathBuf> {
89 std::env::var("HOME").ok().map(|home| {
90 Path::new(&home)
91 .join(".miden")
92 .join("toolchains")
93 .join(crate::MIDENC_BUILD_VERSION)
94 })
95}
96
97#[cfg(not(feature = "std"))]
98fn current_sysroot() -> Option<PathBuf> {
99 None
100}
101
102impl Options {
103 pub fn new(
104 name: Option<String>,
105 target: TargetEnv,
106 project_type: ProjectType,
107 current_dir: PathBuf,
108 sysroot: Option<PathBuf>,
109 ) -> Self {
110 let sysroot = sysroot.or_else(current_sysroot);
111
112 Self {
113 name,
114 target,
115 project_type,
116 entrypoint: None,
117 optimize: OptLevel::None,
118 debug: DebugInfo::None,
119 output_types: Default::default(),
120 search_paths: vec![],
121 link_libraries: vec![],
122 sysroot,
123 color: Default::default(),
124 diagnostics: Default::default(),
125 current_dir,
126 trim_path_prefixes: vec![],
127 print_hir_source_locations: false,
128 parse_only: false,
129 analyze_only: false,
130 link_only: false,
131 no_link: false,
132 save_temps: false,
133 print_cfg_after_all: false,
134 print_cfg_after_pass: vec![],
135 print_ir_after_all: false,
136 print_ir_after_pass: vec![],
137 print_ir_after_modified: false,
138 flags: CompileFlags::default(),
139 }
140 }
141
142 #[inline(always)]
143 pub fn with_color(mut self, color: ColorChoice) -> Self {
144 self.color = color;
145 self
146 }
147
148 #[inline(always)]
149 pub fn with_verbosity(mut self, verbosity: Verbosity) -> Self {
150 self.diagnostics.verbosity = verbosity;
151 self
152 }
153
154 #[inline(always)]
155 pub fn with_debug_info(mut self, debug: DebugInfo) -> Self {
156 self.debug = debug;
157 self
158 }
159
160 #[inline(always)]
161 pub fn with_optimization(mut self, level: OptLevel) -> Self {
162 self.optimize = level;
163 self
164 }
165
166 pub fn with_warnings(mut self, warnings: Warnings) -> Self {
167 self.diagnostics.warnings = warnings;
168 self
169 }
170
171 #[inline(always)]
172 pub fn with_output_types(mut self, output_types: OutputTypes) -> Self {
173 self.output_types = output_types;
174 self
175 }
176
177 #[doc(hidden)]
178 pub fn with_extra_flags(mut self, flags: CompileFlags) -> Self {
179 self.flags = flags;
180 self
181 }
182
183 #[doc(hidden)]
184 pub fn set_extra_flags(&mut self, flags: CompileFlags) {
185 self.flags = flags;
186 }
187
188 pub fn default_emitter(&self) -> Arc<dyn Emitter> {
190 use crate::diagnostics::{DefaultEmitter, NullEmitter};
191
192 match self.diagnostics.verbosity {
193 Verbosity::Silent => Arc::new(NullEmitter::new(self.color)),
194 _ => Arc::new(DefaultEmitter::new(self.color)),
195 }
196 }
197
198 #[inline(always)]
200 pub fn emit_source_locations(&self) -> bool {
201 matches!(self.debug, DebugInfo::Line | DebugInfo::Full)
202 }
203
204 #[inline(always)]
206 pub fn emit_debug_decorators(&self) -> bool {
207 matches!(self.debug, DebugInfo::Full)
208 }
209
210 #[inline(always)]
212 pub fn emit_debug_assertions(&self) -> bool {
213 self.debug != DebugInfo::None && matches!(self.optimize, OptLevel::None | OptLevel::Basic)
214 }
215}
216
217#[derive(Debug, Copy, Clone, Default)]
219#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
220pub enum OptLevel {
221 None,
223 Basic,
225 #[default]
227 Balanced,
228 Max,
230 Size,
232 SizeMin,
234}
235
236#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
238#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
239pub enum DebugInfo {
240 None,
242 #[default]
244 Line,
245 Full,
247}
248
249#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
251#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
252pub enum Warnings {
253 None,
255 #[default]
257 All,
258 Error,
260}
261impl fmt::Display for Warnings {
262 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
263 match self {
264 Self::None => f.write_str("none"),
265 Self::All => f.write_str("auto"),
266 Self::Error => f.write_str("error"),
267 }
268 }
269}
270impl FromStr for Warnings {
271 type Err = ();
272
273 fn from_str(s: &str) -> Result<Self, Self::Err> {
274 match s {
275 "none" => Ok(Self::None),
276 "all" => Ok(Self::All),
277 "error" => Ok(Self::Error),
278 _ => Err(()),
279 }
280 }
281}
282
283#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
285#[cfg_attr(feature = "std", derive(clap::ValueEnum))]
286pub enum Verbosity {
287 Debug,
289 #[default]
291 Info,
292 Warning,
294 Error,
296 Silent,
298}